@justeattakeaway/pie-avatar 0.2.0 → 0.4.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 CHANGED
@@ -30,9 +30,12 @@ Ideally, you should install the component using the **`@justeattakeaway/pie-webc
30
30
  ## Documentation
31
31
 
32
32
  ### Properties
33
- | Prop | Options | Description | Default |
34
- |------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------|
35
- | | | | |
33
+
34
+ | Prop | Options | Description | Default |
35
+ |------|---------|-------------|---------|
36
+ | `src` | — | The src attribute for the underlying image tag. | `""` |
37
+ | `tag` | "button", "a", "div" | Which HTML element to use when rendering the avatar.| `div` |
38
+ | `label` | - | User or company name that will be rendered as initials inside the avatar.| `""` |
36
39
 
37
40
  ### Slots
38
41
  | Slot | Description |
@@ -70,6 +70,14 @@
70
70
  },
71
71
  "privacy": "public"
72
72
  },
73
+ {
74
+ "kind": "field",
75
+ "name": "src",
76
+ "type": {
77
+ "text": "AvatarProps['src']"
78
+ },
79
+ "privacy": "public"
80
+ },
73
81
  {
74
82
  "kind": "method",
75
83
  "name": "getInitials",
@@ -117,7 +125,26 @@
117
125
  "text": "TemplateResult"
118
126
  }
119
127
  },
120
- "description": "Renders the icon (placeholder span for now)."
128
+ "description": "Renders the user icon."
129
+ },
130
+ {
131
+ "kind": "method",
132
+ "name": "renderImage",
133
+ "privacy": "private",
134
+ "return": {
135
+ "type": {
136
+ "text": "TemplateResult"
137
+ }
138
+ },
139
+ "parameters": [
140
+ {
141
+ "name": "imgSrc",
142
+ "type": {
143
+ "text": "string"
144
+ }
145
+ }
146
+ ],
147
+ "description": "Renders an image.\nWe assign an empty string to the alt attribute for a11y clarity as it explicitly declares the image as decorative"
121
148
  },
122
149
  {
123
150
  "kind": "field",
package/dist/index.d.ts CHANGED
@@ -6,14 +6,21 @@ import { RTLInterface } from '@justeattakeaway/pie-webc-core';
6
6
  import { TemplateResult } from 'lit';
7
7
 
8
8
  export declare interface AvatarProps {
9
- label?: string;
10
9
  /**
11
10
  * Label for the username that will be turned into initials inside the avatar, if provided.
12
11
  */
12
+ label?: string;
13
+ /**
14
+ * What HTML element the avatar should be such as button, a or div.
15
+ */
13
16
  tag: typeof tags[number];
17
+ /**
18
+ * The src attribute for the avatar image. When provided, displays an image instead of initials.
19
+ */
20
+ src?: string;
14
21
  }
15
22
 
16
- export declare type DefaultProps = ComponentDefaultProps<AvatarProps, keyof Omit<AvatarProps, 'label'>>;
23
+ export declare type DefaultProps = ComponentDefaultProps<AvatarProps, keyof Omit<AvatarProps, 'label' | 'src'>>;
17
24
 
18
25
  export declare const defaultProps: DefaultProps;
19
26
 
@@ -28,6 +35,7 @@ export declare type Initials = {
28
35
  export declare class PieAvatar extends PieAvatar_base implements AvatarProps {
29
36
  tag: "a" | "button" | "div";
30
37
  label: AvatarProps['label'];
38
+ src: AvatarProps['src'];
31
39
  /**
32
40
  * Attempts to extract initials from the label string.
33
41
  * If the label is not provided or is invalid, it returns null.
@@ -42,11 +50,18 @@ export declare class PieAvatar extends PieAvatar_base implements AvatarProps {
42
50
  */
43
51
  private renderInitials;
44
52
  /**
45
- * Renders the icon (placeholder span for now).
53
+ * Renders the user icon.
46
54
  *
47
55
  * @private
48
56
  */
49
57
  private renderIcon;
58
+ /**
59
+ * Renders an image.
60
+ * We assign an empty string to the alt attribute for a11y clarity as it explicitly declares the image as decorative
61
+ *
62
+ * @private
63
+ */
64
+ private renderImage;
50
65
  /**
51
66
  * Renders the inner content of the avatar such as initials, an icon or an image.
52
67
  * It is a getter because the value is computed based on properties
package/dist/index.js CHANGED
@@ -1,23 +1,24 @@
1
- import { LitElement as h, html as n, unsafeCSS as f } from "lit";
2
- import { RtlMixin as g, validPropertyValues as b, safeCustomElement as y } from "@justeattakeaway/pie-webc-core";
1
+ import { LitElement as h, html as s, unsafeCSS as g } from "lit";
2
+ import { RtlMixin as f, validPropertyValues as b, safeCustomElement as m } from "@justeattakeaway/pie-webc-core";
3
+ import "@justeattakeaway/pie-icons-webc/dist/IconUser.js";
3
4
  import { property as v } from "lit/decorators.js";
4
5
  const o = class o extends h {
5
6
  willUpdate() {
6
7
  this.getAttribute("v") || this.setAttribute("v", o.v);
7
8
  }
8
9
  };
9
- o.v = "0.2.0";
10
- let d = o;
11
- const m = "*,*:after,*:before{box-sizing:inherit}:host{display:block}.c-avatar-visuallyHidden{position:absolute;display:block;height:1px;width:1px;overflow:hidden;padding:1px;white-space:nowrap}.c-avatar-content{display:flex;justify-content:center;align-items:center;font-size:calc(var(--dt-font-body-s-size) * 1px);background-color:var(--dt-color-container-inverse);color:var(--dt-color-content-interactive-primary);width:32px;height:32px;border-radius:var(--dt-radius-rounded-e)}.c-avatar-placeholder{display:inline-block;text-align:center;font-size:6px}", x = ["a", "button", "div"], u = {
10
+ o.v = "0.4.0";
11
+ let p = o;
12
+ const y = "*,*:after,*:before{box-sizing:inherit}:host{display:block;--avatar-size: 32px}.c-avatar-visuallyHidden{position:absolute;display:block;height:1px;width:1px;overflow:hidden;padding:1px;white-space:nowrap}.c-avatar{display:flex;justify-content:center;align-items:center;font-size:calc(var(--dt-font-body-s-size) * 1px);background-color:var(--dt-color-container-inverse);color:var(--dt-color-content-interactive-primary);width:var(--avatar-size);height:var(--avatar-size);border-radius:var(--dt-radius-rounded-e);overflow:hidden}.c-avatar--image{width:100%;height:100%;object-fit:cover}.c-avatar--button{border:none;font-family:inherit}", x = ["a", "button", "div"], u = {
12
13
  tag: "div"
13
14
  };
14
- var w = Object.defineProperty, I = Object.getOwnPropertyDescriptor, c = (t, e, a, i) => {
15
- for (var r = i > 1 ? void 0 : i ? I(e, a) : e, l = t.length - 1, p; l >= 0; l--)
16
- (p = t[l]) && (r = (i ? p(e, a, r) : p(r)) || r);
17
- return i && r && w(e, a, r), r;
15
+ var w = Object.defineProperty, I = Object.getOwnPropertyDescriptor, l = (t, a, r, i) => {
16
+ for (var e = i > 1 ? void 0 : i ? I(a, r) : a, d = t.length - 1, c; d >= 0; d--)
17
+ (c = t[d]) && (e = (i ? c(a, r, e) : c(e)) || e);
18
+ return i && e && w(a, r, e), e;
18
19
  };
19
20
  const S = "pie-avatar";
20
- let s = class extends g(d) {
21
+ let n = class extends f(p) {
21
22
  constructor() {
22
23
  super(...arguments), this.tag = u.tag;
23
24
  }
@@ -31,10 +32,10 @@ let s = class extends g(d) {
31
32
  try {
32
33
  if (!t || typeof t != "string" || t.trim().length === 0)
33
34
  return null;
34
- const a = t.trim().replace(/-/g, " ").split(/\s+/).slice(0, 2).map((i) => i[0].toUpperCase());
35
- return a.length === 0 ? null : {
36
- visual: a.join(""),
37
- screenreader: a.join(", ")
35
+ const r = t.trim().replace(/-/g, " ").split(/\s+/).slice(0, 2).map((i) => i[0].toUpperCase());
36
+ return r.length === 0 ? null : {
37
+ visual: r.join(""),
38
+ screenreader: r.join(", ")
38
39
  // joins the two words by comma so initials are correctly pronounced by screenreaders
39
40
  };
40
41
  } catch {
@@ -47,18 +48,27 @@ let s = class extends g(d) {
47
48
  * @private
48
49
  */
49
50
  renderInitials(t) {
50
- return n`
51
+ return s`
51
52
  <span aria-hidden="true" data-test-id="pie-avatar-initials-visual">${t.visual}</span>
52
53
  <span class="c-avatar-visuallyHidden" data-test-id="pie-avatar-initials-screenreader">${t.screenreader}</span>
53
54
  `;
54
55
  }
55
56
  /**
56
- * Renders the icon (placeholder span for now).
57
+ * Renders the user icon.
57
58
  *
58
59
  * @private
59
60
  */
60
61
  renderIcon() {
61
- return n`<span data-test-id="pie-avatar-icon" class="c-avatar-placeholder">Icon Placeholder</span>`;
62
+ return s`<icon-user size="s" aria-hidden="true" data-test-id="pie-avatar-icon"></icon-user>`;
63
+ }
64
+ /**
65
+ * Renders an image.
66
+ * We assign an empty string to the alt attribute for a11y clarity as it explicitly declares the image as decorative
67
+ *
68
+ * @private
69
+ */
70
+ renderImage(t) {
71
+ return s`<img class="c-avatar--image" src="${t}" data-test-id="pie-avatar-image" alt=""/>`;
62
72
  }
63
73
  /**
64
74
  * Renders the inner content of the avatar such as initials, an icon or an image.
@@ -67,6 +77,8 @@ let s = class extends g(d) {
67
77
  * @private
68
78
  */
69
79
  get avatarContent() {
80
+ if (this.src)
81
+ return this.renderImage(this.src);
70
82
  if (this.label) {
71
83
  const t = this.getInitials(this.label);
72
84
  if (t)
@@ -81,26 +93,29 @@ let s = class extends g(d) {
81
93
  * @private
82
94
  */
83
95
  renderAvatarWrapper(t) {
84
- const { tag: e } = this;
85
- return e === "button" ? n`<button data-test-id="pie-avatar-button">${t}</button>` : e === "a" ? n`<a data-test-id="pie-avatar-anchor">${t}</a>` : n`<div class="c-avatar-content" data-test-id="pie-avatar-div">${t}</div>`;
96
+ const { tag: a } = this;
97
+ return a === "button" ? s`<button data-test-id="pie-avatar-button" class="c-avatar c-avatar--button">${t}</button>` : a === "a" ? s`<a data-test-id="pie-avatar-anchor" class="c-avatar">${t}</a>` : s`<div class="c-avatar" data-test-id="pie-avatar-div" ?aria-hidden="${this.src}">${t}</div>`;
86
98
  }
87
99
  render() {
88
100
  return this.renderAvatarWrapper(this.avatarContent);
89
101
  }
90
102
  };
91
- s.styles = f(m);
92
- c([
103
+ n.styles = g(y);
104
+ l([
93
105
  v({ type: String }),
94
106
  b(S, x, u.tag)
95
- ], s.prototype, "tag", 2);
96
- c([
107
+ ], n.prototype, "tag", 2);
108
+ l([
109
+ v({ type: String })
110
+ ], n.prototype, "label", 2);
111
+ l([
97
112
  v({ type: String })
98
- ], s.prototype, "label", 2);
99
- s = c([
100
- y("pie-avatar")
101
- ], s);
113
+ ], n.prototype, "src", 2);
114
+ n = l([
115
+ m("pie-avatar")
116
+ ], n);
102
117
  export {
103
- s as PieAvatar,
118
+ n as PieAvatar,
104
119
  u as defaultProps,
105
120
  x as tags
106
121
  };
package/dist/react.d.ts CHANGED
@@ -7,14 +7,21 @@ import { RTLInterface } from '@justeattakeaway/pie-webc-core';
7
7
  import { TemplateResult } from 'lit';
8
8
 
9
9
  export declare interface AvatarProps {
10
- label?: string;
11
10
  /**
12
11
  * Label for the username that will be turned into initials inside the avatar, if provided.
13
12
  */
13
+ label?: string;
14
+ /**
15
+ * What HTML element the avatar should be such as button, a or div.
16
+ */
14
17
  tag: typeof tags[number];
18
+ /**
19
+ * The src attribute for the avatar image. When provided, displays an image instead of initials.
20
+ */
21
+ src?: string;
15
22
  }
16
23
 
17
- export declare type DefaultProps = ComponentDefaultProps<AvatarProps, keyof Omit<AvatarProps, 'label'>>;
24
+ export declare type DefaultProps = ComponentDefaultProps<AvatarProps, keyof Omit<AvatarProps, 'label' | 'src'>>;
18
25
 
19
26
  export declare const defaultProps: DefaultProps;
20
27
 
@@ -31,6 +38,7 @@ export declare const PieAvatar: React_2.ForwardRefExoticComponent<React_2.PropsW
31
38
  declare class PieAvatar_2 extends PieAvatar_base implements AvatarProps {
32
39
  tag: "a" | "button" | "div";
33
40
  label: AvatarProps['label'];
41
+ src: AvatarProps['src'];
34
42
  /**
35
43
  * Attempts to extract initials from the label string.
36
44
  * If the label is not provided or is invalid, it returns null.
@@ -45,11 +53,18 @@ declare class PieAvatar_2 extends PieAvatar_base implements AvatarProps {
45
53
  */
46
54
  private renderInitials;
47
55
  /**
48
- * Renders the icon (placeholder span for now).
56
+ * Renders the user icon.
49
57
  *
50
58
  * @private
51
59
  */
52
60
  private renderIcon;
61
+ /**
62
+ * Renders an image.
63
+ * We assign an empty string to the alt attribute for a11y clarity as it explicitly declares the image as decorative
64
+ *
65
+ * @private
66
+ */
67
+ private renderImage;
53
68
  /**
54
69
  * Renders the inner content of the avatar such as initials, an icon or an image.
55
70
  * It is a getter because the value is computed based on properties
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@justeattakeaway/pie-avatar",
3
3
  "description": "PIE Design System Avatar built using Web Components",
4
- "version": "0.2.0",
4
+ "version": "0.4.0",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
7
7
  "module": "dist/index.js",
@@ -34,11 +34,12 @@
34
34
  "devDependencies": {
35
35
  "@custom-elements-manifest/analyzer": "0.9.0",
36
36
  "@justeattakeaway/pie-components-config": "0.21.0",
37
- "@justeattakeaway/pie-css": "0.19.0",
37
+ "@justeattakeaway/pie-css": "0.20.0",
38
38
  "@justeattakeaway/pie-monorepo-utils": "0.7.0",
39
39
  "cem-plugin-module-file-extensions": "0.0.5"
40
40
  },
41
41
  "dependencies": {
42
+ "@justeattakeaway/pie-icons-webc": "1.14.2",
42
43
  "@justeattakeaway/pie-webc-core": "1.1.0"
43
44
  },
44
45
  "volta": {
package/src/avatar.scss CHANGED
@@ -4,28 +4,34 @@
4
4
  // Note: For consistency sake, the recommended display should be either
5
5
  // "block" or "inline-block", otherwise it can be ommited for floating elements
6
6
  display: block;
7
+
8
+ --avatar-size: 32px;
7
9
  }
8
10
 
9
11
  .c-avatar-visuallyHidden {
10
12
  @include p.visually-hidden;
11
13
  }
12
14
 
13
- .c-avatar-content {
15
+ .c-avatar {
14
16
  display: flex;
15
17
  justify-content: center;
16
18
  align-items: center;
17
19
  @include p.font-size(--dt-font-body-s-size);
18
20
  background-color: var(--dt-color-container-inverse);
19
21
  color: var(--dt-color-content-interactive-primary);
20
- width: 32px;
21
- height: 32px;
22
+ width: var(--avatar-size);
23
+ height: var(--avatar-size);
22
24
  border-radius:var(--dt-radius-rounded-e);
23
-
25
+ overflow: hidden;
24
26
  }
25
27
 
26
- // Basic placeholder styling - will be removed in subsequent ticket
27
- .c-avatar-placeholder {
28
- display: inline-block;
29
- text-align: center;
30
- font-size: 6px;
28
+ .c-avatar--image {
29
+ width: 100%;
30
+ height: 100%;
31
+ object-fit: cover;
31
32
  }
33
+
34
+ .c-avatar--button {
35
+ border: none;
36
+ font-family: inherit;
37
+ }
package/src/defs.ts CHANGED
@@ -3,18 +3,24 @@ import { type ComponentDefaultProps } from '@justeattakeaway/pie-webc-core';
3
3
  export const tags = ['a', 'button', 'div'] as const;
4
4
 
5
5
  export interface AvatarProps {
6
- label?: string;
7
6
  /**
8
7
  * Label for the username that will be turned into initials inside the avatar, if provided.
9
8
  */
10
- tag: typeof tags[number];
9
+ label?: string;
10
+
11
11
  /**
12
12
  * What HTML element the avatar should be such as button, a or div.
13
13
  */
14
+ tag: typeof tags[number];
15
+
16
+ /**
17
+ * The src attribute for the avatar image. When provided, displays an image instead of initials.
18
+ */
19
+ src?: string;
14
20
 
15
21
  }
16
22
 
17
- export type DefaultProps = ComponentDefaultProps<AvatarProps, keyof Omit<AvatarProps, 'label'>>;
23
+ export type DefaultProps = ComponentDefaultProps<AvatarProps, keyof Omit<AvatarProps, 'label' | 'src'>>;
18
24
  export const defaultProps: DefaultProps = {
19
25
  tag: 'div',
20
26
  };
package/src/index.ts CHANGED
@@ -3,6 +3,7 @@ import {
3
3
  } from 'lit';
4
4
  import { PieElement } from '@justeattakeaway/pie-webc-core/src/internals/PieElement';
5
5
  import { RtlMixin, safeCustomElement, validPropertyValues } from '@justeattakeaway/pie-webc-core';
6
+ import '@justeattakeaway/pie-icons-webc/dist/IconUser.js';
6
7
 
7
8
  import { property } from 'lit/decorators.js';
8
9
  import styles from './avatar.scss?inline';
@@ -18,6 +19,7 @@ const componentSelector = 'pie-avatar';
18
19
  /**
19
20
  * @tagname pie-avatar
20
21
  */
22
+
21
23
  @safeCustomElement('pie-avatar')
22
24
  export class PieAvatar extends RtlMixin(PieElement) implements AvatarProps {
23
25
  @property({ type: String })
@@ -27,6 +29,9 @@ export class PieAvatar extends RtlMixin(PieElement) implements AvatarProps {
27
29
  @property({ type: String })
28
30
  public label: AvatarProps['label'];
29
31
 
32
+ @property({ type: String })
33
+ public src: AvatarProps['src'];
34
+
30
35
  /**
31
36
  * Attempts to extract initials from the label string.
32
37
  * If the label is not provided or is invalid, it returns null.
@@ -68,12 +73,22 @@ export class PieAvatar extends RtlMixin(PieElement) implements AvatarProps {
68
73
  }
69
74
 
70
75
  /**
71
- * Renders the icon (placeholder span for now).
76
+ * Renders the user icon.
72
77
  *
73
78
  * @private
74
79
  */
75
80
  private renderIcon (): TemplateResult {
76
- return html`<span data-test-id="pie-avatar-icon" class="c-avatar-placeholder">Icon Placeholder</span>`;
81
+ return html`<icon-user size="s" aria-hidden="true" data-test-id="pie-avatar-icon"></icon-user>`;
82
+ }
83
+
84
+ /**
85
+ * Renders an image.
86
+ * We assign an empty string to the alt attribute for a11y clarity as it explicitly declares the image as decorative
87
+ *
88
+ * @private
89
+ */
90
+ private renderImage (imgSrc: string): TemplateResult {
91
+ return html`<img class="c-avatar--image" src="${imgSrc}" data-test-id="pie-avatar-image" alt=""/>`;
77
92
  }
78
93
 
79
94
  /**
@@ -83,7 +98,9 @@ export class PieAvatar extends RtlMixin(PieElement) implements AvatarProps {
83
98
  * @private
84
99
  */
85
100
  private get avatarContent (): TemplateResult {
86
- // TODO: handle unauthenticated and src here
101
+ if (this.src) {
102
+ return this.renderImage(this.src);
103
+ }
87
104
 
88
105
  if (this.label) {
89
106
  const initials = this.getInitials(this.label);
@@ -105,14 +122,14 @@ export class PieAvatar extends RtlMixin(PieElement) implements AvatarProps {
105
122
  const { tag } = this;
106
123
 
107
124
  if (tag === 'button') {
108
- return html`<button data-test-id="pie-avatar-button">${content}</button>`;
125
+ return html`<button data-test-id="pie-avatar-button" class="c-avatar c-avatar--button">${content}</button>`;
109
126
  }
110
127
 
111
128
  if (tag === 'a') {
112
- return html`<a data-test-id="pie-avatar-anchor">${content}</a>`;
129
+ return html`<a data-test-id="pie-avatar-anchor" class="c-avatar">${content}</a>`;
113
130
  }
114
131
 
115
- return html`<div class="c-avatar-content" data-test-id="pie-avatar-div">${content}</div>`;
132
+ return html`<div class="c-avatar" data-test-id="pie-avatar-div" ?aria-hidden="${this.src}">${content}</div>`;
116
133
  }
117
134
 
118
135
  render () {