@libs-ui/components-avatar 0.2.279 → 0.2.281
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 +37 -11
- package/esm2022/index.mjs +2 -3
- package/esm2022/interfaces/index.mjs +2 -0
- package/fesm2022/libs-ui-components-avatar.mjs +1 -82
- package/fesm2022/libs-ui-components-avatar.mjs.map +1 -1
- package/index.d.ts +1 -2
- package/interfaces/index.d.ts +1 -0
- package/package.json +3 -3
- package/demo/demo.component.d.ts +0 -20
- package/esm2022/demo/demo.component.mjs +0 -84
package/README.md
CHANGED
|
@@ -101,17 +101,18 @@ export class ExampleComponent {
|
|
|
101
101
|
|
|
102
102
|
### Inputs
|
|
103
103
|
|
|
104
|
-
| Tên
|
|
105
|
-
|
|
106
|
-
| linkAvatar
|
|
107
|
-
| linkAvatarError
|
|
108
|
-
| textAvatar
|
|
109
|
-
| idGenColor
|
|
110
|
-
| size
|
|
111
|
-
| typeShape
|
|
112
|
-
| classInclude
|
|
113
|
-
| classImageInclude
|
|
114
|
-
| getLastTextAfterSpace | `boolean`
|
|
104
|
+
| Tên | Kiểu dữ liệu | Mặc định | Mô tả |
|
|
105
|
+
|--------------------|-----------------------------|----------|----------------------------------------------------------------------|
|
|
106
|
+
| linkAvatar | `string` | - | Đường dẫn của hình ảnh avatar |
|
|
107
|
+
| linkAvatarError | `string` | - | Đường dẫn của hình ảnh thay thế khi avatar chính bị lỗi |
|
|
108
|
+
| textAvatar | `string` | - | Văn bản hiển thị khi không có hình ảnh (thường là chữ cái đầu của tên) |
|
|
109
|
+
| idGenColor | `string` | - | ID dùng để tạo màu nền tự động khi sử dụng văn bản |
|
|
110
|
+
| size | `16 \| 24 \| 32 \| 40 \| 48 \| 64` | `32` | Kích thước của avatar (tính bằng pixel) |
|
|
111
|
+
| typeShape | `'circle' \| 'rectangle'` | `'circle'`| Hình dạng của avatar (tròn hoặc vuông) |
|
|
112
|
+
| classInclude | `string` | `'mr-[8px]'` | CSS class bổ sung cho container chính |
|
|
113
|
+
| classImageInclude | `string` | `''` | CSS class bổ sung cho thẻ img |
|
|
114
|
+
| getLastTextAfterSpace | `boolean` | `false` | Nếu true, chỉ lấy chữ cái đầu tiên của từ cuối cùng trong textAvatar |
|
|
115
|
+
| clickPreviewImage | `boolean` | `false` | Cho phép click vào avatar để mở xem ảnh preview |
|
|
115
116
|
|
|
116
117
|
### Outputs
|
|
117
118
|
|
|
@@ -235,3 +236,28 @@ export class AvatarGroupComponent {
|
|
|
235
236
|
}
|
|
236
237
|
</div>
|
|
237
238
|
```
|
|
239
|
+
|
|
240
|
+
## Demo
|
|
241
|
+
|
|
242
|
+
Để xem các ví dụ tương tác về component Avatar, bạn có thể sử dụng `LibsUiComponentsAvatarDemoComponent` trong ứng dụng của mình:
|
|
243
|
+
|
|
244
|
+
```typescript
|
|
245
|
+
import { Component } from '@angular/core';
|
|
246
|
+
import { LibsUiComponentsAvatarDemoComponent } from '@libs-ui/components-avatar';
|
|
247
|
+
|
|
248
|
+
@Component({
|
|
249
|
+
selector: 'app-avatar-demo',
|
|
250
|
+
standalone: true,
|
|
251
|
+
imports: [LibsUiComponentsAvatarDemoComponent],
|
|
252
|
+
template: `
|
|
253
|
+
<lib-avatar-demo></lib-avatar-demo>
|
|
254
|
+
`
|
|
255
|
+
})
|
|
256
|
+
export class AvatarDemoComponent {}
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
Hoặc thêm trực tiếp trong template HTML:
|
|
260
|
+
|
|
261
|
+
```html
|
|
262
|
+
<lib-avatar-demo></lib-avatar-demo>
|
|
263
|
+
```
|
package/esm2022/index.mjs
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
1
|
export * from './avatar.component';
|
|
2
|
-
export * from './interfaces
|
|
3
|
-
|
|
4
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9saWJzLXVpL2NvbXBvbmVudHMvYXZhdGFyL3NyYy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxjQUFjLG9CQUFvQixDQUFDO0FBQ25DLGNBQWMsK0JBQStCLENBQUM7QUFDOUMsY0FBYyx1QkFBdUIsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImV4cG9ydCAqIGZyb20gJy4vYXZhdGFyLmNvbXBvbmVudCc7XG5leHBvcnQgKiBmcm9tICcuL2ludGVyZmFjZXMvYXZhdGFyLmludGVyZmFjZSc7XG5leHBvcnQgKiBmcm9tICcuL2RlbW8vZGVtby5jb21wb25lbnQnOyJdfQ==
|
|
2
|
+
export * from './interfaces';
|
|
3
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9saWJzLXVpL2NvbXBvbmVudHMvYXZhdGFyL3NyYy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxjQUFjLG9CQUFvQixDQUFDO0FBQ25DLGNBQWMsY0FBYyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiZXhwb3J0ICogZnJvbSAnLi9hdmF0YXIuY29tcG9uZW50JztcbmV4cG9ydCAqIGZyb20gJy4vaW50ZXJmYWNlcyc7Il19
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
export * from './avatar.interface';
|
|
2
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9saWJzLXVpL2NvbXBvbmVudHMvYXZhdGFyL3NyYy9pbnRlcmZhY2VzL2luZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLGNBQWMsb0JBQW9CLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgKiBmcm9tICcuL2F2YXRhci5pbnRlcmZhY2UnOyJdfQ==
|
|
@@ -3,7 +3,6 @@ import { signal, computed, input, output, inject, effect, untracked, Component }
|
|
|
3
3
|
import { getColorById, deleteUnicode } from '@libs-ui/utils';
|
|
4
4
|
import { LibsUiComponentsGalleryViewerComponent } from '@libs-ui/components-gallery';
|
|
5
5
|
import { LibsUiDynamicComponentService } from '@libs-ui/services-dynamic-component';
|
|
6
|
-
import { NgFor } from '@angular/common';
|
|
7
6
|
|
|
8
7
|
class LibsUiComponentsAvatarComponent {
|
|
9
8
|
// #region PROPERTY
|
|
@@ -118,89 +117,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImpo
|
|
|
118
117
|
args: [{ selector: 'libs_ui-components-avatar', standalone: true, template: "<div class=\"libs_ui-component-avatar {{ classInclude() }}\"\n [class.libs_ui-component-avatar-rectangle]=\"typeShape() === 'rectangle'\"\n [style.width.px]='size()'\n [style.height.px]='size()'>\n @if (!isShowIcon()) {\n <img [class]=\"classImageInclude() + (clickPreviewImage() ? ' cursor-pointer' : 'cursor-default')\"\n [src]='linkAvatar()'\n (error)=\"handlerImageError($event)\"\n (click)=\"handlerClickImage()\" />\n } @else {\n <div class='libs_ui-component-avatar-icon {{ containertextAvatarClassInclude() }}'\n [style.background]='color()'>\n <div class=\"uppercase text-[#ffffff] libs-ui-font-h{{ fontSize() }}s {{ textAvatarClassInclude() }}\"\n [innerHTML]=\"textAvatar()\">\n </div>\n </div>\n }\n</div>\n", styles: [".libs_ui-component-avatar{position:relative;border-radius:50%;width:100%;height:100%;display:flex;align-items:center;justify-content:center;background:#fff;transition:width .4s,height .4s}.libs_ui-component-avatar-icon,.libs_ui-component-avatar img{border:1px solid #f8f9fa;display:flex;align-items:center;justify-content:center;border-radius:50%;width:100%;height:100%}.libs_ui-component-avatar-icon{width:100%;height:100%}.libs_ui-component-avatar-rectangle{border-radius:4px}.libs_ui-component-avatar-rectangle-icon,.libs_ui-component-avatar-rectangle img{border:none;border-radius:4px;margin:auto}\n"] }]
|
|
119
118
|
}], ctorParameters: () => [] });
|
|
120
119
|
|
|
121
|
-
class LibsUiComponentsAvatarDemoComponent {
|
|
122
|
-
// Basic demo data
|
|
123
|
-
exampleAvatar = 'https://randomuser.me/api/portraits/men/33.jpg';
|
|
124
|
-
fallbackAvatar = 'https://randomuser.me/api/portraits/lego/6.jpg';
|
|
125
|
-
// Size variants
|
|
126
|
-
sizeOptions = [16, 24, 32, 40, 48, 64];
|
|
127
|
-
selectedSize = 40;
|
|
128
|
-
// Shape variants
|
|
129
|
-
shapeOptions = ['circle', 'rectangle'];
|
|
130
|
-
selectedShape = 'circle';
|
|
131
|
-
// Text avatar demo
|
|
132
|
-
userNames = [
|
|
133
|
-
'Nguyễn Văn A',
|
|
134
|
-
'Trần Thị B',
|
|
135
|
-
'Lê Văn C',
|
|
136
|
-
'Phạm Thị D',
|
|
137
|
-
'Vũ Hoàng E',
|
|
138
|
-
'Đặng Thị F'
|
|
139
|
-
];
|
|
140
|
-
// Demo for avatar group
|
|
141
|
-
users = [
|
|
142
|
-
{
|
|
143
|
-
id: 'user-1',
|
|
144
|
-
name: 'Nguyễn Văn A',
|
|
145
|
-
avatar: 'https://randomuser.me/api/portraits/men/32.jpg',
|
|
146
|
-
size: 64
|
|
147
|
-
},
|
|
148
|
-
{
|
|
149
|
-
id: 'user-2',
|
|
150
|
-
name: 'Trần Thị B',
|
|
151
|
-
avatar: 'https://randomuser.me/api/portraits/women/32.jpg',
|
|
152
|
-
size: 48
|
|
153
|
-
},
|
|
154
|
-
{
|
|
155
|
-
id: 'user-3',
|
|
156
|
-
name: 'Lê Văn C',
|
|
157
|
-
avatar: 'https://randomuser.me/api/portraits/men/33.jpg',
|
|
158
|
-
size: 32
|
|
159
|
-
},
|
|
160
|
-
{
|
|
161
|
-
id: 'user-4',
|
|
162
|
-
name: 'Phạm Thị D',
|
|
163
|
-
avatar: undefined,
|
|
164
|
-
size: 24
|
|
165
|
-
}
|
|
166
|
-
];
|
|
167
|
-
// Demo for error handling
|
|
168
|
-
invalidImageUrl = 'https://example.com/invalid-image.jpg';
|
|
169
|
-
showErrorMessage = false;
|
|
170
|
-
// Methods
|
|
171
|
-
toggleShape() {
|
|
172
|
-
this.selectedShape = this.selectedShape === 'circle' ? 'rectangle' : 'circle';
|
|
173
|
-
}
|
|
174
|
-
setSize(size) {
|
|
175
|
-
this.selectedSize = size;
|
|
176
|
-
}
|
|
177
|
-
handleAvatarError() {
|
|
178
|
-
this.showErrorMessage = true;
|
|
179
|
-
setTimeout(() => {
|
|
180
|
-
this.showErrorMessage = false;
|
|
181
|
-
}, 3000);
|
|
182
|
-
}
|
|
183
|
-
copyToClipboard(text) {
|
|
184
|
-
navigator.clipboard.writeText(text).then(() => {
|
|
185
|
-
alert('Đã sao chép vào clipboard');
|
|
186
|
-
}).catch(err => {
|
|
187
|
-
console.error('Không thể sao chép: ', err);
|
|
188
|
-
});
|
|
189
|
-
}
|
|
190
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: LibsUiComponentsAvatarDemoComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
191
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: LibsUiComponentsAvatarDemoComponent, isStandalone: true, selector: "lib-avatar-demo", ngImport: i0, template: "<div class=\"max-w-6xl mx-auto p-5 font-sans text-gray-800\">\n <header class=\"text-center py-10 bg-white rounded-lg mb-8 shadow-sm\">\n <h1 class=\"text-4xl font-bold text-gray-800 mb-2\">Demo Avatar Component</h1>\n <p class=\"text-xl text-gray-500\">Th\u01B0 vi\u1EC7n component Avatar cho Angular</p>\n </header>\n\n <main>\n <section class=\"bg-white rounded-lg p-8 mb-8 shadow-sm\">\n <h2 class=\"text-2xl font-bold text-gray-800 mb-5 pb-3 border-b border-gray-200\">Gi\u1EDBi thi\u1EC7u</h2>\n <p>\n <code class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">@libs-ui/components-avatar</code> l\u00E0 m\u1ED9t\n component Angular \u0111\u1EC3 hi\u1EC3n th\u1ECB avatar ng\u01B0\u1EDDi d\u00F9ng v\u1EDBi nhi\u1EC1u t\u00F9y ch\u1ECDn nh\u01B0 h\u00ECnh \u1EA3nh, ch\u1EEF c\u00E1i \u0111\u1EA7u,\n m\u00E0u s\u1EAFc t\u1EF1 \u0111\u1ED9ng, v\u00E0 h\u1ED7 tr\u1EE3 fallback khi \u1EA3nh b\u1ECB l\u1ED7i.\n </p>\n </section>\n\n <section class=\"bg-white rounded-lg p-8 mb-8 shadow-sm\">\n <h2 class=\"text-2xl font-bold text-gray-800 mb-5 pb-3 border-b border-gray-200\">C\u00E0i \u0111\u1EB7t</h2>\n\n <div class=\"mb-6\">\n <h3 class=\"text-xl font-semibold text-gray-700 mb-3\">Y\u00EAu c\u1EA7u</h3>\n <ul class=\"list-disc pl-5 space-y-2 text-gray-600\">\n <li><span class=\"font-semibold\">Angular</span>: 18.0.0 tr\u1EDF l\u00EAn</li>\n <li><span class=\"font-semibold\">Tailwind CSS</span>: 3.3.0 tr\u1EDF l\u00EAn</li>\n </ul>\n </div>\n\n <p class=\"mb-4\">\u0110\u1EC3 c\u00E0i \u0111\u1EB7t th\u01B0 vi\u1EC7n, s\u1EED d\u1EE5ng npm ho\u1EB7c yarn:</p>\n\n <div class=\"flex items-center bg-gray-100 p-4 rounded-lg mb-6\">\n <pre class=\"flex-1 text-sm overflow-x-auto\"><code>npm install @libs-ui/components-avatar</code></pre>\n <button class=\"ml-4 px-3 py-1 bg-blue-500 text-white rounded hover:bg-blue-600 transition-colors\"\n (click)=\"copyToClipboard('npm install @libs-ui/components-avatar')\">\n Sao ch\u00E9p\n </button>\n </div>\n\n <p class=\"mb-4\">Ho\u1EB7c v\u1EDBi yarn:</p>\n\n <div class=\"flex items-center bg-gray-100 p-4 rounded-lg mb-6\">\n <pre class=\"flex-1 text-sm overflow-x-auto\"><code>yarn add @libs-ui/components-avatar</code></pre>\n <button class=\"ml-4 px-3 py-1 bg-blue-500 text-white rounded hover:bg-blue-600 transition-colors\"\n (click)=\"copyToClipboard('yarn add @libs-ui/components-avatar')\">\n Sao ch\u00E9p\n </button>\n </div>\n </section>\n\n <section class=\"bg-white rounded-lg p-8 mb-8 shadow-sm\">\n <h2 class=\"text-2xl font-bold text-gray-800 mb-5 pb-3 border-b border-gray-200\">Demo tr\u1EF1c ti\u1EBFp</h2>\n\n <!-- Basic Avatar Demo -->\n <div class=\"mb-8\">\n <h3 class=\"text-xl font-semibold text-gray-700 mb-4\">Avatar c\u01A1 b\u1EA3n</h3>\n <div class=\"flex items-center p-4 bg-gray-50 rounded-lg\">\n <libs_ui-components-avatar [linkAvatar]=\"exampleAvatar\"\n [size]=\"selectedSize\"\n [typeShape]=\"selectedShape\">\n </libs_ui-components-avatar>\n <div>\n <p class=\"text-gray-700\">Avatar v\u1EDBi h\u00ECnh \u1EA3nh t\u1EEB URL</p>\n <p class=\"text-sm text-gray-500\">K\u00EDch th\u01B0\u1EDBc: {{ selectedSize }}px, H\u00ECnh d\u1EA1ng: {{ selectedShape }}</p>\n </div>\n </div>\n <div class=\"mt-4 flex flex-wrap gap-3\">\n <button *ngFor=\"let size of sizeOptions\"\n (click)=\"setSize(size)\"\n class=\"px-3 py-1 border rounded\"\n [class.bg-blue-500]=\"selectedSize === size\"\n [class.text-white]=\"selectedSize === size\">\n {{ size }}px\n </button>\n <button (click)=\"toggleShape()\"\n class=\"px-3 py-1 border rounded ml-4\">\n \u0110\u1ED5i h\u00ECnh d\u1EA1ng\n </button>\n </div>\n </div>\n\n <!-- Text Avatar Demo -->\n <div class=\"mb-8\">\n <h3 class=\"text-xl font-semibold text-gray-700 mb-4\">Avatar v\u0103n b\u1EA3n</h3>\n <div class=\"flex flex-wrap gap-3 p-4 bg-gray-50 rounded-lg\">\n @for (name of userNames; track name) {\n <libs_ui-components-avatar [getLastTextAfterSpace]=\"true\" [textAvatar]=\"name\"\n [idGenColor]=\"name\"\n [size]=\"40\"\n >\n </libs_ui-components-avatar>\n }\n </div>\n <p class=\"mt-2 text-sm text-gray-500\">Hi\u1EC3n th\u1ECB ch\u1EEF c\u00E1i \u0111\u1EA7u ti\u00EAn c\u1EE7a t\u00EAn v\u1EDBi m\u00E0u n\u1EC1n t\u1EF1 \u0111\u1ED9ng d\u1EF1a tr\u00EAn ID.</p>\n </div>\n\n <!-- Avatar Group Demo -->\n <div class=\"mb-8\">\n <h3 class=\"text-xl font-semibold text-gray-700 mb-4\">Nh\u00F3m Avatar</h3>\n <div class=\"flex items-center p-4 bg-gray-50 rounded-lg\">\n @for (user of users; track user) {\n <libs_ui-components-avatar [linkAvatar]=\"user['avatar']\"\n [textAvatar]=\"user['name']\"\n [idGenColor]=\"user['id']\"\n [size]=\"user['size']\"\n [typeShape]=\"user['id'] === 'user-4' ? 'rectangle' : 'circle'\"\n [classInclude]=\"'mr-2'\">\n </libs_ui-components-avatar>\n }\n </div>\n <p class=\"mt-2 text-sm text-gray-500\">Nh\u00F3m avatars v\u1EDBi k\u00EDch th\u01B0\u1EDBc kh\u00E1c nhau v\u00E0 hi\u1EC3n th\u1ECB fallback khi kh\u00F4ng c\u00F3\n h\u00ECnh \u1EA3nh.</p>\n </div>\n\n <!-- Error Handling Demo -->\n <div class=\"mb-8\">\n <h3 class=\"text-xl font-semibold text-gray-700 mb-4\">X\u1EED l\u00FD l\u1ED7i</h3>\n <div class=\"flex items-center p-4 bg-gray-50 rounded-lg\">\n <libs_ui-components-avatar [linkAvatar]=\"invalidImageUrl\"\n [linkAvatarError]=\"fallbackAvatar\"\n [textAvatar]=\"'Error Fallback'\"\n [idGenColor]=\"'error-demo'\"\n [size]=\"48\">\n </libs_ui-components-avatar>\n <div>\n <p class=\"text-gray-700\">Avatar v\u1EDBi x\u1EED l\u00FD l\u1ED7i h\u00ECnh \u1EA3nh</p>\n <p class=\"text-sm text-gray-500\">Khi h\u00ECnh \u1EA3nh ch\u00EDnh b\u1ECB l\u1ED7i, s\u1EBD hi\u1EC3n th\u1ECB h\u00ECnh \u1EA3nh thay th\u1EBF.</p>\n </div>\n </div>\n </div>\n\n <!-- Fallback to Text Demo -->\n <div class=\"mb-8\">\n <h3 class=\"text-xl font-semibold text-gray-700 mb-4\">Fallback v\u1EC1 v\u0103n b\u1EA3n</h3>\n <div class=\"flex items-center p-4 bg-gray-50 rounded-lg\">\n <libs_ui-components-avatar [linkAvatar]=\"invalidImageUrl\"\n [textAvatar]=\"'Text Fallback'\"\n [idGenColor]=\"'text-fallback'\"\n [size]=\"48\"\n (outAvatarError)=\"handleAvatarError()\">\n </libs_ui-components-avatar>\n <div>\n <p class=\"text-gray-700\">Avatar v\u1EDBi fallback v\u1EC1 v\u0103n b\u1EA3n</p>\n <p class=\"text-sm text-gray-500\">Khi kh\u00F4ng c\u00F3 h\u00ECnh \u1EA3nh, s\u1EBD hi\u1EC3n th\u1ECB ch\u1EEF c\u00E1i \u0111\u1EA7u c\u1EE7a v\u0103n b\u1EA3n v\u1EDBi m\u00E0u n\u1EC1n t\u1EF1\n \u0111\u1ED9ng.</p>\n @if (showErrorMessage) {\n <p class=\"text-sm text-red-500 mt-2\">Kh\u00F4ng th\u1EC3 t\u1EA3i h\u00ECnh \u1EA3nh. \u0110\u00E3 hi\u1EC3n th\u1ECB v\u0103n b\u1EA3n thay th\u1EBF.</p>\n }\n </div>\n </div>\n </div>\n </section>\n\n <section class=\"bg-white rounded-lg p-8 mb-8 shadow-sm\">\n <h2 class=\"text-2xl font-bold text-gray-800 mb-5 pb-3 border-b border-gray-200\">C\u00E1ch s\u1EED d\u1EE5ng</h2>\n\n <div class=\"mb-8\">\n <h3 class=\"text-xl font-semibold text-gray-700 mb-4\">C\u00E1ch 1: S\u1EED d\u1EE5ng file HTML ri\u00EAng bi\u1EC7t</h3>\n\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-6 mb-4\">\n <div>\n <h4 class=\"font-semibold mb-2 text-gray-700\">HTML (example.component.html)</h4>\n <pre class=\"bg-gray-100 p-4 rounded-lg overflow-x-auto text-sm\"><code><libs_ui-components-avatar\n [linkAvatar]=\"'https://example.com/avatar.jpg'\"\n [textAvatar]=\"'Nguy\u1EC5n V\u0103n A'\"\n [idGenColor]=\"'user-123'\"\n [size]=\"40\"\n [typeShape]=\"'circle'\">\n</libs_ui-components-avatar></code></pre>\n </div>\n\n <div>\n <h4 class=\"font-semibold mb-2 text-gray-700\">TypeScript (example.component.ts)</h4>\n <pre class=\"bg-gray-100 p-4 rounded-lg overflow-x-auto text-sm\"><code>import { Component } from '@angular/core';\nimport { LibsUiComponentsAvatarComponent } from '@libs-ui/components-avatar';\n\n@Component({\n selector: 'app-example',\n standalone: true,\n imports: [LibsUiComponentsAvatarComponent],\n templateUrl: './example.component.html'\n})\nexport class ExampleComponent {\n // Component logic\n}</code></pre>\n </div>\n </div>\n </div>\n\n <div class=\"mb-8\">\n <h3 class=\"text-xl font-semibold text-gray-700 mb-4\">C\u00E1ch 2: X\u1EED l\u00FD s\u1EF1 ki\u1EC7n l\u1ED7i</h3>\n\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-6 mb-4\">\n <div>\n <h4 class=\"font-semibold mb-2 text-gray-700\">HTML (error-handler.component.html)</h4>\n <pre class=\"bg-gray-100 p-4 rounded-lg overflow-x-auto text-sm\"><code><libs_ui-components-avatar\n [linkAvatar]=\"user.avatar\"\n [linkAvatarError]=\"defaultAvatar\"\n [textAvatar]=\"user.name\"\n [idGenColor]=\"user.id\"\n [size]=\"40\"\n (outAvatarError)=\"handleAvatarError()\">\n</libs_ui-components-avatar></code></pre>\n </div>\n\n <div>\n <h4 class=\"font-semibold mb-2 text-gray-700\">TypeScript (error-handler.component.ts)</h4>\n <pre class=\"bg-gray-100 p-4 rounded-lg overflow-x-auto text-sm\"><code>import { Component } from '@angular/core';\nimport { LibsUiComponentsAvatarComponent } from '@libs-ui/components-avatar';\n\n@Component({\n selector: 'app-error-handler',\n standalone: true,\n imports: [LibsUiComponentsAvatarComponent],\n templateUrl: './error-handler.component.html'\n})\nexport class ErrorHandlerComponent {\n user = {\n id: 'user-123',\n name: 'Nguy\u1EC5n V\u0103n A',\n avatar: 'https://example.com/avatar.jpg'\n };\n \n defaultAvatar = 'https://example.com/default-avatar.jpg';\n\n handleAvatarError() {\n console.log('Kh\u00F4ng th\u1EC3 t\u1EA3i \u0111\u01B0\u1EE3c h\u00ECnh \u1EA3nh avatar');\n // Th\u1EF1c hi\u1EC7n c\u00E1c x\u1EED l\u00FD kh\u00E1c khi c\u00F3 l\u1ED7i\n }\n}</code></pre>\n </div>\n </div>\n </div>\n </section>\n\n <section class=\"bg-white rounded-lg p-8 mb-8 shadow-sm\">\n <h2 class=\"text-2xl font-bold text-gray-800 mb-5 pb-3 border-b border-gray-200\">T\u00E0i li\u1EC7u API</h2>\n\n <h3 class=\"text-xl font-semibold text-gray-700 mb-4\">Inputs</h3>\n <div class=\"overflow-x-auto mb-8\">\n <table class=\"min-w-full bg-white border border-gray-200\">\n <thead>\n <tr>\n <th class=\"py-3 px-4 border-b border-gray-200 bg-gray-100 text-left font-semibold text-gray-700\">T\u00EAn</th>\n <th class=\"py-3 px-4 border-b border-gray-200 bg-gray-100 text-left font-semibold text-gray-700\">Ki\u1EC3u d\u1EEF\n li\u1EC7u</th>\n <th class=\"py-3 px-4 border-b border-gray-200 bg-gray-100 text-left font-semibold text-gray-700\">M\u1EB7c \u0111\u1ECBnh\n </th>\n <th class=\"py-3 px-4 border-b border-gray-200 bg-gray-100 text-left font-semibold text-gray-700\">M\u00F4 t\u1EA3\n </th>\n </tr>\n </thead>\n <tbody>\n <tr>\n <td class=\"py-2 px-4 border-b border-gray-200\"><code\n class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">linkAvatar</code></td>\n <td class=\"py-2 px-4 border-b border-gray-200\"><code\n class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">string</code></td>\n <td class=\"py-2 px-4 border-b border-gray-200\">-</td>\n <td class=\"py-2 px-4 border-b border-gray-200\">\u0110\u01B0\u1EDDng d\u1EABn c\u1EE7a h\u00ECnh \u1EA3nh avatar</td>\n </tr>\n <tr>\n <td class=\"py-2 px-4 border-b border-gray-200\"><code\n class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">linkAvatarError</code></td>\n <td class=\"py-2 px-4 border-b border-gray-200\"><code\n class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">string</code></td>\n <td class=\"py-2 px-4 border-b border-gray-200\">-</td>\n <td class=\"py-2 px-4 border-b border-gray-200\">\u0110\u01B0\u1EDDng d\u1EABn c\u1EE7a h\u00ECnh \u1EA3nh thay th\u1EBF khi avatar ch\u00EDnh b\u1ECB l\u1ED7i\n </td>\n </tr>\n <tr>\n <td class=\"py-2 px-4 border-b border-gray-200\"><code\n class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">textAvatar</code></td>\n <td class=\"py-2 px-4 border-b border-gray-200\"><code\n class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">string</code></td>\n <td class=\"py-2 px-4 border-b border-gray-200\">-</td>\n <td class=\"py-2 px-4 border-b border-gray-200\">V\u0103n b\u1EA3n hi\u1EC3n th\u1ECB khi kh\u00F4ng c\u00F3 h\u00ECnh \u1EA3nh (th\u01B0\u1EDDng l\u00E0 ch\u1EEF c\u00E1i\n \u0111\u1EA7u c\u1EE7a t\u00EAn)</td>\n </tr>\n <tr>\n <td class=\"py-2 px-4 border-b border-gray-200\"><code\n class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">idGenColor</code></td>\n <td class=\"py-2 px-4 border-b border-gray-200\"><code\n class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">string</code></td>\n <td class=\"py-2 px-4 border-b border-gray-200\">-</td>\n <td class=\"py-2 px-4 border-b border-gray-200\">ID d\u00F9ng \u0111\u1EC3 t\u1EA1o m\u00E0u n\u1EC1n t\u1EF1 \u0111\u1ED9ng khi s\u1EED d\u1EE5ng v\u0103n b\u1EA3n</td>\n </tr>\n <tr>\n <td class=\"py-2 px-4 border-b border-gray-200\"><code\n class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">size</code></td>\n <td class=\"py-2 px-4 border-b border-gray-200\"><code class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">16\n | 24 | 32 | 40 | 48 | 64</code></td>\n <td class=\"py-2 px-4 border-b border-gray-200\">32</td>\n <td class=\"py-2 px-4 border-b border-gray-200\">K\u00EDch th\u01B0\u1EDBc c\u1EE7a avatar (t\u00EDnh b\u1EB1ng pixel)</td>\n </tr>\n <tr>\n <td class=\"py-2 px-4 border-b border-gray-200\"><code\n class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">typeShape</code></td>\n <td class=\"py-2 px-4 border-b border-gray-200\"><code\n class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">'circle' | 'rectangle'</code></td>\n <td class=\"py-2 px-4 border-b border-gray-200\">'circle'</td>\n <td class=\"py-2 px-4 border-b border-gray-200\">H\u00ECnh d\u1EA1ng c\u1EE7a avatar (tr\u00F2n ho\u1EB7c vu\u00F4ng)</td>\n </tr>\n <tr>\n <td class=\"py-2 px-4 border-b border-gray-200\"><code\n class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">classInclude</code></td>\n <td class=\"py-2 px-4 border-b border-gray-200\"><code\n class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">string</code></td>\n <td class=\"py-2 px-4 border-b border-gray-200\">'mr-[8px]'</td>\n <td class=\"py-2 px-4 border-b border-gray-200\">CSS class b\u1ED5 sung cho container ch\u00EDnh</td>\n </tr>\n <tr>\n <td class=\"py-2 px-4 border-b border-gray-200\"><code\n class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">classImageInclude</code></td>\n <td class=\"py-2 px-4 border-b border-gray-200\"><code\n class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">string</code></td>\n <td class=\"py-2 px-4 border-b border-gray-200\">''</td>\n <td class=\"py-2 px-4 border-b border-gray-200\">CSS class b\u1ED5 sung cho th\u1EBB img</td>\n </tr>\n <tr>\n <td class=\"py-2 px-4 border-b border-gray-200\"><code\n class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">getLastTextAfterSpace</code></td>\n <td class=\"py-2 px-4 border-b border-gray-200\"><code\n class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">boolean</code></td>\n <td class=\"py-2 px-4 border-b border-gray-200\">false</td>\n <td class=\"py-2 px-4 border-b border-gray-200\">N\u1EBFu true, ch\u1EC9 l\u1EA5y ch\u1EEF c\u00E1i \u0111\u1EA7u ti\u00EAn c\u1EE7a t\u1EEB cu\u1ED1i c\u00F9ng trong\n textAvatar</td>\n </tr>\n </tbody>\n </table>\n </div>\n\n <h3 class=\"text-xl font-semibold text-gray-700 mb-4\">Outputs</h3>\n <div class=\"overflow-x-auto mb-8\">\n <table class=\"min-w-full bg-white border border-gray-200\">\n <thead>\n <tr>\n <th class=\"py-3 px-4 border-b border-gray-200 bg-gray-100 text-left font-semibold text-gray-700\">T\u00EAn</th>\n <th class=\"py-3 px-4 border-b border-gray-200 bg-gray-100 text-left font-semibold text-gray-700\">Ki\u1EC3u d\u1EEF\n li\u1EC7u</th>\n <th class=\"py-3 px-4 border-b border-gray-200 bg-gray-100 text-left font-semibold text-gray-700\">M\u00F4 t\u1EA3\n </th>\n </tr>\n </thead>\n <tbody>\n <tr>\n <td class=\"py-2 px-4 border-b border-gray-200\"><code\n class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">outAvatarError</code></td>\n <td class=\"py-2 px-4 border-b border-gray-200\"><code\n class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">void</code></td>\n <td class=\"py-2 px-4 border-b border-gray-200\">S\u1EF1 ki\u1EC7n \u0111\u01B0\u1EE3c k\u00EDch ho\u1EA1t khi linkAvatar b\u1ECB l\u1ED7i v\u00E0 kh\u00F4ng c\u00F3\n linkAvatarError</td>\n </tr>\n </tbody>\n </table>\n </div>\n\n <h3 class=\"text-xl font-semibold text-gray-700 mb-4\">Interfaces</h3>\n <div class=\"bg-gray-50 p-6 rounded-lg\">\n <h4 class=\"text-lg font-semibold text-gray-700 mb-3\">IAvatarConfig</h4>\n <pre class=\"bg-gray-100 p-4 rounded-lg overflow-x-auto text-sm mb-3\"><code>export interface IAvatarConfig {\n classImageInclude?: string;\n classInclude?: string;\n size?: TYPE_SIZE_AVATAR_CONFIG;\n linkAvatar?: string;\n linkAvatarError?: string;\n idGenColor?: string;\n textAvatar?: string;\n typeShape?: TYPE_SHAPE_AVATAR;\n getLastTextAfterSpace?: boolean;\n }\n\nexport type TYPE_SIZE_AVATAR_CONFIG = 16 | 24 | 32 | 40 | 48 | 64;\nexport type TYPE_SHAPE_AVATAR = 'circle' | 'rectangle';</code></pre>\n <p class=\"text-gray-600\">Interface \u0111\u1ECBnh ngh\u0129a c\u1EA5u h\u00ECnh c\u1EE7a avatar component.</p>\n </div>\n </section>\n </main>\n</div>\n", styles: [":host{display:block;width:100%;padding:16px}.demo-wrapper{background-color:#f9fafb;border-radius:8px;padding:16px;margin-bottom:16px}.code-block{font-family:monospace;background-color:#f3f4f6;border-radius:4px;padding:2px 4px;font-size:14px}button{transition:all .2s ease}button:hover{opacity:.9}button:active{transform:scale(.98)}.size-option{cursor:pointer;border:1px solid #e5e7eb;padding:4px 8px;border-radius:4px}.size-option.selected{background-color:#3b82f6;color:#fff;border-color:#3b82f6}.shape-option{cursor:pointer;border:1px solid #e5e7eb;padding:4px 8px;border-radius:4px;margin-left:8px}.shape-option.selected{background-color:#3b82f6;color:#fff;border-color:#3b82f6}.error-message{color:#ef4444;margin-top:8px;font-size:14px}.copy-button{background-color:#3b82f6;color:#fff;border-radius:4px;padding:4px 8px;font-size:14px;border:none;cursor:pointer}\n"], dependencies: [{ kind: "component", type: LibsUiComponentsAvatarComponent, selector: "libs_ui-components-avatar", inputs: ["typeShape", "classInclude", "size", "linkAvatar", "linkAvatarError", "classImageInclude", "zIndexPreviewImage", "clickPreviewImage", "idGenColor", "getLastTextAfterSpace", "textAvatar", "textAvatarClassInclude", "containertextAvatarClassInclude"], outputs: ["outAvatarError", "outEventPreviewImage"] }, { kind: "directive", type: NgFor, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }] });
|
|
192
|
-
}
|
|
193
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: LibsUiComponentsAvatarDemoComponent, decorators: [{
|
|
194
|
-
type: Component,
|
|
195
|
-
args: [{ selector: 'lib-avatar-demo', standalone: true, imports: [
|
|
196
|
-
LibsUiComponentsAvatarComponent,
|
|
197
|
-
NgFor
|
|
198
|
-
], template: "<div class=\"max-w-6xl mx-auto p-5 font-sans text-gray-800\">\n <header class=\"text-center py-10 bg-white rounded-lg mb-8 shadow-sm\">\n <h1 class=\"text-4xl font-bold text-gray-800 mb-2\">Demo Avatar Component</h1>\n <p class=\"text-xl text-gray-500\">Th\u01B0 vi\u1EC7n component Avatar cho Angular</p>\n </header>\n\n <main>\n <section class=\"bg-white rounded-lg p-8 mb-8 shadow-sm\">\n <h2 class=\"text-2xl font-bold text-gray-800 mb-5 pb-3 border-b border-gray-200\">Gi\u1EDBi thi\u1EC7u</h2>\n <p>\n <code class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">@libs-ui/components-avatar</code> l\u00E0 m\u1ED9t\n component Angular \u0111\u1EC3 hi\u1EC3n th\u1ECB avatar ng\u01B0\u1EDDi d\u00F9ng v\u1EDBi nhi\u1EC1u t\u00F9y ch\u1ECDn nh\u01B0 h\u00ECnh \u1EA3nh, ch\u1EEF c\u00E1i \u0111\u1EA7u,\n m\u00E0u s\u1EAFc t\u1EF1 \u0111\u1ED9ng, v\u00E0 h\u1ED7 tr\u1EE3 fallback khi \u1EA3nh b\u1ECB l\u1ED7i.\n </p>\n </section>\n\n <section class=\"bg-white rounded-lg p-8 mb-8 shadow-sm\">\n <h2 class=\"text-2xl font-bold text-gray-800 mb-5 pb-3 border-b border-gray-200\">C\u00E0i \u0111\u1EB7t</h2>\n\n <div class=\"mb-6\">\n <h3 class=\"text-xl font-semibold text-gray-700 mb-3\">Y\u00EAu c\u1EA7u</h3>\n <ul class=\"list-disc pl-5 space-y-2 text-gray-600\">\n <li><span class=\"font-semibold\">Angular</span>: 18.0.0 tr\u1EDF l\u00EAn</li>\n <li><span class=\"font-semibold\">Tailwind CSS</span>: 3.3.0 tr\u1EDF l\u00EAn</li>\n </ul>\n </div>\n\n <p class=\"mb-4\">\u0110\u1EC3 c\u00E0i \u0111\u1EB7t th\u01B0 vi\u1EC7n, s\u1EED d\u1EE5ng npm ho\u1EB7c yarn:</p>\n\n <div class=\"flex items-center bg-gray-100 p-4 rounded-lg mb-6\">\n <pre class=\"flex-1 text-sm overflow-x-auto\"><code>npm install @libs-ui/components-avatar</code></pre>\n <button class=\"ml-4 px-3 py-1 bg-blue-500 text-white rounded hover:bg-blue-600 transition-colors\"\n (click)=\"copyToClipboard('npm install @libs-ui/components-avatar')\">\n Sao ch\u00E9p\n </button>\n </div>\n\n <p class=\"mb-4\">Ho\u1EB7c v\u1EDBi yarn:</p>\n\n <div class=\"flex items-center bg-gray-100 p-4 rounded-lg mb-6\">\n <pre class=\"flex-1 text-sm overflow-x-auto\"><code>yarn add @libs-ui/components-avatar</code></pre>\n <button class=\"ml-4 px-3 py-1 bg-blue-500 text-white rounded hover:bg-blue-600 transition-colors\"\n (click)=\"copyToClipboard('yarn add @libs-ui/components-avatar')\">\n Sao ch\u00E9p\n </button>\n </div>\n </section>\n\n <section class=\"bg-white rounded-lg p-8 mb-8 shadow-sm\">\n <h2 class=\"text-2xl font-bold text-gray-800 mb-5 pb-3 border-b border-gray-200\">Demo tr\u1EF1c ti\u1EBFp</h2>\n\n <!-- Basic Avatar Demo -->\n <div class=\"mb-8\">\n <h3 class=\"text-xl font-semibold text-gray-700 mb-4\">Avatar c\u01A1 b\u1EA3n</h3>\n <div class=\"flex items-center p-4 bg-gray-50 rounded-lg\">\n <libs_ui-components-avatar [linkAvatar]=\"exampleAvatar\"\n [size]=\"selectedSize\"\n [typeShape]=\"selectedShape\">\n </libs_ui-components-avatar>\n <div>\n <p class=\"text-gray-700\">Avatar v\u1EDBi h\u00ECnh \u1EA3nh t\u1EEB URL</p>\n <p class=\"text-sm text-gray-500\">K\u00EDch th\u01B0\u1EDBc: {{ selectedSize }}px, H\u00ECnh d\u1EA1ng: {{ selectedShape }}</p>\n </div>\n </div>\n <div class=\"mt-4 flex flex-wrap gap-3\">\n <button *ngFor=\"let size of sizeOptions\"\n (click)=\"setSize(size)\"\n class=\"px-3 py-1 border rounded\"\n [class.bg-blue-500]=\"selectedSize === size\"\n [class.text-white]=\"selectedSize === size\">\n {{ size }}px\n </button>\n <button (click)=\"toggleShape()\"\n class=\"px-3 py-1 border rounded ml-4\">\n \u0110\u1ED5i h\u00ECnh d\u1EA1ng\n </button>\n </div>\n </div>\n\n <!-- Text Avatar Demo -->\n <div class=\"mb-8\">\n <h3 class=\"text-xl font-semibold text-gray-700 mb-4\">Avatar v\u0103n b\u1EA3n</h3>\n <div class=\"flex flex-wrap gap-3 p-4 bg-gray-50 rounded-lg\">\n @for (name of userNames; track name) {\n <libs_ui-components-avatar [getLastTextAfterSpace]=\"true\" [textAvatar]=\"name\"\n [idGenColor]=\"name\"\n [size]=\"40\"\n >\n </libs_ui-components-avatar>\n }\n </div>\n <p class=\"mt-2 text-sm text-gray-500\">Hi\u1EC3n th\u1ECB ch\u1EEF c\u00E1i \u0111\u1EA7u ti\u00EAn c\u1EE7a t\u00EAn v\u1EDBi m\u00E0u n\u1EC1n t\u1EF1 \u0111\u1ED9ng d\u1EF1a tr\u00EAn ID.</p>\n </div>\n\n <!-- Avatar Group Demo -->\n <div class=\"mb-8\">\n <h3 class=\"text-xl font-semibold text-gray-700 mb-4\">Nh\u00F3m Avatar</h3>\n <div class=\"flex items-center p-4 bg-gray-50 rounded-lg\">\n @for (user of users; track user) {\n <libs_ui-components-avatar [linkAvatar]=\"user['avatar']\"\n [textAvatar]=\"user['name']\"\n [idGenColor]=\"user['id']\"\n [size]=\"user['size']\"\n [typeShape]=\"user['id'] === 'user-4' ? 'rectangle' : 'circle'\"\n [classInclude]=\"'mr-2'\">\n </libs_ui-components-avatar>\n }\n </div>\n <p class=\"mt-2 text-sm text-gray-500\">Nh\u00F3m avatars v\u1EDBi k\u00EDch th\u01B0\u1EDBc kh\u00E1c nhau v\u00E0 hi\u1EC3n th\u1ECB fallback khi kh\u00F4ng c\u00F3\n h\u00ECnh \u1EA3nh.</p>\n </div>\n\n <!-- Error Handling Demo -->\n <div class=\"mb-8\">\n <h3 class=\"text-xl font-semibold text-gray-700 mb-4\">X\u1EED l\u00FD l\u1ED7i</h3>\n <div class=\"flex items-center p-4 bg-gray-50 rounded-lg\">\n <libs_ui-components-avatar [linkAvatar]=\"invalidImageUrl\"\n [linkAvatarError]=\"fallbackAvatar\"\n [textAvatar]=\"'Error Fallback'\"\n [idGenColor]=\"'error-demo'\"\n [size]=\"48\">\n </libs_ui-components-avatar>\n <div>\n <p class=\"text-gray-700\">Avatar v\u1EDBi x\u1EED l\u00FD l\u1ED7i h\u00ECnh \u1EA3nh</p>\n <p class=\"text-sm text-gray-500\">Khi h\u00ECnh \u1EA3nh ch\u00EDnh b\u1ECB l\u1ED7i, s\u1EBD hi\u1EC3n th\u1ECB h\u00ECnh \u1EA3nh thay th\u1EBF.</p>\n </div>\n </div>\n </div>\n\n <!-- Fallback to Text Demo -->\n <div class=\"mb-8\">\n <h3 class=\"text-xl font-semibold text-gray-700 mb-4\">Fallback v\u1EC1 v\u0103n b\u1EA3n</h3>\n <div class=\"flex items-center p-4 bg-gray-50 rounded-lg\">\n <libs_ui-components-avatar [linkAvatar]=\"invalidImageUrl\"\n [textAvatar]=\"'Text Fallback'\"\n [idGenColor]=\"'text-fallback'\"\n [size]=\"48\"\n (outAvatarError)=\"handleAvatarError()\">\n </libs_ui-components-avatar>\n <div>\n <p class=\"text-gray-700\">Avatar v\u1EDBi fallback v\u1EC1 v\u0103n b\u1EA3n</p>\n <p class=\"text-sm text-gray-500\">Khi kh\u00F4ng c\u00F3 h\u00ECnh \u1EA3nh, s\u1EBD hi\u1EC3n th\u1ECB ch\u1EEF c\u00E1i \u0111\u1EA7u c\u1EE7a v\u0103n b\u1EA3n v\u1EDBi m\u00E0u n\u1EC1n t\u1EF1\n \u0111\u1ED9ng.</p>\n @if (showErrorMessage) {\n <p class=\"text-sm text-red-500 mt-2\">Kh\u00F4ng th\u1EC3 t\u1EA3i h\u00ECnh \u1EA3nh. \u0110\u00E3 hi\u1EC3n th\u1ECB v\u0103n b\u1EA3n thay th\u1EBF.</p>\n }\n </div>\n </div>\n </div>\n </section>\n\n <section class=\"bg-white rounded-lg p-8 mb-8 shadow-sm\">\n <h2 class=\"text-2xl font-bold text-gray-800 mb-5 pb-3 border-b border-gray-200\">C\u00E1ch s\u1EED d\u1EE5ng</h2>\n\n <div class=\"mb-8\">\n <h3 class=\"text-xl font-semibold text-gray-700 mb-4\">C\u00E1ch 1: S\u1EED d\u1EE5ng file HTML ri\u00EAng bi\u1EC7t</h3>\n\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-6 mb-4\">\n <div>\n <h4 class=\"font-semibold mb-2 text-gray-700\">HTML (example.component.html)</h4>\n <pre class=\"bg-gray-100 p-4 rounded-lg overflow-x-auto text-sm\"><code><libs_ui-components-avatar\n [linkAvatar]=\"'https://example.com/avatar.jpg'\"\n [textAvatar]=\"'Nguy\u1EC5n V\u0103n A'\"\n [idGenColor]=\"'user-123'\"\n [size]=\"40\"\n [typeShape]=\"'circle'\">\n</libs_ui-components-avatar></code></pre>\n </div>\n\n <div>\n <h4 class=\"font-semibold mb-2 text-gray-700\">TypeScript (example.component.ts)</h4>\n <pre class=\"bg-gray-100 p-4 rounded-lg overflow-x-auto text-sm\"><code>import { Component } from '@angular/core';\nimport { LibsUiComponentsAvatarComponent } from '@libs-ui/components-avatar';\n\n@Component({\n selector: 'app-example',\n standalone: true,\n imports: [LibsUiComponentsAvatarComponent],\n templateUrl: './example.component.html'\n})\nexport class ExampleComponent {\n // Component logic\n}</code></pre>\n </div>\n </div>\n </div>\n\n <div class=\"mb-8\">\n <h3 class=\"text-xl font-semibold text-gray-700 mb-4\">C\u00E1ch 2: X\u1EED l\u00FD s\u1EF1 ki\u1EC7n l\u1ED7i</h3>\n\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-6 mb-4\">\n <div>\n <h4 class=\"font-semibold mb-2 text-gray-700\">HTML (error-handler.component.html)</h4>\n <pre class=\"bg-gray-100 p-4 rounded-lg overflow-x-auto text-sm\"><code><libs_ui-components-avatar\n [linkAvatar]=\"user.avatar\"\n [linkAvatarError]=\"defaultAvatar\"\n [textAvatar]=\"user.name\"\n [idGenColor]=\"user.id\"\n [size]=\"40\"\n (outAvatarError)=\"handleAvatarError()\">\n</libs_ui-components-avatar></code></pre>\n </div>\n\n <div>\n <h4 class=\"font-semibold mb-2 text-gray-700\">TypeScript (error-handler.component.ts)</h4>\n <pre class=\"bg-gray-100 p-4 rounded-lg overflow-x-auto text-sm\"><code>import { Component } from '@angular/core';\nimport { LibsUiComponentsAvatarComponent } from '@libs-ui/components-avatar';\n\n@Component({\n selector: 'app-error-handler',\n standalone: true,\n imports: [LibsUiComponentsAvatarComponent],\n templateUrl: './error-handler.component.html'\n})\nexport class ErrorHandlerComponent {\n user = {\n id: 'user-123',\n name: 'Nguy\u1EC5n V\u0103n A',\n avatar: 'https://example.com/avatar.jpg'\n };\n \n defaultAvatar = 'https://example.com/default-avatar.jpg';\n\n handleAvatarError() {\n console.log('Kh\u00F4ng th\u1EC3 t\u1EA3i \u0111\u01B0\u1EE3c h\u00ECnh \u1EA3nh avatar');\n // Th\u1EF1c hi\u1EC7n c\u00E1c x\u1EED l\u00FD kh\u00E1c khi c\u00F3 l\u1ED7i\n }\n}</code></pre>\n </div>\n </div>\n </div>\n </section>\n\n <section class=\"bg-white rounded-lg p-8 mb-8 shadow-sm\">\n <h2 class=\"text-2xl font-bold text-gray-800 mb-5 pb-3 border-b border-gray-200\">T\u00E0i li\u1EC7u API</h2>\n\n <h3 class=\"text-xl font-semibold text-gray-700 mb-4\">Inputs</h3>\n <div class=\"overflow-x-auto mb-8\">\n <table class=\"min-w-full bg-white border border-gray-200\">\n <thead>\n <tr>\n <th class=\"py-3 px-4 border-b border-gray-200 bg-gray-100 text-left font-semibold text-gray-700\">T\u00EAn</th>\n <th class=\"py-3 px-4 border-b border-gray-200 bg-gray-100 text-left font-semibold text-gray-700\">Ki\u1EC3u d\u1EEF\n li\u1EC7u</th>\n <th class=\"py-3 px-4 border-b border-gray-200 bg-gray-100 text-left font-semibold text-gray-700\">M\u1EB7c \u0111\u1ECBnh\n </th>\n <th class=\"py-3 px-4 border-b border-gray-200 bg-gray-100 text-left font-semibold text-gray-700\">M\u00F4 t\u1EA3\n </th>\n </tr>\n </thead>\n <tbody>\n <tr>\n <td class=\"py-2 px-4 border-b border-gray-200\"><code\n class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">linkAvatar</code></td>\n <td class=\"py-2 px-4 border-b border-gray-200\"><code\n class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">string</code></td>\n <td class=\"py-2 px-4 border-b border-gray-200\">-</td>\n <td class=\"py-2 px-4 border-b border-gray-200\">\u0110\u01B0\u1EDDng d\u1EABn c\u1EE7a h\u00ECnh \u1EA3nh avatar</td>\n </tr>\n <tr>\n <td class=\"py-2 px-4 border-b border-gray-200\"><code\n class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">linkAvatarError</code></td>\n <td class=\"py-2 px-4 border-b border-gray-200\"><code\n class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">string</code></td>\n <td class=\"py-2 px-4 border-b border-gray-200\">-</td>\n <td class=\"py-2 px-4 border-b border-gray-200\">\u0110\u01B0\u1EDDng d\u1EABn c\u1EE7a h\u00ECnh \u1EA3nh thay th\u1EBF khi avatar ch\u00EDnh b\u1ECB l\u1ED7i\n </td>\n </tr>\n <tr>\n <td class=\"py-2 px-4 border-b border-gray-200\"><code\n class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">textAvatar</code></td>\n <td class=\"py-2 px-4 border-b border-gray-200\"><code\n class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">string</code></td>\n <td class=\"py-2 px-4 border-b border-gray-200\">-</td>\n <td class=\"py-2 px-4 border-b border-gray-200\">V\u0103n b\u1EA3n hi\u1EC3n th\u1ECB khi kh\u00F4ng c\u00F3 h\u00ECnh \u1EA3nh (th\u01B0\u1EDDng l\u00E0 ch\u1EEF c\u00E1i\n \u0111\u1EA7u c\u1EE7a t\u00EAn)</td>\n </tr>\n <tr>\n <td class=\"py-2 px-4 border-b border-gray-200\"><code\n class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">idGenColor</code></td>\n <td class=\"py-2 px-4 border-b border-gray-200\"><code\n class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">string</code></td>\n <td class=\"py-2 px-4 border-b border-gray-200\">-</td>\n <td class=\"py-2 px-4 border-b border-gray-200\">ID d\u00F9ng \u0111\u1EC3 t\u1EA1o m\u00E0u n\u1EC1n t\u1EF1 \u0111\u1ED9ng khi s\u1EED d\u1EE5ng v\u0103n b\u1EA3n</td>\n </tr>\n <tr>\n <td class=\"py-2 px-4 border-b border-gray-200\"><code\n class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">size</code></td>\n <td class=\"py-2 px-4 border-b border-gray-200\"><code class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">16\n | 24 | 32 | 40 | 48 | 64</code></td>\n <td class=\"py-2 px-4 border-b border-gray-200\">32</td>\n <td class=\"py-2 px-4 border-b border-gray-200\">K\u00EDch th\u01B0\u1EDBc c\u1EE7a avatar (t\u00EDnh b\u1EB1ng pixel)</td>\n </tr>\n <tr>\n <td class=\"py-2 px-4 border-b border-gray-200\"><code\n class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">typeShape</code></td>\n <td class=\"py-2 px-4 border-b border-gray-200\"><code\n class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">'circle' | 'rectangle'</code></td>\n <td class=\"py-2 px-4 border-b border-gray-200\">'circle'</td>\n <td class=\"py-2 px-4 border-b border-gray-200\">H\u00ECnh d\u1EA1ng c\u1EE7a avatar (tr\u00F2n ho\u1EB7c vu\u00F4ng)</td>\n </tr>\n <tr>\n <td class=\"py-2 px-4 border-b border-gray-200\"><code\n class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">classInclude</code></td>\n <td class=\"py-2 px-4 border-b border-gray-200\"><code\n class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">string</code></td>\n <td class=\"py-2 px-4 border-b border-gray-200\">'mr-[8px]'</td>\n <td class=\"py-2 px-4 border-b border-gray-200\">CSS class b\u1ED5 sung cho container ch\u00EDnh</td>\n </tr>\n <tr>\n <td class=\"py-2 px-4 border-b border-gray-200\"><code\n class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">classImageInclude</code></td>\n <td class=\"py-2 px-4 border-b border-gray-200\"><code\n class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">string</code></td>\n <td class=\"py-2 px-4 border-b border-gray-200\">''</td>\n <td class=\"py-2 px-4 border-b border-gray-200\">CSS class b\u1ED5 sung cho th\u1EBB img</td>\n </tr>\n <tr>\n <td class=\"py-2 px-4 border-b border-gray-200\"><code\n class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">getLastTextAfterSpace</code></td>\n <td class=\"py-2 px-4 border-b border-gray-200\"><code\n class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">boolean</code></td>\n <td class=\"py-2 px-4 border-b border-gray-200\">false</td>\n <td class=\"py-2 px-4 border-b border-gray-200\">N\u1EBFu true, ch\u1EC9 l\u1EA5y ch\u1EEF c\u00E1i \u0111\u1EA7u ti\u00EAn c\u1EE7a t\u1EEB cu\u1ED1i c\u00F9ng trong\n textAvatar</td>\n </tr>\n </tbody>\n </table>\n </div>\n\n <h3 class=\"text-xl font-semibold text-gray-700 mb-4\">Outputs</h3>\n <div class=\"overflow-x-auto mb-8\">\n <table class=\"min-w-full bg-white border border-gray-200\">\n <thead>\n <tr>\n <th class=\"py-3 px-4 border-b border-gray-200 bg-gray-100 text-left font-semibold text-gray-700\">T\u00EAn</th>\n <th class=\"py-3 px-4 border-b border-gray-200 bg-gray-100 text-left font-semibold text-gray-700\">Ki\u1EC3u d\u1EEF\n li\u1EC7u</th>\n <th class=\"py-3 px-4 border-b border-gray-200 bg-gray-100 text-left font-semibold text-gray-700\">M\u00F4 t\u1EA3\n </th>\n </tr>\n </thead>\n <tbody>\n <tr>\n <td class=\"py-2 px-4 border-b border-gray-200\"><code\n class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">outAvatarError</code></td>\n <td class=\"py-2 px-4 border-b border-gray-200\"><code\n class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">void</code></td>\n <td class=\"py-2 px-4 border-b border-gray-200\">S\u1EF1 ki\u1EC7n \u0111\u01B0\u1EE3c k\u00EDch ho\u1EA1t khi linkAvatar b\u1ECB l\u1ED7i v\u00E0 kh\u00F4ng c\u00F3\n linkAvatarError</td>\n </tr>\n </tbody>\n </table>\n </div>\n\n <h3 class=\"text-xl font-semibold text-gray-700 mb-4\">Interfaces</h3>\n <div class=\"bg-gray-50 p-6 rounded-lg\">\n <h4 class=\"text-lg font-semibold text-gray-700 mb-3\">IAvatarConfig</h4>\n <pre class=\"bg-gray-100 p-4 rounded-lg overflow-x-auto text-sm mb-3\"><code>export interface IAvatarConfig {\n classImageInclude?: string;\n classInclude?: string;\n size?: TYPE_SIZE_AVATAR_CONFIG;\n linkAvatar?: string;\n linkAvatarError?: string;\n idGenColor?: string;\n textAvatar?: string;\n typeShape?: TYPE_SHAPE_AVATAR;\n getLastTextAfterSpace?: boolean;\n }\n\nexport type TYPE_SIZE_AVATAR_CONFIG = 16 | 24 | 32 | 40 | 48 | 64;\nexport type TYPE_SHAPE_AVATAR = 'circle' | 'rectangle';</code></pre>\n <p class=\"text-gray-600\">Interface \u0111\u1ECBnh ngh\u0129a c\u1EA5u h\u00ECnh c\u1EE7a avatar component.</p>\n </div>\n </section>\n </main>\n</div>\n", styles: [":host{display:block;width:100%;padding:16px}.demo-wrapper{background-color:#f9fafb;border-radius:8px;padding:16px;margin-bottom:16px}.code-block{font-family:monospace;background-color:#f3f4f6;border-radius:4px;padding:2px 4px;font-size:14px}button{transition:all .2s ease}button:hover{opacity:.9}button:active{transform:scale(.98)}.size-option{cursor:pointer;border:1px solid #e5e7eb;padding:4px 8px;border-radius:4px}.size-option.selected{background-color:#3b82f6;color:#fff;border-color:#3b82f6}.shape-option{cursor:pointer;border:1px solid #e5e7eb;padding:4px 8px;border-radius:4px;margin-left:8px}.shape-option.selected{background-color:#3b82f6;color:#fff;border-color:#3b82f6}.error-message{color:#ef4444;margin-top:8px;font-size:14px}.copy-button{background-color:#3b82f6;color:#fff;border-radius:4px;padding:4px 8px;font-size:14px;border:none;cursor:pointer}\n"] }]
|
|
199
|
-
}] });
|
|
200
|
-
|
|
201
120
|
/**
|
|
202
121
|
* Generated bundle index. Do not edit.
|
|
203
122
|
*/
|
|
204
123
|
|
|
205
|
-
export { LibsUiComponentsAvatarComponent
|
|
124
|
+
export { LibsUiComponentsAvatarComponent };
|
|
206
125
|
//# sourceMappingURL=libs-ui-components-avatar.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"libs-ui-components-avatar.mjs","sources":["../../../../../libs-ui/components/avatar/src/avatar.component.ts","../../../../../libs-ui/components/avatar/src/avatar.component.html","../../../../../libs-ui/components/avatar/src/demo/demo.component.ts","../../../../../libs-ui/components/avatar/src/demo/demo.component.html","../../../../../libs-ui/components/avatar/src/libs-ui-components-avatar.ts"],"sourcesContent":["import { Component, ComponentRef, computed, effect, inject, input, OnDestroy, output, signal, untracked } from '@angular/core';\nimport { IEvent } from '@libs-ui/interfaces-types';\nimport { deleteUnicode, getColorById } from '@libs-ui/utils';\nimport { TYPE_SHAPE_AVATAR, TYPE_SIZE_AVATAR_CONFIG } from './interfaces/avatar.interface';\nimport { LibsUiComponentsGalleryViewerComponent } from '@libs-ui/components-gallery'\nimport { LibsUiDynamicComponentService } from '@libs-ui/services-dynamic-component';\n\n@Component({\n // eslint-disable-next-line @angular-eslint/component-selector\n selector: 'libs_ui-components-avatar',\n templateUrl: './avatar.component.html',\n standalone: true,\n styleUrls: ['./avatar.component.scss']\n})\nexport class LibsUiComponentsAvatarComponent implements OnDestroy {\n // #region PROPERTY\n protected isErrorLinkAvatar = signal<boolean>(false);\n protected isErrorLinkAvatarError = signal<boolean>(false);\n protected isShowIcon = signal<boolean>(false);\n protected color = computed(() => getColorById(this.idGenColor() || ''));\n protected fontSize = computed(this.fontSizeComputed.bind(this));\n\n private galleryViewerComponent?: ComponentRef<LibsUiComponentsGalleryViewerComponent>;\n\n // #region INPUT\n readonly typeShape = input<TYPE_SHAPE_AVATAR | undefined, TYPE_SHAPE_AVATAR | undefined>('circle', { transform: value => value ?? 'circle' });\n readonly classInclude = input<string | undefined, string | undefined>('mr-[8px]', { transform: (value) => value ?? 'mr-[8px]' });\n readonly size = input<TYPE_SIZE_AVATAR_CONFIG | undefined, TYPE_SIZE_AVATAR_CONFIG | undefined>(32, { transform: value => value ?? 32 });\n readonly linkAvatar = input<string>();\n readonly linkAvatarError = input<string>();\n readonly classImageInclude = input<string | undefined, string | undefined>('', { transform: (value) => value ?? '' });\n readonly zIndexPreviewImage = input<number>();\n readonly clickPreviewImage = input<boolean>();\n readonly idGenColor = input<string>();\n readonly getLastTextAfterSpace = input<boolean>(); // Lấy text cuối cùng sau khi cắt khoảng trắng. Lưu ý truyền biến này trước khi truyền biến textAvatar\n readonly textAvatar = input<string | undefined, string | undefined>('', {\n transform: (value) => {\n value = deleteUnicode(value || '').replace(/[^a-zA-Z0-9\\s]/g, '').trim();\n\n if (this.getLastTextAfterSpace()) {\n value = value.split(' ').pop() || '';\n }\n\n return value[0] || '—';\n }\n });\n readonly textAvatarClassInclude = input<string, string | undefined>('', { transform: (value) => value ?? '' });\n readonly containertextAvatarClassInclude = input<string, string | undefined>('', { transform: (value) => value ?? '' });\n\n // #region OUTPUT\n readonly outAvatarError = output<void>();\n readonly outEventPreviewImage = output<'open' | 'remove'>();\n\n // #region INJECT\n private dynamicComponentService = inject(LibsUiDynamicComponentService);\n\n constructor() {\n effect(() => {\n this.linkAvatar();\n untracked(() => {\n this.isShowIcon.set(false);\n this.isErrorLinkAvatar.set(false);\n this.isErrorLinkAvatarError.set(false);\n })\n });\n }\n\n /* FUNCTIONS */\n protected async handlerImageError(e: ErrorEvent) {\n if (!this.linkAvatarError()?.trim() && this.idGenColor() && this.textAvatar()) {\n this.outAvatarError.emit();\n this.isShowIcon.set(true);\n\n return;\n }\n if (this.isErrorLinkAvatar()) {\n this.isErrorLinkAvatarError.set(true)\n }\n this.isErrorLinkAvatar.set(true);\n\n if (this.isErrorLinkAvatarError() && this.idGenColor() && this.textAvatar()) {\n this.isShowIcon.set(true)\n }\n\n\n if (this.isErrorLinkAvatarError()) {\n return;\n }\n if (!this.linkAvatarError()) {\n this.outAvatarError.emit();\n\n return;\n }\n (e as IEvent).target.src = this.linkAvatarError();\n }\n\n protected handlerClickImage() {\n if (this.galleryViewerComponent || !this.clickPreviewImage()) {\n return;\n }\n this.outEventPreviewImage.emit('open');\n this.galleryViewerComponent = this.dynamicComponentService.resolveComponentFactory(LibsUiComponentsGalleryViewerComponent);\n this.galleryViewerComponent.setInput('images', [{ imageSrc: this.linkAvatar() }]);\n this.galleryViewerComponent.setInput('fieldDisplaySrcImage', 'imageSrc');\n this.galleryViewerComponent.setInput('singleImage', true);\n this.galleryViewerComponent.setInput('zIndex', this.zIndexPreviewImage());\n this.galleryViewerComponent.instance.outClose.subscribe(() => {\n this.dynamicComponentService.remove(this.galleryViewerComponent);\n this.galleryViewerComponent = undefined;\n this.outEventPreviewImage.emit('remove');\n })\n\n this.dynamicComponentService.addToBody(this.galleryViewerComponent);\n }\n\n /* COMPUTED PROPERTIES FUNCTION */\n private fontSizeComputed() {\n if (this.size() === 16 || this.size() === 24) {\n return 6;\n }\n\n if (this.size() === 32) {\n return 4;\n }\n\n if (this.size() === 40) {\n return 3;\n }\n\n if (this.size() === 64) {\n return 1;\n }\n return 4;\n }\n\n ngOnDestroy(): void {\n this.dynamicComponentService.remove(this.galleryViewerComponent);\n this.galleryViewerComponent = undefined;\n }\n}","<div class=\"libs_ui-component-avatar {{ classInclude() }}\"\n [class.libs_ui-component-avatar-rectangle]=\"typeShape() === 'rectangle'\"\n [style.width.px]='size()'\n [style.height.px]='size()'>\n @if (!isShowIcon()) {\n <img [class]=\"classImageInclude() + (clickPreviewImage() ? ' cursor-pointer' : 'cursor-default')\"\n [src]='linkAvatar()'\n (error)=\"handlerImageError($event)\"\n (click)=\"handlerClickImage()\" />\n } @else {\n <div class='libs_ui-component-avatar-icon {{ containertextAvatarClassInclude() }}'\n [style.background]='color()'>\n <div class=\"uppercase text-[#ffffff] libs-ui-font-h{{ fontSize() }}s {{ textAvatarClassInclude() }}\"\n [innerHTML]=\"textAvatar()\">\n </div>\n </div>\n }\n</div>\n","import { NgFor } from '@angular/common';\nimport { Component } from '@angular/core';\nimport { LibsUiComponentsAvatarComponent } from '../avatar.component';\nimport { TYPE_SHAPE_AVATAR, TYPE_SIZE_AVATAR_CONFIG } from '../interfaces/avatar.interface';\n\n@Component({\n selector: 'lib-avatar-demo',\n standalone: true,\n imports: [\n LibsUiComponentsAvatarComponent,\n NgFor\n ],\n templateUrl: './demo.component.html',\n styleUrl: './demo.component.scss'\n})\nexport class LibsUiComponentsAvatarDemoComponent {\n // Basic demo data\n exampleAvatar = 'https://randomuser.me/api/portraits/men/33.jpg';\n fallbackAvatar = 'https://randomuser.me/api/portraits/lego/6.jpg';\n\n // Size variants\n sizeOptions: TYPE_SIZE_AVATAR_CONFIG[] = [16, 24, 32, 40, 48, 64];\n selectedSize: TYPE_SIZE_AVATAR_CONFIG = 40;\n\n // Shape variants\n shapeOptions: TYPE_SHAPE_AVATAR[] = ['circle', 'rectangle'];\n selectedShape: TYPE_SHAPE_AVATAR = 'circle';\n\n // Text avatar demo\n userNames = [\n 'Nguyễn Văn A',\n 'Trần Thị B',\n 'Lê Văn C',\n 'Phạm Thị D',\n 'Vũ Hoàng E',\n 'Đặng Thị F'\n ];\n\n // Demo for avatar group\n users = [\n {\n id: 'user-1',\n name: 'Nguyễn Văn A',\n avatar: 'https://randomuser.me/api/portraits/men/32.jpg',\n size: 64\n },\n {\n id: 'user-2',\n name: 'Trần Thị B',\n avatar: 'https://randomuser.me/api/portraits/women/32.jpg',\n size: 48\n },\n {\n id: 'user-3',\n name: 'Lê Văn C',\n avatar: 'https://randomuser.me/api/portraits/men/33.jpg',\n size: 32\n },\n {\n id: 'user-4',\n name: 'Phạm Thị D',\n avatar: undefined,\n size: 24\n }\n ] as Array<Record<string, any>>;\n\n // Demo for error handling\n invalidImageUrl = 'https://example.com/invalid-image.jpg';\n showErrorMessage = false;\n\n // Methods\n toggleShape() {\n this.selectedShape = this.selectedShape === 'circle' ? 'rectangle' : 'circle';\n }\n\n setSize(size: TYPE_SIZE_AVATAR_CONFIG) {\n this.selectedSize = size;\n }\n\n handleAvatarError() {\n this.showErrorMessage = true;\n setTimeout(() => {\n this.showErrorMessage = false;\n }, 3000);\n }\n\n copyToClipboard(text: string) {\n navigator.clipboard.writeText(text).then(() => {\n alert('Đã sao chép vào clipboard');\n }).catch(err => {\n console.error('Không thể sao chép: ', err);\n });\n }\n} ","<div class=\"max-w-6xl mx-auto p-5 font-sans text-gray-800\">\n <header class=\"text-center py-10 bg-white rounded-lg mb-8 shadow-sm\">\n <h1 class=\"text-4xl font-bold text-gray-800 mb-2\">Demo Avatar Component</h1>\n <p class=\"text-xl text-gray-500\">Thư viện component Avatar cho Angular</p>\n </header>\n\n <main>\n <section class=\"bg-white rounded-lg p-8 mb-8 shadow-sm\">\n <h2 class=\"text-2xl font-bold text-gray-800 mb-5 pb-3 border-b border-gray-200\">Giới thiệu</h2>\n <p>\n <code class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">@libs-ui/components-avatar</code> là một\n component Angular để hiển thị avatar người dùng với nhiều tùy chọn như hình ảnh, chữ cái đầu,\n màu sắc tự động, và hỗ trợ fallback khi ảnh bị lỗi.\n </p>\n </section>\n\n <section class=\"bg-white rounded-lg p-8 mb-8 shadow-sm\">\n <h2 class=\"text-2xl font-bold text-gray-800 mb-5 pb-3 border-b border-gray-200\">Cài đặt</h2>\n\n <div class=\"mb-6\">\n <h3 class=\"text-xl font-semibold text-gray-700 mb-3\">Yêu cầu</h3>\n <ul class=\"list-disc pl-5 space-y-2 text-gray-600\">\n <li><span class=\"font-semibold\">Angular</span>: 18.0.0 trở lên</li>\n <li><span class=\"font-semibold\">Tailwind CSS</span>: 3.3.0 trở lên</li>\n </ul>\n </div>\n\n <p class=\"mb-4\">Để cài đặt thư viện, sử dụng npm hoặc yarn:</p>\n\n <div class=\"flex items-center bg-gray-100 p-4 rounded-lg mb-6\">\n <pre class=\"flex-1 text-sm overflow-x-auto\"><code>npm install @libs-ui/components-avatar</code></pre>\n <button class=\"ml-4 px-3 py-1 bg-blue-500 text-white rounded hover:bg-blue-600 transition-colors\"\n (click)=\"copyToClipboard('npm install @libs-ui/components-avatar')\">\n Sao chép\n </button>\n </div>\n\n <p class=\"mb-4\">Hoặc với yarn:</p>\n\n <div class=\"flex items-center bg-gray-100 p-4 rounded-lg mb-6\">\n <pre class=\"flex-1 text-sm overflow-x-auto\"><code>yarn add @libs-ui/components-avatar</code></pre>\n <button class=\"ml-4 px-3 py-1 bg-blue-500 text-white rounded hover:bg-blue-600 transition-colors\"\n (click)=\"copyToClipboard('yarn add @libs-ui/components-avatar')\">\n Sao chép\n </button>\n </div>\n </section>\n\n <section class=\"bg-white rounded-lg p-8 mb-8 shadow-sm\">\n <h2 class=\"text-2xl font-bold text-gray-800 mb-5 pb-3 border-b border-gray-200\">Demo trực tiếp</h2>\n\n <!-- Basic Avatar Demo -->\n <div class=\"mb-8\">\n <h3 class=\"text-xl font-semibold text-gray-700 mb-4\">Avatar cơ bản</h3>\n <div class=\"flex items-center p-4 bg-gray-50 rounded-lg\">\n <libs_ui-components-avatar [linkAvatar]=\"exampleAvatar\"\n [size]=\"selectedSize\"\n [typeShape]=\"selectedShape\">\n </libs_ui-components-avatar>\n <div>\n <p class=\"text-gray-700\">Avatar với hình ảnh từ URL</p>\n <p class=\"text-sm text-gray-500\">Kích thước: {{ selectedSize }}px, Hình dạng: {{ selectedShape }}</p>\n </div>\n </div>\n <div class=\"mt-4 flex flex-wrap gap-3\">\n <button *ngFor=\"let size of sizeOptions\"\n (click)=\"setSize(size)\"\n class=\"px-3 py-1 border rounded\"\n [class.bg-blue-500]=\"selectedSize === size\"\n [class.text-white]=\"selectedSize === size\">\n {{ size }}px\n </button>\n <button (click)=\"toggleShape()\"\n class=\"px-3 py-1 border rounded ml-4\">\n Đổi hình dạng\n </button>\n </div>\n </div>\n\n <!-- Text Avatar Demo -->\n <div class=\"mb-8\">\n <h3 class=\"text-xl font-semibold text-gray-700 mb-4\">Avatar văn bản</h3>\n <div class=\"flex flex-wrap gap-3 p-4 bg-gray-50 rounded-lg\">\n @for (name of userNames; track name) {\n <libs_ui-components-avatar [getLastTextAfterSpace]=\"true\" [textAvatar]=\"name\"\n [idGenColor]=\"name\"\n [size]=\"40\"\n >\n </libs_ui-components-avatar>\n }\n </div>\n <p class=\"mt-2 text-sm text-gray-500\">Hiển thị chữ cái đầu tiên của tên với màu nền tự động dựa trên ID.</p>\n </div>\n\n <!-- Avatar Group Demo -->\n <div class=\"mb-8\">\n <h3 class=\"text-xl font-semibold text-gray-700 mb-4\">Nhóm Avatar</h3>\n <div class=\"flex items-center p-4 bg-gray-50 rounded-lg\">\n @for (user of users; track user) {\n <libs_ui-components-avatar [linkAvatar]=\"user['avatar']\"\n [textAvatar]=\"user['name']\"\n [idGenColor]=\"user['id']\"\n [size]=\"user['size']\"\n [typeShape]=\"user['id'] === 'user-4' ? 'rectangle' : 'circle'\"\n [classInclude]=\"'mr-2'\">\n </libs_ui-components-avatar>\n }\n </div>\n <p class=\"mt-2 text-sm text-gray-500\">Nhóm avatars với kích thước khác nhau và hiển thị fallback khi không có\n hình ảnh.</p>\n </div>\n\n <!-- Error Handling Demo -->\n <div class=\"mb-8\">\n <h3 class=\"text-xl font-semibold text-gray-700 mb-4\">Xử lý lỗi</h3>\n <div class=\"flex items-center p-4 bg-gray-50 rounded-lg\">\n <libs_ui-components-avatar [linkAvatar]=\"invalidImageUrl\"\n [linkAvatarError]=\"fallbackAvatar\"\n [textAvatar]=\"'Error Fallback'\"\n [idGenColor]=\"'error-demo'\"\n [size]=\"48\">\n </libs_ui-components-avatar>\n <div>\n <p class=\"text-gray-700\">Avatar với xử lý lỗi hình ảnh</p>\n <p class=\"text-sm text-gray-500\">Khi hình ảnh chính bị lỗi, sẽ hiển thị hình ảnh thay thế.</p>\n </div>\n </div>\n </div>\n\n <!-- Fallback to Text Demo -->\n <div class=\"mb-8\">\n <h3 class=\"text-xl font-semibold text-gray-700 mb-4\">Fallback về văn bản</h3>\n <div class=\"flex items-center p-4 bg-gray-50 rounded-lg\">\n <libs_ui-components-avatar [linkAvatar]=\"invalidImageUrl\"\n [textAvatar]=\"'Text Fallback'\"\n [idGenColor]=\"'text-fallback'\"\n [size]=\"48\"\n (outAvatarError)=\"handleAvatarError()\">\n </libs_ui-components-avatar>\n <div>\n <p class=\"text-gray-700\">Avatar với fallback về văn bản</p>\n <p class=\"text-sm text-gray-500\">Khi không có hình ảnh, sẽ hiển thị chữ cái đầu của văn bản với màu nền tự\n động.</p>\n @if (showErrorMessage) {\n <p class=\"text-sm text-red-500 mt-2\">Không thể tải hình ảnh. Đã hiển thị văn bản thay thế.</p>\n }\n </div>\n </div>\n </div>\n </section>\n\n <section class=\"bg-white rounded-lg p-8 mb-8 shadow-sm\">\n <h2 class=\"text-2xl font-bold text-gray-800 mb-5 pb-3 border-b border-gray-200\">Cách sử dụng</h2>\n\n <div class=\"mb-8\">\n <h3 class=\"text-xl font-semibold text-gray-700 mb-4\">Cách 1: Sử dụng file HTML riêng biệt</h3>\n\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-6 mb-4\">\n <div>\n <h4 class=\"font-semibold mb-2 text-gray-700\">HTML (example.component.html)</h4>\n <pre class=\"bg-gray-100 p-4 rounded-lg overflow-x-auto text-sm\"><code><libs_ui-components-avatar\n [linkAvatar]=\"'https://example.com/avatar.jpg'\"\n [textAvatar]=\"'Nguyễn Văn A'\"\n [idGenColor]=\"'user-123'\"\n [size]=\"40\"\n [typeShape]=\"'circle'\">\n</libs_ui-components-avatar></code></pre>\n </div>\n\n <div>\n <h4 class=\"font-semibold mb-2 text-gray-700\">TypeScript (example.component.ts)</h4>\n <pre class=\"bg-gray-100 p-4 rounded-lg overflow-x-auto text-sm\"><code>import { Component } from '@angular/core';\nimport { LibsUiComponentsAvatarComponent } from '@libs-ui/components-avatar';\n\n@Component({\n selector: 'app-example',\n standalone: true,\n imports: [LibsUiComponentsAvatarComponent],\n templateUrl: './example.component.html'\n})\nexport class ExampleComponent {\n // Component logic\n}</code></pre>\n </div>\n </div>\n </div>\n\n <div class=\"mb-8\">\n <h3 class=\"text-xl font-semibold text-gray-700 mb-4\">Cách 2: Xử lý sự kiện lỗi</h3>\n\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-6 mb-4\">\n <div>\n <h4 class=\"font-semibold mb-2 text-gray-700\">HTML (error-handler.component.html)</h4>\n <pre class=\"bg-gray-100 p-4 rounded-lg overflow-x-auto text-sm\"><code><libs_ui-components-avatar\n [linkAvatar]=\"user.avatar\"\n [linkAvatarError]=\"defaultAvatar\"\n [textAvatar]=\"user.name\"\n [idGenColor]=\"user.id\"\n [size]=\"40\"\n (outAvatarError)=\"handleAvatarError()\">\n</libs_ui-components-avatar></code></pre>\n </div>\n\n <div>\n <h4 class=\"font-semibold mb-2 text-gray-700\">TypeScript (error-handler.component.ts)</h4>\n <pre class=\"bg-gray-100 p-4 rounded-lg overflow-x-auto text-sm\"><code>import { Component } from '@angular/core';\nimport { LibsUiComponentsAvatarComponent } from '@libs-ui/components-avatar';\n\n@Component({\n selector: 'app-error-handler',\n standalone: true,\n imports: [LibsUiComponentsAvatarComponent],\n templateUrl: './error-handler.component.html'\n})\nexport class ErrorHandlerComponent {\n user = {\n id: 'user-123',\n name: 'Nguyễn Văn A',\n avatar: 'https://example.com/avatar.jpg'\n };\n \n defaultAvatar = 'https://example.com/default-avatar.jpg';\n\n handleAvatarError() {\n console.log('Không thể tải được hình ảnh avatar');\n // Thực hiện các xử lý khác khi có lỗi\n }\n}</code></pre>\n </div>\n </div>\n </div>\n </section>\n\n <section class=\"bg-white rounded-lg p-8 mb-8 shadow-sm\">\n <h2 class=\"text-2xl font-bold text-gray-800 mb-5 pb-3 border-b border-gray-200\">Tài liệu API</h2>\n\n <h3 class=\"text-xl font-semibold text-gray-700 mb-4\">Inputs</h3>\n <div class=\"overflow-x-auto mb-8\">\n <table class=\"min-w-full bg-white border border-gray-200\">\n <thead>\n <tr>\n <th class=\"py-3 px-4 border-b border-gray-200 bg-gray-100 text-left font-semibold text-gray-700\">Tên</th>\n <th class=\"py-3 px-4 border-b border-gray-200 bg-gray-100 text-left font-semibold text-gray-700\">Kiểu dữ\n liệu</th>\n <th class=\"py-3 px-4 border-b border-gray-200 bg-gray-100 text-left font-semibold text-gray-700\">Mặc định\n </th>\n <th class=\"py-3 px-4 border-b border-gray-200 bg-gray-100 text-left font-semibold text-gray-700\">Mô tả\n </th>\n </tr>\n </thead>\n <tbody>\n <tr>\n <td class=\"py-2 px-4 border-b border-gray-200\"><code\n class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">linkAvatar</code></td>\n <td class=\"py-2 px-4 border-b border-gray-200\"><code\n class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">string</code></td>\n <td class=\"py-2 px-4 border-b border-gray-200\">-</td>\n <td class=\"py-2 px-4 border-b border-gray-200\">Đường dẫn của hình ảnh avatar</td>\n </tr>\n <tr>\n <td class=\"py-2 px-4 border-b border-gray-200\"><code\n class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">linkAvatarError</code></td>\n <td class=\"py-2 px-4 border-b border-gray-200\"><code\n class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">string</code></td>\n <td class=\"py-2 px-4 border-b border-gray-200\">-</td>\n <td class=\"py-2 px-4 border-b border-gray-200\">Đường dẫn của hình ảnh thay thế khi avatar chính bị lỗi\n </td>\n </tr>\n <tr>\n <td class=\"py-2 px-4 border-b border-gray-200\"><code\n class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">textAvatar</code></td>\n <td class=\"py-2 px-4 border-b border-gray-200\"><code\n class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">string</code></td>\n <td class=\"py-2 px-4 border-b border-gray-200\">-</td>\n <td class=\"py-2 px-4 border-b border-gray-200\">Văn bản hiển thị khi không có hình ảnh (thường là chữ cái\n đầu của tên)</td>\n </tr>\n <tr>\n <td class=\"py-2 px-4 border-b border-gray-200\"><code\n class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">idGenColor</code></td>\n <td class=\"py-2 px-4 border-b border-gray-200\"><code\n class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">string</code></td>\n <td class=\"py-2 px-4 border-b border-gray-200\">-</td>\n <td class=\"py-2 px-4 border-b border-gray-200\">ID dùng để tạo màu nền tự động khi sử dụng văn bản</td>\n </tr>\n <tr>\n <td class=\"py-2 px-4 border-b border-gray-200\"><code\n class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">size</code></td>\n <td class=\"py-2 px-4 border-b border-gray-200\"><code class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">16\n | 24 | 32 | 40 | 48 | 64</code></td>\n <td class=\"py-2 px-4 border-b border-gray-200\">32</td>\n <td class=\"py-2 px-4 border-b border-gray-200\">Kích thước của avatar (tính bằng pixel)</td>\n </tr>\n <tr>\n <td class=\"py-2 px-4 border-b border-gray-200\"><code\n class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">typeShape</code></td>\n <td class=\"py-2 px-4 border-b border-gray-200\"><code\n class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">'circle' | 'rectangle'</code></td>\n <td class=\"py-2 px-4 border-b border-gray-200\">'circle'</td>\n <td class=\"py-2 px-4 border-b border-gray-200\">Hình dạng của avatar (tròn hoặc vuông)</td>\n </tr>\n <tr>\n <td class=\"py-2 px-4 border-b border-gray-200\"><code\n class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">classInclude</code></td>\n <td class=\"py-2 px-4 border-b border-gray-200\"><code\n class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">string</code></td>\n <td class=\"py-2 px-4 border-b border-gray-200\">'mr-[8px]'</td>\n <td class=\"py-2 px-4 border-b border-gray-200\">CSS class bổ sung cho container chính</td>\n </tr>\n <tr>\n <td class=\"py-2 px-4 border-b border-gray-200\"><code\n class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">classImageInclude</code></td>\n <td class=\"py-2 px-4 border-b border-gray-200\"><code\n class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">string</code></td>\n <td class=\"py-2 px-4 border-b border-gray-200\">''</td>\n <td class=\"py-2 px-4 border-b border-gray-200\">CSS class bổ sung cho thẻ img</td>\n </tr>\n <tr>\n <td class=\"py-2 px-4 border-b border-gray-200\"><code\n class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">getLastTextAfterSpace</code></td>\n <td class=\"py-2 px-4 border-b border-gray-200\"><code\n class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">boolean</code></td>\n <td class=\"py-2 px-4 border-b border-gray-200\">false</td>\n <td class=\"py-2 px-4 border-b border-gray-200\">Nếu true, chỉ lấy chữ cái đầu tiên của từ cuối cùng trong\n textAvatar</td>\n </tr>\n </tbody>\n </table>\n </div>\n\n <h3 class=\"text-xl font-semibold text-gray-700 mb-4\">Outputs</h3>\n <div class=\"overflow-x-auto mb-8\">\n <table class=\"min-w-full bg-white border border-gray-200\">\n <thead>\n <tr>\n <th class=\"py-3 px-4 border-b border-gray-200 bg-gray-100 text-left font-semibold text-gray-700\">Tên</th>\n <th class=\"py-3 px-4 border-b border-gray-200 bg-gray-100 text-left font-semibold text-gray-700\">Kiểu dữ\n liệu</th>\n <th class=\"py-3 px-4 border-b border-gray-200 bg-gray-100 text-left font-semibold text-gray-700\">Mô tả\n </th>\n </tr>\n </thead>\n <tbody>\n <tr>\n <td class=\"py-2 px-4 border-b border-gray-200\"><code\n class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">outAvatarError</code></td>\n <td class=\"py-2 px-4 border-b border-gray-200\"><code\n class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">void</code></td>\n <td class=\"py-2 px-4 border-b border-gray-200\">Sự kiện được kích hoạt khi linkAvatar bị lỗi và không có\n linkAvatarError</td>\n </tr>\n </tbody>\n </table>\n </div>\n\n <h3 class=\"text-xl font-semibold text-gray-700 mb-4\">Interfaces</h3>\n <div class=\"bg-gray-50 p-6 rounded-lg\">\n <h4 class=\"text-lg font-semibold text-gray-700 mb-3\">IAvatarConfig</h4>\n <pre class=\"bg-gray-100 p-4 rounded-lg overflow-x-auto text-sm mb-3\"><code>export interface IAvatarConfig {\n classImageInclude?: string;\n classInclude?: string;\n size?: TYPE_SIZE_AVATAR_CONFIG;\n linkAvatar?: string;\n linkAvatarError?: string;\n idGenColor?: string;\n textAvatar?: string;\n typeShape?: TYPE_SHAPE_AVATAR;\n getLastTextAfterSpace?: boolean;\n }\n\nexport type TYPE_SIZE_AVATAR_CONFIG = 16 | 24 | 32 | 40 | 48 | 64;\nexport type TYPE_SHAPE_AVATAR = 'circle' | 'rectangle';</code></pre>\n <p class=\"text-gray-600\">Interface định nghĩa cấu hình của avatar component.</p>\n </div>\n </section>\n </main>\n</div>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"libs-ui-components-avatar.mjs","sources":["../../../../../libs-ui/components/avatar/src/avatar.component.ts","../../../../../libs-ui/components/avatar/src/avatar.component.html","../../../../../libs-ui/components/avatar/src/libs-ui-components-avatar.ts"],"sourcesContent":["import { Component, ComponentRef, computed, effect, inject, input, OnDestroy, output, signal, untracked } from '@angular/core';\nimport { IEvent } from '@libs-ui/interfaces-types';\nimport { deleteUnicode, getColorById } from '@libs-ui/utils';\nimport { TYPE_SHAPE_AVATAR, TYPE_SIZE_AVATAR_CONFIG } from './interfaces/avatar.interface';\nimport { LibsUiComponentsGalleryViewerComponent } from '@libs-ui/components-gallery'\nimport { LibsUiDynamicComponentService } from '@libs-ui/services-dynamic-component';\n\n@Component({\n // eslint-disable-next-line @angular-eslint/component-selector\n selector: 'libs_ui-components-avatar',\n templateUrl: './avatar.component.html',\n standalone: true,\n styleUrls: ['./avatar.component.scss']\n})\nexport class LibsUiComponentsAvatarComponent implements OnDestroy {\n // #region PROPERTY\n protected isErrorLinkAvatar = signal<boolean>(false);\n protected isErrorLinkAvatarError = signal<boolean>(false);\n protected isShowIcon = signal<boolean>(false);\n protected color = computed(() => getColorById(this.idGenColor() || ''));\n protected fontSize = computed(this.fontSizeComputed.bind(this));\n\n private galleryViewerComponent?: ComponentRef<LibsUiComponentsGalleryViewerComponent>;\n\n // #region INPUT\n readonly typeShape = input<TYPE_SHAPE_AVATAR | undefined, TYPE_SHAPE_AVATAR | undefined>('circle', { transform: value => value ?? 'circle' });\n readonly classInclude = input<string | undefined, string | undefined>('mr-[8px]', { transform: (value) => value ?? 'mr-[8px]' });\n readonly size = input<TYPE_SIZE_AVATAR_CONFIG | undefined, TYPE_SIZE_AVATAR_CONFIG | undefined>(32, { transform: value => value ?? 32 });\n readonly linkAvatar = input<string>();\n readonly linkAvatarError = input<string>();\n readonly classImageInclude = input<string | undefined, string | undefined>('', { transform: (value) => value ?? '' });\n readonly zIndexPreviewImage = input<number>();\n readonly clickPreviewImage = input<boolean>();\n readonly idGenColor = input<string>();\n readonly getLastTextAfterSpace = input<boolean>(); // Lấy text cuối cùng sau khi cắt khoảng trắng. Lưu ý truyền biến này trước khi truyền biến textAvatar\n readonly textAvatar = input<string | undefined, string | undefined>('', {\n transform: (value) => {\n value = deleteUnicode(value || '').replace(/[^a-zA-Z0-9\\s]/g, '').trim();\n\n if (this.getLastTextAfterSpace()) {\n value = value.split(' ').pop() || '';\n }\n\n return value[0] || '—';\n }\n });\n readonly textAvatarClassInclude = input<string, string | undefined>('', { transform: (value) => value ?? '' });\n readonly containertextAvatarClassInclude = input<string, string | undefined>('', { transform: (value) => value ?? '' });\n\n // #region OUTPUT\n readonly outAvatarError = output<void>();\n readonly outEventPreviewImage = output<'open' | 'remove'>();\n\n // #region INJECT\n private dynamicComponentService = inject(LibsUiDynamicComponentService);\n\n constructor() {\n effect(() => {\n this.linkAvatar();\n untracked(() => {\n this.isShowIcon.set(false);\n this.isErrorLinkAvatar.set(false);\n this.isErrorLinkAvatarError.set(false);\n })\n });\n }\n\n /* FUNCTIONS */\n protected async handlerImageError(e: ErrorEvent) {\n if (!this.linkAvatarError()?.trim() && this.idGenColor() && this.textAvatar()) {\n this.outAvatarError.emit();\n this.isShowIcon.set(true);\n\n return;\n }\n if (this.isErrorLinkAvatar()) {\n this.isErrorLinkAvatarError.set(true)\n }\n this.isErrorLinkAvatar.set(true);\n\n if (this.isErrorLinkAvatarError() && this.idGenColor() && this.textAvatar()) {\n this.isShowIcon.set(true)\n }\n\n\n if (this.isErrorLinkAvatarError()) {\n return;\n }\n if (!this.linkAvatarError()) {\n this.outAvatarError.emit();\n\n return;\n }\n (e as IEvent).target.src = this.linkAvatarError();\n }\n\n protected handlerClickImage() {\n if (this.galleryViewerComponent || !this.clickPreviewImage()) {\n return;\n }\n this.outEventPreviewImage.emit('open');\n this.galleryViewerComponent = this.dynamicComponentService.resolveComponentFactory(LibsUiComponentsGalleryViewerComponent);\n this.galleryViewerComponent.setInput('images', [{ imageSrc: this.linkAvatar() }]);\n this.galleryViewerComponent.setInput('fieldDisplaySrcImage', 'imageSrc');\n this.galleryViewerComponent.setInput('singleImage', true);\n this.galleryViewerComponent.setInput('zIndex', this.zIndexPreviewImage());\n this.galleryViewerComponent.instance.outClose.subscribe(() => {\n this.dynamicComponentService.remove(this.galleryViewerComponent);\n this.galleryViewerComponent = undefined;\n this.outEventPreviewImage.emit('remove');\n })\n\n this.dynamicComponentService.addToBody(this.galleryViewerComponent);\n }\n\n /* COMPUTED PROPERTIES FUNCTION */\n private fontSizeComputed() {\n if (this.size() === 16 || this.size() === 24) {\n return 6;\n }\n\n if (this.size() === 32) {\n return 4;\n }\n\n if (this.size() === 40) {\n return 3;\n }\n\n if (this.size() === 64) {\n return 1;\n }\n return 4;\n }\n\n ngOnDestroy(): void {\n this.dynamicComponentService.remove(this.galleryViewerComponent);\n this.galleryViewerComponent = undefined;\n }\n}","<div class=\"libs_ui-component-avatar {{ classInclude() }}\"\n [class.libs_ui-component-avatar-rectangle]=\"typeShape() === 'rectangle'\"\n [style.width.px]='size()'\n [style.height.px]='size()'>\n @if (!isShowIcon()) {\n <img [class]=\"classImageInclude() + (clickPreviewImage() ? ' cursor-pointer' : 'cursor-default')\"\n [src]='linkAvatar()'\n (error)=\"handlerImageError($event)\"\n (click)=\"handlerClickImage()\" />\n } @else {\n <div class='libs_ui-component-avatar-icon {{ containertextAvatarClassInclude() }}'\n [style.background]='color()'>\n <div class=\"uppercase text-[#ffffff] libs-ui-font-h{{ fontSize() }}s {{ textAvatarClassInclude() }}\"\n [innerHTML]=\"textAvatar()\">\n </div>\n </div>\n }\n</div>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
package/index.d.ts
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './avatar.interface';
|
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@libs-ui/components-avatar",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.281",
|
|
4
4
|
"peerDependencies": {
|
|
5
5
|
"@angular/core": "^18.2.0",
|
|
6
|
-
"@libs-ui/interfaces-types": "
|
|
7
|
-
"@libs-ui/utils": "
|
|
6
|
+
"@libs-ui/interfaces-types": "0.2.281",
|
|
7
|
+
"@libs-ui/utils": "0.2.281"
|
|
8
8
|
},
|
|
9
9
|
"sideEffects": false,
|
|
10
10
|
"module": "fesm2022/libs-ui-components-avatar.mjs",
|
package/demo/demo.component.d.ts
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import { TYPE_SHAPE_AVATAR, TYPE_SIZE_AVATAR_CONFIG } from '../interfaces/avatar.interface';
|
|
2
|
-
import * as i0 from "@angular/core";
|
|
3
|
-
export declare class LibsUiComponentsAvatarDemoComponent {
|
|
4
|
-
exampleAvatar: string;
|
|
5
|
-
fallbackAvatar: string;
|
|
6
|
-
sizeOptions: TYPE_SIZE_AVATAR_CONFIG[];
|
|
7
|
-
selectedSize: TYPE_SIZE_AVATAR_CONFIG;
|
|
8
|
-
shapeOptions: TYPE_SHAPE_AVATAR[];
|
|
9
|
-
selectedShape: TYPE_SHAPE_AVATAR;
|
|
10
|
-
userNames: string[];
|
|
11
|
-
users: Array<Record<string, any>>;
|
|
12
|
-
invalidImageUrl: string;
|
|
13
|
-
showErrorMessage: boolean;
|
|
14
|
-
toggleShape(): void;
|
|
15
|
-
setSize(size: TYPE_SIZE_AVATAR_CONFIG): void;
|
|
16
|
-
handleAvatarError(): void;
|
|
17
|
-
copyToClipboard(text: string): void;
|
|
18
|
-
static ɵfac: i0.ɵɵFactoryDeclaration<LibsUiComponentsAvatarDemoComponent, never>;
|
|
19
|
-
static ɵcmp: i0.ɵɵComponentDeclaration<LibsUiComponentsAvatarDemoComponent, "lib-avatar-demo", never, {}, {}, never, never, true, never>;
|
|
20
|
-
}
|
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
import { NgFor } from '@angular/common';
|
|
2
|
-
import { Component } from '@angular/core';
|
|
3
|
-
import { LibsUiComponentsAvatarComponent } from '../avatar.component';
|
|
4
|
-
import * as i0 from "@angular/core";
|
|
5
|
-
export class LibsUiComponentsAvatarDemoComponent {
|
|
6
|
-
// Basic demo data
|
|
7
|
-
exampleAvatar = 'https://randomuser.me/api/portraits/men/33.jpg';
|
|
8
|
-
fallbackAvatar = 'https://randomuser.me/api/portraits/lego/6.jpg';
|
|
9
|
-
// Size variants
|
|
10
|
-
sizeOptions = [16, 24, 32, 40, 48, 64];
|
|
11
|
-
selectedSize = 40;
|
|
12
|
-
// Shape variants
|
|
13
|
-
shapeOptions = ['circle', 'rectangle'];
|
|
14
|
-
selectedShape = 'circle';
|
|
15
|
-
// Text avatar demo
|
|
16
|
-
userNames = [
|
|
17
|
-
'Nguyễn Văn A',
|
|
18
|
-
'Trần Thị B',
|
|
19
|
-
'Lê Văn C',
|
|
20
|
-
'Phạm Thị D',
|
|
21
|
-
'Vũ Hoàng E',
|
|
22
|
-
'Đặng Thị F'
|
|
23
|
-
];
|
|
24
|
-
// Demo for avatar group
|
|
25
|
-
users = [
|
|
26
|
-
{
|
|
27
|
-
id: 'user-1',
|
|
28
|
-
name: 'Nguyễn Văn A',
|
|
29
|
-
avatar: 'https://randomuser.me/api/portraits/men/32.jpg',
|
|
30
|
-
size: 64
|
|
31
|
-
},
|
|
32
|
-
{
|
|
33
|
-
id: 'user-2',
|
|
34
|
-
name: 'Trần Thị B',
|
|
35
|
-
avatar: 'https://randomuser.me/api/portraits/women/32.jpg',
|
|
36
|
-
size: 48
|
|
37
|
-
},
|
|
38
|
-
{
|
|
39
|
-
id: 'user-3',
|
|
40
|
-
name: 'Lê Văn C',
|
|
41
|
-
avatar: 'https://randomuser.me/api/portraits/men/33.jpg',
|
|
42
|
-
size: 32
|
|
43
|
-
},
|
|
44
|
-
{
|
|
45
|
-
id: 'user-4',
|
|
46
|
-
name: 'Phạm Thị D',
|
|
47
|
-
avatar: undefined,
|
|
48
|
-
size: 24
|
|
49
|
-
}
|
|
50
|
-
];
|
|
51
|
-
// Demo for error handling
|
|
52
|
-
invalidImageUrl = 'https://example.com/invalid-image.jpg';
|
|
53
|
-
showErrorMessage = false;
|
|
54
|
-
// Methods
|
|
55
|
-
toggleShape() {
|
|
56
|
-
this.selectedShape = this.selectedShape === 'circle' ? 'rectangle' : 'circle';
|
|
57
|
-
}
|
|
58
|
-
setSize(size) {
|
|
59
|
-
this.selectedSize = size;
|
|
60
|
-
}
|
|
61
|
-
handleAvatarError() {
|
|
62
|
-
this.showErrorMessage = true;
|
|
63
|
-
setTimeout(() => {
|
|
64
|
-
this.showErrorMessage = false;
|
|
65
|
-
}, 3000);
|
|
66
|
-
}
|
|
67
|
-
copyToClipboard(text) {
|
|
68
|
-
navigator.clipboard.writeText(text).then(() => {
|
|
69
|
-
alert('Đã sao chép vào clipboard');
|
|
70
|
-
}).catch(err => {
|
|
71
|
-
console.error('Không thể sao chép: ', err);
|
|
72
|
-
});
|
|
73
|
-
}
|
|
74
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: LibsUiComponentsAvatarDemoComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
75
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: LibsUiComponentsAvatarDemoComponent, isStandalone: true, selector: "lib-avatar-demo", ngImport: i0, template: "<div class=\"max-w-6xl mx-auto p-5 font-sans text-gray-800\">\n <header class=\"text-center py-10 bg-white rounded-lg mb-8 shadow-sm\">\n <h1 class=\"text-4xl font-bold text-gray-800 mb-2\">Demo Avatar Component</h1>\n <p class=\"text-xl text-gray-500\">Th\u01B0 vi\u1EC7n component Avatar cho Angular</p>\n </header>\n\n <main>\n <section class=\"bg-white rounded-lg p-8 mb-8 shadow-sm\">\n <h2 class=\"text-2xl font-bold text-gray-800 mb-5 pb-3 border-b border-gray-200\">Gi\u1EDBi thi\u1EC7u</h2>\n <p>\n <code class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">@libs-ui/components-avatar</code> l\u00E0 m\u1ED9t\n component Angular \u0111\u1EC3 hi\u1EC3n th\u1ECB avatar ng\u01B0\u1EDDi d\u00F9ng v\u1EDBi nhi\u1EC1u t\u00F9y ch\u1ECDn nh\u01B0 h\u00ECnh \u1EA3nh, ch\u1EEF c\u00E1i \u0111\u1EA7u,\n m\u00E0u s\u1EAFc t\u1EF1 \u0111\u1ED9ng, v\u00E0 h\u1ED7 tr\u1EE3 fallback khi \u1EA3nh b\u1ECB l\u1ED7i.\n </p>\n </section>\n\n <section class=\"bg-white rounded-lg p-8 mb-8 shadow-sm\">\n <h2 class=\"text-2xl font-bold text-gray-800 mb-5 pb-3 border-b border-gray-200\">C\u00E0i \u0111\u1EB7t</h2>\n\n <div class=\"mb-6\">\n <h3 class=\"text-xl font-semibold text-gray-700 mb-3\">Y\u00EAu c\u1EA7u</h3>\n <ul class=\"list-disc pl-5 space-y-2 text-gray-600\">\n <li><span class=\"font-semibold\">Angular</span>: 18.0.0 tr\u1EDF l\u00EAn</li>\n <li><span class=\"font-semibold\">Tailwind CSS</span>: 3.3.0 tr\u1EDF l\u00EAn</li>\n </ul>\n </div>\n\n <p class=\"mb-4\">\u0110\u1EC3 c\u00E0i \u0111\u1EB7t th\u01B0 vi\u1EC7n, s\u1EED d\u1EE5ng npm ho\u1EB7c yarn:</p>\n\n <div class=\"flex items-center bg-gray-100 p-4 rounded-lg mb-6\">\n <pre class=\"flex-1 text-sm overflow-x-auto\"><code>npm install @libs-ui/components-avatar</code></pre>\n <button class=\"ml-4 px-3 py-1 bg-blue-500 text-white rounded hover:bg-blue-600 transition-colors\"\n (click)=\"copyToClipboard('npm install @libs-ui/components-avatar')\">\n Sao ch\u00E9p\n </button>\n </div>\n\n <p class=\"mb-4\">Ho\u1EB7c v\u1EDBi yarn:</p>\n\n <div class=\"flex items-center bg-gray-100 p-4 rounded-lg mb-6\">\n <pre class=\"flex-1 text-sm overflow-x-auto\"><code>yarn add @libs-ui/components-avatar</code></pre>\n <button class=\"ml-4 px-3 py-1 bg-blue-500 text-white rounded hover:bg-blue-600 transition-colors\"\n (click)=\"copyToClipboard('yarn add @libs-ui/components-avatar')\">\n Sao ch\u00E9p\n </button>\n </div>\n </section>\n\n <section class=\"bg-white rounded-lg p-8 mb-8 shadow-sm\">\n <h2 class=\"text-2xl font-bold text-gray-800 mb-5 pb-3 border-b border-gray-200\">Demo tr\u1EF1c ti\u1EBFp</h2>\n\n <!-- Basic Avatar Demo -->\n <div class=\"mb-8\">\n <h3 class=\"text-xl font-semibold text-gray-700 mb-4\">Avatar c\u01A1 b\u1EA3n</h3>\n <div class=\"flex items-center p-4 bg-gray-50 rounded-lg\">\n <libs_ui-components-avatar [linkAvatar]=\"exampleAvatar\"\n [size]=\"selectedSize\"\n [typeShape]=\"selectedShape\">\n </libs_ui-components-avatar>\n <div>\n <p class=\"text-gray-700\">Avatar v\u1EDBi h\u00ECnh \u1EA3nh t\u1EEB URL</p>\n <p class=\"text-sm text-gray-500\">K\u00EDch th\u01B0\u1EDBc: {{ selectedSize }}px, H\u00ECnh d\u1EA1ng: {{ selectedShape }}</p>\n </div>\n </div>\n <div class=\"mt-4 flex flex-wrap gap-3\">\n <button *ngFor=\"let size of sizeOptions\"\n (click)=\"setSize(size)\"\n class=\"px-3 py-1 border rounded\"\n [class.bg-blue-500]=\"selectedSize === size\"\n [class.text-white]=\"selectedSize === size\">\n {{ size }}px\n </button>\n <button (click)=\"toggleShape()\"\n class=\"px-3 py-1 border rounded ml-4\">\n \u0110\u1ED5i h\u00ECnh d\u1EA1ng\n </button>\n </div>\n </div>\n\n <!-- Text Avatar Demo -->\n <div class=\"mb-8\">\n <h3 class=\"text-xl font-semibold text-gray-700 mb-4\">Avatar v\u0103n b\u1EA3n</h3>\n <div class=\"flex flex-wrap gap-3 p-4 bg-gray-50 rounded-lg\">\n @for (name of userNames; track name) {\n <libs_ui-components-avatar [getLastTextAfterSpace]=\"true\" [textAvatar]=\"name\"\n [idGenColor]=\"name\"\n [size]=\"40\"\n >\n </libs_ui-components-avatar>\n }\n </div>\n <p class=\"mt-2 text-sm text-gray-500\">Hi\u1EC3n th\u1ECB ch\u1EEF c\u00E1i \u0111\u1EA7u ti\u00EAn c\u1EE7a t\u00EAn v\u1EDBi m\u00E0u n\u1EC1n t\u1EF1 \u0111\u1ED9ng d\u1EF1a tr\u00EAn ID.</p>\n </div>\n\n <!-- Avatar Group Demo -->\n <div class=\"mb-8\">\n <h3 class=\"text-xl font-semibold text-gray-700 mb-4\">Nh\u00F3m Avatar</h3>\n <div class=\"flex items-center p-4 bg-gray-50 rounded-lg\">\n @for (user of users; track user) {\n <libs_ui-components-avatar [linkAvatar]=\"user['avatar']\"\n [textAvatar]=\"user['name']\"\n [idGenColor]=\"user['id']\"\n [size]=\"user['size']\"\n [typeShape]=\"user['id'] === 'user-4' ? 'rectangle' : 'circle'\"\n [classInclude]=\"'mr-2'\">\n </libs_ui-components-avatar>\n }\n </div>\n <p class=\"mt-2 text-sm text-gray-500\">Nh\u00F3m avatars v\u1EDBi k\u00EDch th\u01B0\u1EDBc kh\u00E1c nhau v\u00E0 hi\u1EC3n th\u1ECB fallback khi kh\u00F4ng c\u00F3\n h\u00ECnh \u1EA3nh.</p>\n </div>\n\n <!-- Error Handling Demo -->\n <div class=\"mb-8\">\n <h3 class=\"text-xl font-semibold text-gray-700 mb-4\">X\u1EED l\u00FD l\u1ED7i</h3>\n <div class=\"flex items-center p-4 bg-gray-50 rounded-lg\">\n <libs_ui-components-avatar [linkAvatar]=\"invalidImageUrl\"\n [linkAvatarError]=\"fallbackAvatar\"\n [textAvatar]=\"'Error Fallback'\"\n [idGenColor]=\"'error-demo'\"\n [size]=\"48\">\n </libs_ui-components-avatar>\n <div>\n <p class=\"text-gray-700\">Avatar v\u1EDBi x\u1EED l\u00FD l\u1ED7i h\u00ECnh \u1EA3nh</p>\n <p class=\"text-sm text-gray-500\">Khi h\u00ECnh \u1EA3nh ch\u00EDnh b\u1ECB l\u1ED7i, s\u1EBD hi\u1EC3n th\u1ECB h\u00ECnh \u1EA3nh thay th\u1EBF.</p>\n </div>\n </div>\n </div>\n\n <!-- Fallback to Text Demo -->\n <div class=\"mb-8\">\n <h3 class=\"text-xl font-semibold text-gray-700 mb-4\">Fallback v\u1EC1 v\u0103n b\u1EA3n</h3>\n <div class=\"flex items-center p-4 bg-gray-50 rounded-lg\">\n <libs_ui-components-avatar [linkAvatar]=\"invalidImageUrl\"\n [textAvatar]=\"'Text Fallback'\"\n [idGenColor]=\"'text-fallback'\"\n [size]=\"48\"\n (outAvatarError)=\"handleAvatarError()\">\n </libs_ui-components-avatar>\n <div>\n <p class=\"text-gray-700\">Avatar v\u1EDBi fallback v\u1EC1 v\u0103n b\u1EA3n</p>\n <p class=\"text-sm text-gray-500\">Khi kh\u00F4ng c\u00F3 h\u00ECnh \u1EA3nh, s\u1EBD hi\u1EC3n th\u1ECB ch\u1EEF c\u00E1i \u0111\u1EA7u c\u1EE7a v\u0103n b\u1EA3n v\u1EDBi m\u00E0u n\u1EC1n t\u1EF1\n \u0111\u1ED9ng.</p>\n @if (showErrorMessage) {\n <p class=\"text-sm text-red-500 mt-2\">Kh\u00F4ng th\u1EC3 t\u1EA3i h\u00ECnh \u1EA3nh. \u0110\u00E3 hi\u1EC3n th\u1ECB v\u0103n b\u1EA3n thay th\u1EBF.</p>\n }\n </div>\n </div>\n </div>\n </section>\n\n <section class=\"bg-white rounded-lg p-8 mb-8 shadow-sm\">\n <h2 class=\"text-2xl font-bold text-gray-800 mb-5 pb-3 border-b border-gray-200\">C\u00E1ch s\u1EED d\u1EE5ng</h2>\n\n <div class=\"mb-8\">\n <h3 class=\"text-xl font-semibold text-gray-700 mb-4\">C\u00E1ch 1: S\u1EED d\u1EE5ng file HTML ri\u00EAng bi\u1EC7t</h3>\n\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-6 mb-4\">\n <div>\n <h4 class=\"font-semibold mb-2 text-gray-700\">HTML (example.component.html)</h4>\n <pre class=\"bg-gray-100 p-4 rounded-lg overflow-x-auto text-sm\"><code><libs_ui-components-avatar\n [linkAvatar]=\"'https://example.com/avatar.jpg'\"\n [textAvatar]=\"'Nguy\u1EC5n V\u0103n A'\"\n [idGenColor]=\"'user-123'\"\n [size]=\"40\"\n [typeShape]=\"'circle'\">\n</libs_ui-components-avatar></code></pre>\n </div>\n\n <div>\n <h4 class=\"font-semibold mb-2 text-gray-700\">TypeScript (example.component.ts)</h4>\n <pre class=\"bg-gray-100 p-4 rounded-lg overflow-x-auto text-sm\"><code>import { Component } from '@angular/core';\nimport { LibsUiComponentsAvatarComponent } from '@libs-ui/components-avatar';\n\n@Component({\n selector: 'app-example',\n standalone: true,\n imports: [LibsUiComponentsAvatarComponent],\n templateUrl: './example.component.html'\n})\nexport class ExampleComponent {\n // Component logic\n}</code></pre>\n </div>\n </div>\n </div>\n\n <div class=\"mb-8\">\n <h3 class=\"text-xl font-semibold text-gray-700 mb-4\">C\u00E1ch 2: X\u1EED l\u00FD s\u1EF1 ki\u1EC7n l\u1ED7i</h3>\n\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-6 mb-4\">\n <div>\n <h4 class=\"font-semibold mb-2 text-gray-700\">HTML (error-handler.component.html)</h4>\n <pre class=\"bg-gray-100 p-4 rounded-lg overflow-x-auto text-sm\"><code><libs_ui-components-avatar\n [linkAvatar]=\"user.avatar\"\n [linkAvatarError]=\"defaultAvatar\"\n [textAvatar]=\"user.name\"\n [idGenColor]=\"user.id\"\n [size]=\"40\"\n (outAvatarError)=\"handleAvatarError()\">\n</libs_ui-components-avatar></code></pre>\n </div>\n\n <div>\n <h4 class=\"font-semibold mb-2 text-gray-700\">TypeScript (error-handler.component.ts)</h4>\n <pre class=\"bg-gray-100 p-4 rounded-lg overflow-x-auto text-sm\"><code>import { Component } from '@angular/core';\nimport { LibsUiComponentsAvatarComponent } from '@libs-ui/components-avatar';\n\n@Component({\n selector: 'app-error-handler',\n standalone: true,\n imports: [LibsUiComponentsAvatarComponent],\n templateUrl: './error-handler.component.html'\n})\nexport class ErrorHandlerComponent {\n user = {\n id: 'user-123',\n name: 'Nguy\u1EC5n V\u0103n A',\n avatar: 'https://example.com/avatar.jpg'\n };\n \n defaultAvatar = 'https://example.com/default-avatar.jpg';\n\n handleAvatarError() {\n console.log('Kh\u00F4ng th\u1EC3 t\u1EA3i \u0111\u01B0\u1EE3c h\u00ECnh \u1EA3nh avatar');\n // Th\u1EF1c hi\u1EC7n c\u00E1c x\u1EED l\u00FD kh\u00E1c khi c\u00F3 l\u1ED7i\n }\n}</code></pre>\n </div>\n </div>\n </div>\n </section>\n\n <section class=\"bg-white rounded-lg p-8 mb-8 shadow-sm\">\n <h2 class=\"text-2xl font-bold text-gray-800 mb-5 pb-3 border-b border-gray-200\">T\u00E0i li\u1EC7u API</h2>\n\n <h3 class=\"text-xl font-semibold text-gray-700 mb-4\">Inputs</h3>\n <div class=\"overflow-x-auto mb-8\">\n <table class=\"min-w-full bg-white border border-gray-200\">\n <thead>\n <tr>\n <th class=\"py-3 px-4 border-b border-gray-200 bg-gray-100 text-left font-semibold text-gray-700\">T\u00EAn</th>\n <th class=\"py-3 px-4 border-b border-gray-200 bg-gray-100 text-left font-semibold text-gray-700\">Ki\u1EC3u d\u1EEF\n li\u1EC7u</th>\n <th class=\"py-3 px-4 border-b border-gray-200 bg-gray-100 text-left font-semibold text-gray-700\">M\u1EB7c \u0111\u1ECBnh\n </th>\n <th class=\"py-3 px-4 border-b border-gray-200 bg-gray-100 text-left font-semibold text-gray-700\">M\u00F4 t\u1EA3\n </th>\n </tr>\n </thead>\n <tbody>\n <tr>\n <td class=\"py-2 px-4 border-b border-gray-200\"><code\n class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">linkAvatar</code></td>\n <td class=\"py-2 px-4 border-b border-gray-200\"><code\n class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">string</code></td>\n <td class=\"py-2 px-4 border-b border-gray-200\">-</td>\n <td class=\"py-2 px-4 border-b border-gray-200\">\u0110\u01B0\u1EDDng d\u1EABn c\u1EE7a h\u00ECnh \u1EA3nh avatar</td>\n </tr>\n <tr>\n <td class=\"py-2 px-4 border-b border-gray-200\"><code\n class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">linkAvatarError</code></td>\n <td class=\"py-2 px-4 border-b border-gray-200\"><code\n class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">string</code></td>\n <td class=\"py-2 px-4 border-b border-gray-200\">-</td>\n <td class=\"py-2 px-4 border-b border-gray-200\">\u0110\u01B0\u1EDDng d\u1EABn c\u1EE7a h\u00ECnh \u1EA3nh thay th\u1EBF khi avatar ch\u00EDnh b\u1ECB l\u1ED7i\n </td>\n </tr>\n <tr>\n <td class=\"py-2 px-4 border-b border-gray-200\"><code\n class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">textAvatar</code></td>\n <td class=\"py-2 px-4 border-b border-gray-200\"><code\n class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">string</code></td>\n <td class=\"py-2 px-4 border-b border-gray-200\">-</td>\n <td class=\"py-2 px-4 border-b border-gray-200\">V\u0103n b\u1EA3n hi\u1EC3n th\u1ECB khi kh\u00F4ng c\u00F3 h\u00ECnh \u1EA3nh (th\u01B0\u1EDDng l\u00E0 ch\u1EEF c\u00E1i\n \u0111\u1EA7u c\u1EE7a t\u00EAn)</td>\n </tr>\n <tr>\n <td class=\"py-2 px-4 border-b border-gray-200\"><code\n class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">idGenColor</code></td>\n <td class=\"py-2 px-4 border-b border-gray-200\"><code\n class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">string</code></td>\n <td class=\"py-2 px-4 border-b border-gray-200\">-</td>\n <td class=\"py-2 px-4 border-b border-gray-200\">ID d\u00F9ng \u0111\u1EC3 t\u1EA1o m\u00E0u n\u1EC1n t\u1EF1 \u0111\u1ED9ng khi s\u1EED d\u1EE5ng v\u0103n b\u1EA3n</td>\n </tr>\n <tr>\n <td class=\"py-2 px-4 border-b border-gray-200\"><code\n class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">size</code></td>\n <td class=\"py-2 px-4 border-b border-gray-200\"><code class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">16\n | 24 | 32 | 40 | 48 | 64</code></td>\n <td class=\"py-2 px-4 border-b border-gray-200\">32</td>\n <td class=\"py-2 px-4 border-b border-gray-200\">K\u00EDch th\u01B0\u1EDBc c\u1EE7a avatar (t\u00EDnh b\u1EB1ng pixel)</td>\n </tr>\n <tr>\n <td class=\"py-2 px-4 border-b border-gray-200\"><code\n class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">typeShape</code></td>\n <td class=\"py-2 px-4 border-b border-gray-200\"><code\n class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">'circle' | 'rectangle'</code></td>\n <td class=\"py-2 px-4 border-b border-gray-200\">'circle'</td>\n <td class=\"py-2 px-4 border-b border-gray-200\">H\u00ECnh d\u1EA1ng c\u1EE7a avatar (tr\u00F2n ho\u1EB7c vu\u00F4ng)</td>\n </tr>\n <tr>\n <td class=\"py-2 px-4 border-b border-gray-200\"><code\n class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">classInclude</code></td>\n <td class=\"py-2 px-4 border-b border-gray-200\"><code\n class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">string</code></td>\n <td class=\"py-2 px-4 border-b border-gray-200\">'mr-[8px]'</td>\n <td class=\"py-2 px-4 border-b border-gray-200\">CSS class b\u1ED5 sung cho container ch\u00EDnh</td>\n </tr>\n <tr>\n <td class=\"py-2 px-4 border-b border-gray-200\"><code\n class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">classImageInclude</code></td>\n <td class=\"py-2 px-4 border-b border-gray-200\"><code\n class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">string</code></td>\n <td class=\"py-2 px-4 border-b border-gray-200\">''</td>\n <td class=\"py-2 px-4 border-b border-gray-200\">CSS class b\u1ED5 sung cho th\u1EBB img</td>\n </tr>\n <tr>\n <td class=\"py-2 px-4 border-b border-gray-200\"><code\n class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">getLastTextAfterSpace</code></td>\n <td class=\"py-2 px-4 border-b border-gray-200\"><code\n class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">boolean</code></td>\n <td class=\"py-2 px-4 border-b border-gray-200\">false</td>\n <td class=\"py-2 px-4 border-b border-gray-200\">N\u1EBFu true, ch\u1EC9 l\u1EA5y ch\u1EEF c\u00E1i \u0111\u1EA7u ti\u00EAn c\u1EE7a t\u1EEB cu\u1ED1i c\u00F9ng trong\n textAvatar</td>\n </tr>\n </tbody>\n </table>\n </div>\n\n <h3 class=\"text-xl font-semibold text-gray-700 mb-4\">Outputs</h3>\n <div class=\"overflow-x-auto mb-8\">\n <table class=\"min-w-full bg-white border border-gray-200\">\n <thead>\n <tr>\n <th class=\"py-3 px-4 border-b border-gray-200 bg-gray-100 text-left font-semibold text-gray-700\">T\u00EAn</th>\n <th class=\"py-3 px-4 border-b border-gray-200 bg-gray-100 text-left font-semibold text-gray-700\">Ki\u1EC3u d\u1EEF\n li\u1EC7u</th>\n <th class=\"py-3 px-4 border-b border-gray-200 bg-gray-100 text-left font-semibold text-gray-700\">M\u00F4 t\u1EA3\n </th>\n </tr>\n </thead>\n <tbody>\n <tr>\n <td class=\"py-2 px-4 border-b border-gray-200\"><code\n class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">outAvatarError</code></td>\n <td class=\"py-2 px-4 border-b border-gray-200\"><code\n class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">void</code></td>\n <td class=\"py-2 px-4 border-b border-gray-200\">S\u1EF1 ki\u1EC7n \u0111\u01B0\u1EE3c k\u00EDch ho\u1EA1t khi linkAvatar b\u1ECB l\u1ED7i v\u00E0 kh\u00F4ng c\u00F3\n linkAvatarError</td>\n </tr>\n </tbody>\n </table>\n </div>\n\n <h3 class=\"text-xl font-semibold text-gray-700 mb-4\">Interfaces</h3>\n <div class=\"bg-gray-50 p-6 rounded-lg\">\n <h4 class=\"text-lg font-semibold text-gray-700 mb-3\">IAvatarConfig</h4>\n <pre class=\"bg-gray-100 p-4 rounded-lg overflow-x-auto text-sm mb-3\"><code>export interface IAvatarConfig {\n classImageInclude?: string;\n classInclude?: string;\n size?: TYPE_SIZE_AVATAR_CONFIG;\n linkAvatar?: string;\n linkAvatarError?: string;\n idGenColor?: string;\n textAvatar?: string;\n typeShape?: TYPE_SHAPE_AVATAR;\n getLastTextAfterSpace?: boolean;\n }\n\nexport type TYPE_SIZE_AVATAR_CONFIG = 16 | 24 | 32 | 40 | 48 | 64;\nexport type TYPE_SHAPE_AVATAR = 'circle' | 'rectangle';</code></pre>\n <p class=\"text-gray-600\">Interface \u0111\u1ECBnh ngh\u0129a c\u1EA5u h\u00ECnh c\u1EE7a avatar component.</p>\n </div>\n </section>\n </main>\n</div>\n", styles: [":host{display:block;width:100%;padding:16px}.demo-wrapper{background-color:#f9fafb;border-radius:8px;padding:16px;margin-bottom:16px}.code-block{font-family:monospace;background-color:#f3f4f6;border-radius:4px;padding:2px 4px;font-size:14px}button{transition:all .2s ease}button:hover{opacity:.9}button:active{transform:scale(.98)}.size-option{cursor:pointer;border:1px solid #e5e7eb;padding:4px 8px;border-radius:4px}.size-option.selected{background-color:#3b82f6;color:#fff;border-color:#3b82f6}.shape-option{cursor:pointer;border:1px solid #e5e7eb;padding:4px 8px;border-radius:4px;margin-left:8px}.shape-option.selected{background-color:#3b82f6;color:#fff;border-color:#3b82f6}.error-message{color:#ef4444;margin-top:8px;font-size:14px}.copy-button{background-color:#3b82f6;color:#fff;border-radius:4px;padding:4px 8px;font-size:14px;border:none;cursor:pointer}\n"], dependencies: [{ kind: "component", type: LibsUiComponentsAvatarComponent, selector: "libs_ui-components-avatar", inputs: ["typeShape", "classInclude", "size", "linkAvatar", "linkAvatarError", "classImageInclude", "zIndexPreviewImage", "clickPreviewImage", "idGenColor", "getLastTextAfterSpace", "textAvatar", "textAvatarClassInclude", "containertextAvatarClassInclude"], outputs: ["outAvatarError", "outEventPreviewImage"] }, { kind: "directive", type: NgFor, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }] });
|
|
76
|
-
}
|
|
77
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: LibsUiComponentsAvatarDemoComponent, decorators: [{
|
|
78
|
-
type: Component,
|
|
79
|
-
args: [{ selector: 'lib-avatar-demo', standalone: true, imports: [
|
|
80
|
-
LibsUiComponentsAvatarComponent,
|
|
81
|
-
NgFor
|
|
82
|
-
], template: "<div class=\"max-w-6xl mx-auto p-5 font-sans text-gray-800\">\n <header class=\"text-center py-10 bg-white rounded-lg mb-8 shadow-sm\">\n <h1 class=\"text-4xl font-bold text-gray-800 mb-2\">Demo Avatar Component</h1>\n <p class=\"text-xl text-gray-500\">Th\u01B0 vi\u1EC7n component Avatar cho Angular</p>\n </header>\n\n <main>\n <section class=\"bg-white rounded-lg p-8 mb-8 shadow-sm\">\n <h2 class=\"text-2xl font-bold text-gray-800 mb-5 pb-3 border-b border-gray-200\">Gi\u1EDBi thi\u1EC7u</h2>\n <p>\n <code class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">@libs-ui/components-avatar</code> l\u00E0 m\u1ED9t\n component Angular \u0111\u1EC3 hi\u1EC3n th\u1ECB avatar ng\u01B0\u1EDDi d\u00F9ng v\u1EDBi nhi\u1EC1u t\u00F9y ch\u1ECDn nh\u01B0 h\u00ECnh \u1EA3nh, ch\u1EEF c\u00E1i \u0111\u1EA7u,\n m\u00E0u s\u1EAFc t\u1EF1 \u0111\u1ED9ng, v\u00E0 h\u1ED7 tr\u1EE3 fallback khi \u1EA3nh b\u1ECB l\u1ED7i.\n </p>\n </section>\n\n <section class=\"bg-white rounded-lg p-8 mb-8 shadow-sm\">\n <h2 class=\"text-2xl font-bold text-gray-800 mb-5 pb-3 border-b border-gray-200\">C\u00E0i \u0111\u1EB7t</h2>\n\n <div class=\"mb-6\">\n <h3 class=\"text-xl font-semibold text-gray-700 mb-3\">Y\u00EAu c\u1EA7u</h3>\n <ul class=\"list-disc pl-5 space-y-2 text-gray-600\">\n <li><span class=\"font-semibold\">Angular</span>: 18.0.0 tr\u1EDF l\u00EAn</li>\n <li><span class=\"font-semibold\">Tailwind CSS</span>: 3.3.0 tr\u1EDF l\u00EAn</li>\n </ul>\n </div>\n\n <p class=\"mb-4\">\u0110\u1EC3 c\u00E0i \u0111\u1EB7t th\u01B0 vi\u1EC7n, s\u1EED d\u1EE5ng npm ho\u1EB7c yarn:</p>\n\n <div class=\"flex items-center bg-gray-100 p-4 rounded-lg mb-6\">\n <pre class=\"flex-1 text-sm overflow-x-auto\"><code>npm install @libs-ui/components-avatar</code></pre>\n <button class=\"ml-4 px-3 py-1 bg-blue-500 text-white rounded hover:bg-blue-600 transition-colors\"\n (click)=\"copyToClipboard('npm install @libs-ui/components-avatar')\">\n Sao ch\u00E9p\n </button>\n </div>\n\n <p class=\"mb-4\">Ho\u1EB7c v\u1EDBi yarn:</p>\n\n <div class=\"flex items-center bg-gray-100 p-4 rounded-lg mb-6\">\n <pre class=\"flex-1 text-sm overflow-x-auto\"><code>yarn add @libs-ui/components-avatar</code></pre>\n <button class=\"ml-4 px-3 py-1 bg-blue-500 text-white rounded hover:bg-blue-600 transition-colors\"\n (click)=\"copyToClipboard('yarn add @libs-ui/components-avatar')\">\n Sao ch\u00E9p\n </button>\n </div>\n </section>\n\n <section class=\"bg-white rounded-lg p-8 mb-8 shadow-sm\">\n <h2 class=\"text-2xl font-bold text-gray-800 mb-5 pb-3 border-b border-gray-200\">Demo tr\u1EF1c ti\u1EBFp</h2>\n\n <!-- Basic Avatar Demo -->\n <div class=\"mb-8\">\n <h3 class=\"text-xl font-semibold text-gray-700 mb-4\">Avatar c\u01A1 b\u1EA3n</h3>\n <div class=\"flex items-center p-4 bg-gray-50 rounded-lg\">\n <libs_ui-components-avatar [linkAvatar]=\"exampleAvatar\"\n [size]=\"selectedSize\"\n [typeShape]=\"selectedShape\">\n </libs_ui-components-avatar>\n <div>\n <p class=\"text-gray-700\">Avatar v\u1EDBi h\u00ECnh \u1EA3nh t\u1EEB URL</p>\n <p class=\"text-sm text-gray-500\">K\u00EDch th\u01B0\u1EDBc: {{ selectedSize }}px, H\u00ECnh d\u1EA1ng: {{ selectedShape }}</p>\n </div>\n </div>\n <div class=\"mt-4 flex flex-wrap gap-3\">\n <button *ngFor=\"let size of sizeOptions\"\n (click)=\"setSize(size)\"\n class=\"px-3 py-1 border rounded\"\n [class.bg-blue-500]=\"selectedSize === size\"\n [class.text-white]=\"selectedSize === size\">\n {{ size }}px\n </button>\n <button (click)=\"toggleShape()\"\n class=\"px-3 py-1 border rounded ml-4\">\n \u0110\u1ED5i h\u00ECnh d\u1EA1ng\n </button>\n </div>\n </div>\n\n <!-- Text Avatar Demo -->\n <div class=\"mb-8\">\n <h3 class=\"text-xl font-semibold text-gray-700 mb-4\">Avatar v\u0103n b\u1EA3n</h3>\n <div class=\"flex flex-wrap gap-3 p-4 bg-gray-50 rounded-lg\">\n @for (name of userNames; track name) {\n <libs_ui-components-avatar [getLastTextAfterSpace]=\"true\" [textAvatar]=\"name\"\n [idGenColor]=\"name\"\n [size]=\"40\"\n >\n </libs_ui-components-avatar>\n }\n </div>\n <p class=\"mt-2 text-sm text-gray-500\">Hi\u1EC3n th\u1ECB ch\u1EEF c\u00E1i \u0111\u1EA7u ti\u00EAn c\u1EE7a t\u00EAn v\u1EDBi m\u00E0u n\u1EC1n t\u1EF1 \u0111\u1ED9ng d\u1EF1a tr\u00EAn ID.</p>\n </div>\n\n <!-- Avatar Group Demo -->\n <div class=\"mb-8\">\n <h3 class=\"text-xl font-semibold text-gray-700 mb-4\">Nh\u00F3m Avatar</h3>\n <div class=\"flex items-center p-4 bg-gray-50 rounded-lg\">\n @for (user of users; track user) {\n <libs_ui-components-avatar [linkAvatar]=\"user['avatar']\"\n [textAvatar]=\"user['name']\"\n [idGenColor]=\"user['id']\"\n [size]=\"user['size']\"\n [typeShape]=\"user['id'] === 'user-4' ? 'rectangle' : 'circle'\"\n [classInclude]=\"'mr-2'\">\n </libs_ui-components-avatar>\n }\n </div>\n <p class=\"mt-2 text-sm text-gray-500\">Nh\u00F3m avatars v\u1EDBi k\u00EDch th\u01B0\u1EDBc kh\u00E1c nhau v\u00E0 hi\u1EC3n th\u1ECB fallback khi kh\u00F4ng c\u00F3\n h\u00ECnh \u1EA3nh.</p>\n </div>\n\n <!-- Error Handling Demo -->\n <div class=\"mb-8\">\n <h3 class=\"text-xl font-semibold text-gray-700 mb-4\">X\u1EED l\u00FD l\u1ED7i</h3>\n <div class=\"flex items-center p-4 bg-gray-50 rounded-lg\">\n <libs_ui-components-avatar [linkAvatar]=\"invalidImageUrl\"\n [linkAvatarError]=\"fallbackAvatar\"\n [textAvatar]=\"'Error Fallback'\"\n [idGenColor]=\"'error-demo'\"\n [size]=\"48\">\n </libs_ui-components-avatar>\n <div>\n <p class=\"text-gray-700\">Avatar v\u1EDBi x\u1EED l\u00FD l\u1ED7i h\u00ECnh \u1EA3nh</p>\n <p class=\"text-sm text-gray-500\">Khi h\u00ECnh \u1EA3nh ch\u00EDnh b\u1ECB l\u1ED7i, s\u1EBD hi\u1EC3n th\u1ECB h\u00ECnh \u1EA3nh thay th\u1EBF.</p>\n </div>\n </div>\n </div>\n\n <!-- Fallback to Text Demo -->\n <div class=\"mb-8\">\n <h3 class=\"text-xl font-semibold text-gray-700 mb-4\">Fallback v\u1EC1 v\u0103n b\u1EA3n</h3>\n <div class=\"flex items-center p-4 bg-gray-50 rounded-lg\">\n <libs_ui-components-avatar [linkAvatar]=\"invalidImageUrl\"\n [textAvatar]=\"'Text Fallback'\"\n [idGenColor]=\"'text-fallback'\"\n [size]=\"48\"\n (outAvatarError)=\"handleAvatarError()\">\n </libs_ui-components-avatar>\n <div>\n <p class=\"text-gray-700\">Avatar v\u1EDBi fallback v\u1EC1 v\u0103n b\u1EA3n</p>\n <p class=\"text-sm text-gray-500\">Khi kh\u00F4ng c\u00F3 h\u00ECnh \u1EA3nh, s\u1EBD hi\u1EC3n th\u1ECB ch\u1EEF c\u00E1i \u0111\u1EA7u c\u1EE7a v\u0103n b\u1EA3n v\u1EDBi m\u00E0u n\u1EC1n t\u1EF1\n \u0111\u1ED9ng.</p>\n @if (showErrorMessage) {\n <p class=\"text-sm text-red-500 mt-2\">Kh\u00F4ng th\u1EC3 t\u1EA3i h\u00ECnh \u1EA3nh. \u0110\u00E3 hi\u1EC3n th\u1ECB v\u0103n b\u1EA3n thay th\u1EBF.</p>\n }\n </div>\n </div>\n </div>\n </section>\n\n <section class=\"bg-white rounded-lg p-8 mb-8 shadow-sm\">\n <h2 class=\"text-2xl font-bold text-gray-800 mb-5 pb-3 border-b border-gray-200\">C\u00E1ch s\u1EED d\u1EE5ng</h2>\n\n <div class=\"mb-8\">\n <h3 class=\"text-xl font-semibold text-gray-700 mb-4\">C\u00E1ch 1: S\u1EED d\u1EE5ng file HTML ri\u00EAng bi\u1EC7t</h3>\n\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-6 mb-4\">\n <div>\n <h4 class=\"font-semibold mb-2 text-gray-700\">HTML (example.component.html)</h4>\n <pre class=\"bg-gray-100 p-4 rounded-lg overflow-x-auto text-sm\"><code><libs_ui-components-avatar\n [linkAvatar]=\"'https://example.com/avatar.jpg'\"\n [textAvatar]=\"'Nguy\u1EC5n V\u0103n A'\"\n [idGenColor]=\"'user-123'\"\n [size]=\"40\"\n [typeShape]=\"'circle'\">\n</libs_ui-components-avatar></code></pre>\n </div>\n\n <div>\n <h4 class=\"font-semibold mb-2 text-gray-700\">TypeScript (example.component.ts)</h4>\n <pre class=\"bg-gray-100 p-4 rounded-lg overflow-x-auto text-sm\"><code>import { Component } from '@angular/core';\nimport { LibsUiComponentsAvatarComponent } from '@libs-ui/components-avatar';\n\n@Component({\n selector: 'app-example',\n standalone: true,\n imports: [LibsUiComponentsAvatarComponent],\n templateUrl: './example.component.html'\n})\nexport class ExampleComponent {\n // Component logic\n}</code></pre>\n </div>\n </div>\n </div>\n\n <div class=\"mb-8\">\n <h3 class=\"text-xl font-semibold text-gray-700 mb-4\">C\u00E1ch 2: X\u1EED l\u00FD s\u1EF1 ki\u1EC7n l\u1ED7i</h3>\n\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-6 mb-4\">\n <div>\n <h4 class=\"font-semibold mb-2 text-gray-700\">HTML (error-handler.component.html)</h4>\n <pre class=\"bg-gray-100 p-4 rounded-lg overflow-x-auto text-sm\"><code><libs_ui-components-avatar\n [linkAvatar]=\"user.avatar\"\n [linkAvatarError]=\"defaultAvatar\"\n [textAvatar]=\"user.name\"\n [idGenColor]=\"user.id\"\n [size]=\"40\"\n (outAvatarError)=\"handleAvatarError()\">\n</libs_ui-components-avatar></code></pre>\n </div>\n\n <div>\n <h4 class=\"font-semibold mb-2 text-gray-700\">TypeScript (error-handler.component.ts)</h4>\n <pre class=\"bg-gray-100 p-4 rounded-lg overflow-x-auto text-sm\"><code>import { Component } from '@angular/core';\nimport { LibsUiComponentsAvatarComponent } from '@libs-ui/components-avatar';\n\n@Component({\n selector: 'app-error-handler',\n standalone: true,\n imports: [LibsUiComponentsAvatarComponent],\n templateUrl: './error-handler.component.html'\n})\nexport class ErrorHandlerComponent {\n user = {\n id: 'user-123',\n name: 'Nguy\u1EC5n V\u0103n A',\n avatar: 'https://example.com/avatar.jpg'\n };\n \n defaultAvatar = 'https://example.com/default-avatar.jpg';\n\n handleAvatarError() {\n console.log('Kh\u00F4ng th\u1EC3 t\u1EA3i \u0111\u01B0\u1EE3c h\u00ECnh \u1EA3nh avatar');\n // Th\u1EF1c hi\u1EC7n c\u00E1c x\u1EED l\u00FD kh\u00E1c khi c\u00F3 l\u1ED7i\n }\n}</code></pre>\n </div>\n </div>\n </div>\n </section>\n\n <section class=\"bg-white rounded-lg p-8 mb-8 shadow-sm\">\n <h2 class=\"text-2xl font-bold text-gray-800 mb-5 pb-3 border-b border-gray-200\">T\u00E0i li\u1EC7u API</h2>\n\n <h3 class=\"text-xl font-semibold text-gray-700 mb-4\">Inputs</h3>\n <div class=\"overflow-x-auto mb-8\">\n <table class=\"min-w-full bg-white border border-gray-200\">\n <thead>\n <tr>\n <th class=\"py-3 px-4 border-b border-gray-200 bg-gray-100 text-left font-semibold text-gray-700\">T\u00EAn</th>\n <th class=\"py-3 px-4 border-b border-gray-200 bg-gray-100 text-left font-semibold text-gray-700\">Ki\u1EC3u d\u1EEF\n li\u1EC7u</th>\n <th class=\"py-3 px-4 border-b border-gray-200 bg-gray-100 text-left font-semibold text-gray-700\">M\u1EB7c \u0111\u1ECBnh\n </th>\n <th class=\"py-3 px-4 border-b border-gray-200 bg-gray-100 text-left font-semibold text-gray-700\">M\u00F4 t\u1EA3\n </th>\n </tr>\n </thead>\n <tbody>\n <tr>\n <td class=\"py-2 px-4 border-b border-gray-200\"><code\n class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">linkAvatar</code></td>\n <td class=\"py-2 px-4 border-b border-gray-200\"><code\n class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">string</code></td>\n <td class=\"py-2 px-4 border-b border-gray-200\">-</td>\n <td class=\"py-2 px-4 border-b border-gray-200\">\u0110\u01B0\u1EDDng d\u1EABn c\u1EE7a h\u00ECnh \u1EA3nh avatar</td>\n </tr>\n <tr>\n <td class=\"py-2 px-4 border-b border-gray-200\"><code\n class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">linkAvatarError</code></td>\n <td class=\"py-2 px-4 border-b border-gray-200\"><code\n class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">string</code></td>\n <td class=\"py-2 px-4 border-b border-gray-200\">-</td>\n <td class=\"py-2 px-4 border-b border-gray-200\">\u0110\u01B0\u1EDDng d\u1EABn c\u1EE7a h\u00ECnh \u1EA3nh thay th\u1EBF khi avatar ch\u00EDnh b\u1ECB l\u1ED7i\n </td>\n </tr>\n <tr>\n <td class=\"py-2 px-4 border-b border-gray-200\"><code\n class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">textAvatar</code></td>\n <td class=\"py-2 px-4 border-b border-gray-200\"><code\n class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">string</code></td>\n <td class=\"py-2 px-4 border-b border-gray-200\">-</td>\n <td class=\"py-2 px-4 border-b border-gray-200\">V\u0103n b\u1EA3n hi\u1EC3n th\u1ECB khi kh\u00F4ng c\u00F3 h\u00ECnh \u1EA3nh (th\u01B0\u1EDDng l\u00E0 ch\u1EEF c\u00E1i\n \u0111\u1EA7u c\u1EE7a t\u00EAn)</td>\n </tr>\n <tr>\n <td class=\"py-2 px-4 border-b border-gray-200\"><code\n class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">idGenColor</code></td>\n <td class=\"py-2 px-4 border-b border-gray-200\"><code\n class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">string</code></td>\n <td class=\"py-2 px-4 border-b border-gray-200\">-</td>\n <td class=\"py-2 px-4 border-b border-gray-200\">ID d\u00F9ng \u0111\u1EC3 t\u1EA1o m\u00E0u n\u1EC1n t\u1EF1 \u0111\u1ED9ng khi s\u1EED d\u1EE5ng v\u0103n b\u1EA3n</td>\n </tr>\n <tr>\n <td class=\"py-2 px-4 border-b border-gray-200\"><code\n class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">size</code></td>\n <td class=\"py-2 px-4 border-b border-gray-200\"><code class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">16\n | 24 | 32 | 40 | 48 | 64</code></td>\n <td class=\"py-2 px-4 border-b border-gray-200\">32</td>\n <td class=\"py-2 px-4 border-b border-gray-200\">K\u00EDch th\u01B0\u1EDBc c\u1EE7a avatar (t\u00EDnh b\u1EB1ng pixel)</td>\n </tr>\n <tr>\n <td class=\"py-2 px-4 border-b border-gray-200\"><code\n class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">typeShape</code></td>\n <td class=\"py-2 px-4 border-b border-gray-200\"><code\n class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">'circle' | 'rectangle'</code></td>\n <td class=\"py-2 px-4 border-b border-gray-200\">'circle'</td>\n <td class=\"py-2 px-4 border-b border-gray-200\">H\u00ECnh d\u1EA1ng c\u1EE7a avatar (tr\u00F2n ho\u1EB7c vu\u00F4ng)</td>\n </tr>\n <tr>\n <td class=\"py-2 px-4 border-b border-gray-200\"><code\n class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">classInclude</code></td>\n <td class=\"py-2 px-4 border-b border-gray-200\"><code\n class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">string</code></td>\n <td class=\"py-2 px-4 border-b border-gray-200\">'mr-[8px]'</td>\n <td class=\"py-2 px-4 border-b border-gray-200\">CSS class b\u1ED5 sung cho container ch\u00EDnh</td>\n </tr>\n <tr>\n <td class=\"py-2 px-4 border-b border-gray-200\"><code\n class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">classImageInclude</code></td>\n <td class=\"py-2 px-4 border-b border-gray-200\"><code\n class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">string</code></td>\n <td class=\"py-2 px-4 border-b border-gray-200\">''</td>\n <td class=\"py-2 px-4 border-b border-gray-200\">CSS class b\u1ED5 sung cho th\u1EBB img</td>\n </tr>\n <tr>\n <td class=\"py-2 px-4 border-b border-gray-200\"><code\n class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">getLastTextAfterSpace</code></td>\n <td class=\"py-2 px-4 border-b border-gray-200\"><code\n class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">boolean</code></td>\n <td class=\"py-2 px-4 border-b border-gray-200\">false</td>\n <td class=\"py-2 px-4 border-b border-gray-200\">N\u1EBFu true, ch\u1EC9 l\u1EA5y ch\u1EEF c\u00E1i \u0111\u1EA7u ti\u00EAn c\u1EE7a t\u1EEB cu\u1ED1i c\u00F9ng trong\n textAvatar</td>\n </tr>\n </tbody>\n </table>\n </div>\n\n <h3 class=\"text-xl font-semibold text-gray-700 mb-4\">Outputs</h3>\n <div class=\"overflow-x-auto mb-8\">\n <table class=\"min-w-full bg-white border border-gray-200\">\n <thead>\n <tr>\n <th class=\"py-3 px-4 border-b border-gray-200 bg-gray-100 text-left font-semibold text-gray-700\">T\u00EAn</th>\n <th class=\"py-3 px-4 border-b border-gray-200 bg-gray-100 text-left font-semibold text-gray-700\">Ki\u1EC3u d\u1EEF\n li\u1EC7u</th>\n <th class=\"py-3 px-4 border-b border-gray-200 bg-gray-100 text-left font-semibold text-gray-700\">M\u00F4 t\u1EA3\n </th>\n </tr>\n </thead>\n <tbody>\n <tr>\n <td class=\"py-2 px-4 border-b border-gray-200\"><code\n class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">outAvatarError</code></td>\n <td class=\"py-2 px-4 border-b border-gray-200\"><code\n class=\"text-sm bg-gray-100 px-1.5 py-0.5 rounded\">void</code></td>\n <td class=\"py-2 px-4 border-b border-gray-200\">S\u1EF1 ki\u1EC7n \u0111\u01B0\u1EE3c k\u00EDch ho\u1EA1t khi linkAvatar b\u1ECB l\u1ED7i v\u00E0 kh\u00F4ng c\u00F3\n linkAvatarError</td>\n </tr>\n </tbody>\n </table>\n </div>\n\n <h3 class=\"text-xl font-semibold text-gray-700 mb-4\">Interfaces</h3>\n <div class=\"bg-gray-50 p-6 rounded-lg\">\n <h4 class=\"text-lg font-semibold text-gray-700 mb-3\">IAvatarConfig</h4>\n <pre class=\"bg-gray-100 p-4 rounded-lg overflow-x-auto text-sm mb-3\"><code>export interface IAvatarConfig {\n classImageInclude?: string;\n classInclude?: string;\n size?: TYPE_SIZE_AVATAR_CONFIG;\n linkAvatar?: string;\n linkAvatarError?: string;\n idGenColor?: string;\n textAvatar?: string;\n typeShape?: TYPE_SHAPE_AVATAR;\n getLastTextAfterSpace?: boolean;\n }\n\nexport type TYPE_SIZE_AVATAR_CONFIG = 16 | 24 | 32 | 40 | 48 | 64;\nexport type TYPE_SHAPE_AVATAR = 'circle' | 'rectangle';</code></pre>\n <p class=\"text-gray-600\">Interface \u0111\u1ECBnh ngh\u0129a c\u1EA5u h\u00ECnh c\u1EE7a avatar component.</p>\n </div>\n </section>\n </main>\n</div>\n", styles: [":host{display:block;width:100%;padding:16px}.demo-wrapper{background-color:#f9fafb;border-radius:8px;padding:16px;margin-bottom:16px}.code-block{font-family:monospace;background-color:#f3f4f6;border-radius:4px;padding:2px 4px;font-size:14px}button{transition:all .2s ease}button:hover{opacity:.9}button:active{transform:scale(.98)}.size-option{cursor:pointer;border:1px solid #e5e7eb;padding:4px 8px;border-radius:4px}.size-option.selected{background-color:#3b82f6;color:#fff;border-color:#3b82f6}.shape-option{cursor:pointer;border:1px solid #e5e7eb;padding:4px 8px;border-radius:4px;margin-left:8px}.shape-option.selected{background-color:#3b82f6;color:#fff;border-color:#3b82f6}.error-message{color:#ef4444;margin-top:8px;font-size:14px}.copy-button{background-color:#3b82f6;color:#fff;border-radius:4px;padding:4px 8px;font-size:14px;border:none;cursor:pointer}\n"] }]
|
|
83
|
-
}] });
|
|
84
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGVtby5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9saWJzLXVpL2NvbXBvbmVudHMvYXZhdGFyL3NyYy9kZW1vL2RlbW8uY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vbGlicy11aS9jb21wb25lbnRzL2F2YXRhci9zcmMvZGVtby9kZW1vLmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxLQUFLLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUN4QyxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQzFDLE9BQU8sRUFBRSwrQkFBK0IsRUFBRSxNQUFNLHFCQUFxQixDQUFDOztBQWF0RSxNQUFNLE9BQU8sbUNBQW1DO0lBQzlDLGtCQUFrQjtJQUNsQixhQUFhLEdBQUcsZ0RBQWdELENBQUM7SUFDakUsY0FBYyxHQUFHLGdEQUFnRCxDQUFDO0lBRWxFLGdCQUFnQjtJQUNoQixXQUFXLEdBQThCLENBQUMsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUMsQ0FBQztJQUNsRSxZQUFZLEdBQTRCLEVBQUUsQ0FBQztJQUUzQyxpQkFBaUI7SUFDakIsWUFBWSxHQUF3QixDQUFDLFFBQVEsRUFBRSxXQUFXLENBQUMsQ0FBQztJQUM1RCxhQUFhLEdBQXNCLFFBQVEsQ0FBQztJQUU1QyxtQkFBbUI7SUFDbkIsU0FBUyxHQUFHO1FBQ1YsY0FBYztRQUNkLFlBQVk7UUFDWixVQUFVO1FBQ1YsWUFBWTtRQUNaLFlBQVk7UUFDWixZQUFZO0tBQ2IsQ0FBQztJQUVGLHdCQUF3QjtJQUN4QixLQUFLLEdBQUc7UUFDTjtZQUNFLEVBQUUsRUFBRSxRQUFRO1lBQ1osSUFBSSxFQUFFLGNBQWM7WUFDcEIsTUFBTSxFQUFFLGdEQUFnRDtZQUN4RCxJQUFJLEVBQUUsRUFBRTtTQUNUO1FBQ0Q7WUFDRSxFQUFFLEVBQUUsUUFBUTtZQUNaLElBQUksRUFBRSxZQUFZO1lBQ2xCLE1BQU0sRUFBRSxrREFBa0Q7WUFDMUQsSUFBSSxFQUFFLEVBQUU7U0FDVDtRQUNEO1lBQ0UsRUFBRSxFQUFFLFFBQVE7WUFDWixJQUFJLEVBQUUsVUFBVTtZQUNoQixNQUFNLEVBQUUsZ0RBQWdEO1lBQ3hELElBQUksRUFBRSxFQUFFO1NBQ1Q7UUFDRDtZQUNFLEVBQUUsRUFBRSxRQUFRO1lBQ1osSUFBSSxFQUFFLFlBQVk7WUFDbEIsTUFBTSxFQUFFLFNBQVM7WUFDakIsSUFBSSxFQUFFLEVBQUU7U0FDVDtLQUM0QixDQUFDO0lBRWhDLDBCQUEwQjtJQUMxQixlQUFlLEdBQUcsdUNBQXVDLENBQUM7SUFDMUQsZ0JBQWdCLEdBQUcsS0FBSyxDQUFDO0lBRXpCLFVBQVU7SUFDVixXQUFXO1FBQ1QsSUFBSSxDQUFDLGFBQWEsR0FBRyxJQUFJLENBQUMsYUFBYSxLQUFLLFFBQVEsQ0FBQyxDQUFDLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUM7SUFDaEYsQ0FBQztJQUVELE9BQU8sQ0FBQyxJQUE2QjtRQUNuQyxJQUFJLENBQUMsWUFBWSxHQUFHLElBQUksQ0FBQztJQUMzQixDQUFDO0lBRUQsaUJBQWlCO1FBQ2YsSUFBSSxDQUFDLGdCQUFnQixHQUFHLElBQUksQ0FBQztRQUM3QixVQUFVLENBQUMsR0FBRyxFQUFFO1lBQ2QsSUFBSSxDQUFDLGdCQUFnQixHQUFHLEtBQUssQ0FBQztRQUNoQyxDQUFDLEVBQUUsSUFBSSxDQUFDLENBQUM7SUFDWCxDQUFDO0lBRUQsZUFBZSxDQUFDLElBQVk7UUFDMUIsU0FBUyxDQUFDLFNBQVMsQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLENBQUMsSUFBSSxDQUFDLEdBQUcsRUFBRTtZQUM1QyxLQUFLLENBQUMsMkJBQTJCLENBQUMsQ0FBQztRQUNyQyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLEVBQUU7WUFDYixPQUFPLENBQUMsS0FBSyxDQUFDLHNCQUFzQixFQUFFLEdBQUcsQ0FBQyxDQUFDO1FBQzdDLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQzt3R0E3RVUsbUNBQW1DOzRGQUFuQyxtQ0FBbUMsMkVDZmhELHU5bUJBeVhBLDY1QkRoWEksK0JBQStCLDZYQUMvQixLQUFLOzs0RkFLSSxtQ0FBbUM7a0JBVi9DLFNBQVM7K0JBQ0UsaUJBQWlCLGNBQ2YsSUFBSSxXQUNQO3dCQUNQLCtCQUErQjt3QkFDL0IsS0FBSztxQkFDTiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IE5nRm9yIH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uJztcbmltcG9ydCB7IENvbXBvbmVudCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgTGlic1VpQ29tcG9uZW50c0F2YXRhckNvbXBvbmVudCB9IGZyb20gJy4uL2F2YXRhci5jb21wb25lbnQnO1xuaW1wb3J0IHsgVFlQRV9TSEFQRV9BVkFUQVIsIFRZUEVfU0laRV9BVkFUQVJfQ09ORklHIH0gZnJvbSAnLi4vaW50ZXJmYWNlcy9hdmF0YXIuaW50ZXJmYWNlJztcblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnbGliLWF2YXRhci1kZW1vJyxcbiAgc3RhbmRhbG9uZTogdHJ1ZSxcbiAgaW1wb3J0czogW1xuICAgIExpYnNVaUNvbXBvbmVudHNBdmF0YXJDb21wb25lbnQsXG4gICAgTmdGb3JcbiAgXSxcbiAgdGVtcGxhdGVVcmw6ICcuL2RlbW8uY29tcG9uZW50Lmh0bWwnLFxuICBzdHlsZVVybDogJy4vZGVtby5jb21wb25lbnQuc2Nzcydcbn0pXG5leHBvcnQgY2xhc3MgTGlic1VpQ29tcG9uZW50c0F2YXRhckRlbW9Db21wb25lbnQge1xuICAvLyBCYXNpYyBkZW1vIGRhdGFcbiAgZXhhbXBsZUF2YXRhciA9ICdodHRwczovL3JhbmRvbXVzZXIubWUvYXBpL3BvcnRyYWl0cy9tZW4vMzMuanBnJztcbiAgZmFsbGJhY2tBdmF0YXIgPSAnaHR0cHM6Ly9yYW5kb211c2VyLm1lL2FwaS9wb3J0cmFpdHMvbGVnby82LmpwZyc7XG5cbiAgLy8gU2l6ZSB2YXJpYW50c1xuICBzaXplT3B0aW9uczogVFlQRV9TSVpFX0FWQVRBUl9DT05GSUdbXSA9IFsxNiwgMjQsIDMyLCA0MCwgNDgsIDY0XTtcbiAgc2VsZWN0ZWRTaXplOiBUWVBFX1NJWkVfQVZBVEFSX0NPTkZJRyA9IDQwO1xuXG4gIC8vIFNoYXBlIHZhcmlhbnRzXG4gIHNoYXBlT3B0aW9uczogVFlQRV9TSEFQRV9BVkFUQVJbXSA9IFsnY2lyY2xlJywgJ3JlY3RhbmdsZSddO1xuICBzZWxlY3RlZFNoYXBlOiBUWVBFX1NIQVBFX0FWQVRBUiA9ICdjaXJjbGUnO1xuXG4gIC8vIFRleHQgYXZhdGFyIGRlbW9cbiAgdXNlck5hbWVzID0gW1xuICAgICdOZ3V54buFbiBWxINuIEEnLFxuICAgICdUcuG6p24gVGjhu4sgQicsXG4gICAgJ0zDqiBWxINuIEMnLFxuICAgICdQaOG6oW0gVGjhu4sgRCcsXG4gICAgJ1bFqSBIb8OgbmcgRScsXG4gICAgJ8SQ4bq3bmcgVGjhu4sgRidcbiAgXTtcblxuICAvLyBEZW1vIGZvciBhdmF0YXIgZ3JvdXBcbiAgdXNlcnMgPSBbXG4gICAge1xuICAgICAgaWQ6ICd1c2VyLTEnLFxuICAgICAgbmFtZTogJ05ndXnhu4VuIFbEg24gQScsXG4gICAgICBhdmF0YXI6ICdodHRwczovL3JhbmRvbXVzZXIubWUvYXBpL3BvcnRyYWl0cy9tZW4vMzIuanBnJyxcbiAgICAgIHNpemU6IDY0XG4gICAgfSxcbiAgICB7XG4gICAgICBpZDogJ3VzZXItMicsXG4gICAgICBuYW1lOiAnVHLhuqduIFRo4buLIEInLFxuICAgICAgYXZhdGFyOiAnaHR0cHM6Ly9yYW5kb211c2VyLm1lL2FwaS9wb3J0cmFpdHMvd29tZW4vMzIuanBnJyxcbiAgICAgIHNpemU6IDQ4XG4gICAgfSxcbiAgICB7XG4gICAgICBpZDogJ3VzZXItMycsXG4gICAgICBuYW1lOiAnTMOqIFbEg24gQycsXG4gICAgICBhdmF0YXI6ICdodHRwczovL3JhbmRvbXVzZXIubWUvYXBpL3BvcnRyYWl0cy9tZW4vMzMuanBnJyxcbiAgICAgIHNpemU6IDMyXG4gICAgfSxcbiAgICB7XG4gICAgICBpZDogJ3VzZXItNCcsXG4gICAgICBuYW1lOiAnUGjhuqFtIFRo4buLIEQnLFxuICAgICAgYXZhdGFyOiB1bmRlZmluZWQsXG4gICAgICBzaXplOiAyNFxuICAgIH1cbiAgXSBhcyBBcnJheTxSZWNvcmQ8c3RyaW5nLCBhbnk+PjtcblxuICAvLyBEZW1vIGZvciBlcnJvciBoYW5kbGluZ1xuICBpbnZhbGlkSW1hZ2VVcmwgPSAnaHR0cHM6Ly9leGFtcGxlLmNvbS9pbnZhbGlkLWltYWdlLmpwZyc7XG4gIHNob3dFcnJvck1lc3NhZ2UgPSBmYWxzZTtcblxuICAvLyBNZXRob2RzXG4gIHRvZ2dsZVNoYXBlKCkge1xuICAgIHRoaXMuc2VsZWN0ZWRTaGFwZSA9IHRoaXMuc2VsZWN0ZWRTaGFwZSA9PT0gJ2NpcmNsZScgPyAncmVjdGFuZ2xlJyA6ICdjaXJjbGUnO1xuICB9XG5cbiAgc2V0U2l6ZShzaXplOiBUWVBFX1NJWkVfQVZBVEFSX0NPTkZJRykge1xuICAgIHRoaXMuc2VsZWN0ZWRTaXplID0gc2l6ZTtcbiAgfVxuXG4gIGhhbmRsZUF2YXRhckVycm9yKCkge1xuICAgIHRoaXMuc2hvd0Vycm9yTWVzc2FnZSA9IHRydWU7XG4gICAgc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICB0aGlzLnNob3dFcnJvck1lc3NhZ2UgPSBmYWxzZTtcbiAgICB9LCAzMDAwKTtcbiAgfVxuXG4gIGNvcHlUb0NsaXBib2FyZCh0ZXh0OiBzdHJpbmcpIHtcbiAgICBuYXZpZ2F0b3IuY2xpcGJvYXJkLndyaXRlVGV4dCh0ZXh0KS50aGVuKCgpID0+IHtcbiAgICAgIGFsZXJ0KCfEkMOjIHNhbyBjaMOpcCB2w6BvIGNsaXBib2FyZCcpO1xuICAgIH0pLmNhdGNoKGVyciA9PiB7XG4gICAgICBjb25zb2xlLmVycm9yKCdLaMO0bmcgdGjhu4Mgc2FvIGNow6lwOiAnLCBlcnIpO1xuICAgIH0pO1xuICB9XG59ICIsIjxkaXYgY2xhc3M9XCJtYXgtdy02eGwgbXgtYXV0byBwLTUgZm9udC1zYW5zIHRleHQtZ3JheS04MDBcIj5cbiAgPGhlYWRlciBjbGFzcz1cInRleHQtY2VudGVyIHB5LTEwIGJnLXdoaXRlIHJvdW5kZWQtbGcgbWItOCBzaGFkb3ctc21cIj5cbiAgICA8aDEgY2xhc3M9XCJ0ZXh0LTR4bCBmb250LWJvbGQgdGV4dC1ncmF5LTgwMCBtYi0yXCI+RGVtbyBBdmF0YXIgQ29tcG9uZW50PC9oMT5cbiAgICA8cCBjbGFzcz1cInRleHQteGwgdGV4dC1ncmF5LTUwMFwiPlRoxrAgdmnhu4duIGNvbXBvbmVudCBBdmF0YXIgY2hvIEFuZ3VsYXI8L3A+XG4gIDwvaGVhZGVyPlxuXG4gIDxtYWluPlxuICAgIDxzZWN0aW9uIGNsYXNzPVwiYmctd2hpdGUgcm91bmRlZC1sZyBwLTggbWItOCBzaGFkb3ctc21cIj5cbiAgICAgIDxoMiBjbGFzcz1cInRleHQtMnhsIGZvbnQtYm9sZCB0ZXh0LWdyYXktODAwIG1iLTUgcGItMyBib3JkZXItYiBib3JkZXItZ3JheS0yMDBcIj5HaeG7m2kgdGhp4buHdTwvaDI+XG4gICAgICA8cD5cbiAgICAgICAgPGNvZGUgY2xhc3M9XCJ0ZXh0LXNtIGJnLWdyYXktMTAwIHB4LTEuNSBweS0wLjUgcm91bmRlZFwiPiYjNjQ7bGlicy11aS9jb21wb25lbnRzLWF2YXRhcjwvY29kZT4gbMOgIG3hu5l0XG4gICAgICAgIGNvbXBvbmVudCBBbmd1bGFyIMSR4buDIGhp4buDbiB0aOG7iyBhdmF0YXIgbmfGsOG7nWkgZMO5bmcgduG7m2kgbmhp4buBdSB0w7l5IGNo4buNbiBuaMawIGjDrG5oIOG6o25oLCBjaOG7ryBjw6FpIMSR4bqndSxcbiAgICAgICAgbcOgdSBz4bqvYyB04buxIMSR4buZbmcsIHbDoCBo4buXIHRy4bujIGZhbGxiYWNrIGtoaSDhuqNuaCBi4buLIGzhu5dpLlxuICAgICAgPC9wPlxuICAgIDwvc2VjdGlvbj5cblxuICAgIDxzZWN0aW9uIGNsYXNzPVwiYmctd2hpdGUgcm91bmRlZC1sZyBwLTggbWItOCBzaGFkb3ctc21cIj5cbiAgICAgIDxoMiBjbGFzcz1cInRleHQtMnhsIGZvbnQtYm9sZCB0ZXh0LWdyYXktODAwIG1iLTUgcGItMyBib3JkZXItYiBib3JkZXItZ3JheS0yMDBcIj5Dw6BpIMSR4bq3dDwvaDI+XG5cbiAgICAgIDxkaXYgY2xhc3M9XCJtYi02XCI+XG4gICAgICAgIDxoMyBjbGFzcz1cInRleHQteGwgZm9udC1zZW1pYm9sZCB0ZXh0LWdyYXktNzAwIG1iLTNcIj5Zw6p1IGPhuqd1PC9oMz5cbiAgICAgICAgPHVsIGNsYXNzPVwibGlzdC1kaXNjIHBsLTUgc3BhY2UteS0yIHRleHQtZ3JheS02MDBcIj5cbiAgICAgICAgICA8bGk+PHNwYW4gY2xhc3M9XCJmb250LXNlbWlib2xkXCI+QW5ndWxhcjwvc3Bhbj46IDE4LjAuMCB0cuG7nyBsw6puPC9saT5cbiAgICAgICAgICA8bGk+PHNwYW4gY2xhc3M9XCJmb250LXNlbWlib2xkXCI+VGFpbHdpbmQgQ1NTPC9zcGFuPjogMy4zLjAgdHLhu58gbMOqbjwvbGk+XG4gICAgICAgIDwvdWw+XG4gICAgICA8L2Rpdj5cblxuICAgICAgPHAgY2xhc3M9XCJtYi00XCI+xJDhu4MgY8OgaSDEkeG6t3QgdGjGsCB2aeG7h24sIHPhu60gZOG7pW5nIG5wbSBob+G6t2MgeWFybjo8L3A+XG5cbiAgICAgIDxkaXYgY2xhc3M9XCJmbGV4IGl0ZW1zLWNlbnRlciBiZy1ncmF5LTEwMCBwLTQgcm91bmRlZC1sZyBtYi02XCI+XG4gICAgICAgIDxwcmUgY2xhc3M9XCJmbGV4LTEgdGV4dC1zbSBvdmVyZmxvdy14LWF1dG9cIj48Y29kZT5ucG0gaW5zdGFsbCAmIzY0O2xpYnMtdWkvY29tcG9uZW50cy1hdmF0YXI8L2NvZGU+PC9wcmU+XG4gICAgICAgIDxidXR0b24gY2xhc3M9XCJtbC00IHB4LTMgcHktMSBiZy1ibHVlLTUwMCB0ZXh0LXdoaXRlIHJvdW5kZWQgaG92ZXI6YmctYmx1ZS02MDAgdHJhbnNpdGlvbi1jb2xvcnNcIlxuICAgICAgICAgIChjbGljayk9XCJjb3B5VG9DbGlwYm9hcmQoJ25wbSBpbnN0YWxsIEBsaWJzLXVpL2NvbXBvbmVudHMtYXZhdGFyJylcIj5cbiAgICAgICAgICBTYW8gY2jDqXBcbiAgICAgICAgPC9idXR0b24+XG4gICAgICA8L2Rpdj5cblxuICAgICAgPHAgY2xhc3M9XCJtYi00XCI+SG/hurdjIHbhu5tpIHlhcm46PC9wPlxuXG4gICAgICA8ZGl2IGNsYXNzPVwiZmxleCBpdGVtcy1jZW50ZXIgYmctZ3JheS0xMDAgcC00IHJvdW5kZWQtbGcgbWItNlwiPlxuICAgICAgICA8cHJlIGNsYXNzPVwiZmxleC0xIHRleHQtc20gb3ZlcmZsb3cteC1hdXRvXCI+PGNvZGU+eWFybiBhZGQgJiM2NDtsaWJzLXVpL2NvbXBvbmVudHMtYXZhdGFyPC9jb2RlPjwvcHJlPlxuICAgICAgICA8YnV0dG9uIGNsYXNzPVwibWwtNCBweC0zIHB5LTEgYmctYmx1ZS01MDAgdGV4dC13aGl0ZSByb3VuZGVkIGhvdmVyOmJnLWJsdWUtNjAwIHRyYW5zaXRpb24tY29sb3JzXCJcbiAgICAgICAgICAoY2xpY2spPVwiY29weVRvQ2xpcGJvYXJkKCd5YXJuIGFkZCBAbGlicy11aS9jb21wb25lbnRzLWF2YXRhcicpXCI+XG4gICAgICAgICAgU2FvIGNow6lwXG4gICAgICAgIDwvYnV0dG9uPlxuICAgICAgPC9kaXY+XG4gICAgPC9zZWN0aW9uPlxuXG4gICAgPHNlY3Rpb24gY2xhc3M9XCJiZy13aGl0ZSByb3VuZGVkLWxnIHAtOCBtYi04IHNoYWRvdy1zbVwiPlxuICAgICAgPGgyIGNsYXNzPVwidGV4dC0yeGwgZm9udC1ib2xkIHRleHQtZ3JheS04MDAgbWItNSBwYi0zIGJvcmRlci1iIGJvcmRlci1ncmF5LTIwMFwiPkRlbW8gdHLhu7FjIHRp4bq/cDwvaDI+XG5cbiAgICAgIDwhLS0gQmFzaWMgQXZhdGFyIERlbW8gLS0+XG4gICAgICA8ZGl2IGNsYXNzPVwibWItOFwiPlxuICAgICAgICA8aDMgY2xhc3M9XCJ0ZXh0LXhsIGZvbnQtc2VtaWJvbGQgdGV4dC1ncmF5LTcwMCBtYi00XCI+QXZhdGFyIGPGoSBi4bqjbjwvaDM+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJmbGV4IGl0ZW1zLWNlbnRlciBwLTQgYmctZ3JheS01MCByb3VuZGVkLWxnXCI+XG4gICAgICAgICAgPGxpYnNfdWktY29tcG9uZW50cy1hdmF0YXIgW2xpbmtBdmF0YXJdPVwiZXhhbXBsZUF2YXRhclwiXG4gICAgICAgICAgICBbc2l6ZV09XCJzZWxlY3RlZFNpemVcIlxuICAgICAgICAgICAgW3R5cGVTaGFwZV09XCJzZWxlY3RlZFNoYXBlXCI+XG4gICAgICAgICAgPC9saWJzX3VpLWNvbXBvbmVudHMtYXZhdGFyPlxuICAgICAgICAgIDxkaXY+XG4gICAgICAgICAgICA8cCBjbGFzcz1cInRleHQtZ3JheS03MDBcIj5BdmF0YXIgduG7m2kgaMOsbmgg4bqjbmggdOG7qyBVUkw8L3A+XG4gICAgICAgICAgICA8cCBjbGFzcz1cInRleHQtc20gdGV4dC1ncmF5LTUwMFwiPkvDrWNoIHRoxrDhu5tjOiB7eyBzZWxlY3RlZFNpemUgfX1weCwgSMOsbmggZOG6oW5nOiB7eyBzZWxlY3RlZFNoYXBlIH19PC9wPlxuICAgICAgICAgIDwvZGl2PlxuICAgICAgICA8L2Rpdj5cbiAgICAgICAgPGRpdiBjbGFzcz1cIm10LTQgZmxleCBmbGV4LXdyYXAgZ2FwLTNcIj5cbiAgICAgICAgICA8YnV0dG9uICpuZ0Zvcj1cImxldCBzaXplIG9mIHNpemVPcHRpb25zXCJcbiAgICAgICAgICAgIChjbGljayk9XCJzZXRTaXplKHNpemUpXCJcbiAgICAgICAgICAgIGNsYXNzPVwicHgtMyBweS0xIGJvcmRlciByb3VuZGVkXCJcbiAgICAgICAgICAgIFtjbGFzcy5iZy1ibHVlLTUwMF09XCJzZWxlY3RlZFNpemUgPT09IHNpemVcIlxuICAgICAgICAgICAgW2NsYXNzLnRleHQtd2hpdGVdPVwic2VsZWN0ZWRTaXplID09PSBzaXplXCI+XG4gICAgICAgICAgICB7eyBzaXplIH19cHhcbiAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgICA8YnV0dG9uIChjbGljayk9XCJ0b2dnbGVTaGFwZSgpXCJcbiAgICAgICAgICAgIGNsYXNzPVwicHgtMyBweS0xIGJvcmRlciByb3VuZGVkIG1sLTRcIj5cbiAgICAgICAgICAgIMSQ4buVaSBow6xuaCBk4bqhbmdcbiAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgPC9kaXY+XG4gICAgICA8L2Rpdj5cblxuICAgICAgPCEtLSBUZXh0IEF2YXRhciBEZW1vIC0tPlxuICAgICAgPGRpdiBjbGFzcz1cIm1iLThcIj5cbiAgICAgICAgPGgzIGNsYXNzPVwidGV4dC14bCBmb250LXNlbWlib2xkIHRleHQtZ3JheS03MDAgbWItNFwiPkF2YXRhciB2xINuIGLhuqNuPC9oMz5cbiAgICAgICAgPGRpdiBjbGFzcz1cImZsZXggZmxleC13cmFwIGdhcC0zIHAtNCBiZy1ncmF5LTUwIHJvdW5kZWQtbGdcIj5cbiAgICAgICAgICBAZm9yIChuYW1lIG9mIHVzZXJOYW1lczsgdHJhY2sgbmFtZSkge1xuICAgICAgICAgICAgPGxpYnNfdWktY29tcG9uZW50cy1hdmF0YXIgW2dldExhc3RUZXh0QWZ0ZXJTcGFjZV09XCJ0cnVlXCIgW3RleHRBdmF0YXJdPVwibmFtZVwiXG4gICAgICAgICAgICAgIFtpZEdlbkNvbG9yXT1cIm5hbWVcIlxuICAgICAgICAgICAgICBbc2l6ZV09XCI0MFwiXG4gICAgICAgICAgICAgID5cbiAgICAgICAgICAgIDwvbGlic191aS1jb21wb25lbnRzLWF2YXRhcj5cbiAgICAgICAgICB9XG4gICAgICAgIDwvZGl2PlxuICAgICAgICA8cCBjbGFzcz1cIm10LTIgdGV4dC1zbSB0ZXh0LWdyYXktNTAwXCI+SGnhu4NuIHRo4buLIGNo4buvIGPDoWkgxJHhuqd1IHRpw6puIGPhu6dhIHTDqm4gduG7m2kgbcOgdSBu4buBbiB04buxIMSR4buZbmcgZOG7sWEgdHLDqm4gSUQuPC9wPlxuICAgICAgPC9kaXY+XG5cbiAgICAgIDwhLS0gQXZhdGFyIEdyb3VwIERlbW8gLS0+XG4gICAgICA8ZGl2IGNsYXNzPVwibWItOFwiPlxuICAgICAgICA8aDMgY2xhc3M9XCJ0ZXh0LXhsIGZvbnQtc2VtaWJvbGQgdGV4dC1ncmF5LTcwMCBtYi00XCI+TmjDs20gQXZhdGFyPC9oMz5cbiAgICAgICAgPGRpdiBjbGFzcz1cImZsZXggaXRlbXMtY2VudGVyIHAtNCBiZy1ncmF5LTUwIHJvdW5kZWQtbGdcIj5cbiAgICAgICAgICBAZm9yICh1c2VyIG9mIHVzZXJzOyB0cmFjayB1c2VyKSB7XG4gICAgICAgICAgICA8bGlic191aS1jb21wb25lbnRzLWF2YXRhciBbbGlua0F2YXRhcl09XCJ1c2VyWydhdmF0YXInXVwiXG4gICAgICAgICAgICAgIFt0ZXh0QXZhdGFyXT1cInVzZXJbJ25hbWUnXVwiXG4gICAgICAgICAgICAgIFtpZEdlbkNvbG9yXT1cInVzZXJbJ2lkJ11cIlxuICAgICAgICAgICAgICBbc2l6ZV09XCJ1c2VyWydzaXplJ11cIlxuICAgICAgICAgICAgICBbdHlwZVNoYXBlXT1cInVzZXJbJ2lkJ10gPT09ICd1c2VyLTQnID8gJ3JlY3RhbmdsZScgOiAnY2lyY2xlJ1wiXG4gICAgICAgICAgICAgIFtjbGFzc0luY2x1ZGVdPVwiJ21yLTInXCI+XG4gICAgICAgICAgICA8L2xpYnNfdWktY29tcG9uZW50cy1hdmF0YXI+XG4gICAgICAgICAgfVxuICAgICAgICA8L2Rpdj5cbiAgICAgICAgPHAgY2xhc3M9XCJtdC0yIHRleHQtc20gdGV4dC1ncmF5LTUwMFwiPk5ow7NtIGF2YXRhcnMgduG7m2kga8OtY2ggdGjGsOG7m2Mga2jDoWMgbmhhdSB2w6AgaGnhu4NuIHRo4buLIGZhbGxiYWNrIGtoaSBraMO0bmcgY8OzXG4gICAgICAgICAgaMOsbmgg4bqjbmguPC9wPlxuICAgICAgPC9kaXY+XG5cbiAgICAgIDwhLS0gRXJyb3IgSGFuZGxpbmcgRGVtbyAtLT5cbiAgICAgIDxkaXYgY2xhc3M9XCJtYi04XCI+XG4gICAgICAgIDxoMyBjbGFzcz1cInRleHQteGwgZm9udC1zZW1pYm9sZCB0ZXh0LWdyYXktNzAwIG1iLTRcIj5Y4butIGzDvSBs4buXaTwvaDM+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJmbGV4IGl0ZW1zLWNlbnRlciBwLTQgYmctZ3JheS01MCByb3VuZGVkLWxnXCI+XG4gICAgICAgICAgPGxpYnNfdWktY29tcG9uZW50cy1hdmF0YXIgW2xpbmtBdmF0YXJdPVwiaW52YWxpZEltYWdlVXJsXCJcbiAgICAgICAgICAgIFtsaW5rQXZhdGFyRXJyb3JdPVwiZmFsbGJhY2tBdmF0YXJcIlxuICAgICAgICAgICAgW3RleHRBdmF0YXJdPVwiJ0Vycm9yIEZhbGxiYWNrJ1wiXG4gICAgICAgICAgICBbaWRHZW5Db2xvcl09XCInZXJyb3ItZGVtbydcIlxuICAgICAgICAgICAgW3NpemVdPVwiNDhcIj5cbiAgICAgICAgICA8L2xpYnNfdWktY29tcG9uZW50cy1hdmF0YXI+XG4gICAgICAgICAgPGRpdj5cbiAgICAgICAgICAgIDxwIGNsYXNzPVwidGV4dC1ncmF5LTcwMFwiPkF2YXRhciB24bubaSB44butIGzDvSBs4buXaSBow6xuaCDhuqNuaDwvcD5cbiAgICAgICAgICAgIDxwIGNsYXNzPVwidGV4dC1zbSB0ZXh0LWdyYXktNTAwXCI+S2hpIGjDrG5oIOG6o25oIGNow61uaCBi4buLIGzhu5dpLCBz4bq9IGhp4buDbiB0aOG7iyBow6xuaCDhuqNuaCB0aGF5IHRo4bq/LjwvcD5cbiAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgPC9kaXY+XG4gICAgICA8L2Rpdj5cblxuICAgICAgPCEtLSBGYWxsYmFjayB0byBUZXh0IERlbW8gLS0+XG4gICAgICA8ZGl2IGNsYXNzPVwibWItOFwiPlxuICAgICAgICA8aDMgY2xhc3M9XCJ0ZXh0LXhsIGZvbnQtc2VtaWJvbGQgdGV4dC1ncmF5LTcwMCBtYi00XCI+RmFsbGJhY2sgduG7gSB2xINuIGLhuqNuPC9oMz5cbiAgICAgICAgPGRpdiBjbGFzcz1cImZsZXggaXRlbXMtY2VudGVyIHAtNCBiZy1ncmF5LTUwIHJvdW5kZWQtbGdcIj5cbiAgICAgICAgICA8bGlic191aS1jb21wb25lbnRzLWF2YXRhciBbbGlua0F2YXRhcl09XCJpbnZhbGlkSW1hZ2VVcmxcIlxuICAgICAgICAgICAgW3RleHRBdmF0YXJdPVwiJ1RleHQgRmFsbGJhY2snXCJcbiAgICAgICAgICAgIFtpZEdlbkNvbG9yXT1cIid0ZXh0LWZhbGxiYWNrJ1wiXG4gICAgICAgICAgICBbc2l6ZV09XCI0OFwiXG4gICAgICAgICAgICAob3V0QXZhdGFyRXJyb3IpPVwiaGFuZGxlQXZhdGFyRXJyb3IoKVwiPlxuICAgICAgICAgIDwvbGlic191aS1jb21wb25lbnRzLWF2YXRhcj5cbiAgICAgICAgICA8ZGl2PlxuICAgICAgICAgICAgPHAgY2xhc3M9XCJ0ZXh0LWdyYXktNzAwXCI+QXZhdGFyIHbhu5tpIGZhbGxiYWNrIHbhu4EgdsSDbiBi4bqjbjwvcD5cbiAgICAgICAgICAgIDxwIGNsYXNzPVwidGV4dC1zbSB0ZXh0LWdyYXktNTAwXCI+S2hpIGtow7RuZyBjw7MgaMOsbmgg4bqjbmgsIHPhur0gaGnhu4NuIHRo4buLIGNo4buvIGPDoWkgxJHhuqd1IGPhu6dhIHbEg24gYuG6o24gduG7m2kgbcOgdSBu4buBbiB04buxXG4gICAgICAgICAgICAgIMSR4buZbmcuPC9wPlxuICAgICAgICAgICAgQGlmIChzaG93RXJyb3JNZXNzYWdlKSB7XG4gICAgICAgICAgICAgIDxwIGNsYXNzPVwidGV4dC1zbSB0ZXh0LXJlZC01MDAgbXQtMlwiPktow7RuZyB0aOG7gyB04bqjaSBow6xuaCDhuqNuaC4gxJDDoyBoaeG7g24gdGjhu4sgdsSDbiBi4bqjbiB0aGF5IHRo4bq/LjwvcD5cbiAgICAgICAgICAgIH1cbiAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgPC9kaXY+XG4gICAgICA8L2Rpdj5cbiAgICA8L3NlY3Rpb24+XG5cbiAgICA8c2VjdGlvbiBjbGFzcz1cImJnLXdoaXRlIHJvdW5kZWQtbGcgcC04IG1iLTggc2hhZG93LXNtXCI+XG4gICAgICA8aDIgY2xhc3M9XCJ0ZXh0LTJ4bCBmb250LWJvbGQgdGV4dC1ncmF5LTgwMCBtYi01IHBiLTMgYm9yZGVyLWIgYm9yZGVyLWdyYXktMjAwXCI+Q8OhY2ggc+G7rSBk4bulbmc8L2gyPlxuXG4gICAgICA8ZGl2IGNsYXNzPVwibWItOFwiPlxuICAgICAgICA8aDMgY2xhc3M9XCJ0ZXh0LXhsIGZvbnQtc2VtaWJvbGQgdGV4dC1ncmF5LTcwMCBtYi00XCI+Q8OhY2ggMTogU+G7rSBk4bulbmcgZmlsZSBIVE1MIHJpw6puZyBiaeG7h3Q8L2gzPlxuXG4gICAgICAgIDxkaXYgY2xhc3M9XCJncmlkIGdyaWQtY29scy0xIG1kOmdyaWQtY29scy0yIGdhcC02IG1iLTRcIj5cbiAgICAgICAgICA8ZGl2PlxuICAgICAgICAgICAgPGg0IGNsYXNzPVwiZm9udC1zZW1pYm9sZCBtYi0yIHRleHQtZ3JheS03MDBcIj5IVE1MIChleGFtcGxlLmNvbXBvbmVudC5odG1sKTwvaDQ+XG4gICAgICAgICAgICA8cHJlIGNsYXNzPVwiYmctZ3JheS0xMDAgcC00IHJvdW5kZWQtbGcgb3ZlcmZsb3cteC1hdXRvIHRleHQtc21cIj48Y29kZT4mbHQ7bGlic191aS1jb21wb25lbnRzLWF2YXRhclxuICBbbGlua0F2YXRhcl09XCInaHR0cHM6Ly9leGFtcGxlLmNvbS9hdmF0YXIuanBnJ1wiXG4gIFt0ZXh0QXZhdGFyXT1cIidOZ3V54buFbiBWxINuIEEnXCJcbiAgW2lkR2VuQ29sb3JdPVwiJ3VzZXItMTIzJ1wiXG4gIFtzaXplXT1cIjQwXCJcbiAgW3R5cGVTaGFwZV09XCInY2lyY2xlJ1wiJmd0O1xuJmx0Oy9saWJzX3VpLWNvbXBvbmVudHMtYXZhdGFyJmd0OzwvY29kZT48L3ByZT5cbiAgICAgICAgICA8L2Rpdj5cblxuICAgICAgICAgIDxkaXY+XG4gICAgICAgICAgICA8aDQgY2xhc3M9XCJmb250LXNlbWlib2xkIG1iLTIgdGV4dC1ncmF5LTcwMFwiPlR5cGVTY3JpcHQgKGV4YW1wbGUuY29tcG9uZW50LnRzKTwvaDQ+XG4gICAgICAgICAgICA8cHJlIGNsYXNzPVwiYmctZ3JheS0xMDAgcC00IHJvdW5kZWQtbGcgb3ZlcmZsb3cteC1hdXRvIHRleHQtc21cIj48Y29kZT5pbXBvcnQgJiMxMjM7IENvbXBvbmVudCAmIzEyNTsgZnJvbSAnJiM2NDthbmd1bGFyL2NvcmUnO1xuaW1wb3J0ICYjMTIzOyBMaWJzVWlDb21wb25lbnRzQXZhdGFyQ29tcG9uZW50ICYjMTI1OyBmcm9tICcmIzY0O2xpYnMtdWkvY29tcG9uZW50cy1hdmF0YXInO1xuXG4mIzY0O0NvbXBvbmVudCgmIzEyMztcbiAgc2VsZWN0b3I6ICdhcHAtZXhhbXBsZScsXG4gIHN0YW5kYWxvbmU6IHRydWUsXG4gIGltcG9ydHM6IFtMaWJzVWlDb21wb25lbnRzQXZhdGFyQ29tcG9uZW50XSxcbiAgdGVtcGxhdGVVcmw6ICcuL2V4YW1wbGUuY29tcG9uZW50Lmh0bWwnXG4mIzEyNTspXG5leHBvcnQgY2xhc3MgRXhhbXBsZUNvbXBvbmVudCAmIzEyMztcbiAgLy8gQ29tcG9uZW50IGxvZ2ljXG4mIzEyNTs8L2NvZGU+PC9wcmU+XG4gICAgICAgICAgPC9kaXY+XG4gICAgICAgIDwvZGl2PlxuICAgICAgPC9kaXY+XG5cbiAgICAgIDxkaXYgY2xhc3M9XCJtYi04XCI+XG4gICAgICAgIDxoMyBjbGFzcz1cInRleHQteGwgZm9udC1zZW1pYm9sZCB0ZXh0LWdyYXktNzAwIG1iLTRcIj5Dw6FjaCAyOiBY4butIGzDvSBz4buxIGtp4buHbiBs4buXaTwvaDM+XG5cbiAgICAgICAgPGRpdiBjbGFzcz1cImdyaWQgZ3JpZC1jb2xzLTEgbWQ6Z3JpZC1jb2xzLTIgZ2FwLTYgbWItNFwiPlxuICAgICAgICAgIDxkaXY+XG4gICAgICAgICAgICA8aDQgY2xhc3M9XCJmb250LXNlbWlib2xkIG1iLTIgdGV4dC1ncmF5LTcwMFwiPkhUTUwgKGVycm9yLWhhbmRsZXIuY29tcG9uZW50Lmh0bWwpPC9oND5cbiAgICAgICAgICAgIDxwcmUgY2xhc3M9XCJiZy1ncmF5LTEwMCBwLTQgcm91bmRlZC1sZyBvdmVyZmxvdy14LWF1dG8gdGV4dC1zbVwiPjxjb2RlPiZsdDtsaWJzX3VpLWNvbXBvbmVudHMtYXZhdGFyXG4gIFtsaW5rQXZhdGFyXT1cInVzZXIuYXZhdGFyXCJcbiAgW2xpbmtBdmF0YXJFcnJvcl09XCJkZWZhdWx0QXZhdGFyXCJcbiAgW3RleHRBdmF0YXJdPVwidXNlci5uYW1lXCJcbiAgW2lkR2VuQ29sb3JdPVwidXNlci5pZFwiXG4gIFtzaXplXT1cIjQwXCJcbiAgKG91dEF2YXRhckVycm9yKT1cImhhbmRsZUF2YXRhckVycm9yKClcIiZndDtcbiZsdDsvbGlic191aS1jb21wb25lbnRzLWF2YXRhciZndDs8L2NvZGU+PC9wcmU+XG4gICAgICAgICAgPC9kaXY+XG5cbiAgICAgICAgICA8ZGl2PlxuICAgICAgICAgICAgPGg0IGNsYXNzPVwiZm9udC1zZW1pYm9sZCBtYi0yIHRleHQtZ3JheS03MDBcIj5UeXBlU2NyaXB0IChlcnJvci1oYW5kbGVyLmNvbXBvbmVudC50cyk8L2g0PlxuICAgICAgICAgICAgPHByZSBjbGFzcz1cImJnLWdyYXktMTAwIHAtNCByb3VuZGVkLWxnIG92ZXJmbG93LXgtYXV0byB0ZXh0LXNtXCI+PGNvZGU+aW1wb3J0ICYjMTIzOyBDb21wb25lbnQgJiMxMjU7IGZyb20gJyYjNjQ7YW5ndWxhci9jb3JlJztcbmltcG9ydCAmIzEyMzsgTGlic1VpQ29tcG9uZW50c0F2YXRhckNvbXBvbmVudCAmIzEyNTsgZnJvbSAnJiM2NDtsaWJzLXVpL2NvbXBvbmVudHMtYXZhdGFyJztcblxuJiM2NDtDb21wb25lbnQoJiMxMjM7XG4gIHNlbGVjdG9yOiAnYXBwLWVycm9yLWhhbmRsZXInLFxuICBzdGFuZGFsb25lOiB0cnVlLFxuICBpbXBvcnRzOiBbTGlic1VpQ29tcG9uZW50c0F2YXRhckNvbXBvbmVudF0sXG4gIHRlbXBsYXRlVXJsOiAnLi9lcnJvci1oYW5kbGVyLmNvbXBvbmVudC5odG1sJ1xuJiMxMjU7KVxuZXhwb3J0IGNsYXNzIEVycm9ySGFuZGxlckNvbXBvbmVudCAmIzEyMztcbiAgdXNlciA9ICYjMTIzO1xuICAgIGlkOiAndXNlci0xMjMnLFxuICAgIG5hbWU6ICdOZ3V54buFbiBWxINuIEEnLFxuICAgIGF2YXRhcjogJ2h0dHBzOi8vZXhhbXBsZS5jb20vYXZhdGFyLmpwZydcbiAgJiMxMjU7O1xuICBcbiAgZGVmYXVsdEF2YXRhciA9ICdodHRwczovL2V4YW1wbGUuY29tL2RlZmF1bHQtYXZhdGFyLmpwZyc7XG5cbiAgaGFuZGxlQXZhdGFyRXJyb3IoKSAmIzEyMztcbiAgICBjb25zb2xlLmxvZygnS2jDtG5nIHRo4buDIHThuqNpIMSRxrDhu6NjIGjDrG5oIOG6o25oIGF2YXRhcicpO1xuICAgIC8vIFRo4buxYyBoaeG7h24gY8OhYyB44butIGzDvSBraMOhYyBraGkgY8OzIGzhu5dpXG4gICYjMTI1O1xuJiMxMjU7PC9jb2RlPjwvcHJlPlxuICAgICAgICAgIDwvZGl2PlxuICAgICAgICA8L2Rpdj5cbiAgICAgIDwvZGl2PlxuICAgIDwvc2VjdGlvbj5cblxuICAgIDxzZWN0aW9uIGNsYXNzPVwiYmctd2hpdGUgcm91bmRlZC1sZyBwLTggbWItOCBzaGFkb3ctc21cIj5cbiAgICAgIDxoMiBjbGFzcz1cInRleHQtMnhsIGZvbnQtYm9sZCB0ZXh0LWdyYXktODAwIG1iLTUgcGItMyBib3JkZXItYiBib3JkZXItZ3JheS0yMDBcIj5Uw6BpIGxp4buHdSBBUEk8L2gyPlxuXG4gICAgICA8aDMgY2xhc3M9XCJ0ZXh0LXhsIGZvbnQtc2VtaWJvbGQgdGV4dC1ncmF5LTcwMCBtYi00XCI+SW5wdXRzPC9oMz5cbiAgICAgIDxkaXYgY2xhc3M9XCJvdmVyZmxvdy14LWF1dG8gbWItOFwiPlxuICAgICAgICA8dGFibGUgY2xhc3M9XCJtaW4tdy1mdWxsIGJnLXdoaXRlIGJvcmRlciBib3JkZXItZ3JheS0yMDBcIj5cbiAgICAgICAgICA8dGhlYWQ+XG4gICAgICAgICAgICA8dHI+XG4gICAgICAgICAgICAgIDx0aCBjbGFzcz1cInB5LTMgcHgtNCBib3JkZXItYiBib3JkZXItZ3JheS0yMDAgYmctZ3JheS0xMDAgdGV4dC1sZWZ0IGZvbnQtc2VtaWJvbGQgdGV4dC1ncmF5LTcwMFwiPlTDqm48L3RoPlxuICAgICAgICAgICAgICA8dGggY2xhc3M9XCJweS0zIHB4LTQgYm9yZGVyLWIgYm9yZGVyLWdyYXktMjAwIGJnLWdyYXktMTAwIHRleHQtbGVmdCBmb250LXNlbWlib2xkIHRleHQtZ3JheS03MDBcIj5LaeG7g3UgZOG7r1xuICAgICAgICAgICAgICAgIGxp4buHdTwvdGg+XG4gICAgICAgICAgICAgIDx0aCBjbGFzcz1cInB5LTMgcHgtNCBib3JkZXItYiBib3JkZXItZ3JheS0yMDAgYmctZ3JheS0xMDAgdGV4dC1sZWZ0IGZvbnQtc2VtaWJvbGQgdGV4dC1ncmF5LTcwMFwiPk3hurdjIMSR4buLbmhcbiAgICAgICAgICAgICAgPC90aD5cbiAgICAgICAgICAgICAgPHRoIGNsYXNzPVwicHktMyBweC00IGJvcmRlci1iIGJvcmRlci1ncmF5LTIwMCBiZy1ncmF5LTEwMCB0ZXh0LWxlZnQgZm9udC1zZW1pYm9sZCB0ZXh0LWdyYXktNzAwXCI+TcO0IHThuqNcbiAgICAgICAgICAgICAgPC90aD5cbiAgICAgICAgICAgIDwvdHI+XG4gICAgICAgICAgPC90aGVhZD5cbiAgICAgICAgICA8dGJvZHk+XG4gICAgICAgICAgICA8dHI+XG4gICAgICAgICAgICAgIDx0ZCBjbGFzcz1cInB5LTIgcHgtNCBib3JkZXItYiBib3JkZXItZ3JheS0yMDBcIj48Y29kZVxuICAgICAgICAgICAgICAgICAgY2xhc3M9XCJ0ZXh0LXNtIGJnLWdyYXktMTAwIHB4LTEuNSBweS0wLjUgcm91bmRlZFwiPmxpbmtBdmF0YXI8L2NvZGU+PC90ZD5cbiAgICAgICAgICAgICAgPHRkIGNsYXNzPVwicHktMiBweC00IGJvcmRlci1iIGJvcmRlci1ncmF5LTIwMFwiPjxjb2RlXG4gICAgICAgICAgICAgICAgICBjbGFzcz1cInRleHQtc20gYmctZ3JheS0xMDAgcHgtMS41IHB5LTAuNSByb3VuZGVkXCI+c3RyaW5nPC9jb2RlPjwvdGQ+XG4gICAgICAgICAgICAgIDx0ZCBjbGFzcz1cInB5LTIgcHgtNCBib3JkZXItYiBib3JkZXItZ3JheS0yMDBcIj4tPC90ZD5cbiAgICAgICAgICAgICAgPHRkIGNsYXNzPVwicHktMiBweC00IGJvcmRlci1iIGJvcmRlci1ncmF5LTIwMFwiPsSQxrDhu51uZyBk4bqrbiBj4bunYSBow6xuaCDhuqNuaCBhdmF0YXI8L3RkPlxuICAgICAgICAgICAgPC90cj5cbiAgICAgICAgICAgIDx0cj5cbiAgICAgICAgICAgICAgPHRkIGNsYXNzPVwicHktMiBweC00IGJvcmRlci1iIGJvcmRlci1ncmF5LTIwMFwiPjxjb2RlXG4gICAgICAgICAgICAgICAgICBjbGFzcz1cInRleHQtc20gYmctZ3JheS0xMDAgcHgtMS41IHB5LTAuNSByb3VuZGVkXCI+bGlua0F2YXRhckVycm9yPC9jb2RlPjwvdGQ+XG4gICAgICAgICAgICAgIDx0ZCBjbGFzcz1cInB5LTIgcHgtNCBib3JkZXItYiBib3JkZXItZ3JheS0yMDBcIj48Y29kZVxuICAgICAgICAgICAgICAgICAgY2xhc3M9XCJ0ZXh0LXNtIGJnLWdyYXktMTAwIHB4LTEuNSBweS0wLjUgcm91bmRlZFwiPnN0cmluZzwvY29kZT48L3RkPlxuICAgICAgICAgICAgICA8dGQgY2xhc3M9XCJweS0yIHB4LTQgYm9yZGVyLWIgYm9yZGVyLWdyYXktMjAwXCI+LTwvdGQ+XG4gICAgICAgICAgICAgIDx0ZCBjbGFzcz1cInB5LTIgcHgtNCBib3JkZXItYiBib3JkZXItZ3JheS0yMDBcIj7EkMaw4budbmcgZOG6q24gY+G7p2EgaMOsbmgg4bqjbmggdGhheSB0aOG6vyBraGkgYXZhdGFyIGNow61uaCBi4buLIGzhu5dpXG4gICAgICAgICAgICAgIDwvdGQ+XG4gICAgICAgICAgICA8L3RyPlxuICAgICAgICAgICAgPHRyPlxuICAgICAgICAgICAgICA8dGQgY2xhc3M9XCJweS0yIHB4LTQgYm9yZGVyLWIgYm9yZGVyLWdyYXktMjAwXCI+PGNvZGVcbiAgICAgICAgICAgICAgICAgIGNsYXNzPVwidGV4dC1zbSBiZy1ncmF5LTEwMCBweC0xLjUgcHktMC41IHJvdW5kZWRcIj50ZXh0QXZhdGFyPC9jb2RlPjwvdGQ+XG4gICAgICAgICAgICAgIDx0ZCBjbGFzcz1cInB5LTIgcHgtNCBib3JkZXItYiBib3JkZXItZ3JheS0yMDBcIj48Y29kZVxuICAgICAgICAgICAgICAgICAgY2xhc3M9XCJ0ZXh0LXNtIGJnLWdyYXktMTAwIHB4LTEuNSBweS0wLjUgcm91bmRlZFwiPnN0cmluZzwvY29kZT48L3RkPlxuICAgICAgICAgICAgICA8dGQgY2xhc3M9XCJweS0yIHB4LTQgYm9yZGVyLWIgYm9yZGVyLWdyYXktMjAwXCI+LTwvdGQ+XG4gICAgICAgICAgICAgIDx0ZCBjbGFzcz1cInB5LTIgcHgtNCBib3JkZXItYiBib3JkZXItZ3JheS0yMDBcIj5WxINuIGLhuqNuIGhp4buDbiB0aOG7iyBraGkga2jDtG5nIGPDsyBow6xuaCDhuqNuaCAodGjGsOG7nW5nIGzDoCBjaOG7ryBjw6FpXG4gICAgICAgICAgICAgICAgxJHhuqd1IGPhu6dhIHTDqm4pPC90ZD5cbiAgICAgICAgICAgIDwvdHI+XG4gICAgICAgICAgICA8dHI+XG4gICAgICAgICAgICAgIDx0ZCBjbGFzcz1cInB5LTIgcHgtNCBib3JkZXItYiBib3JkZXItZ3JheS0yMDBcIj48Y29kZVxuICAgICAgICAgICAgICAgICAgY2xhc3M9XCJ0ZXh0LXNtIGJnLWdyYXktMTAwIHB4LTEuNSBweS0wLjUgcm91bmRlZFwiPmlkR2VuQ29sb3I8L2NvZGU+PC90ZD5cbiAgICAgICAgICAgICAgPHRkIGNsYXNzPVwicHktMiBweC00IGJvcmRlci1iIGJvcmRlci1ncmF5LTIwMFwiPjxjb2RlXG4gICAgICAgICAgICAgICAgICBjbGFzcz1cInRleHQtc20gYmctZ3JheS0xMDAgcHgtMS41IHB5LTAuNSByb3VuZGVkXCI+c3RyaW5nPC9jb2RlPjwvdGQ+XG4gICAgICAgICAgICAgIDx0ZCBjbGFzcz1cInB5LTIgcHgtNCBib3JkZXItYiBib3JkZXItZ3JheS0yMDBcIj4tPC90ZD5cbiAgICAgICAgICAgICAgPHRkIGNsYXNzPVwicHktMiBweC00IGJvcmRlci1iIGJvcmRlci1ncmF5LTIwMFwiPklEIGTDuW5nIMSR4buDIHThuqFvIG3DoHUgbuG7gW4gdOG7sSDEkeG7mW5nIGtoaSBz4butIGThu6VuZyB2xINuIGLhuqNuPC90ZD5cbiAgICAgICAgICAgIDwvdHI+XG4gICAgICAgICAgICA8dHI+XG4gICAgICAgICAgICAgIDx0ZCBjbGFzcz1cInB5LTIgcHgtNCBib3JkZXItYiBib3JkZXItZ3JheS0yMDBcIj48Y29kZVxuICAgICAgICAgICAgICAgICAgY2xhc3M9XCJ0ZXh0LXNtIGJnLWdyYXktMTAwIHB4LTEuNSBweS0wLjUgcm91bmRlZFwiPnNpemU8L2NvZGU+PC90ZD5cbiAgICAgICAgICAgICAgPHRkIGNsYXNzPVwicHktMiBweC00IGJvcmRlci1iIGJvcmRlci1ncmF5LTIwMFwiPjxjb2RlIGNsYXNzPVwidGV4dC1zbSBiZy1ncmF5LTEwMCBweC0xLjUgcHktMC41IHJvdW5kZWRcIj4xNlxuICAgICAgICAgICAgICAgICAgfCAyNCB8IDMyIHwgNDAgfCA0OCB8IDY0PC9jb2RlPjwvdGQ+XG4gICAgICAgICAgICAgIDx0ZCBjbGFzcz1cInB5LTIgcHgtNCBib3JkZXItYiBib3JkZXItZ3JheS0yMDBcIj4zMjwvdGQ+XG4gICAgICAgICAgICAgIDx0ZCBjbGFzcz1cInB5LTIgcHgtNCBib3JkZXItYiBib3JkZXItZ3JheS0yMDBcIj5Lw61jaCB0aMaw4bubYyBj4bunYSBhdmF0YXIgKHTDrW5oIGLhurFuZyBwaXhlbCk8L3RkPlxuICAgICAgICAgICAgPC90cj5cbiAgICAgICAgICAgIDx0cj5cbiAgICAgICAgICAgICAgPHRkIGNsYXNzPVwicHktMiBweC00IGJvcmRlci1iIGJvcmRlci1ncmF5LTIwMFwiPjxjb2RlXG4gICAgICAgICAgICAgICAgICBjbGFzcz1cInRleHQtc20gYmctZ3JheS0xMDAgcHgtMS41IHB5LTAuNSByb3VuZGVkXCI+dHlwZVNoYXBlPC9jb2RlPjwvdGQ+XG4gICAgICAgICAgICAgIDx0ZCBjbGFzcz1cInB5LTIgcHgtNCBib3JkZXItYiBib3JkZXItZ3JheS0yMDBcIj48Y29kZVxuICAgICAgICAgICAgICAgICAgY2xhc3M9XCJ0ZXh0LXNtIGJnLWdyYXktMTAwIHB4LTEuNSBweS0wLjUgcm91bmRlZFwiPidjaXJjbGUnIHwgJ3JlY3RhbmdsZSc8L2NvZGU+PC90ZD5cbiAgICAgICAgICAgICAgPHRkIGNsYXNzPVwicHktMiBweC00IGJvcmRlci1iIGJvcmRlci1ncmF5LTIwMFwiPidjaXJjbGUnPC90ZD5cbiAgICAgICAgICAgICAgPHRkIGNsYXNzPVwicHktMiBweC00IGJvcmRlci1iIGJvcmRlci1ncmF5LTIwMFwiPkjDrG5oIGThuqFuZyBj4bunYSBhdmF0YXIgKHRyw7JuIGhv4bq3YyB2dcO0bmcpPC90ZD5cbiAgICAgICAgICAgIDwvdHI+XG4gICAgICAgICAgICA8dHI+XG4gICAgICAgICAgICAgIDx0ZCBjbGFzcz1cInB5LTIgcHgtNCBib3JkZXItYiBib3JkZXItZ3JheS0yMDBcIj48Y29kZVxuICAgICAgICAgICAgICAgICAgY2xhc3M9XCJ0ZXh0LXNtIGJnLWdyYXktMTAwIHB4LTEuNSBweS0wLjUgcm91bmRlZFwiPmNsYXNzSW5jbHVkZTwvY29kZT48L3RkPlxuICAgICAgICAgICAgICA8dGQgY2xhc3M9XCJweS0yIHB4LTQgYm9yZGVyLWIgYm9yZGVyLWdyYXktMjAwXCI+PGNvZGVcbiAgICAgICAgICAgICAgICAgIGNsYXNzPVwidGV4dC1zbSBiZy1ncmF5LTEwMCBweC0xLjUgcHktMC41IHJvdW5kZWRcIj5zdHJpbmc8L2NvZGU+PC90ZD5cbiAgICAgICAgICAgICAgPHRkIGNsYXNzPVwicHktMiBweC00IGJvcmRlci1iIGJvcmRlci1ncmF5LTIwMFwiPidtci1bOHB4XSc8L3RkPlxuICAgICAgICAgICAgICA8dGQgY2xhc3M9XCJweS0yIHB4LTQgYm9yZGVyLWIgYm9yZGVyLWdyYXktMjAwXCI+Q1NTIGNsYXNzIGLhu5Ugc3VuZyBjaG8gY29udGFpbmVyIGNow61uaDwvdGQ+XG4gICAgICAgICAgICA8L3RyPlxuICAgICAgICAgICAgPHRyPlxuICAgICAgICAgICAgICA8dGQgY2xhc3M9XCJweS0yIHB4LTQgYm9yZGVyLWIgYm9yZGVyLWdyYXktMjAwXCI+PGNvZGVcbiAgICAgICAgICAgICAgICAgIGNsYXNzPVwidGV4dC1zbSBiZy1ncmF5LTEwMCBweC0xLjUgcHktMC41IHJvdW5kZWRcIj5jbGFzc0ltYWdlSW5jbHVkZTwvY29kZT48L3RkPlxuICAgICAgICAgICAgICA8dGQgY2xhc3M9XCJweS0yIHB4LTQgYm9yZGVyLWIgYm9yZGVyLWdyYXktMjAwXCI+PGNvZGVcbiAgICAgICAgICAgICAgICAgIGNsYXNzPVwidGV4dC1zbSBiZy1ncmF5LTEwMCBweC0xLjUgcHktMC41IHJvdW5kZWRcIj5zdHJpbmc8L2NvZGU+PC90ZD5cbiAgICAgICAgICAgICAgPHRkIGNsYXNzPVwicHktMiBweC00IGJvcmRlci1iIGJvcmRlci1ncmF5LTIwMFwiPicnPC90ZD5cbiAgICAgICAgICAgICAgPHRkIGNsYXNzPVwicHktMiBweC00IGJvcmRlci1iIGJvcmRlci1ncmF5LTIwMFwiPkNTUyBjbGFzcyBi4buVIHN1bmcgY2hvIHRo4bq7IGltZzwvdGQ+XG4gICAgICAgICAgICA8L3RyPlxuICAgICAgICAgICAgPHRyPlxuICAgICAgICAgICAgICA8dGQgY2xhc3M9XCJweS0yIHB4LTQgYm9yZGVyLWIgYm9yZGVyLWdyYXktMjAwXCI+PGNvZGVcbiAgICAgICAgICAgICAgICAgIGNsYXNzPVwidGV4dC1zbSBiZy1ncmF5LTEwMCBweC0xLjUgcHktMC41IHJvdW5kZWRcIj5nZXRMYXN0VGV4dEFmdGVyU3BhY2U8L2NvZGU+PC90ZD5cbiAgICAgICAgICAgICAgPHRkIGNsYXNzPVwicHktMiBweC00IGJvcmRlci1iIGJvcmRlci1ncmF5LTIwMFwiPjxjb2RlXG4gICAgICAgICAgICAgICAgICBjbGFzcz1cInRleHQtc20gYmctZ3JheS0xMDAgcHgtMS41IHB5LTAuNSByb3VuZGVkXCI+Ym9vbGVhbjwvY29kZT48L3RkPlxuICAgICAgICAgICAgICA8dGQgY2xhc3M9XCJweS0yIHB4LTQgYm9yZGVyLWIgYm9yZGVyLWdyYXktMjAwXCI+ZmFsc2U8L3RkPlxuICAgICAgICAgICAgICA8dGQgY2xhc3M9XCJweS0yIHB4LTQgYm9yZGVyLWIgYm9yZGVyLWdyYXktMjAwXCI+TuG6v3UgdHJ1ZSwgY2jhu4kgbOG6pXkgY2jhu68gY8OhaSDEkeG6p3UgdGnDqm4gY+G7p2EgdOG7qyBjdeG7kWkgY8O5bmcgdHJvbmdcbiAgICAgICAgICAgICAgICB0ZXh0QXZhdGFyPC90ZD5cbiAgICAgICAgICAgIDwvdHI+XG4gICAgICAgICAgPC90Ym9keT5cbiAgICAgICAgPC90YWJsZT5cbiAgICAgIDwvZGl2PlxuXG4gICAgICA8aDMgY2xhc3M9XCJ0ZXh0LXhsIGZvbnQtc2VtaWJvbGQgdGV4dC1ncmF5LTcwMCBtYi00XCI+T3V0cHV0czwvaDM+XG4gICAgICA8ZGl2IGNsYXNzPVwib3ZlcmZsb3cteC1hdXRvIG1iLThcIj5cbiAgICAgICAgPHRhYmxlIGNsYXNzPVwibWluLXctZnVsbCBiZy13aGl0ZSBib3JkZXIgYm9yZGVyLWdyYXktMjAwXCI+XG4gICAgICAgICAgPHRoZWFkPlxuICAgICAgICAgICAgPHRyPlxuICAgICAgICAgICAgICA8dGggY2xhc3M9XCJweS0zIHB4LTQgYm9yZGVyLWIgYm9yZGVyLWdyYXktMjAwIGJnLWdyYXktMTAwIHRleHQtbGVmdCBmb250LXNlbWlib2xkIHRleHQtZ3JheS03MDBcIj5Uw6puPC90aD5cbiAgICAgICAgICAgICAgPHRoIGNsYXNzPVwicHktMyBweC00IGJvcmRlci1iIGJvcmRlci1ncmF5LTIwMCBiZy1ncmF5LTEwMCB0ZXh0LWxlZnQgZm9udC1zZW1pYm9sZCB0ZXh0LWdyYXktNzAwXCI+S2nhu4N1IGThu69cbiAgICAgICAgICAgICAgICBsaeG7h3U8L3RoPlxuICAgICAgICAgICAgICA8dGggY2xhc3M9XCJweS0zIHB4LTQgYm9yZGVyLWIgYm9yZGVyLWdyYXktMjAwIGJnLWdyYXktMTAwIHRleHQtbGVmdCBmb250LXNlbWlib2xkIHRleHQtZ3JheS03MDBcIj5Nw7QgdOG6o1xuICAgICAgICAgICAgICA8L3RoPlxuICAgICAgICAgICAgPC90cj5cbiAgICAgICAgICA8L3RoZWFkPlxuICAgICAgICAgIDx0Ym9keT5cbiAgICAgICAgICAgIDx0cj5cbiAgICAgICAgICAgICAgPHRkIGNsYXNzPVwicHktMiBweC00IGJvcmRlci1iIGJvcmRlci1ncmF5LTIwMFwiPjxjb2RlXG4gICAgICAgICAgICAgICAgICBjbGFzcz1cInRleHQtc20gYmctZ3JheS0xMDAgcHgtMS41IHB5LTAuNSByb3VuZGVkXCI+b3V0QXZhdGFyRXJyb3I8L2NvZGU+PC90ZD5cbiAgICAgICAgICAgICAgPHRkIGNsYXNzPVwicHktMiBweC00IGJvcmRlci1iIGJvcmRlci1ncmF5LTIwMFwiPjxjb2RlXG4gICAgICAgICAgICAgICAgICBjbGFzcz1cInRleHQtc20gYmctZ3JheS0xMDAgcHgtMS41IHB5LTAuNSByb3VuZGVkXCI+dm9pZDwvY29kZT48L3RkPlxuICAgICAgICAgICAgICA8dGQgY2xhc3M9XCJweS0yIHB4LTQgYm9yZGVyLWIgYm9yZGVyLWdyYXktMjAwXCI+U+G7sSBraeG7h24gxJHGsOG7o2Mga8OtY2ggaG/huqF0IGtoaSBsaW5rQXZhdGFyIGLhu4sgbOG7l2kgdsOgIGtow7RuZyBjw7NcbiAgICAgICAgICAgICAgICBsaW5rQXZhdGFyRXJyb3I8L3RkPlxuICAgICAgICAgICAgPC90cj5cbiAgICAgICAgICA8L3Rib2R5PlxuICAgICAgICA8L3RhYmxlPlxuICAgICAgPC9kaXY+XG5cbiAgICAgIDxoMyBjbGFzcz1cInRleHQteGwgZm9udC1zZW1pYm9sZCB0ZXh0LWdyYXktNzAwIG1iLTRcIj5JbnRlcmZhY2VzPC9oMz5cbiAgICAgIDxkaXYgY2xhc3M9XCJiZy1ncmF5LTUwIHAtNiByb3VuZGVkLWxnXCI+XG4gICAgICAgIDxoNCBjbGFzcz1cInRleHQtbGcgZm9udC1zZW1pYm9sZCB0ZXh0LWdyYXktNzAwIG1iLTNcIj5JQXZhdGFyQ29uZmlnPC9oND5cbiAgICAgICAgPHByZSBjbGFzcz1cImJnLWdyYXktMTAwIHAtNCByb3VuZGVkLWxnIG92ZXJmbG93LXgtYXV0byB0ZXh0LXNtIG1iLTNcIj48Y29kZT5leHBvcnQgaW50ZXJmYWNlIElBdmF0YXJDb25maWcgJiMxMjM7XG4gIGNsYXNzSW1hZ2VJbmNsdWRlPzogc3RyaW5nO1xuICBjbGFzc0luY2x1ZGU/OiBzdHJpbmc7XG4gIHNpemU/OiBUWVBFX1NJWkVfQVZBVEFSX0NPTkZJRztcbiAgbGlua0F2YXRhcj86IHN0cmluZztcbiAgbGlua0F2YXRhckVycm9yPzogc3RyaW5nO1xuICBpZEdlbkNvbG9yPzogc3RyaW5nO1xuICB0ZXh0QXZhdGFyPzogc3RyaW5nO1xuICB0eXBlU2hhcGU/OiBUWVBFX1NIQVBFX0FWQVRBUjtcbiAgZ2V0TGFzdFRleHRBZnRlclNwYWNlPzogYm9vbGVhbjtcbiAgJiMxMjU7XG5cbmV4cG9ydCB0eXBlIFRZUEVfU0laRV9BVkFUQVJfQ09ORklHID0gMTYgfCAyNCB8IDMyIHwgNDAgfCA0OCB8IDY0O1xuZXhwb3J0IHR5cGUgVFlQRV9TSEFQRV9BVkFUQVIgPSAnY2lyY2xlJyB8ICdyZWN0YW5nbGUnOzwvY29kZT48L3ByZT5cbiAgICAgICAgPHAgY2xhc3M9XCJ0ZXh0LWdyYXktNjAwXCI+SW50ZXJmYWNlIMSR4buLbmggbmdoxKlhIGPhuqV1IGjDrG5oIGPhu6dhIGF2YXRhciBjb21wb25lbnQuPC9wPlxuICAgICAgPC9kaXY+XG4gICAgPC9zZWN0aW9uPlxuICA8L21haW4+XG48L2Rpdj5cbiJdfQ==
|