ng-hub-ui-avatar 19.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +170 -0
- package/fesm2022/ng-hub-ui-avatar.mjs +891 -0
- package/fesm2022/ng-hub-ui-avatar.mjs.map +1 -0
- package/index.d.ts +5 -0
- package/lib/avatar-config.d.ts +18 -0
- package/lib/avatar-config.service.d.ts +12 -0
- package/lib/avatar-config.token.d.ts +6 -0
- package/lib/avatar.component.d.ts +114 -0
- package/lib/avatar.module.d.ts +11 -0
- package/lib/avatar.service.d.ts +43 -0
- package/lib/sources/async-source.d.ts +13 -0
- package/lib/sources/avatar-source.enum.d.ts +13 -0
- package/lib/sources/custom-no-cache.d.ts +13 -0
- package/lib/sources/custom.d.ts +13 -0
- package/lib/sources/facebook.d.ts +13 -0
- package/lib/sources/github.d.ts +17 -0
- package/lib/sources/google.d.ts +22 -0
- package/lib/sources/gravatar.d.ts +13 -0
- package/lib/sources/initials.d.ts +20 -0
- package/lib/sources/instagram.d.ts +21 -0
- package/lib/sources/skype.d.ts +12 -0
- package/lib/sources/source.creator.d.ts +5 -0
- package/lib/sources/source.d.ts +21 -0
- package/lib/sources/source.factory.d.ts +16 -0
- package/lib/sources/twitter.d.ts +14 -0
- package/lib/sources/value.d.ts +12 -0
- package/lib/sources/vkontakte.d.ts +19 -0
- package/ng-hub-ui-avatar-19.0.0.tgz +0 -0
- package/package.json +64 -0
- package/public_api.d.ts +5 -0
|
@@ -0,0 +1,891 @@
|
|
|
1
|
+
import * as i0 from '@angular/core';
|
|
2
|
+
import { InjectionToken, Injectable, Optional, Inject, EventEmitter, SecurityContext, Component, Input, Output, NgModule } from '@angular/core';
|
|
3
|
+
import { NgStyle, NgIf, CommonModule } from '@angular/common';
|
|
4
|
+
import { takeWhile, map } from 'rxjs/operators';
|
|
5
|
+
import * as i1 from '@angular/common/http';
|
|
6
|
+
import * as i3 from '@angular/platform-browser';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Contract of all async sources.
|
|
10
|
+
* Every async source must implement the processResponse method that extracts the avatar url from the data
|
|
11
|
+
*/
|
|
12
|
+
class AsyncSource {
|
|
13
|
+
constructor(sourceId) {
|
|
14
|
+
this.sourceId = sourceId;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
var AvatarSource;
|
|
19
|
+
(function (AvatarSource) {
|
|
20
|
+
AvatarSource["FACEBOOK"] = "facebook";
|
|
21
|
+
AvatarSource["GOOGLE"] = "google";
|
|
22
|
+
AvatarSource["TWITTER"] = "twitter";
|
|
23
|
+
AvatarSource["INSTAGRAM"] = "instagram";
|
|
24
|
+
AvatarSource["VKONTAKTE"] = "vkontakte";
|
|
25
|
+
AvatarSource["SKYPE"] = "skype";
|
|
26
|
+
AvatarSource["GRAVATAR"] = "gravatar";
|
|
27
|
+
AvatarSource["GITHUB"] = "github";
|
|
28
|
+
AvatarSource["CUSTOM"] = "custom";
|
|
29
|
+
AvatarSource["INITIALS"] = "initials";
|
|
30
|
+
AvatarSource["VALUE"] = "value";
|
|
31
|
+
})(AvatarSource || (AvatarSource = {}));
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Facebook source implementation.
|
|
35
|
+
* Fetch avatar source based on facebook identifier
|
|
36
|
+
* and image size
|
|
37
|
+
*/
|
|
38
|
+
class Facebook {
|
|
39
|
+
constructor(sourceId) {
|
|
40
|
+
this.sourceId = sourceId;
|
|
41
|
+
this.sourceType = AvatarSource.FACEBOOK;
|
|
42
|
+
}
|
|
43
|
+
getAvatar(size) {
|
|
44
|
+
return ('https://graph.facebook.com/' +
|
|
45
|
+
`${this.sourceId}/picture?width=${size}&height=${size}`);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Twitter source implementation.
|
|
51
|
+
* Fetch avatar source based on google identifier
|
|
52
|
+
* and image size
|
|
53
|
+
*/
|
|
54
|
+
class Twitter {
|
|
55
|
+
constructor(sourceId) {
|
|
56
|
+
this.sourceId = sourceId;
|
|
57
|
+
this.sourceType = AvatarSource.TWITTER;
|
|
58
|
+
}
|
|
59
|
+
getAvatar(size) {
|
|
60
|
+
const twitterImgSize = this.getImageSize(size);
|
|
61
|
+
return `https://twitter.com/${this.sourceId}/profile_image?size=${twitterImgSize}`;
|
|
62
|
+
}
|
|
63
|
+
getImageSize(size) {
|
|
64
|
+
if (size <= 24) {
|
|
65
|
+
return 'mini';
|
|
66
|
+
}
|
|
67
|
+
if (size <= 48) {
|
|
68
|
+
return 'normal';
|
|
69
|
+
}
|
|
70
|
+
if (size <= 73) {
|
|
71
|
+
return 'bigger';
|
|
72
|
+
}
|
|
73
|
+
return 'original';
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Google source implementation.
|
|
79
|
+
* Fetch avatar source based on google identifier
|
|
80
|
+
* and image size
|
|
81
|
+
*/
|
|
82
|
+
class Google extends AsyncSource {
|
|
83
|
+
constructor(sourceId) {
|
|
84
|
+
super(sourceId);
|
|
85
|
+
this.sourceType = AvatarSource.GOOGLE;
|
|
86
|
+
}
|
|
87
|
+
getAvatar() {
|
|
88
|
+
return `https://picasaweb.google.com/data/entry/api/user/${this.sourceId}?alt=json`;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Extract google avatar from json data
|
|
92
|
+
*/
|
|
93
|
+
processResponse(data, size) {
|
|
94
|
+
const avatarSrc = data.entry.gphoto$thumbnail.$t;
|
|
95
|
+
if (avatarSrc) {
|
|
96
|
+
return avatarSrc.replace('s64', 's' + size);
|
|
97
|
+
}
|
|
98
|
+
return null;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Instagram source implementation.
|
|
104
|
+
* Fetch avatar source based on instagram identifier
|
|
105
|
+
*/
|
|
106
|
+
class Instagram extends AsyncSource {
|
|
107
|
+
constructor(sourceId) {
|
|
108
|
+
super(sourceId);
|
|
109
|
+
this.sourceType = AvatarSource.INSTAGRAM;
|
|
110
|
+
}
|
|
111
|
+
getAvatar() {
|
|
112
|
+
return `https://www.instagram.com/${this.sourceId}/?__a=1`;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* extract instagram avatar from json data
|
|
116
|
+
*/
|
|
117
|
+
processResponse(data, size) {
|
|
118
|
+
return `${data.graphql.user.profile_pic_url_hd}&s=${size}`;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Custom source implementation.
|
|
124
|
+
* return custom image as an avatar
|
|
125
|
+
*
|
|
126
|
+
*/
|
|
127
|
+
class Custom {
|
|
128
|
+
constructor(sourceId) {
|
|
129
|
+
this.sourceId = sourceId;
|
|
130
|
+
this.sourceType = AvatarSource.CUSTOM;
|
|
131
|
+
}
|
|
132
|
+
getAvatar() {
|
|
133
|
+
return this.sourceId;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Initials source implementation.
|
|
139
|
+
* return the initials of the given value
|
|
140
|
+
*/
|
|
141
|
+
class Initials {
|
|
142
|
+
constructor(sourceId) {
|
|
143
|
+
this.sourceId = sourceId;
|
|
144
|
+
this.sourceType = AvatarSource.INITIALS;
|
|
145
|
+
}
|
|
146
|
+
getAvatar(size) {
|
|
147
|
+
return this.getInitials(this.sourceId, size);
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Returns the initial letters of a name in a string.
|
|
151
|
+
*/
|
|
152
|
+
getInitials(name, size) {
|
|
153
|
+
name = name.trim();
|
|
154
|
+
if (!name) {
|
|
155
|
+
return '';
|
|
156
|
+
}
|
|
157
|
+
const initials = name.split(' ');
|
|
158
|
+
if (size && size < initials.length) {
|
|
159
|
+
return this.constructInitials(initials.slice(0, size));
|
|
160
|
+
}
|
|
161
|
+
else {
|
|
162
|
+
return this.constructInitials(initials);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Iterates a person's name string to get the initials of each word in uppercase.
|
|
167
|
+
*/
|
|
168
|
+
constructInitials(elements) {
|
|
169
|
+
if (!elements || !elements.length) {
|
|
170
|
+
return '';
|
|
171
|
+
}
|
|
172
|
+
return elements
|
|
173
|
+
.filter(element => element && element.length > 0)
|
|
174
|
+
.map(element => element[0].toUpperCase())
|
|
175
|
+
.join('');
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
function isRetina() {
|
|
180
|
+
if (typeof window !== 'undefined' && window !== null) {
|
|
181
|
+
if (window.devicePixelRatio > 1.25) {
|
|
182
|
+
return true;
|
|
183
|
+
}
|
|
184
|
+
const mediaQuery = '(-webkit-min-device-pixel-ratio: 1.25), (min--moz-device-pixel-ratio: 1.25), (-o-min-device-pixel-ratio: 5/4), (min-resolution: 1.25dppx)';
|
|
185
|
+
if (window.matchMedia && window.matchMedia(mediaQuery).matches) {
|
|
186
|
+
return true;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
return false;
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Helper function to calculate MD5 hash using the Crypto API.
|
|
193
|
+
*/
|
|
194
|
+
function hashMD5(value) {
|
|
195
|
+
// Convert string to Uint8Array
|
|
196
|
+
const encoder = new TextEncoder();
|
|
197
|
+
const data = encoder.encode(value);
|
|
198
|
+
// Use SubtleCrypto for hashing
|
|
199
|
+
return crypto.subtle.digest('MD5', data).then((hash) => {
|
|
200
|
+
// Convert ArrayBuffer to hexadecimal string
|
|
201
|
+
return Array.from(new Uint8Array(hash))
|
|
202
|
+
.map((b) => b.toString(16).padStart(2, '0'))
|
|
203
|
+
.join('');
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Gravatar source implementation.
|
|
208
|
+
* Fetch avatar source based on gravatar email
|
|
209
|
+
*/
|
|
210
|
+
class Gravatar {
|
|
211
|
+
constructor(value) {
|
|
212
|
+
this.value = value;
|
|
213
|
+
this.sourceType = AvatarSource.GRAVATAR;
|
|
214
|
+
// Use regex to check if the value is already an MD5 hash, otherwise calculate it
|
|
215
|
+
if (value.match('^[a-f0-9]{32}$')) {
|
|
216
|
+
this.sourceId = value;
|
|
217
|
+
}
|
|
218
|
+
else {
|
|
219
|
+
hashMD5(value).then((hash) => {
|
|
220
|
+
this.sourceId = hash;
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
getAvatar(size) {
|
|
225
|
+
const avatarSize = isRetina() ? size * 2 : size;
|
|
226
|
+
return `https://secure.gravatar.com/avatar/${this.sourceId}?s=${avatarSize}&d=404`;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* Skype source implementation.
|
|
232
|
+
* Fetch avatar source based on skype identifier
|
|
233
|
+
*/
|
|
234
|
+
class Skype {
|
|
235
|
+
constructor(sourceId) {
|
|
236
|
+
this.sourceId = sourceId;
|
|
237
|
+
this.sourceType = AvatarSource.SKYPE;
|
|
238
|
+
}
|
|
239
|
+
getAvatar() {
|
|
240
|
+
return `https://api.skype.com/users/${this.sourceId}/profile/avatar`;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
/**
|
|
245
|
+
* Value source implementation.
|
|
246
|
+
* return the value as avatar
|
|
247
|
+
*/
|
|
248
|
+
class Value {
|
|
249
|
+
constructor(sourceId) {
|
|
250
|
+
this.sourceId = sourceId;
|
|
251
|
+
this.sourceType = AvatarSource.VALUE;
|
|
252
|
+
}
|
|
253
|
+
getAvatar() {
|
|
254
|
+
return this.sourceId;
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
/**
|
|
259
|
+
* Vkontakte source implementation.
|
|
260
|
+
* Fetch avatar source based on vkontakte identifier
|
|
261
|
+
* and image size
|
|
262
|
+
*/
|
|
263
|
+
const apiVersion = 5.8;
|
|
264
|
+
class Vkontakte extends AsyncSource {
|
|
265
|
+
constructor(sourceId) {
|
|
266
|
+
super(sourceId);
|
|
267
|
+
this.sourceType = AvatarSource.VKONTAKTE;
|
|
268
|
+
}
|
|
269
|
+
getAvatar(size) {
|
|
270
|
+
const imgSize = this.getImageSize(size);
|
|
271
|
+
return `https://api.vk.com/method/users.get?user_id=${this.sourceId}&v=${apiVersion}&fields=${imgSize}`;
|
|
272
|
+
}
|
|
273
|
+
/**
|
|
274
|
+
* extract vkontakte avatar from json data
|
|
275
|
+
*/
|
|
276
|
+
processResponse(data) {
|
|
277
|
+
// avatar key property is the size used to generate avatar url
|
|
278
|
+
// size property is always the last key in the response object
|
|
279
|
+
const sizeProperty = Object.keys(data['response'][0]).pop();
|
|
280
|
+
if (!sizeProperty) {
|
|
281
|
+
return null;
|
|
282
|
+
}
|
|
283
|
+
// return avatar src
|
|
284
|
+
return data['response'][0][sizeProperty] || null;
|
|
285
|
+
}
|
|
286
|
+
/**
|
|
287
|
+
* Returns image size related to vkontakte API
|
|
288
|
+
*/
|
|
289
|
+
getImageSize(size) {
|
|
290
|
+
if (size <= 50) {
|
|
291
|
+
return 'photo_50';
|
|
292
|
+
}
|
|
293
|
+
if (size <= 100) {
|
|
294
|
+
return 'photo_100';
|
|
295
|
+
}
|
|
296
|
+
if (size <= 200) {
|
|
297
|
+
return 'photo_200';
|
|
298
|
+
}
|
|
299
|
+
return 'photo_max';
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
/**
|
|
304
|
+
* GitHub source implementation.
|
|
305
|
+
* Fetch avatar source based on github identifier
|
|
306
|
+
*/
|
|
307
|
+
class Github extends AsyncSource {
|
|
308
|
+
constructor(sourceId) {
|
|
309
|
+
super(sourceId);
|
|
310
|
+
this.sourceType = AvatarSource.GITHUB;
|
|
311
|
+
}
|
|
312
|
+
getAvatar() {
|
|
313
|
+
return `https://api.github.com/users/${this.sourceId}`;
|
|
314
|
+
}
|
|
315
|
+
/**
|
|
316
|
+
* extract github avatar from json data
|
|
317
|
+
*/
|
|
318
|
+
processResponse(data, size) {
|
|
319
|
+
if (size) {
|
|
320
|
+
return `${data.avatar_url}&s=${size}`;
|
|
321
|
+
}
|
|
322
|
+
return data.avatar_url;
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
/**
|
|
327
|
+
* Token used to inject the AvatarConfig object
|
|
328
|
+
*/
|
|
329
|
+
const AVATAR_CONFIG = new InjectionToken('avatar.config');
|
|
330
|
+
|
|
331
|
+
class AvatarConfigService {
|
|
332
|
+
constructor(userConfig) {
|
|
333
|
+
this.userConfig = userConfig;
|
|
334
|
+
}
|
|
335
|
+
getAvatarSources(defaultSources) {
|
|
336
|
+
if (this.userConfig &&
|
|
337
|
+
this.userConfig.sourcePriorityOrder &&
|
|
338
|
+
this.userConfig.sourcePriorityOrder.length) {
|
|
339
|
+
const uniqueSources = [
|
|
340
|
+
...new Set(this.userConfig.sourcePriorityOrder)
|
|
341
|
+
];
|
|
342
|
+
const validSources = uniqueSources.filter((source) => defaultSources.includes(source));
|
|
343
|
+
return [
|
|
344
|
+
...validSources,
|
|
345
|
+
...defaultSources.filter((source) => !validSources.includes(source))
|
|
346
|
+
];
|
|
347
|
+
}
|
|
348
|
+
return defaultSources;
|
|
349
|
+
}
|
|
350
|
+
getAvatarColors(defaultColors) {
|
|
351
|
+
return ((this.userConfig &&
|
|
352
|
+
this.userConfig.colors &&
|
|
353
|
+
this.userConfig.colors.length &&
|
|
354
|
+
this.userConfig.colors) ||
|
|
355
|
+
defaultColors);
|
|
356
|
+
}
|
|
357
|
+
getDisableSrcCache(defaultDisableSrcCache) {
|
|
358
|
+
if (this.userConfig == null ||
|
|
359
|
+
this.userConfig.disableSrcCache == null) {
|
|
360
|
+
return defaultDisableSrcCache;
|
|
361
|
+
}
|
|
362
|
+
else {
|
|
363
|
+
return this.userConfig.disableSrcCache;
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.4", ngImport: i0, type: AvatarConfigService, deps: [{ token: AVATAR_CONFIG, optional: true }], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
367
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.0.4", ngImport: i0, type: AvatarConfigService, providedIn: 'root' }); }
|
|
368
|
+
}
|
|
369
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.4", ngImport: i0, type: AvatarConfigService, decorators: [{
|
|
370
|
+
type: Injectable,
|
|
371
|
+
args: [{ providedIn: 'root' }]
|
|
372
|
+
}], ctorParameters: () => [{ type: undefined, decorators: [{
|
|
373
|
+
type: Optional
|
|
374
|
+
}, {
|
|
375
|
+
type: Inject,
|
|
376
|
+
args: [AVATAR_CONFIG]
|
|
377
|
+
}] }] });
|
|
378
|
+
|
|
379
|
+
/**
|
|
380
|
+
* list of Supported avatar sources
|
|
381
|
+
*/
|
|
382
|
+
const defaultSources = [
|
|
383
|
+
AvatarSource.FACEBOOK,
|
|
384
|
+
AvatarSource.GOOGLE,
|
|
385
|
+
AvatarSource.TWITTER,
|
|
386
|
+
AvatarSource.INSTAGRAM,
|
|
387
|
+
AvatarSource.VKONTAKTE,
|
|
388
|
+
AvatarSource.SKYPE,
|
|
389
|
+
AvatarSource.GRAVATAR,
|
|
390
|
+
AvatarSource.GITHUB,
|
|
391
|
+
AvatarSource.CUSTOM,
|
|
392
|
+
AvatarSource.INITIALS,
|
|
393
|
+
AvatarSource.VALUE
|
|
394
|
+
];
|
|
395
|
+
/**
|
|
396
|
+
* list of default colors
|
|
397
|
+
*/
|
|
398
|
+
const defaultColors = [
|
|
399
|
+
'#1abc9c',
|
|
400
|
+
'#3498db',
|
|
401
|
+
'#f1c40f',
|
|
402
|
+
'#8e44ad',
|
|
403
|
+
'#e74c3c',
|
|
404
|
+
'#d35400',
|
|
405
|
+
'#2c3e50',
|
|
406
|
+
'#7f8c8d'
|
|
407
|
+
];
|
|
408
|
+
/**
|
|
409
|
+
* Default disable custom source cache settings
|
|
410
|
+
*/
|
|
411
|
+
const defaultDisableSrcCache = false;
|
|
412
|
+
/**
|
|
413
|
+
* Provides utilities methods related to Avatar component
|
|
414
|
+
*/
|
|
415
|
+
class AvatarService {
|
|
416
|
+
constructor(http, avatarConfigService) {
|
|
417
|
+
this.http = http;
|
|
418
|
+
this.avatarConfigService = avatarConfigService;
|
|
419
|
+
this.avatarSources = defaultSources;
|
|
420
|
+
this.avatarColors = defaultColors;
|
|
421
|
+
this.failedSources = new Map();
|
|
422
|
+
this.overrideAvatarSources();
|
|
423
|
+
this.overrideAvatarColors();
|
|
424
|
+
}
|
|
425
|
+
fetchAvatar(avatarUrl) {
|
|
426
|
+
return this.http.get(avatarUrl);
|
|
427
|
+
}
|
|
428
|
+
getRandomColor(avatarText) {
|
|
429
|
+
if (!avatarText) {
|
|
430
|
+
return 'transparent';
|
|
431
|
+
}
|
|
432
|
+
const asciiCodeSum = this.calculateAsciiCode(avatarText);
|
|
433
|
+
return this.avatarColors[asciiCodeSum % this.avatarColors.length];
|
|
434
|
+
}
|
|
435
|
+
compareSources(sourceType1, sourceType2) {
|
|
436
|
+
return (this.getSourcePriority(sourceType1) - this.getSourcePriority(sourceType2));
|
|
437
|
+
}
|
|
438
|
+
isSource(source) {
|
|
439
|
+
return this.avatarSources.includes(source);
|
|
440
|
+
}
|
|
441
|
+
isTextAvatar(sourceType) {
|
|
442
|
+
return [AvatarSource.INITIALS, AvatarSource.VALUE].includes(sourceType);
|
|
443
|
+
}
|
|
444
|
+
buildSourceKey(source) {
|
|
445
|
+
return source.sourceType + '-' + source.sourceId;
|
|
446
|
+
}
|
|
447
|
+
sourceHasFailedBefore(source) {
|
|
448
|
+
return this.failedSources.has(this.buildSourceKey(source));
|
|
449
|
+
}
|
|
450
|
+
markSourceAsFailed(source) {
|
|
451
|
+
this.failedSources.set(this.buildSourceKey(source), source);
|
|
452
|
+
}
|
|
453
|
+
overrideAvatarSources() {
|
|
454
|
+
this.avatarSources = this.avatarConfigService.getAvatarSources(defaultSources);
|
|
455
|
+
}
|
|
456
|
+
overrideAvatarColors() {
|
|
457
|
+
this.avatarColors = this.avatarConfigService.getAvatarColors(defaultColors);
|
|
458
|
+
}
|
|
459
|
+
calculateAsciiCode(value) {
|
|
460
|
+
return value
|
|
461
|
+
.split('')
|
|
462
|
+
.map(letter => letter.charCodeAt(0))
|
|
463
|
+
.reduce((previous, current) => previous + current);
|
|
464
|
+
}
|
|
465
|
+
getSourcePriority(sourceType) {
|
|
466
|
+
return this.avatarSources.indexOf(sourceType);
|
|
467
|
+
}
|
|
468
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.4", ngImport: i0, type: AvatarService, deps: [{ token: i1.HttpClient }, { token: AvatarConfigService }], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
469
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.0.4", ngImport: i0, type: AvatarService, providedIn: 'root' }); }
|
|
470
|
+
}
|
|
471
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.4", ngImport: i0, type: AvatarService, decorators: [{
|
|
472
|
+
type: Injectable,
|
|
473
|
+
args: [{ providedIn: 'root' }]
|
|
474
|
+
}], ctorParameters: () => [{ type: i1.HttpClient }, { type: AvatarConfigService }] });
|
|
475
|
+
|
|
476
|
+
/**
|
|
477
|
+
* Custom source implementation (with no cache).
|
|
478
|
+
* return custom image as an avatar
|
|
479
|
+
*
|
|
480
|
+
*/
|
|
481
|
+
class CustomNoCache {
|
|
482
|
+
constructor(sourceId) {
|
|
483
|
+
this.sourceId = sourceId;
|
|
484
|
+
this.sourceType = AvatarSource.CUSTOM;
|
|
485
|
+
}
|
|
486
|
+
getAvatar() {
|
|
487
|
+
const urlSuffix = Math.random();
|
|
488
|
+
return `${this.sourceId}${this.sourceId.indexOf('?') > -1 ? '&' : '?'}_=${urlSuffix}`;
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
/**
|
|
493
|
+
* Factory class that implements factory method pattern.
|
|
494
|
+
* Used to create Source implementation class based
|
|
495
|
+
* on the source Type
|
|
496
|
+
*/
|
|
497
|
+
class SourceFactory {
|
|
498
|
+
constructor(avatarConfigService) {
|
|
499
|
+
this.sources = {};
|
|
500
|
+
const disableSrcCache = avatarConfigService.getDisableSrcCache(defaultDisableSrcCache);
|
|
501
|
+
this.sources[AvatarSource.FACEBOOK] = Facebook;
|
|
502
|
+
this.sources[AvatarSource.TWITTER] = Twitter;
|
|
503
|
+
this.sources[AvatarSource.GOOGLE] = Google;
|
|
504
|
+
this.sources[AvatarSource.INSTAGRAM] = Instagram;
|
|
505
|
+
this.sources[AvatarSource.SKYPE] = Skype;
|
|
506
|
+
this.sources[AvatarSource.GRAVATAR] = Gravatar;
|
|
507
|
+
this.sources[AvatarSource.CUSTOM] = disableSrcCache ? CustomNoCache : Custom;
|
|
508
|
+
this.sources[AvatarSource.INITIALS] = Initials;
|
|
509
|
+
this.sources[AvatarSource.VALUE] = Value;
|
|
510
|
+
this.sources[AvatarSource.VKONTAKTE] = Vkontakte;
|
|
511
|
+
this.sources[AvatarSource.GITHUB] = Github;
|
|
512
|
+
}
|
|
513
|
+
newInstance(sourceType, sourceValue) {
|
|
514
|
+
return new this.sources[sourceType](sourceValue);
|
|
515
|
+
}
|
|
516
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.4", ngImport: i0, type: SourceFactory, deps: [{ token: AvatarConfigService }], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
517
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.0.4", ngImport: i0, type: SourceFactory, providedIn: 'root' }); }
|
|
518
|
+
}
|
|
519
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.4", ngImport: i0, type: SourceFactory, decorators: [{
|
|
520
|
+
type: Injectable,
|
|
521
|
+
args: [{ providedIn: 'root' }]
|
|
522
|
+
}], ctorParameters: () => [{ type: AvatarConfigService }] });
|
|
523
|
+
|
|
524
|
+
/**
|
|
525
|
+
* Universal avatar component that
|
|
526
|
+
* generates avatar from different sources
|
|
527
|
+
*
|
|
528
|
+
* export
|
|
529
|
+
* class AvatarComponent
|
|
530
|
+
* implements {OnChanges}
|
|
531
|
+
*/
|
|
532
|
+
class AvatarComponent {
|
|
533
|
+
constructor(sourceFactory, avatarService, sanitizer) {
|
|
534
|
+
this.sourceFactory = sourceFactory;
|
|
535
|
+
this.avatarService = avatarService;
|
|
536
|
+
this.sanitizer = sanitizer;
|
|
537
|
+
this.round = true;
|
|
538
|
+
this.size = 50;
|
|
539
|
+
this.textSizeRatio = 3;
|
|
540
|
+
this.fgColor = '#FFF';
|
|
541
|
+
this.style = {};
|
|
542
|
+
this.cornerRadius = 0;
|
|
543
|
+
this.initialsSize = 0;
|
|
544
|
+
this.clickOnAvatar = new EventEmitter();
|
|
545
|
+
this.isAlive = true;
|
|
546
|
+
this.avatarSrc = null;
|
|
547
|
+
this.avatarAlt = null;
|
|
548
|
+
this.avatarText = null;
|
|
549
|
+
this.avatarStyle = {};
|
|
550
|
+
this.hostStyle = {};
|
|
551
|
+
this.currentIndex = -1;
|
|
552
|
+
this.sources = [];
|
|
553
|
+
}
|
|
554
|
+
onAvatarClicked() {
|
|
555
|
+
this.clickOnAvatar.emit(this.sources[this.currentIndex]);
|
|
556
|
+
}
|
|
557
|
+
/**
|
|
558
|
+
* Detect inputs change
|
|
559
|
+
*
|
|
560
|
+
* param {{ [propKey: string]: SimpleChange }} changes
|
|
561
|
+
*
|
|
562
|
+
* memberof AvatarComponent
|
|
563
|
+
*/
|
|
564
|
+
ngOnChanges(changes) {
|
|
565
|
+
for (const propName in changes) {
|
|
566
|
+
if (this.avatarService.isSource(propName)) {
|
|
567
|
+
const sourceType = AvatarSource[propName.toUpperCase()];
|
|
568
|
+
const currentValue = changes[propName].currentValue;
|
|
569
|
+
if (currentValue && typeof currentValue === 'string') {
|
|
570
|
+
this.addSource(sourceType, currentValue);
|
|
571
|
+
}
|
|
572
|
+
else {
|
|
573
|
+
const sanitized = this.sanitizer.sanitize(SecurityContext.URL, currentValue);
|
|
574
|
+
if (sanitized) {
|
|
575
|
+
this.addSource(sourceType, sanitized);
|
|
576
|
+
}
|
|
577
|
+
else {
|
|
578
|
+
this.removeSource(sourceType);
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
// reinitialize the avatar component when a source property value has changed
|
|
584
|
+
// the fallback system must be re-invoked with the new values.
|
|
585
|
+
this.initializeAvatar();
|
|
586
|
+
}
|
|
587
|
+
/**
|
|
588
|
+
* Fetch avatar source
|
|
589
|
+
*
|
|
590
|
+
* memberOf AvatarComponent
|
|
591
|
+
*/
|
|
592
|
+
fetchAvatarSource() {
|
|
593
|
+
const previousSource = this.sources[this.currentIndex];
|
|
594
|
+
if (previousSource) {
|
|
595
|
+
this.avatarService.markSourceAsFailed(previousSource);
|
|
596
|
+
}
|
|
597
|
+
const source = this.findNextSource();
|
|
598
|
+
if (!source) {
|
|
599
|
+
return;
|
|
600
|
+
}
|
|
601
|
+
if (this.avatarService.isTextAvatar(source.sourceType)) {
|
|
602
|
+
this.buildTextAvatar(source);
|
|
603
|
+
this.avatarSrc = null;
|
|
604
|
+
}
|
|
605
|
+
else {
|
|
606
|
+
this.buildImageAvatar(source);
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
findNextSource() {
|
|
610
|
+
while (++this.currentIndex < this.sources.length) {
|
|
611
|
+
const source = this.sources[this.currentIndex];
|
|
612
|
+
if (source && !this.avatarService.sourceHasFailedBefore(source)) {
|
|
613
|
+
return source;
|
|
614
|
+
}
|
|
615
|
+
}
|
|
616
|
+
return null;
|
|
617
|
+
}
|
|
618
|
+
ngOnDestroy() {
|
|
619
|
+
this.isAlive = false;
|
|
620
|
+
}
|
|
621
|
+
/**
|
|
622
|
+
* Initialize the avatar component and its fallback system
|
|
623
|
+
*/
|
|
624
|
+
initializeAvatar() {
|
|
625
|
+
this.currentIndex = -1;
|
|
626
|
+
if (this.sources.length > 0) {
|
|
627
|
+
this.sortAvatarSources();
|
|
628
|
+
this.fetchAvatarSource();
|
|
629
|
+
this.hostStyle = {
|
|
630
|
+
width: this.size + 'px',
|
|
631
|
+
height: this.size + 'px'
|
|
632
|
+
};
|
|
633
|
+
}
|
|
634
|
+
}
|
|
635
|
+
sortAvatarSources() {
|
|
636
|
+
this.sources.sort((source1, source2) => this.avatarService.compareSources(source1.sourceType, source2.sourceType));
|
|
637
|
+
}
|
|
638
|
+
buildTextAvatar(avatarSource) {
|
|
639
|
+
this.avatarText = avatarSource.getAvatar(+this.initialsSize);
|
|
640
|
+
this.avatarStyle = this.getInitialsStyle(avatarSource.sourceId);
|
|
641
|
+
}
|
|
642
|
+
buildImageAvatar(avatarSource) {
|
|
643
|
+
this.avatarStyle = this.getImageStyle();
|
|
644
|
+
if (avatarSource instanceof AsyncSource) {
|
|
645
|
+
this.fetchAndProcessAsyncAvatar(avatarSource);
|
|
646
|
+
}
|
|
647
|
+
else {
|
|
648
|
+
this.avatarSrc = this.sanitizer.bypassSecurityTrustUrl(avatarSource.getAvatar(+this.size));
|
|
649
|
+
this.avatarAlt = avatarSource.getAvatar(+this.size);
|
|
650
|
+
}
|
|
651
|
+
}
|
|
652
|
+
/**
|
|
653
|
+
*
|
|
654
|
+
* returns initials style
|
|
655
|
+
*
|
|
656
|
+
* memberOf AvatarComponent
|
|
657
|
+
*/
|
|
658
|
+
getInitialsStyle(avatarValue) {
|
|
659
|
+
return {
|
|
660
|
+
textAlign: 'center',
|
|
661
|
+
borderRadius: this.round ? '100%' : this.cornerRadius + 'px',
|
|
662
|
+
border: this.borderColor ? '1px solid ' + this.borderColor : '',
|
|
663
|
+
textTransform: 'uppercase',
|
|
664
|
+
color: this.fgColor,
|
|
665
|
+
backgroundColor: this.bgColor
|
|
666
|
+
? this.bgColor
|
|
667
|
+
: this.avatarService.getRandomColor(avatarValue),
|
|
668
|
+
font: Math.floor(+this.size / this.textSizeRatio) +
|
|
669
|
+
'px Helvetica, Arial, sans-serif',
|
|
670
|
+
lineHeight: this.size + 'px',
|
|
671
|
+
...this.style
|
|
672
|
+
};
|
|
673
|
+
}
|
|
674
|
+
/**
|
|
675
|
+
*
|
|
676
|
+
* returns image style
|
|
677
|
+
*
|
|
678
|
+
* memberOf AvatarComponent
|
|
679
|
+
*/
|
|
680
|
+
getImageStyle() {
|
|
681
|
+
return {
|
|
682
|
+
maxWidth: '100%',
|
|
683
|
+
borderRadius: this.round ? '50%' : this.cornerRadius + 'px',
|
|
684
|
+
border: this.borderColor ? '1px solid ' + this.borderColor : '',
|
|
685
|
+
width: this.size + 'px',
|
|
686
|
+
height: this.size + 'px',
|
|
687
|
+
...this.style
|
|
688
|
+
};
|
|
689
|
+
}
|
|
690
|
+
/**
|
|
691
|
+
* Fetch avatar image asynchronously.
|
|
692
|
+
*
|
|
693
|
+
* param {Source} source represents avatar source
|
|
694
|
+
* memberof AvatarComponent
|
|
695
|
+
*/
|
|
696
|
+
fetchAndProcessAsyncAvatar(source) {
|
|
697
|
+
if (this.avatarService.sourceHasFailedBefore(source)) {
|
|
698
|
+
return;
|
|
699
|
+
}
|
|
700
|
+
this.avatarService
|
|
701
|
+
.fetchAvatar(source.getAvatar(+this.size))
|
|
702
|
+
.pipe(takeWhile(() => this.isAlive), map((response) => source.processResponse(response, +this.size)))
|
|
703
|
+
.subscribe({
|
|
704
|
+
next: (avatarSrc) => (this.avatarSrc = avatarSrc),
|
|
705
|
+
error: () => {
|
|
706
|
+
this.fetchAvatarSource();
|
|
707
|
+
}
|
|
708
|
+
});
|
|
709
|
+
}
|
|
710
|
+
/**
|
|
711
|
+
* Add avatar source
|
|
712
|
+
*
|
|
713
|
+
* param sourceType avatar source type e.g facebook,twitter, etc.
|
|
714
|
+
* param sourceValue source value e.g facebookId value, etc.
|
|
715
|
+
*/
|
|
716
|
+
addSource(sourceType, sourceValue) {
|
|
717
|
+
const source = this.sources.find((s) => s.sourceType === sourceType);
|
|
718
|
+
if (source) {
|
|
719
|
+
source.sourceId = sourceValue;
|
|
720
|
+
}
|
|
721
|
+
else {
|
|
722
|
+
this.sources.push(this.sourceFactory.newInstance(sourceType, sourceValue));
|
|
723
|
+
}
|
|
724
|
+
}
|
|
725
|
+
/**
|
|
726
|
+
* Remove avatar source
|
|
727
|
+
*
|
|
728
|
+
* param sourceType avatar source type e.g facebook,twitter, etc.
|
|
729
|
+
*/
|
|
730
|
+
removeSource(sourceType) {
|
|
731
|
+
this.sources = this.sources.filter((source) => source.sourceType !== sourceType);
|
|
732
|
+
}
|
|
733
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.4", ngImport: i0, type: AvatarComponent, deps: [{ token: SourceFactory }, { token: AvatarService }, { token: i3.DomSanitizer }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
734
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.0.4", type: AvatarComponent, isStandalone: true, selector: "ng-hub-ui-avatar, hub-avatar", inputs: { round: "round", size: "size", textSizeRatio: "textSizeRatio", bgColor: "bgColor", fgColor: "fgColor", borderColor: "borderColor", style: "style", cornerRadius: "cornerRadius", facebook: ["facebookId", "facebook"], twitter: ["twitterId", "twitter"], google: ["googleId", "google"], instagram: ["instagramId", "instagram"], vkontakte: ["vkontakteId", "vkontakte"], skype: ["skypeId", "skype"], gravatar: ["gravatarId", "gravatar"], github: ["githubId", "github"], custom: ["src", "custom"], customAlt: ["alt", "customAlt"], initials: ["name", "initials"], value: "value", referrerpolicy: "referrerpolicy", placeholder: "placeholder", initialsSize: "initialsSize" }, outputs: { clickOnAvatar: "clickOnAvatar" }, usesOnChanges: true, ngImport: i0, template: `
|
|
735
|
+
<div
|
|
736
|
+
(click)="onAvatarClicked()"
|
|
737
|
+
class="avatar-container"
|
|
738
|
+
[ngStyle]="hostStyle"
|
|
739
|
+
>
|
|
740
|
+
<img
|
|
741
|
+
*ngIf="avatarSrc; else textAvatar"
|
|
742
|
+
[src]="avatarSrc"
|
|
743
|
+
[alt]="customAlt ? customAlt : avatarAlt"
|
|
744
|
+
[width]="size"
|
|
745
|
+
[height]="size"
|
|
746
|
+
[ngStyle]="avatarStyle"
|
|
747
|
+
[referrerPolicy]="referrerpolicy"
|
|
748
|
+
(error)="fetchAvatarSource()"
|
|
749
|
+
class="avatar-content"
|
|
750
|
+
loading="lazy"
|
|
751
|
+
/>
|
|
752
|
+
<ng-template #textAvatar>
|
|
753
|
+
<div
|
|
754
|
+
*ngIf="avatarText"
|
|
755
|
+
class="avatar-content"
|
|
756
|
+
[ngStyle]="avatarStyle"
|
|
757
|
+
>
|
|
758
|
+
{{ avatarText }}
|
|
759
|
+
</div>
|
|
760
|
+
</ng-template>
|
|
761
|
+
</div>
|
|
762
|
+
`, isInline: true, styles: [":host{border-radius:50%}\n"], dependencies: [{ kind: "directive", type: NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] }); }
|
|
763
|
+
}
|
|
764
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.4", ngImport: i0, type: AvatarComponent, decorators: [{
|
|
765
|
+
type: Component,
|
|
766
|
+
args: [{ selector: 'ng-hub-ui-avatar, hub-avatar', standalone: true, imports: [NgStyle, NgIf], template: `
|
|
767
|
+
<div
|
|
768
|
+
(click)="onAvatarClicked()"
|
|
769
|
+
class="avatar-container"
|
|
770
|
+
[ngStyle]="hostStyle"
|
|
771
|
+
>
|
|
772
|
+
<img
|
|
773
|
+
*ngIf="avatarSrc; else textAvatar"
|
|
774
|
+
[src]="avatarSrc"
|
|
775
|
+
[alt]="customAlt ? customAlt : avatarAlt"
|
|
776
|
+
[width]="size"
|
|
777
|
+
[height]="size"
|
|
778
|
+
[ngStyle]="avatarStyle"
|
|
779
|
+
[referrerPolicy]="referrerpolicy"
|
|
780
|
+
(error)="fetchAvatarSource()"
|
|
781
|
+
class="avatar-content"
|
|
782
|
+
loading="lazy"
|
|
783
|
+
/>
|
|
784
|
+
<ng-template #textAvatar>
|
|
785
|
+
<div
|
|
786
|
+
*ngIf="avatarText"
|
|
787
|
+
class="avatar-content"
|
|
788
|
+
[ngStyle]="avatarStyle"
|
|
789
|
+
>
|
|
790
|
+
{{ avatarText }}
|
|
791
|
+
</div>
|
|
792
|
+
</ng-template>
|
|
793
|
+
</div>
|
|
794
|
+
`, styles: [":host{border-radius:50%}\n"] }]
|
|
795
|
+
}], ctorParameters: () => [{ type: SourceFactory }, { type: AvatarService }, { type: i3.DomSanitizer }], propDecorators: { round: [{
|
|
796
|
+
type: Input
|
|
797
|
+
}], size: [{
|
|
798
|
+
type: Input
|
|
799
|
+
}], textSizeRatio: [{
|
|
800
|
+
type: Input
|
|
801
|
+
}], bgColor: [{
|
|
802
|
+
type: Input
|
|
803
|
+
}], fgColor: [{
|
|
804
|
+
type: Input
|
|
805
|
+
}], borderColor: [{
|
|
806
|
+
type: Input
|
|
807
|
+
}], style: [{
|
|
808
|
+
type: Input
|
|
809
|
+
}], cornerRadius: [{
|
|
810
|
+
type: Input
|
|
811
|
+
}], facebook: [{
|
|
812
|
+
type: Input,
|
|
813
|
+
args: ['facebookId']
|
|
814
|
+
}], twitter: [{
|
|
815
|
+
type: Input,
|
|
816
|
+
args: ['twitterId']
|
|
817
|
+
}], google: [{
|
|
818
|
+
type: Input,
|
|
819
|
+
args: ['googleId']
|
|
820
|
+
}], instagram: [{
|
|
821
|
+
type: Input,
|
|
822
|
+
args: ['instagramId']
|
|
823
|
+
}], vkontakte: [{
|
|
824
|
+
type: Input,
|
|
825
|
+
args: ['vkontakteId']
|
|
826
|
+
}], skype: [{
|
|
827
|
+
type: Input,
|
|
828
|
+
args: ['skypeId']
|
|
829
|
+
}], gravatar: [{
|
|
830
|
+
type: Input,
|
|
831
|
+
args: ['gravatarId']
|
|
832
|
+
}], github: [{
|
|
833
|
+
type: Input,
|
|
834
|
+
args: ['githubId']
|
|
835
|
+
}], custom: [{
|
|
836
|
+
type: Input,
|
|
837
|
+
args: ['src']
|
|
838
|
+
}], customAlt: [{
|
|
839
|
+
type: Input,
|
|
840
|
+
args: ['alt']
|
|
841
|
+
}], initials: [{
|
|
842
|
+
type: Input,
|
|
843
|
+
args: ['name']
|
|
844
|
+
}], value: [{
|
|
845
|
+
type: Input
|
|
846
|
+
}], referrerpolicy: [{
|
|
847
|
+
type: Input
|
|
848
|
+
}], placeholder: [{
|
|
849
|
+
type: Input
|
|
850
|
+
}], initialsSize: [{
|
|
851
|
+
type: Input
|
|
852
|
+
}], clickOnAvatar: [{
|
|
853
|
+
type: Output
|
|
854
|
+
}] } });
|
|
855
|
+
|
|
856
|
+
class AvatarModule {
|
|
857
|
+
static forRoot(avatarConfig) {
|
|
858
|
+
return {
|
|
859
|
+
ngModule: AvatarModule,
|
|
860
|
+
providers: [
|
|
861
|
+
{
|
|
862
|
+
provide: AVATAR_CONFIG,
|
|
863
|
+
useValue: avatarConfig ? avatarConfig : {}
|
|
864
|
+
}
|
|
865
|
+
]
|
|
866
|
+
};
|
|
867
|
+
}
|
|
868
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.4", ngImport: i0, type: AvatarModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
|
|
869
|
+
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "19.0.4", ngImport: i0, type: AvatarModule, imports: [CommonModule, AvatarComponent] }); }
|
|
870
|
+
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "19.0.4", ngImport: i0, type: AvatarModule, providers: [SourceFactory, AvatarService, AvatarConfigService], imports: [CommonModule] }); }
|
|
871
|
+
}
|
|
872
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.4", ngImport: i0, type: AvatarModule, decorators: [{
|
|
873
|
+
type: NgModule,
|
|
874
|
+
args: [{
|
|
875
|
+
imports: [CommonModule, AvatarComponent],
|
|
876
|
+
declarations: [],
|
|
877
|
+
providers: [SourceFactory, AvatarService, AvatarConfigService],
|
|
878
|
+
exports: []
|
|
879
|
+
}]
|
|
880
|
+
}] });
|
|
881
|
+
|
|
882
|
+
/*
|
|
883
|
+
* Public API Surface of ng-hub-ui-avatar
|
|
884
|
+
*/
|
|
885
|
+
|
|
886
|
+
/**
|
|
887
|
+
* Generated bundle index. Do not edit.
|
|
888
|
+
*/
|
|
889
|
+
|
|
890
|
+
export { AvatarComponent, AvatarModule, AvatarService, AvatarSource, defaultColors, defaultDisableSrcCache, defaultSources };
|
|
891
|
+
//# sourceMappingURL=ng-hub-ui-avatar.mjs.map
|