@justeattakeaway/pie-avatar 0.1.1 → 0.3.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 +6 -3
- package/custom-elements.json +129 -3
- package/dist/index.d.ts +57 -2
- package/dist/index.js +98 -18
- package/dist/react.d.ts +57 -2
- package/dist/react.js +9 -6
- package/package.json +2 -1
- package/src/avatar.scss +17 -0
- package/src/defs.ts +25 -3
- package/src/index.ts +106 -4
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
|
-
|
|
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 |
|
package/custom-elements.json
CHANGED
|
@@ -11,8 +11,42 @@
|
|
|
11
11
|
{
|
|
12
12
|
"kind": "javascript-module",
|
|
13
13
|
"path": "src/defs.js",
|
|
14
|
-
"declarations": [
|
|
15
|
-
|
|
14
|
+
"declarations": [
|
|
15
|
+
{
|
|
16
|
+
"kind": "variable",
|
|
17
|
+
"name": "tags",
|
|
18
|
+
"type": {
|
|
19
|
+
"text": "['a', 'button', 'div']"
|
|
20
|
+
},
|
|
21
|
+
"default": "['a', 'button', 'div']"
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"kind": "variable",
|
|
25
|
+
"name": "defaultProps",
|
|
26
|
+
"type": {
|
|
27
|
+
"text": "DefaultProps"
|
|
28
|
+
},
|
|
29
|
+
"default": "{\n tag: 'div',\n}"
|
|
30
|
+
}
|
|
31
|
+
],
|
|
32
|
+
"exports": [
|
|
33
|
+
{
|
|
34
|
+
"kind": "js",
|
|
35
|
+
"name": "tags",
|
|
36
|
+
"declaration": {
|
|
37
|
+
"name": "tags",
|
|
38
|
+
"module": "src/defs.js"
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
"kind": "js",
|
|
43
|
+
"name": "defaultProps",
|
|
44
|
+
"declaration": {
|
|
45
|
+
"name": "defaultProps",
|
|
46
|
+
"module": "src/defs.js"
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
]
|
|
16
50
|
},
|
|
17
51
|
{
|
|
18
52
|
"kind": "javascript-module",
|
|
@@ -22,7 +56,99 @@
|
|
|
22
56
|
"kind": "class",
|
|
23
57
|
"description": "",
|
|
24
58
|
"name": "PieAvatar",
|
|
25
|
-
"members": [
|
|
59
|
+
"members": [
|
|
60
|
+
{
|
|
61
|
+
"kind": "field",
|
|
62
|
+
"name": "tag",
|
|
63
|
+
"privacy": "public"
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
"kind": "field",
|
|
67
|
+
"name": "label",
|
|
68
|
+
"type": {
|
|
69
|
+
"text": "AvatarProps['label']"
|
|
70
|
+
},
|
|
71
|
+
"privacy": "public"
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
"kind": "method",
|
|
75
|
+
"name": "getInitials",
|
|
76
|
+
"privacy": "private",
|
|
77
|
+
"return": {
|
|
78
|
+
"type": {
|
|
79
|
+
"text": "Initials | null"
|
|
80
|
+
}
|
|
81
|
+
},
|
|
82
|
+
"parameters": [
|
|
83
|
+
{
|
|
84
|
+
"name": "name",
|
|
85
|
+
"type": {
|
|
86
|
+
"text": "string"
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
],
|
|
90
|
+
"description": "Attempts to extract initials from the label string.\nIf the label is not provided or is invalid, it returns null."
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
"kind": "method",
|
|
94
|
+
"name": "renderInitials",
|
|
95
|
+
"privacy": "private",
|
|
96
|
+
"return": {
|
|
97
|
+
"type": {
|
|
98
|
+
"text": "TemplateResult"
|
|
99
|
+
}
|
|
100
|
+
},
|
|
101
|
+
"parameters": [
|
|
102
|
+
{
|
|
103
|
+
"name": "initials",
|
|
104
|
+
"type": {
|
|
105
|
+
"text": "Initials"
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
],
|
|
109
|
+
"description": "Renders the initials both for visual display and for screen readers."
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
"kind": "method",
|
|
113
|
+
"name": "renderIcon",
|
|
114
|
+
"privacy": "private",
|
|
115
|
+
"return": {
|
|
116
|
+
"type": {
|
|
117
|
+
"text": "TemplateResult"
|
|
118
|
+
}
|
|
119
|
+
},
|
|
120
|
+
"description": "Renders the icon (placeholder span for now)."
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
"kind": "field",
|
|
124
|
+
"name": "avatarContent",
|
|
125
|
+
"type": {
|
|
126
|
+
"text": "TemplateResult"
|
|
127
|
+
},
|
|
128
|
+
"privacy": "private",
|
|
129
|
+
"description": "Renders the inner content of the avatar such as initials, an icon or an image.\nIt is a getter because the value is computed based on properties",
|
|
130
|
+
"readonly": true
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
"kind": "method",
|
|
134
|
+
"name": "renderAvatarWrapper",
|
|
135
|
+
"privacy": "private",
|
|
136
|
+
"return": {
|
|
137
|
+
"type": {
|
|
138
|
+
"text": "TemplateResult"
|
|
139
|
+
}
|
|
140
|
+
},
|
|
141
|
+
"parameters": [
|
|
142
|
+
{
|
|
143
|
+
"name": "content",
|
|
144
|
+
"type": {
|
|
145
|
+
"text": "TemplateResult"
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
],
|
|
149
|
+
"description": "Renders the avatar wrapper element based on the `tag` property.\nCan be a `button`, `a` or a `div`."
|
|
150
|
+
}
|
|
151
|
+
],
|
|
26
152
|
"mixins": [
|
|
27
153
|
{
|
|
28
154
|
"name": "RtlMixin",
|
package/dist/index.d.ts
CHANGED
|
@@ -1,20 +1,75 @@
|
|
|
1
|
+
import { ComponentDefaultProps } from '@justeattakeaway/pie-webc-core';
|
|
1
2
|
import { CSSResult } from 'lit';
|
|
2
3
|
import { GenericConstructor } from '@justeattakeaway/pie-webc-core';
|
|
3
4
|
import { PieElement } from '@justeattakeaway/pie-webc-core/src/internals/PieElement';
|
|
4
5
|
import { RTLInterface } from '@justeattakeaway/pie-webc-core';
|
|
5
|
-
import { TemplateResult } from 'lit
|
|
6
|
+
import { TemplateResult } from 'lit';
|
|
6
7
|
|
|
7
8
|
export declare interface AvatarProps {
|
|
9
|
+
/**
|
|
10
|
+
* Label for the username that will be turned into initials inside the avatar, if provided.
|
|
11
|
+
*/
|
|
12
|
+
label?: string;
|
|
13
|
+
/**
|
|
14
|
+
* What HTML element the avatar should be such as button, a or div.
|
|
15
|
+
*/
|
|
16
|
+
tag: typeof tags[number];
|
|
8
17
|
}
|
|
9
18
|
|
|
19
|
+
export declare type DefaultProps = ComponentDefaultProps<AvatarProps, keyof Omit<AvatarProps, 'label'>>;
|
|
20
|
+
|
|
21
|
+
export declare const defaultProps: DefaultProps;
|
|
22
|
+
|
|
23
|
+
export declare type Initials = {
|
|
24
|
+
visual: string;
|
|
25
|
+
screenreader: string;
|
|
26
|
+
};
|
|
27
|
+
|
|
10
28
|
/**
|
|
11
29
|
* @tagname pie-avatar
|
|
12
30
|
*/
|
|
13
31
|
export declare class PieAvatar extends PieAvatar_base implements AvatarProps {
|
|
14
|
-
|
|
32
|
+
tag: "a" | "button" | "div";
|
|
33
|
+
label: AvatarProps['label'];
|
|
34
|
+
/**
|
|
35
|
+
* Attempts to extract initials from the label string.
|
|
36
|
+
* If the label is not provided or is invalid, it returns null.
|
|
37
|
+
*
|
|
38
|
+
* @private
|
|
39
|
+
*/
|
|
40
|
+
private getInitials;
|
|
41
|
+
/**
|
|
42
|
+
* Renders the initials both for visual display and for screen readers.
|
|
43
|
+
*
|
|
44
|
+
* @private
|
|
45
|
+
*/
|
|
46
|
+
private renderInitials;
|
|
47
|
+
/**
|
|
48
|
+
* Renders the icon (placeholder span for now).
|
|
49
|
+
*
|
|
50
|
+
* @private
|
|
51
|
+
*/
|
|
52
|
+
private renderIcon;
|
|
53
|
+
/**
|
|
54
|
+
* Renders the inner content of the avatar such as initials, an icon or an image.
|
|
55
|
+
* It is a getter because the value is computed based on properties
|
|
56
|
+
*
|
|
57
|
+
* @private
|
|
58
|
+
*/
|
|
59
|
+
private get avatarContent();
|
|
60
|
+
/**
|
|
61
|
+
* Renders the avatar wrapper element based on the `tag` property.
|
|
62
|
+
* Can be a `button`, `a` or a `div`.
|
|
63
|
+
*
|
|
64
|
+
* @private
|
|
65
|
+
*/
|
|
66
|
+
private renderAvatarWrapper;
|
|
67
|
+
render(): TemplateResult;
|
|
15
68
|
static styles: CSSResult;
|
|
16
69
|
}
|
|
17
70
|
|
|
18
71
|
declare const PieAvatar_base: GenericConstructor<RTLInterface> & typeof PieElement;
|
|
19
72
|
|
|
73
|
+
export declare const tags: readonly ["a", "button", "div"];
|
|
74
|
+
|
|
20
75
|
export { }
|
package/dist/index.js
CHANGED
|
@@ -1,27 +1,107 @@
|
|
|
1
|
-
import { LitElement as
|
|
2
|
-
import { RtlMixin as
|
|
3
|
-
|
|
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";
|
|
3
|
+
import "@justeattakeaway/pie-icons-webc/dist/IconUser.js";
|
|
4
|
+
import { property as u } from "lit/decorators.js";
|
|
5
|
+
const o = class o extends h {
|
|
4
6
|
willUpdate() {
|
|
5
|
-
this.getAttribute("v") || this.setAttribute("v",
|
|
7
|
+
this.getAttribute("v") || this.setAttribute("v", o.v);
|
|
6
8
|
}
|
|
7
9
|
};
|
|
8
|
-
|
|
9
|
-
let
|
|
10
|
-
const
|
|
11
|
-
|
|
12
|
-
for (var t = o > 1 ? void 0 : o ? b(l, v) : l, r = i.length - 1, n; r >= 0; r--)
|
|
13
|
-
(n = i[r]) && (t = n(t) || t);
|
|
14
|
-
return t;
|
|
10
|
+
o.v = "0.3.0";
|
|
11
|
+
let d = o;
|
|
12
|
+
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)}", x = ["a", "button", "div"], v = {
|
|
13
|
+
tag: "div"
|
|
15
14
|
};
|
|
16
|
-
|
|
15
|
+
var w = Object.defineProperty, S = Object.getOwnPropertyDescriptor, c = (t, e, r, i) => {
|
|
16
|
+
for (var a = i > 1 ? void 0 : i ? S(e, r) : e, l = t.length - 1, p; l >= 0; l--)
|
|
17
|
+
(p = t[l]) && (a = (i ? p(e, r, a) : p(a)) || a);
|
|
18
|
+
return i && a && w(e, r, a), a;
|
|
19
|
+
};
|
|
20
|
+
const C = "pie-avatar";
|
|
21
|
+
let s = class extends g(d) {
|
|
22
|
+
constructor() {
|
|
23
|
+
super(...arguments), this.tag = v.tag;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Attempts to extract initials from the label string.
|
|
27
|
+
* If the label is not provided or is invalid, it returns null.
|
|
28
|
+
*
|
|
29
|
+
* @private
|
|
30
|
+
*/
|
|
31
|
+
getInitials(t) {
|
|
32
|
+
try {
|
|
33
|
+
if (!t || typeof t != "string" || t.trim().length === 0)
|
|
34
|
+
return null;
|
|
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(", ")
|
|
39
|
+
// joins the two words by comma so initials are correctly pronounced by screenreaders
|
|
40
|
+
};
|
|
41
|
+
} catch {
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Renders the initials both for visual display and for screen readers.
|
|
47
|
+
*
|
|
48
|
+
* @private
|
|
49
|
+
*/
|
|
50
|
+
renderInitials(t) {
|
|
51
|
+
return n`
|
|
52
|
+
<span aria-hidden="true" data-test-id="pie-avatar-initials-visual">${t.visual}</span>
|
|
53
|
+
<span class="c-avatar-visuallyHidden" data-test-id="pie-avatar-initials-screenreader">${t.screenreader}</span>
|
|
54
|
+
`;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Renders the icon (placeholder span for now).
|
|
58
|
+
*
|
|
59
|
+
* @private
|
|
60
|
+
*/
|
|
61
|
+
renderIcon() {
|
|
62
|
+
return n`<icon-user size="s" aria-hidden="true" data-test-id="pie-avatar-icon"></icon-user>`;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Renders the inner content of the avatar such as initials, an icon or an image.
|
|
66
|
+
* It is a getter because the value is computed based on properties
|
|
67
|
+
*
|
|
68
|
+
* @private
|
|
69
|
+
*/
|
|
70
|
+
get avatarContent() {
|
|
71
|
+
if (this.label) {
|
|
72
|
+
const t = this.getInitials(this.label);
|
|
73
|
+
if (t)
|
|
74
|
+
return this.renderInitials(t);
|
|
75
|
+
}
|
|
76
|
+
return this.renderIcon();
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Renders the avatar wrapper element based on the `tag` property.
|
|
80
|
+
* Can be a `button`, `a` or a `div`.
|
|
81
|
+
*
|
|
82
|
+
* @private
|
|
83
|
+
*/
|
|
84
|
+
renderAvatarWrapper(t) {
|
|
85
|
+
const { tag: e } = this;
|
|
86
|
+
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>`;
|
|
87
|
+
}
|
|
17
88
|
render() {
|
|
18
|
-
return
|
|
89
|
+
return this.renderAvatarWrapper(this.avatarContent);
|
|
19
90
|
}
|
|
20
91
|
};
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
92
|
+
s.styles = f(m);
|
|
93
|
+
c([
|
|
94
|
+
u({ type: String }),
|
|
95
|
+
b(C, x, v.tag)
|
|
96
|
+
], s.prototype, "tag", 2);
|
|
97
|
+
c([
|
|
98
|
+
u({ type: String })
|
|
99
|
+
], s.prototype, "label", 2);
|
|
100
|
+
s = c([
|
|
101
|
+
y("pie-avatar")
|
|
102
|
+
], s);
|
|
25
103
|
export {
|
|
26
|
-
|
|
104
|
+
s as PieAvatar,
|
|
105
|
+
v as defaultProps,
|
|
106
|
+
x as tags
|
|
27
107
|
};
|
package/dist/react.d.ts
CHANGED
|
@@ -1,20 +1,73 @@
|
|
|
1
|
+
import { ComponentDefaultProps } from '@justeattakeaway/pie-webc-core';
|
|
1
2
|
import { CSSResult } from 'lit';
|
|
2
3
|
import { GenericConstructor } from '@justeattakeaway/pie-webc-core';
|
|
3
4
|
import { PieElement } from '@justeattakeaway/pie-webc-core/src/internals/PieElement';
|
|
4
5
|
import * as React_2 from 'react';
|
|
5
6
|
import { RTLInterface } from '@justeattakeaway/pie-webc-core';
|
|
6
|
-
import { TemplateResult } from 'lit
|
|
7
|
+
import { TemplateResult } from 'lit';
|
|
7
8
|
|
|
8
9
|
export declare interface AvatarProps {
|
|
10
|
+
/**
|
|
11
|
+
* Label for the username that will be turned into initials inside the avatar, if provided.
|
|
12
|
+
*/
|
|
13
|
+
label?: string;
|
|
14
|
+
/**
|
|
15
|
+
* What HTML element the avatar should be such as button, a or div.
|
|
16
|
+
*/
|
|
17
|
+
tag: typeof tags[number];
|
|
9
18
|
}
|
|
10
19
|
|
|
20
|
+
export declare type DefaultProps = ComponentDefaultProps<AvatarProps, keyof Omit<AvatarProps, 'label'>>;
|
|
21
|
+
|
|
22
|
+
export declare const defaultProps: DefaultProps;
|
|
23
|
+
|
|
24
|
+
export declare type Initials = {
|
|
25
|
+
visual: string;
|
|
26
|
+
screenreader: string;
|
|
27
|
+
};
|
|
28
|
+
|
|
11
29
|
export declare const PieAvatar: React_2.ForwardRefExoticComponent<React_2.PropsWithoutRef<AvatarProps> & React_2.RefAttributes<PieAvatar_2> & ReactBaseType>;
|
|
12
30
|
|
|
13
31
|
/**
|
|
14
32
|
* @tagname pie-avatar
|
|
15
33
|
*/
|
|
16
34
|
declare class PieAvatar_2 extends PieAvatar_base implements AvatarProps {
|
|
17
|
-
|
|
35
|
+
tag: "a" | "button" | "div";
|
|
36
|
+
label: AvatarProps['label'];
|
|
37
|
+
/**
|
|
38
|
+
* Attempts to extract initials from the label string.
|
|
39
|
+
* If the label is not provided or is invalid, it returns null.
|
|
40
|
+
*
|
|
41
|
+
* @private
|
|
42
|
+
*/
|
|
43
|
+
private getInitials;
|
|
44
|
+
/**
|
|
45
|
+
* Renders the initials both for visual display and for screen readers.
|
|
46
|
+
*
|
|
47
|
+
* @private
|
|
48
|
+
*/
|
|
49
|
+
private renderInitials;
|
|
50
|
+
/**
|
|
51
|
+
* Renders the icon (placeholder span for now).
|
|
52
|
+
*
|
|
53
|
+
* @private
|
|
54
|
+
*/
|
|
55
|
+
private renderIcon;
|
|
56
|
+
/**
|
|
57
|
+
* Renders the inner content of the avatar such as initials, an icon or an image.
|
|
58
|
+
* It is a getter because the value is computed based on properties
|
|
59
|
+
*
|
|
60
|
+
* @private
|
|
61
|
+
*/
|
|
62
|
+
private get avatarContent();
|
|
63
|
+
/**
|
|
64
|
+
* Renders the avatar wrapper element based on the `tag` property.
|
|
65
|
+
* Can be a `button`, `a` or a `div`.
|
|
66
|
+
*
|
|
67
|
+
* @private
|
|
68
|
+
*/
|
|
69
|
+
private renderAvatarWrapper;
|
|
70
|
+
render(): TemplateResult;
|
|
18
71
|
static styles: CSSResult;
|
|
19
72
|
}
|
|
20
73
|
|
|
@@ -22,4 +75,6 @@ declare const PieAvatar_base: GenericConstructor<RTLInterface> & typeof PieEleme
|
|
|
22
75
|
|
|
23
76
|
declare type ReactBaseType = React_2.HTMLAttributes<HTMLElement>;
|
|
24
77
|
|
|
78
|
+
export declare const tags: readonly ["a", "button", "div"];
|
|
79
|
+
|
|
25
80
|
export { }
|
package/dist/react.js
CHANGED
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
import * as a from "react";
|
|
2
|
-
import { createComponent as
|
|
3
|
-
import { PieAvatar as
|
|
4
|
-
|
|
2
|
+
import { createComponent as t } from "@lit/react";
|
|
3
|
+
import { PieAvatar as e } from "./index.js";
|
|
4
|
+
import { defaultProps as v, tags as c } from "./index.js";
|
|
5
|
+
const r = t({
|
|
5
6
|
displayName: "PieAvatar",
|
|
6
|
-
elementClass:
|
|
7
|
+
elementClass: e,
|
|
7
8
|
react: a,
|
|
8
9
|
tagName: "pie-avatar",
|
|
9
10
|
events: {}
|
|
10
|
-
}),
|
|
11
|
+
}), i = r;
|
|
11
12
|
export {
|
|
12
|
-
|
|
13
|
+
i as PieAvatar,
|
|
14
|
+
v as defaultProps,
|
|
15
|
+
c as tags
|
|
13
16
|
};
|
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.
|
|
4
|
+
"version": "0.3.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"module": "dist/index.js",
|
|
@@ -39,6 +39,7 @@
|
|
|
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
|
@@ -5,3 +5,20 @@
|
|
|
5
5
|
// "block" or "inline-block", otherwise it can be ommited for floating elements
|
|
6
6
|
display: block;
|
|
7
7
|
}
|
|
8
|
+
|
|
9
|
+
.c-avatar-visuallyHidden {
|
|
10
|
+
@include p.visually-hidden;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
.c-avatar-content {
|
|
14
|
+
display: flex;
|
|
15
|
+
justify-content: center;
|
|
16
|
+
align-items: center;
|
|
17
|
+
@include p.font-size(--dt-font-body-s-size);
|
|
18
|
+
background-color: var(--dt-color-container-inverse);
|
|
19
|
+
color: var(--dt-color-content-interactive-primary);
|
|
20
|
+
width: 32px;
|
|
21
|
+
height: 32px;
|
|
22
|
+
border-radius:var(--dt-radius-rounded-e);
|
|
23
|
+
|
|
24
|
+
}
|
package/src/defs.ts
CHANGED
|
@@ -1,3 +1,25 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
export
|
|
1
|
+
import { type ComponentDefaultProps } from '@justeattakeaway/pie-webc-core';
|
|
2
|
+
|
|
3
|
+
export const tags = ['a', 'button', 'div'] as const;
|
|
4
|
+
|
|
5
|
+
export interface AvatarProps {
|
|
6
|
+
/**
|
|
7
|
+
* Label for the username that will be turned into initials inside the avatar, if provided.
|
|
8
|
+
*/
|
|
9
|
+
label?: string;
|
|
10
|
+
/**
|
|
11
|
+
* What HTML element the avatar should be such as button, a or div.
|
|
12
|
+
*/
|
|
13
|
+
tag: typeof tags[number];
|
|
14
|
+
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export type DefaultProps = ComponentDefaultProps<AvatarProps, keyof Omit<AvatarProps, 'label'>>;
|
|
18
|
+
export const defaultProps: DefaultProps = {
|
|
19
|
+
tag: 'div',
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export type Initials = {
|
|
23
|
+
visual: string,
|
|
24
|
+
screenreader: string
|
|
25
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -1,9 +1,15 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
html, type TemplateResult, unsafeCSS,
|
|
3
|
+
} from 'lit';
|
|
2
4
|
import { PieElement } from '@justeattakeaway/pie-webc-core/src/internals/PieElement';
|
|
3
|
-
import { RtlMixin, safeCustomElement } from '@justeattakeaway/pie-webc-core';
|
|
5
|
+
import { RtlMixin, safeCustomElement, validPropertyValues } from '@justeattakeaway/pie-webc-core';
|
|
6
|
+
import '@justeattakeaway/pie-icons-webc/dist/IconUser.js';
|
|
4
7
|
|
|
8
|
+
import { property } from 'lit/decorators.js';
|
|
5
9
|
import styles from './avatar.scss?inline';
|
|
6
|
-
import {
|
|
10
|
+
import {
|
|
11
|
+
type AvatarProps, defaultProps, tags, type Initials,
|
|
12
|
+
} from './defs';
|
|
7
13
|
|
|
8
14
|
// Valid values available to consumers
|
|
9
15
|
export * from './defs';
|
|
@@ -13,10 +19,106 @@ const componentSelector = 'pie-avatar';
|
|
|
13
19
|
/**
|
|
14
20
|
* @tagname pie-avatar
|
|
15
21
|
*/
|
|
22
|
+
|
|
16
23
|
@safeCustomElement('pie-avatar')
|
|
17
24
|
export class PieAvatar extends RtlMixin(PieElement) implements AvatarProps {
|
|
25
|
+
@property({ type: String })
|
|
26
|
+
@validPropertyValues(componentSelector, tags, defaultProps.tag)
|
|
27
|
+
public tag = defaultProps.tag;
|
|
28
|
+
|
|
29
|
+
@property({ type: String })
|
|
30
|
+
public label: AvatarProps['label'];
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Attempts to extract initials from the label string.
|
|
34
|
+
* If the label is not provided or is invalid, it returns null.
|
|
35
|
+
*
|
|
36
|
+
* @private
|
|
37
|
+
*/
|
|
38
|
+
private getInitials (name: string): Initials | null {
|
|
39
|
+
try {
|
|
40
|
+
if (!name || typeof name !== 'string' || name.trim().length === 0) {
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const nameSplit: string[] = name.trim().replace(/-/g, ' ').split(/\s+/); // [Ada, Lovelace]
|
|
45
|
+
const initials: string[] = nameSplit.slice(0, 2).map((word) => word[0].toUpperCase()); // [A, L]
|
|
46
|
+
|
|
47
|
+
if (initials.length === 0) {
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return {
|
|
52
|
+
visual: initials.join(''),
|
|
53
|
+
screenreader: initials.join(', '), // joins the two words by comma so initials are correctly pronounced by screenreaders
|
|
54
|
+
};
|
|
55
|
+
} catch (error) {
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Renders the initials both for visual display and for screen readers.
|
|
62
|
+
*
|
|
63
|
+
* @private
|
|
64
|
+
*/
|
|
65
|
+
private renderInitials (initials: Initials): TemplateResult {
|
|
66
|
+
return html`
|
|
67
|
+
<span aria-hidden="true" data-test-id="pie-avatar-initials-visual">${initials.visual}</span>
|
|
68
|
+
<span class="c-avatar-visuallyHidden" data-test-id="pie-avatar-initials-screenreader">${initials.screenreader}</span>
|
|
69
|
+
`;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Renders the icon (placeholder span for now).
|
|
74
|
+
*
|
|
75
|
+
* @private
|
|
76
|
+
*/
|
|
77
|
+
private renderIcon (): TemplateResult {
|
|
78
|
+
return html`<icon-user size="s" aria-hidden="true" data-test-id="pie-avatar-icon"></icon-user>`;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Renders the inner content of the avatar such as initials, an icon or an image.
|
|
83
|
+
* It is a getter because the value is computed based on properties
|
|
84
|
+
*
|
|
85
|
+
* @private
|
|
86
|
+
*/
|
|
87
|
+
private get avatarContent (): TemplateResult {
|
|
88
|
+
// TODO: handle unauthenticated and src here
|
|
89
|
+
|
|
90
|
+
if (this.label) {
|
|
91
|
+
const initials = this.getInitials(this.label);
|
|
92
|
+
if (initials) {
|
|
93
|
+
return this.renderInitials(initials);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
return this.renderIcon();
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Renders the avatar wrapper element based on the `tag` property.
|
|
102
|
+
* Can be a `button`, `a` or a `div`.
|
|
103
|
+
*
|
|
104
|
+
* @private
|
|
105
|
+
*/
|
|
106
|
+
private renderAvatarWrapper (content: TemplateResult): TemplateResult {
|
|
107
|
+
const { tag } = this;
|
|
108
|
+
|
|
109
|
+
if (tag === 'button') {
|
|
110
|
+
return html`<button data-test-id="pie-avatar-button">${content}</button>`;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
if (tag === 'a') {
|
|
114
|
+
return html`<a data-test-id="pie-avatar-anchor">${content}</a>`;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
return html`<div class="c-avatar-content" data-test-id="pie-avatar-div">${content}</div>`;
|
|
118
|
+
}
|
|
119
|
+
|
|
18
120
|
render () {
|
|
19
|
-
return
|
|
121
|
+
return this.renderAvatarWrapper(this.avatarContent);
|
|
20
122
|
}
|
|
21
123
|
|
|
22
124
|
// Renders a `CSSResult` generated from SCSS by Vite
|