@api-client/ui 0.1.4 → 0.1.5

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.
@@ -1,9 +1,9 @@
1
- import { TemplateResult, LitElement } from 'lit';
1
+ import { TemplateResult, LitElement, PropertyValues, SVGTemplateResult } from 'lit';
2
2
  import type { IUser } from '@api-client/core/models/store/User.js';
3
3
  import '@material/web/focus/md-focus-ring.js';
4
4
  import '@material/web/ripple/ripple.js';
5
+ export type AvatarType = 'button' | 'icon';
5
6
  export default class UserAvatar extends LitElement {
6
- private _user?;
7
7
  /**
8
8
  * Set with the user. The computed user initials.
9
9
  */
@@ -12,23 +12,36 @@ export default class UserAvatar extends LitElement {
12
12
  * The URL to the user picture.
13
13
  */
14
14
  protected accessor userPicture: string | undefined;
15
- get user(): IUser | undefined;
16
15
  /**
16
+ * The user object to display the avatar for.
17
+ */
18
+ accessor user: IUser | undefined;
19
+ /**
20
+ * The type of avatar to render, either 'button' or 'icon'.
17
21
  * @attribute
18
22
  */
19
- set user(value: IUser | undefined);
20
- protected _processUser(user?: IUser): void;
21
- protected _readUserInitials(user: IUser): string | undefined;
22
- protected _pictureError(): void;
23
+ accessor type: AvatarType;
24
+ protected willUpdate(cp: PropertyValues<this>): void;
25
+ /**
26
+ * Handles changes to the user property.
27
+ * @param user The user object
28
+ */
29
+ protected handleUserChange(user?: IUser): void;
30
+ protected readUserInitials(user: IUser): string | undefined;
31
+ protected handlePictureError(): void;
23
32
  /**
24
33
  * @return Template result for an icon
25
34
  */
26
35
  render(): TemplateResult;
36
+ protected renderButton(content: TemplateResult): TemplateResult;
37
+ protected renderIcon(content: TemplateResult): TemplateResult;
27
38
  protected pictureTemplate(url: string): TemplateResult;
28
39
  /**
29
40
  * Renders a bubble with user initials
30
41
  * @param initials The user initials
31
42
  */
32
43
  protected nameTemplate(initials: string): TemplateResult;
44
+ protected renderDefaultAvatar(): TemplateResult;
45
+ protected defaultIcon(): SVGTemplateResult;
33
46
  }
34
47
  //# sourceMappingURL=UserAvatar.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"UserAvatar.d.ts","sourceRoot":"","sources":["../../../../../src/elements/user/internals/UserAvatar.ts"],"names":[],"mappings":"AAAA,OAAO,EAAQ,cAAc,EAAE,UAAU,EAAE,MAAM,KAAK,CAAA;AAEtD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,uCAAuC,CAAA;AAClE,OAAO,sCAAsC,CAAA;AAC7C,OAAO,gCAAgC,CAAA;AAEvC,MAAM,CAAC,OAAO,OAAO,UAAW,SAAQ,UAAU;IAChD,OAAO,CAAC,KAAK,CAAC,CAAO;IAErB;;OAEG;IACM,SAAS,CAAC,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG,SAAS,CAAA;IAE5D;;OAEG;IACM,SAAS,CAAC,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,CAAA;IAE3D,IAAI,IAAI,IAAI,KAAK,GAAG,SAAS,CAE5B;IAED;;OAEG;IACH,IACI,IAAI,CAAC,KAAK,EAAE,KAAK,GAAG,SAAS,EAWhC;IAED,SAAS,CAAC,YAAY,CAAC,IAAI,CAAC,EAAE,KAAK,GAAG,IAAI;IAU1C,SAAS,CAAC,iBAAiB,CAAC,IAAI,EAAE,KAAK,GAAG,MAAM,GAAG,SAAS;IAc5D,SAAS,CAAC,aAAa,IAAI,IAAI;IAI/B;;OAEG;IACM,MAAM,IAAI,cAAc;IAuBjC,SAAS,CAAC,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,cAAc;IAWtD;;;OAGG;IACH,SAAS,CAAC,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,cAAc;CAGzD"}
1
+ {"version":3,"file":"UserAvatar.d.ts","sourceRoot":"","sources":["../../../../../src/elements/user/internals/UserAvatar.ts"],"names":[],"mappings":"AAAA,OAAO,EAAQ,cAAc,EAAE,UAAU,EAAE,cAAc,EAAE,iBAAiB,EAAO,MAAM,KAAK,CAAA;AAE9F,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,uCAAuC,CAAA;AAClE,OAAO,sCAAsC,CAAA;AAC7C,OAAO,gCAAgC,CAAA;AAEvC,MAAM,MAAM,UAAU,GAAG,QAAQ,GAAG,MAAM,CAAA;AAE1C,MAAM,CAAC,OAAO,OAAO,UAAW,SAAQ,UAAU;IAChD;;OAEG;IACM,SAAS,CAAC,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG,SAAS,CAAA;IAE5D;;OAEG;IACM,SAAS,CAAC,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,CAAA;IAE3D;;OAEG;IACyB,QAAQ,CAAC,IAAI,EAAE,KAAK,GAAG,SAAS,CAAA;IAC5D;;;OAGG;IACyB,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAW;cAE7C,UAAU,CAAC,EAAE,EAAE,cAAc,CAAC,IAAI,CAAC,GAAG,IAAI;IAO7D;;;OAGG;IACH,SAAS,CAAC,gBAAgB,CAAC,IAAI,CAAC,EAAE,KAAK,GAAG,IAAI;IAU9C,SAAS,CAAC,gBAAgB,CAAC,IAAI,EAAE,KAAK,GAAG,MAAM,GAAG,SAAS;IAc3D,SAAS,CAAC,kBAAkB,IAAI,IAAI;IAIpC;;OAEG;IACM,MAAM,IAAI,cAAc;IAgBjC,SAAS,CAAC,YAAY,CAAC,OAAO,EAAE,cAAc,GAAG,cAAc;IAW/D,SAAS,CAAC,UAAU,CAAC,OAAO,EAAE,cAAc,GAAG,cAAc;IAI7D,SAAS,CAAC,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,cAAc;IAWtD;;;OAGG;IACH,SAAS,CAAC,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,cAAc;IAIxD,SAAS,CAAC,mBAAmB,IAAI,cAAc;IAI/C,SAAS,CAAC,WAAW,IAAI,iBAAiB;CAiB3C"}
@@ -1,30 +1,35 @@
1
1
  import { __esDecorate, __runInitializers } from "tslib";
2
- import { html, LitElement } from 'lit';
2
+ import { html, LitElement, svg } from 'lit';
3
3
  import { property, state } from 'lit/decorators.js';
4
4
  import '@material/web/focus/md-focus-ring.js';
5
5
  import '@material/web/ripple/ripple.js';
6
6
  let UserAvatar = (() => {
7
7
  let _classSuper = LitElement;
8
- let _instanceExtraInitializers = [];
9
8
  let _userInitials_decorators;
10
9
  let _userInitials_initializers = [];
11
10
  let _userInitials_extraInitializers = [];
12
11
  let _userPicture_decorators;
13
12
  let _userPicture_initializers = [];
14
13
  let _userPicture_extraInitializers = [];
15
- let _set_user_decorators;
14
+ let _user_decorators;
15
+ let _user_initializers = [];
16
+ let _user_extraInitializers = [];
17
+ let _type_decorators;
18
+ let _type_initializers = [];
19
+ let _type_extraInitializers = [];
16
20
  return class UserAvatar extends _classSuper {
17
21
  static {
18
22
  const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
19
23
  _userInitials_decorators = [state()];
20
24
  _userPicture_decorators = [state()];
21
- _set_user_decorators = [property({ type: Object })];
25
+ _user_decorators = [property({ type: Object })];
26
+ _type_decorators = [property({ type: String })];
22
27
  __esDecorate(this, null, _userInitials_decorators, { kind: "accessor", name: "userInitials", static: false, private: false, access: { has: obj => "userInitials" in obj, get: obj => obj.userInitials, set: (obj, value) => { obj.userInitials = value; } }, metadata: _metadata }, _userInitials_initializers, _userInitials_extraInitializers);
23
28
  __esDecorate(this, null, _userPicture_decorators, { kind: "accessor", name: "userPicture", static: false, private: false, access: { has: obj => "userPicture" in obj, get: obj => obj.userPicture, set: (obj, value) => { obj.userPicture = value; } }, metadata: _metadata }, _userPicture_initializers, _userPicture_extraInitializers);
24
- __esDecorate(this, null, _set_user_decorators, { kind: "setter", name: "user", static: false, private: false, access: { has: obj => "user" in obj, set: (obj, value) => { obj.user = value; } }, metadata: _metadata }, null, _instanceExtraInitializers);
29
+ __esDecorate(this, null, _user_decorators, { kind: "accessor", name: "user", static: false, private: false, access: { has: obj => "user" in obj, get: obj => obj.user, set: (obj, value) => { obj.user = value; } }, metadata: _metadata }, _user_initializers, _user_extraInitializers);
30
+ __esDecorate(this, null, _type_decorators, { kind: "accessor", name: "type", static: false, private: false, access: { has: obj => "type" in obj, get: obj => obj.type, set: (obj, value) => { obj.type = value; } }, metadata: _metadata }, _type_initializers, _type_extraInitializers);
25
31
  if (_metadata) Object.defineProperty(this, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
26
32
  }
27
- _user = __runInitializers(this, _instanceExtraInitializers);
28
33
  #userInitials_accessor_storage = __runInitializers(this, _userInitials_initializers, void 0);
29
34
  /**
30
35
  * Set with the user. The computed user initials.
@@ -37,27 +42,32 @@ let UserAvatar = (() => {
37
42
  */
38
43
  get userPicture() { return this.#userPicture_accessor_storage; }
39
44
  set userPicture(value) { this.#userPicture_accessor_storage = value; }
40
- get user() {
41
- return this._user;
42
- }
45
+ #user_accessor_storage = (__runInitializers(this, _userPicture_extraInitializers), __runInitializers(this, _user_initializers, void 0));
46
+ /**
47
+ * The user object to display the avatar for.
48
+ */
49
+ get user() { return this.#user_accessor_storage; }
50
+ set user(value) { this.#user_accessor_storage = value; }
51
+ #type_accessor_storage = (__runInitializers(this, _user_extraInitializers), __runInitializers(this, _type_initializers, 'button'));
43
52
  /**
53
+ * The type of avatar to render, either 'button' or 'icon'.
44
54
  * @attribute
45
55
  */
46
- set user(value) {
47
- const old = this._user;
48
- if (old === value) {
49
- return;
50
- }
51
- if (old && value && old.key === value.key) {
52
- return;
56
+ get type() { return this.#type_accessor_storage; }
57
+ set type(value) { this.#type_accessor_storage = value; }
58
+ willUpdate(cp) {
59
+ if (cp.has('user')) {
60
+ this.handleUserChange(this.user);
53
61
  }
54
- this._user = value;
55
- this.requestUpdate('user', old);
56
- this._processUser(value);
62
+ super.willUpdate(cp);
57
63
  }
58
- _processUser(user) {
64
+ /**
65
+ * Handles changes to the user property.
66
+ * @param user The user object
67
+ */
68
+ handleUserChange(user) {
59
69
  if (user) {
60
- this.userInitials = this._readUserInitials(user);
70
+ this.userInitials = this.readUserInitials(user);
61
71
  this.userPicture = user.picture && user.picture.url;
62
72
  }
63
73
  else {
@@ -65,7 +75,7 @@ let UserAvatar = (() => {
65
75
  this.userPicture = undefined;
66
76
  }
67
77
  }
68
- _readUserInitials(user) {
78
+ readUserInitials(user) {
69
79
  const { name } = user;
70
80
  if (!name) {
71
81
  return undefined;
@@ -78,17 +88,14 @@ let UserAvatar = (() => {
78
88
  .map((i) => i[0]);
79
89
  return parts.join('');
80
90
  }
81
- _pictureError() {
91
+ handlePictureError() {
82
92
  this.userPicture = undefined;
83
93
  }
84
94
  /**
85
95
  * @return Template result for an icon
86
96
  */
87
97
  render() {
88
- const { user, userPicture } = this;
89
- if (!user || user.key === 'default') {
90
- return html ``;
91
- }
98
+ const { userPicture } = this;
92
99
  let content;
93
100
  if (userPicture) {
94
101
  content = this.pictureTemplate(userPicture);
@@ -97,8 +104,14 @@ let UserAvatar = (() => {
97
104
  content = this.nameTemplate(this.userInitials);
98
105
  }
99
106
  else {
100
- content = this.nameTemplate('');
107
+ content = this.renderDefaultAvatar();
108
+ }
109
+ if (this.type === 'icon') {
110
+ return this.renderIcon(content);
101
111
  }
112
+ return this.renderButton(content);
113
+ }
114
+ renderButton(content) {
102
115
  return html `
103
116
  <button id="button" class="icon-button">
104
117
  <md-focus-ring part="focus-ring" for="button"></md-focus-ring>
@@ -108,13 +121,16 @@ let UserAvatar = (() => {
108
121
  </button>
109
122
  `;
110
123
  }
124
+ renderIcon(content) {
125
+ return html `<span role="presentation" class="icon">${content}</span>`;
126
+ }
111
127
  pictureTemplate(url) {
112
128
  return html `
113
129
  <img
114
130
  src="${url}"
115
131
  alt="${this.userInitials || 'Thumb'}"
116
132
  class="user-picture user-icon"
117
- @error="${this._pictureError}"
133
+ @error="${this.handlePictureError}"
118
134
  />
119
135
  `;
120
136
  }
@@ -125,9 +141,29 @@ let UserAvatar = (() => {
125
141
  nameTemplate(initials) {
126
142
  return html ` <span class="avatar-initials user-icon">${initials}</span> `;
127
143
  }
144
+ renderDefaultAvatar() {
145
+ return html `<span class="avatar-default icon"> ${this.defaultIcon()} </span>`;
146
+ }
147
+ defaultIcon() {
148
+ return svg `
149
+ <svg viewBox="0 0 120 120" fill="none" xmlns="http://www.w3.org/2000/svg" class="icon">
150
+ <rect width="120" height="120" rx="60" class="avatar-background" />
151
+ <path
152
+ fill-rule="evenodd"
153
+ clip-rule="evenodd"
154
+ d="M78.0007 48C78.0007 57.9411 69.9419 66 60.0007 66C50.0596 66 42.0007 57.9411 42.0007 48C42.0007 38.0589 50.0596 30 60.0007 30C69.9419 30 78.0007 38.0589 78.0007 48ZM72.0007 48C72.0007 54.6274 66.6282 60 60.0007 60C53.3733 60 48.0007 54.6274 48.0007 48C48.0007 41.3726 53.3733 36 60.0007 36C66.6282 36 72.0007 41.3726 72.0007 48Z"
155
+ class="avatar-lines"
156
+ />
157
+ <path
158
+ d="M60.0007 75C40.5776 75 24.0286 86.4852 17.7246 102.576C19.2603 104.101 20.878 105.543 22.5706 106.896C27.2648 92.1231 41.9909 81 60.0007 81C78.0106 81 92.7367 92.1231 97.4309 106.896C99.1235 105.544 100.741 104.101 102.277 102.576C95.973 86.4853 79.4239 75 60.0007 75Z"
159
+ class="avatar-lines"
160
+ />
161
+ </svg>
162
+ `;
163
+ }
128
164
  constructor() {
129
165
  super(...arguments);
130
- __runInitializers(this, _userPicture_extraInitializers);
166
+ __runInitializers(this, _type_extraInitializers);
131
167
  }
132
168
  };
133
169
  })();
@@ -1 +1 @@
1
- {"version":3,"file":"UserAvatar.js","sourceRoot":"","sources":["../../../../../src/elements/user/internals/UserAvatar.ts"],"names":[],"mappings":"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","sourcesContent":["import { html, TemplateResult, LitElement } from 'lit'\nimport { property, state } from 'lit/decorators.js'\nimport type { IUser } from '@api-client/core/models/store/User.js'\nimport '@material/web/focus/md-focus-ring.js'\nimport '@material/web/ripple/ripple.js'\n\nexport default class UserAvatar extends LitElement {\n private _user?: IUser\n\n /**\n * Set with the user. The computed user initials.\n */\n @state() protected accessor userInitials: string | undefined\n\n /**\n * The URL to the user picture.\n */\n @state() protected accessor userPicture: string | undefined\n\n get user(): IUser | undefined {\n return this._user\n }\n\n /**\n * @attribute\n */\n @property({ type: Object })\n set user(value: IUser | undefined) {\n const old = this._user\n if (old === value) {\n return\n }\n if (old && value && old.key === value.key) {\n return\n }\n this._user = value\n this.requestUpdate('user', old)\n this._processUser(value)\n }\n\n protected _processUser(user?: IUser): void {\n if (user) {\n this.userInitials = this._readUserInitials(user)\n this.userPicture = user.picture && user.picture.url\n } else {\n this.userInitials = undefined\n this.userPicture = undefined\n }\n }\n\n protected _readUserInitials(user: IUser): string | undefined {\n const { name } = user\n if (!name) {\n return undefined\n }\n const max = 2\n const parts = name\n .split(/[\\s-]/)\n .slice(0, max)\n .filter((i) => !!i)\n .map((i) => i[0])\n return parts.join('')\n }\n\n protected _pictureError(): void {\n this.userPicture = undefined\n }\n\n /**\n * @return Template result for an icon\n */\n override render(): TemplateResult {\n const { user, userPicture } = this\n if (!user || user.key === 'default') {\n return html``\n }\n let content: TemplateResult\n if (userPicture) {\n content = this.pictureTemplate(userPicture)\n } else if (this.userInitials) {\n content = this.nameTemplate(this.userInitials)\n } else {\n content = this.nameTemplate('')\n }\n return html`\n <button id=\"button\" class=\"icon-button\">\n <md-focus-ring part=\"focus-ring\" for=\"button\"></md-focus-ring>\n <md-ripple></md-ripple>\n <span role=\"presentation\" class=\"icon\">${content}</span>\n <span class=\"touch\"></span>\n </button>\n `\n }\n\n protected pictureTemplate(url: string): TemplateResult {\n return html`\n <img\n src=\"${url}\"\n alt=\"${this.userInitials || 'Thumb'}\"\n class=\"user-picture user-icon\"\n @error=\"${this._pictureError}\"\n />\n `\n }\n\n /**\n * Renders a bubble with user initials\n * @param initials The user initials\n */\n protected nameTemplate(initials: string): TemplateResult {\n return html` <span class=\"avatar-initials user-icon\">${initials}</span> `\n }\n}\n"]}
1
+ {"version":3,"file":"UserAvatar.js","sourceRoot":"","sources":["../../../../../src/elements/user/internals/UserAvatar.ts"],"names":[],"mappings":"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","sourcesContent":["import { html, TemplateResult, LitElement, PropertyValues, SVGTemplateResult, svg } from 'lit'\nimport { property, state } from 'lit/decorators.js'\nimport type { IUser } from '@api-client/core/models/store/User.js'\nimport '@material/web/focus/md-focus-ring.js'\nimport '@material/web/ripple/ripple.js'\n\nexport type AvatarType = 'button' | 'icon'\n\nexport default class UserAvatar extends LitElement {\n /**\n * Set with the user. The computed user initials.\n */\n @state() protected accessor userInitials: string | undefined\n\n /**\n * The URL to the user picture.\n */\n @state() protected accessor userPicture: string | undefined\n\n /**\n * The user object to display the avatar for.\n */\n @property({ type: Object }) accessor user: IUser | undefined\n /**\n * The type of avatar to render, either 'button' or 'icon'.\n * @attribute\n */\n @property({ type: String }) accessor type: AvatarType = 'button'\n\n protected override willUpdate(cp: PropertyValues<this>): void {\n if (cp.has('user')) {\n this.handleUserChange(this.user)\n }\n super.willUpdate(cp)\n }\n\n /**\n * Handles changes to the user property.\n * @param user The user object\n */\n protected handleUserChange(user?: IUser): void {\n if (user) {\n this.userInitials = this.readUserInitials(user)\n this.userPicture = user.picture && user.picture.url\n } else {\n this.userInitials = undefined\n this.userPicture = undefined\n }\n }\n\n protected readUserInitials(user: IUser): string | undefined {\n const { name } = user\n if (!name) {\n return undefined\n }\n const max = 2\n const parts = name\n .split(/[\\s-]/)\n .slice(0, max)\n .filter((i) => !!i)\n .map((i) => i[0])\n return parts.join('')\n }\n\n protected handlePictureError(): void {\n this.userPicture = undefined\n }\n\n /**\n * @return Template result for an icon\n */\n override render(): TemplateResult {\n const { userPicture } = this\n let content: TemplateResult\n if (userPicture) {\n content = this.pictureTemplate(userPicture)\n } else if (this.userInitials) {\n content = this.nameTemplate(this.userInitials)\n } else {\n content = this.renderDefaultAvatar()\n }\n if (this.type === 'icon') {\n return this.renderIcon(content)\n }\n return this.renderButton(content)\n }\n\n protected renderButton(content: TemplateResult): TemplateResult {\n return html`\n <button id=\"button\" class=\"icon-button\">\n <md-focus-ring part=\"focus-ring\" for=\"button\"></md-focus-ring>\n <md-ripple></md-ripple>\n <span role=\"presentation\" class=\"icon\">${content}</span>\n <span class=\"touch\"></span>\n </button>\n `\n }\n\n protected renderIcon(content: TemplateResult): TemplateResult {\n return html`<span role=\"presentation\" class=\"icon\">${content}</span>`\n }\n\n protected pictureTemplate(url: string): TemplateResult {\n return html`\n <img\n src=\"${url}\"\n alt=\"${this.userInitials || 'Thumb'}\"\n class=\"user-picture user-icon\"\n @error=\"${this.handlePictureError}\"\n />\n `\n }\n\n /**\n * Renders a bubble with user initials\n * @param initials The user initials\n */\n protected nameTemplate(initials: string): TemplateResult {\n return html` <span class=\"avatar-initials user-icon\">${initials}</span> `\n }\n\n protected renderDefaultAvatar(): TemplateResult {\n return html`<span class=\"avatar-default icon\"> ${this.defaultIcon()} </span>`\n }\n\n protected defaultIcon(): SVGTemplateResult {\n return svg`\n <svg viewBox=\"0 0 120 120\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\" class=\"icon\">\n <rect width=\"120\" height=\"120\" rx=\"60\" class=\"avatar-background\" />\n <path\n fill-rule=\"evenodd\"\n clip-rule=\"evenodd\"\n d=\"M78.0007 48C78.0007 57.9411 69.9419 66 60.0007 66C50.0596 66 42.0007 57.9411 42.0007 48C42.0007 38.0589 50.0596 30 60.0007 30C69.9419 30 78.0007 38.0589 78.0007 48ZM72.0007 48C72.0007 54.6274 66.6282 60 60.0007 60C53.3733 60 48.0007 54.6274 48.0007 48C48.0007 41.3726 53.3733 36 60.0007 36C66.6282 36 72.0007 41.3726 72.0007 48Z\"\n class=\"avatar-lines\"\n />\n <path\n d=\"M60.0007 75C40.5776 75 24.0286 86.4852 17.7246 102.576C19.2603 104.101 20.878 105.543 22.5706 106.896C27.2648 92.1231 41.9909 81 60.0007 81C78.0106 81 92.7367 92.1231 97.4309 106.896C99.1235 105.544 100.741 104.101 102.277 102.576C95.973 86.4853 79.4239 75 60.0007 75Z\"\n class=\"avatar-lines\"\n />\n </svg>\n `\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"UserAvatar.styles.d.ts","sourceRoot":"","sources":["../../../../../src/elements/user/internals/UserAvatar.styles.ts"],"names":[],"mappings":";AAEA,wBA6GC"}
1
+ {"version":3,"file":"UserAvatar.styles.d.ts","sourceRoot":"","sources":["../../../../../src/elements/user/internals/UserAvatar.styles.ts"],"names":[],"mappings":";AAEA,wBAmHC"}
@@ -5,8 +5,8 @@ export default css `
5
5
  outline: none;
6
6
  -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
7
7
  justify-content: center;
8
- height: var(--_state-layer-height);
9
- width: var(--_state-layer-width);
8
+ height: 40px;
9
+ width: 40px;
10
10
 
11
11
  --_focus-icon-color: var(--md-icon-button-focus-icon-color, var(--md-sys-color-on-surface-variant, #49454f));
12
12
  --_hover-icon-color: var(--md-icon-button-hover-icon-color, var(--md-sys-color-on-surface-variant, #49454f));
@@ -23,8 +23,6 @@ export default css `
23
23
  );
24
24
  --_pressed-state-layer-opacity: var(--md-icon-button-pressed-state-layer-opacity, 0.12);
25
25
  --_state-layer-shape: var(--md-icon-button-state-layer-shape, var(--md-sys-shape-corner-full, 9999px));
26
- --_state-layer-height: 40px;
27
- --_state-layer-width: 40px;
28
26
  }
29
27
 
30
28
  .icon-button {
@@ -88,15 +86,13 @@ export default css `
88
86
 
89
87
  .user-icon,
90
88
  .avatar-initials {
91
- background-color: var(--user-avatar-initials-background-color, #0540f2);
92
- color: var(--user-avatar-initials-color, #fff);
89
+ background-color: var(--md-sys-color-primary-container, #9eeffe);
90
+ color: var(--md-sys-color-on-primary-container, #001f24);
93
91
  }
94
92
 
95
93
  .avatar-initials {
96
- /* border-radius: 50%; */
97
94
  text-transform: uppercase;
98
95
  font-size: large;
99
- border: 1px #0d47a1 solid;
100
96
  width: 100%;
101
97
  height: 100%;
102
98
  display: flex;
@@ -104,9 +100,19 @@ export default css `
104
100
  justify-content: center;
105
101
  }
106
102
 
107
- .user-icon {
108
- height: var(--_state-layer-height);
109
- width: var(--_state-layer-width);
103
+ .user-icon,
104
+ .icon-button,
105
+ .icon {
106
+ height: inherit;
107
+ width: inherit;
108
+ }
109
+
110
+ .avatar-background {
111
+ fill: var(--md-sys-color-primary-container, #9eeffe);
112
+ }
113
+
114
+ .avatar-lines {
115
+ fill: var(--md-sys-color-on-primary-container, #001f24);
110
116
  }
111
117
  `;
112
118
  //# sourceMappingURL=UserAvatar.styles.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"UserAvatar.styles.js","sourceRoot":"","sources":["../../../../../src/elements/user/internals/UserAvatar.styles.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,CAAA;AAEzB,eAAe,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6GjB,CAAA","sourcesContent":["import { css } from 'lit'\n\nexport default css`\n :host {\n display: inline-flex;\n outline: none;\n -webkit-tap-highlight-color: rgba(0, 0, 0, 0);\n justify-content: center;\n height: var(--_state-layer-height);\n width: var(--_state-layer-width);\n\n --_focus-icon-color: var(--md-icon-button-focus-icon-color, var(--md-sys-color-on-surface-variant, #49454f));\n --_hover-icon-color: var(--md-icon-button-hover-icon-color, var(--md-sys-color-on-surface-variant, #49454f));\n --_hover-state-layer-color: var(\n --md-icon-button-hover-state-layer-color,\n var(--md-sys-color-on-surface-variant, #49454f)\n );\n --_hover-state-layer-opacity: var(--md-icon-button-hover-state-layer-opacity, 0.08);\n --_icon-color: var(--md-icon-button-icon-color, var(--md-sys-color-on-surface-variant, #49454f));\n --_pressed-icon-color: var(--md-icon-button-pressed-icon-color, var(--md-sys-color-on-surface-variant, #49454f));\n --_pressed-state-layer-color: var(\n --md-icon-button-pressed-state-layer-color,\n var(--md-sys-color-on-surface-variant, #49454f)\n );\n --_pressed-state-layer-opacity: var(--md-icon-button-pressed-state-layer-opacity, 0.12);\n --_state-layer-shape: var(--md-icon-button-state-layer-shape, var(--md-sys-shape-corner-full, 9999px));\n --_state-layer-height: 40px;\n --_state-layer-width: 40px;\n }\n\n .icon-button {\n background-color: rgba(0, 0, 0, 0);\n color: var(--_icon-color);\n place-items: center;\n background: none;\n border: none;\n box-sizing: border-box;\n cursor: pointer;\n display: flex;\n place-content: center;\n outline: none;\n padding: 0;\n position: relative;\n text-decoration: none;\n user-select: none;\n z-index: 0;\n flex: 1;\n border-radius: var(--_state-layer-shape);\n --md-ripple-hover-color: var(--_hover-state-layer-color);\n --md-ripple-hover-opacity: var(--_hover-state-layer-opacity);\n --md-ripple-pressed-color: var(--_pressed-state-layer-color);\n --md-ripple-pressed-opacity: var(--_pressed-state-layer-opacity);\n }\n\n .icon-button:hover {\n color: var(--_hover-icon-color);\n }\n\n .icon-button:focus {\n color: var(--_focus-icon-color);\n }\n\n .icon-button:active {\n color: var(--_pressed-icon-color);\n }\n\n md-focus-ring {\n --md-focus-ring-shape-start-start: var(--_state-layer-shape);\n --md-focus-ring-shape-start-end: var(--_state-layer-shape);\n --md-focus-ring-shape-end-end: var(--_state-layer-shape);\n --md-focus-ring-shape-end-start: var(--_state-layer-shape);\n }\n\n md-ripple {\n border-radius: var(--_state-layer-shape);\n }\n\n .icon {\n display: inline-flex;\n border-radius: var(--_state-layer-shape);\n overflow: hidden;\n }\n\n .touch {\n position: absolute;\n height: max(48px, 100%);\n width: max(48px, 100%);\n }\n\n .user-icon,\n .avatar-initials {\n background-color: var(--user-avatar-initials-background-color, #0540f2);\n color: var(--user-avatar-initials-color, #fff);\n }\n\n .avatar-initials {\n /* border-radius: 50%; */\n text-transform: uppercase;\n font-size: large;\n border: 1px #0d47a1 solid;\n width: 100%;\n height: 100%;\n display: flex;\n align-items: center;\n justify-content: center;\n }\n\n .user-icon {\n height: var(--_state-layer-height);\n width: var(--_state-layer-width);\n }\n`\n"]}
1
+ {"version":3,"file":"UserAvatar.styles.js","sourceRoot":"","sources":["../../../../../src/elements/user/internals/UserAvatar.styles.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,CAAA;AAEzB,eAAe,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAmHjB,CAAA","sourcesContent":["import { css } from 'lit'\n\nexport default css`\n :host {\n display: inline-flex;\n outline: none;\n -webkit-tap-highlight-color: rgba(0, 0, 0, 0);\n justify-content: center;\n height: 40px;\n width: 40px;\n\n --_focus-icon-color: var(--md-icon-button-focus-icon-color, var(--md-sys-color-on-surface-variant, #49454f));\n --_hover-icon-color: var(--md-icon-button-hover-icon-color, var(--md-sys-color-on-surface-variant, #49454f));\n --_hover-state-layer-color: var(\n --md-icon-button-hover-state-layer-color,\n var(--md-sys-color-on-surface-variant, #49454f)\n );\n --_hover-state-layer-opacity: var(--md-icon-button-hover-state-layer-opacity, 0.08);\n --_icon-color: var(--md-icon-button-icon-color, var(--md-sys-color-on-surface-variant, #49454f));\n --_pressed-icon-color: var(--md-icon-button-pressed-icon-color, var(--md-sys-color-on-surface-variant, #49454f));\n --_pressed-state-layer-color: var(\n --md-icon-button-pressed-state-layer-color,\n var(--md-sys-color-on-surface-variant, #49454f)\n );\n --_pressed-state-layer-opacity: var(--md-icon-button-pressed-state-layer-opacity, 0.12);\n --_state-layer-shape: var(--md-icon-button-state-layer-shape, var(--md-sys-shape-corner-full, 9999px));\n }\n\n .icon-button {\n background-color: rgba(0, 0, 0, 0);\n color: var(--_icon-color);\n place-items: center;\n background: none;\n border: none;\n box-sizing: border-box;\n cursor: pointer;\n display: flex;\n place-content: center;\n outline: none;\n padding: 0;\n position: relative;\n text-decoration: none;\n user-select: none;\n z-index: 0;\n flex: 1;\n border-radius: var(--_state-layer-shape);\n --md-ripple-hover-color: var(--_hover-state-layer-color);\n --md-ripple-hover-opacity: var(--_hover-state-layer-opacity);\n --md-ripple-pressed-color: var(--_pressed-state-layer-color);\n --md-ripple-pressed-opacity: var(--_pressed-state-layer-opacity);\n }\n\n .icon-button:hover {\n color: var(--_hover-icon-color);\n }\n\n .icon-button:focus {\n color: var(--_focus-icon-color);\n }\n\n .icon-button:active {\n color: var(--_pressed-icon-color);\n }\n\n md-focus-ring {\n --md-focus-ring-shape-start-start: var(--_state-layer-shape);\n --md-focus-ring-shape-start-end: var(--_state-layer-shape);\n --md-focus-ring-shape-end-end: var(--_state-layer-shape);\n --md-focus-ring-shape-end-start: var(--_state-layer-shape);\n }\n\n md-ripple {\n border-radius: var(--_state-layer-shape);\n }\n\n .icon {\n display: inline-flex;\n border-radius: var(--_state-layer-shape);\n overflow: hidden;\n }\n\n .touch {\n position: absolute;\n height: max(48px, 100%);\n width: max(48px, 100%);\n }\n\n .user-icon,\n .avatar-initials {\n background-color: var(--md-sys-color-primary-container, #9eeffe);\n color: var(--md-sys-color-on-primary-container, #001f24);\n }\n\n .avatar-initials {\n text-transform: uppercase;\n font-size: large;\n width: 100%;\n height: 100%;\n display: flex;\n align-items: center;\n justify-content: center;\n }\n\n .user-icon,\n .icon-button,\n .icon {\n height: inherit;\n width: inherit;\n }\n\n .avatar-background {\n fill: var(--md-sys-color-primary-container, #9eeffe);\n }\n\n .avatar-lines {\n fill: var(--md-sys-color-on-primary-container, #001f24);\n }\n`\n"]}
@@ -48,8 +48,8 @@
48
48
  <dt><a href="authorization/index.html">Authorization element</a></dt>
49
49
  <dd>Elements to define HTTP authorization.</dd>
50
50
 
51
- <dt><a href="store/index.html">Net store UI</a></dt>
52
- <dd>UIs related to the net-store library.</dd>
51
+ <dt><a href="user/user-avatar.html">User avatar</a></dt>
52
+ <dd>User avatar element.</dd>
53
53
  </dl>
54
54
  </nav>
55
55
  </main>
@@ -0,0 +1,17 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+
4
+ <head>
5
+ <meta charset="utf-8">
6
+ <meta name="viewport" content="width=device-width, minimum-scale=1, initial-scale=1, user-scalable=yes">
7
+ <title>User Avatar</title>
8
+ <link href="../../../src/styles/m3/tokens.css" rel="stylesheet" type="text/css" />
9
+ <link href="../../../src/styles/m3/theme.css" rel="stylesheet" type="text/css" />
10
+ </head>
11
+
12
+ <body class="demo">
13
+ <div id="app"></div>
14
+ <script type="module" src="../../../.tmp/demo/demo/elements/user/user-avatar.js"></script>
15
+ </body>
16
+
17
+ </html>
@@ -0,0 +1,56 @@
1
+ import { IUser } from '@api-client/core/models/store/User.js'
2
+ import { DemoPage } from '../../../src/demo/DemoPage.js'
3
+ import { reactive } from '../../../src/decorators/index.js'
4
+ import { UserKind } from '@api-client/core/models/kinds.js'
5
+ import { html, TemplateResult } from 'lit'
6
+ import '../../../src/elements/user/ui-user-avatar.js'
7
+
8
+ class ComponentDemoPage extends DemoPage {
9
+ @reactive() accessor user1: IUser
10
+ @reactive() accessor user2: IUser
11
+
12
+ constructor() {
13
+ super()
14
+ this.componentName = 'User Avatar'
15
+ this.user1 = {
16
+ key: '1',
17
+ name: 'John Doe',
18
+ email: [{ email: 'john.doe @example.com', verified: true }],
19
+ picture: {
20
+ url: 'https://i.pravatar.cc/300',
21
+ },
22
+ kind: UserKind,
23
+ status: 'active',
24
+ grantType: 'editor',
25
+ }
26
+ this.user2 = {
27
+ key: '2',
28
+ name: 'John Doe',
29
+ email: [{ email: 'john.doe @example.com', verified: true }],
30
+ kind: UserKind,
31
+ status: 'active',
32
+ grantType: 'editor',
33
+ }
34
+ }
35
+
36
+ contentTemplate(): TemplateResult {
37
+ return html`
38
+ <a href="./">Back</a>
39
+ <section class="centered">
40
+ <h3>Full data</h3>
41
+ <ui-user-avatar .user="${this.user1}"></ui-user-avatar>
42
+ <h3>No image</h3>
43
+ <ui-user-avatar .user="${this.user2}"></ui-user-avatar>
44
+ <h3>No user</h3>
45
+ <ui-user-avatar></ui-user-avatar>
46
+ <h3>Custom size</h3>
47
+ <ui-user-avatar style="width: 128px; height: 128px" .user="${this.user1}"></ui-user-avatar>
48
+ <h3>Icon type</h3>
49
+ <ui-user-avatar .user="${this.user1}" type="icon"></ui-user-avatar>
50
+ </section>
51
+ `
52
+ }
53
+ }
54
+
55
+ const instance = new ComponentDemoPage()
56
+ instance.render()
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@api-client/ui",
3
- "version": "0.1.4",
3
+ "version": "0.1.5",
4
4
  "description": "Internal UI component library for the API Client ecosystem.",
5
5
  "license": "UNLICENSED",
6
6
  "main": "build/src/index.js",
@@ -67,7 +67,7 @@
67
67
  "tsc:watch": "wireit",
68
68
  "tsc": "wireit",
69
69
  "gen:apis": "node demo/model.js",
70
- "dev": "node --import ts-node-maintained/register/esm --enable-source-maps bin/dev.ts --watch --config=wds-demo.config.js",
70
+ "dev": "wireit",
71
71
  "tsc:tests": "wireit",
72
72
  "tsc:demo": "wireit"
73
73
  },
@@ -153,6 +153,25 @@
153
153
  ".tmp/tests/**",
154
154
  ".tsbuildinfo"
155
155
  ]
156
+ },
157
+ "dev": {
158
+ "command": "wds --watch --config=wds-demo.config.js",
159
+ "files": [
160
+ "demo/**"
161
+ ],
162
+ "service": true,
163
+ "dependencies": [
164
+ "build:ts:watch"
165
+ ]
166
+ },
167
+ "build:ts:watch": {
168
+ "command": "tsc --watch --project tsconfig.browser.json",
169
+ "files": [
170
+ "src/**",
171
+ "demo/**",
172
+ "tsconfig.browser.json"
173
+ ],
174
+ "service": true
156
175
  }
157
176
  },
158
177
  "dependencies": {
@@ -6,8 +6,8 @@ export default css`
6
6
  outline: none;
7
7
  -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
8
8
  justify-content: center;
9
- height: var(--_state-layer-height);
10
- width: var(--_state-layer-width);
9
+ height: 40px;
10
+ width: 40px;
11
11
 
12
12
  --_focus-icon-color: var(--md-icon-button-focus-icon-color, var(--md-sys-color-on-surface-variant, #49454f));
13
13
  --_hover-icon-color: var(--md-icon-button-hover-icon-color, var(--md-sys-color-on-surface-variant, #49454f));
@@ -24,8 +24,6 @@ export default css`
24
24
  );
25
25
  --_pressed-state-layer-opacity: var(--md-icon-button-pressed-state-layer-opacity, 0.12);
26
26
  --_state-layer-shape: var(--md-icon-button-state-layer-shape, var(--md-sys-shape-corner-full, 9999px));
27
- --_state-layer-height: 40px;
28
- --_state-layer-width: 40px;
29
27
  }
30
28
 
31
29
  .icon-button {
@@ -89,15 +87,13 @@ export default css`
89
87
 
90
88
  .user-icon,
91
89
  .avatar-initials {
92
- background-color: var(--user-avatar-initials-background-color, #0540f2);
93
- color: var(--user-avatar-initials-color, #fff);
90
+ background-color: var(--md-sys-color-primary-container, #9eeffe);
91
+ color: var(--md-sys-color-on-primary-container, #001f24);
94
92
  }
95
93
 
96
94
  .avatar-initials {
97
- /* border-radius: 50%; */
98
95
  text-transform: uppercase;
99
96
  font-size: large;
100
- border: 1px #0d47a1 solid;
101
97
  width: 100%;
102
98
  height: 100%;
103
99
  display: flex;
@@ -105,8 +101,18 @@ export default css`
105
101
  justify-content: center;
106
102
  }
107
103
 
108
- .user-icon {
109
- height: var(--_state-layer-height);
110
- width: var(--_state-layer-width);
104
+ .user-icon,
105
+ .icon-button,
106
+ .icon {
107
+ height: inherit;
108
+ width: inherit;
109
+ }
110
+
111
+ .avatar-background {
112
+ fill: var(--md-sys-color-primary-container, #9eeffe);
113
+ }
114
+
115
+ .avatar-lines {
116
+ fill: var(--md-sys-color-on-primary-container, #001f24);
111
117
  }
112
118
  `
@@ -1,12 +1,12 @@
1
- import { html, TemplateResult, LitElement } from 'lit'
1
+ import { html, TemplateResult, LitElement, PropertyValues, SVGTemplateResult, svg } from 'lit'
2
2
  import { property, state } from 'lit/decorators.js'
3
3
  import type { IUser } from '@api-client/core/models/store/User.js'
4
4
  import '@material/web/focus/md-focus-ring.js'
5
5
  import '@material/web/ripple/ripple.js'
6
6
 
7
- export default class UserAvatar extends LitElement {
8
- private _user?: IUser
7
+ export type AvatarType = 'button' | 'icon'
9
8
 
9
+ export default class UserAvatar extends LitElement {
10
10
  /**
11
11
  * Set with the user. The computed user initials.
12
12
  */
@@ -17,30 +17,30 @@ export default class UserAvatar extends LitElement {
17
17
  */
18
18
  @state() protected accessor userPicture: string | undefined
19
19
 
20
- get user(): IUser | undefined {
21
- return this._user
22
- }
23
-
24
20
  /**
21
+ * The user object to display the avatar for.
22
+ */
23
+ @property({ type: Object }) accessor user: IUser | undefined
24
+ /**
25
+ * The type of avatar to render, either 'button' or 'icon'.
25
26
  * @attribute
26
27
  */
27
- @property({ type: Object })
28
- set user(value: IUser | undefined) {
29
- const old = this._user
30
- if (old === value) {
31
- return
32
- }
33
- if (old && value && old.key === value.key) {
34
- return
28
+ @property({ type: String }) accessor type: AvatarType = 'button'
29
+
30
+ protected override willUpdate(cp: PropertyValues<this>): void {
31
+ if (cp.has('user')) {
32
+ this.handleUserChange(this.user)
35
33
  }
36
- this._user = value
37
- this.requestUpdate('user', old)
38
- this._processUser(value)
34
+ super.willUpdate(cp)
39
35
  }
40
36
 
41
- protected _processUser(user?: IUser): void {
37
+ /**
38
+ * Handles changes to the user property.
39
+ * @param user The user object
40
+ */
41
+ protected handleUserChange(user?: IUser): void {
42
42
  if (user) {
43
- this.userInitials = this._readUserInitials(user)
43
+ this.userInitials = this.readUserInitials(user)
44
44
  this.userPicture = user.picture && user.picture.url
45
45
  } else {
46
46
  this.userInitials = undefined
@@ -48,7 +48,7 @@ export default class UserAvatar extends LitElement {
48
48
  }
49
49
  }
50
50
 
51
- protected _readUserInitials(user: IUser): string | undefined {
51
+ protected readUserInitials(user: IUser): string | undefined {
52
52
  const { name } = user
53
53
  if (!name) {
54
54
  return undefined
@@ -62,7 +62,7 @@ export default class UserAvatar extends LitElement {
62
62
  return parts.join('')
63
63
  }
64
64
 
65
- protected _pictureError(): void {
65
+ protected handlePictureError(): void {
66
66
  this.userPicture = undefined
67
67
  }
68
68
 
@@ -70,18 +70,22 @@ export default class UserAvatar extends LitElement {
70
70
  * @return Template result for an icon
71
71
  */
72
72
  override render(): TemplateResult {
73
- const { user, userPicture } = this
74
- if (!user || user.key === 'default') {
75
- return html``
76
- }
73
+ const { userPicture } = this
77
74
  let content: TemplateResult
78
75
  if (userPicture) {
79
76
  content = this.pictureTemplate(userPicture)
80
77
  } else if (this.userInitials) {
81
78
  content = this.nameTemplate(this.userInitials)
82
79
  } else {
83
- content = this.nameTemplate('')
80
+ content = this.renderDefaultAvatar()
81
+ }
82
+ if (this.type === 'icon') {
83
+ return this.renderIcon(content)
84
84
  }
85
+ return this.renderButton(content)
86
+ }
87
+
88
+ protected renderButton(content: TemplateResult): TemplateResult {
85
89
  return html`
86
90
  <button id="button" class="icon-button">
87
91
  <md-focus-ring part="focus-ring" for="button"></md-focus-ring>
@@ -92,13 +96,17 @@ export default class UserAvatar extends LitElement {
92
96
  `
93
97
  }
94
98
 
99
+ protected renderIcon(content: TemplateResult): TemplateResult {
100
+ return html`<span role="presentation" class="icon">${content}</span>`
101
+ }
102
+
95
103
  protected pictureTemplate(url: string): TemplateResult {
96
104
  return html`
97
105
  <img
98
106
  src="${url}"
99
107
  alt="${this.userInitials || 'Thumb'}"
100
108
  class="user-picture user-icon"
101
- @error="${this._pictureError}"
109
+ @error="${this.handlePictureError}"
102
110
  />
103
111
  `
104
112
  }
@@ -110,4 +118,26 @@ export default class UserAvatar extends LitElement {
110
118
  protected nameTemplate(initials: string): TemplateResult {
111
119
  return html` <span class="avatar-initials user-icon">${initials}</span> `
112
120
  }
121
+
122
+ protected renderDefaultAvatar(): TemplateResult {
123
+ return html`<span class="avatar-default icon"> ${this.defaultIcon()} </span>`
124
+ }
125
+
126
+ protected defaultIcon(): SVGTemplateResult {
127
+ return svg`
128
+ <svg viewBox="0 0 120 120" fill="none" xmlns="http://www.w3.org/2000/svg" class="icon">
129
+ <rect width="120" height="120" rx="60" class="avatar-background" />
130
+ <path
131
+ fill-rule="evenodd"
132
+ clip-rule="evenodd"
133
+ d="M78.0007 48C78.0007 57.9411 69.9419 66 60.0007 66C50.0596 66 42.0007 57.9411 42.0007 48C42.0007 38.0589 50.0596 30 60.0007 30C69.9419 30 78.0007 38.0589 78.0007 48ZM72.0007 48C72.0007 54.6274 66.6282 60 60.0007 60C53.3733 60 48.0007 54.6274 48.0007 48C48.0007 41.3726 53.3733 36 60.0007 36C66.6282 36 72.0007 41.3726 72.0007 48Z"
134
+ class="avatar-lines"
135
+ />
136
+ <path
137
+ d="M60.0007 75C40.5776 75 24.0286 86.4852 17.7246 102.576C19.2603 104.101 20.878 105.543 22.5706 106.896C27.2648 92.1231 41.9909 81 60.0007 81C78.0106 81 92.7367 92.1231 97.4309 106.896C99.1235 105.544 100.741 104.101 102.277 102.576C95.973 86.4853 79.4239 75 60.0007 75Z"
138
+ class="avatar-lines"
139
+ />
140
+ </svg>
141
+ `
142
+ }
113
143
  }
@@ -17,6 +17,7 @@
17
17
  "rootDir": "./",
18
18
  "baseUrl": ".",
19
19
  "sourceMap": true,
20
+ "declarationMap": true,
20
21
  "declaration": true,
21
22
  "noImplicitThis": true,
22
23
  "noImplicitAny": true,