@justeattakeaway/pie-thumbnail 0.5.0 → 0.6.1
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/custom-elements.json +57 -4
- package/declaration.d.ts +5 -0
- package/dist/index.d.ts +23 -6
- package/dist/index.js +104 -75
- package/dist/react.d.ts +23 -6
- package/package.json +1 -3
- package/src/default-placeholder.svg +1 -0
- package/src/defs.ts +6 -1
- package/src/index.ts +52 -13
- package/src/thumbnail.scss +9 -1
package/custom-elements.json
CHANGED
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
"type": {
|
|
56
56
|
"text": "DefaultProps"
|
|
57
57
|
},
|
|
58
|
-
"default": "{\n variant: 'default',\n size: 48,\n src: '',\n alt: '',\n disabled: false,\n hasPadding: false,\n backgroundColor: 'default',\n aspectRatio: '1by1',\n placeholder: {\n src: '',\n alt: '',\n },\n}"
|
|
58
|
+
"default": "{\n variant: 'default',\n size: 48,\n src: '',\n alt: '',\n disabled: false,\n hasPadding: false,\n hideDefaultPlaceholder: false,\n backgroundColor: 'default',\n aspectRatio: '1by1',\n placeholder: {\n src: '',\n alt: '',\n },\n}"
|
|
59
59
|
}
|
|
60
60
|
],
|
|
61
61
|
"exports": [
|
|
@@ -160,6 +160,12 @@
|
|
|
160
160
|
"privacy": "public",
|
|
161
161
|
"attribute": "hasPadding"
|
|
162
162
|
},
|
|
163
|
+
{
|
|
164
|
+
"kind": "field",
|
|
165
|
+
"name": "hideDefaultPlaceholder",
|
|
166
|
+
"privacy": "public",
|
|
167
|
+
"attribute": "hideDefaultPlaceholder"
|
|
168
|
+
},
|
|
163
169
|
{
|
|
164
170
|
"kind": "field",
|
|
165
171
|
"name": "backgroundColor",
|
|
@@ -183,6 +189,44 @@
|
|
|
183
189
|
},
|
|
184
190
|
"privacy": "private"
|
|
185
191
|
},
|
|
192
|
+
{
|
|
193
|
+
"kind": "field",
|
|
194
|
+
"name": "_hasError",
|
|
195
|
+
"type": {
|
|
196
|
+
"text": "boolean"
|
|
197
|
+
},
|
|
198
|
+
"privacy": "private",
|
|
199
|
+
"default": "false"
|
|
200
|
+
},
|
|
201
|
+
{
|
|
202
|
+
"kind": "field",
|
|
203
|
+
"name": "_isDefaultPlaceholderVisible",
|
|
204
|
+
"type": {
|
|
205
|
+
"text": "boolean"
|
|
206
|
+
},
|
|
207
|
+
"privacy": "private",
|
|
208
|
+
"description": "Determines if the default placeholder should be displayed.",
|
|
209
|
+
"readonly": true
|
|
210
|
+
},
|
|
211
|
+
{
|
|
212
|
+
"kind": "field",
|
|
213
|
+
"name": "_controlledSrc",
|
|
214
|
+
"type": {
|
|
215
|
+
"text": "string"
|
|
216
|
+
},
|
|
217
|
+
"privacy": "private",
|
|
218
|
+
"description": "Returns the appropriate image props based on the following order:\n1. If there is no error, return the provided image props.\n2. If there is an error and a custom placeholder is provided, return the placeholder props.\n3. If there is an error and no custom placeholder is provided, return the component default placeholder.\n4. Otherwise, fall back to the provided src (resulting in a broken image).",
|
|
219
|
+
"readonly": true
|
|
220
|
+
},
|
|
221
|
+
{
|
|
222
|
+
"kind": "field",
|
|
223
|
+
"name": "_controlledAlt",
|
|
224
|
+
"type": {
|
|
225
|
+
"text": "string"
|
|
226
|
+
},
|
|
227
|
+
"privacy": "private",
|
|
228
|
+
"readonly": true
|
|
229
|
+
},
|
|
186
230
|
{
|
|
187
231
|
"kind": "method",
|
|
188
232
|
"name": "_generateSizeStyles",
|
|
@@ -192,19 +236,24 @@
|
|
|
192
236
|
"text": "string"
|
|
193
237
|
}
|
|
194
238
|
},
|
|
195
|
-
"description": "Assigns
|
|
239
|
+
"description": "Assigns CSS variables based on the size prop."
|
|
196
240
|
},
|
|
197
241
|
{
|
|
198
242
|
"kind": "method",
|
|
199
243
|
"name": "_handleImageError",
|
|
200
244
|
"privacy": "private",
|
|
201
|
-
"
|
|
245
|
+
"return": {
|
|
246
|
+
"type": {
|
|
247
|
+
"text": "void"
|
|
248
|
+
}
|
|
249
|
+
},
|
|
250
|
+
"description": "Handles the image error event."
|
|
202
251
|
},
|
|
203
252
|
{
|
|
204
253
|
"kind": "method",
|
|
205
254
|
"name": "_checkImageError",
|
|
206
255
|
"privacy": "private",
|
|
207
|
-
"description": "
|
|
256
|
+
"description": "Checks the image load status and triggers error handling if needed.\nThis is needed as the `onerror` event is not triggered in SSR."
|
|
208
257
|
}
|
|
209
258
|
],
|
|
210
259
|
"attributes": [
|
|
@@ -236,6 +285,10 @@
|
|
|
236
285
|
"name": "hasPadding",
|
|
237
286
|
"fieldName": "hasPadding"
|
|
238
287
|
},
|
|
288
|
+
{
|
|
289
|
+
"name": "hideDefaultPlaceholder",
|
|
290
|
+
"fieldName": "hideDefaultPlaceholder"
|
|
291
|
+
},
|
|
239
292
|
{
|
|
240
293
|
"name": "backgroundColor",
|
|
241
294
|
"fieldName": "backgroundColor"
|
package/declaration.d.ts
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -24,21 +24,34 @@ export declare class PieThumbnail extends LitElement implements ThumbnailProps {
|
|
|
24
24
|
alt: string;
|
|
25
25
|
disabled: boolean;
|
|
26
26
|
hasPadding: boolean;
|
|
27
|
+
hideDefaultPlaceholder: boolean;
|
|
27
28
|
backgroundColor: "default" | "subtle" | "strong" | "dark" | "inverse" | "inverse-alternative";
|
|
28
29
|
placeholder: ThumbnailProps['placeholder'];
|
|
29
30
|
private img;
|
|
31
|
+
private _hasError;
|
|
30
32
|
/**
|
|
31
|
-
*
|
|
32
|
-
|
|
33
|
+
* Determines if the default placeholder should be displayed.
|
|
34
|
+
*/
|
|
35
|
+
private get _isDefaultPlaceholderVisible();
|
|
36
|
+
/**
|
|
37
|
+
* Returns the appropriate image props based on the following order:
|
|
38
|
+
* 1. If there is no error, return the provided image props.
|
|
39
|
+
* 2. If there is an error and a custom placeholder is provided, return the placeholder props.
|
|
40
|
+
* 3. If there is an error and no custom placeholder is provided, return the component default placeholder.
|
|
41
|
+
* 4. Otherwise, fall back to the provided src (resulting in a broken image).
|
|
42
|
+
*/
|
|
43
|
+
private get _controlledSrc();
|
|
44
|
+
private get _controlledAlt();
|
|
45
|
+
/**
|
|
46
|
+
* Assigns CSS variables based on the size prop.
|
|
33
47
|
*/
|
|
34
48
|
private _generateSizeStyles;
|
|
35
49
|
/**
|
|
36
|
-
* Handles
|
|
37
|
-
* with the placeholder props.
|
|
50
|
+
* Handles the image error event.
|
|
38
51
|
*/
|
|
39
52
|
private _handleImageError;
|
|
40
53
|
/**
|
|
41
|
-
*
|
|
54
|
+
* Checks the image load status and triggers error handling if needed.
|
|
42
55
|
* This is needed as the `onerror` event is not triggered in SSR.
|
|
43
56
|
*/
|
|
44
57
|
private _checkImageError;
|
|
@@ -84,7 +97,11 @@ export declare interface ThumbnailProps {
|
|
|
84
97
|
*/
|
|
85
98
|
backgroundColor?: typeof backgroundColors[number];
|
|
86
99
|
/**
|
|
87
|
-
*
|
|
100
|
+
* When true, hides the component default placeholder on image load failure.
|
|
101
|
+
*/
|
|
102
|
+
hideDefaultPlaceholder?: boolean;
|
|
103
|
+
/**
|
|
104
|
+
* Overrides the component default placeholder with a custom one on image load failure.
|
|
88
105
|
*/
|
|
89
106
|
placeholder?: PlaceholderProps;
|
|
90
107
|
/**
|
package/dist/index.js
CHANGED
|
@@ -1,27 +1,27 @@
|
|
|
1
|
-
import { LitElement as
|
|
2
|
-
import { validPropertyValues as
|
|
3
|
-
import { classMap as
|
|
4
|
-
import { property as
|
|
5
|
-
const
|
|
1
|
+
import { LitElement as k, html as _, unsafeCSS as S } from "lit";
|
|
2
|
+
import { validPropertyValues as h, defineCustomElement as P } from "@justeattakeaway/pie-webc-core";
|
|
3
|
+
import { classMap as E } from "lit/directives/class-map.js";
|
|
4
|
+
import { property as l, query as z, state as C } from "lit/decorators.js";
|
|
5
|
+
const I = [
|
|
6
6
|
"default",
|
|
7
7
|
"outline"
|
|
8
|
-
],
|
|
8
|
+
], D = [
|
|
9
9
|
"default",
|
|
10
10
|
"subtle",
|
|
11
11
|
"strong",
|
|
12
12
|
"dark",
|
|
13
13
|
"inverse",
|
|
14
14
|
"inverse-alternative"
|
|
15
|
-
],
|
|
15
|
+
], x = {
|
|
16
16
|
default: "c-thumbnail--backgroundDefault",
|
|
17
17
|
subtle: "c-thumbnail--backgroundSubtle",
|
|
18
18
|
strong: "c-thumbnail--backgroundStrong",
|
|
19
19
|
dark: "c-thumbnail--backgroundDark",
|
|
20
20
|
inverse: "c-thumbnail--backgroundInverse",
|
|
21
21
|
"inverse-alternative": "c-thumbnail--backgroundInverseAlternative"
|
|
22
|
-
}, $ = ["1by1", "4by3", "16by9"], m = 8,
|
|
23
|
-
{ length: (
|
|
24
|
-
(u, t) =>
|
|
22
|
+
}, $ = ["1by1", "4by3", "16by9"], m = 8, g = 24, w = 128, R = Object.freeze(Array.from(
|
|
23
|
+
{ length: (w - g) / m + 1 },
|
|
24
|
+
(u, t) => g + t * m
|
|
25
25
|
)), r = {
|
|
26
26
|
variant: "default",
|
|
27
27
|
size: 48,
|
|
@@ -29,50 +29,71 @@ const E = [
|
|
|
29
29
|
alt: "",
|
|
30
30
|
disabled: !1,
|
|
31
31
|
hasPadding: !1,
|
|
32
|
+
hideDefaultPlaceholder: !1,
|
|
32
33
|
backgroundColor: "default",
|
|
33
34
|
aspectRatio: "1by1",
|
|
34
35
|
placeholder: {
|
|
35
36
|
src: "",
|
|
36
37
|
alt: ""
|
|
37
38
|
}
|
|
38
|
-
},
|
|
39
|
-
var
|
|
40
|
-
for (var
|
|
41
|
-
(
|
|
42
|
-
return
|
|
39
|
+
}, j = ".c-thumbnail{--thumbnail-size: 48px;--thumbnail-border-radius: var(--dt-radius-rounded-b);--thumbnail-bg-color: var(--dt-color-container-default);--thumbnail-padding: calc(var(--dt-spacing-a) / 2);--thumbnail-default-placeholder-padding: var(--dt-spacing-b);--thumbnail-img-border-radius: unset;--thumbnail-img-object-fit: cover;display:flex;justify-content:center;align-items:center;box-sizing:border-box;overflow:hidden;width:var(--thumbnail-size);height:var(--thumbnail-size);border-radius:var(--thumbnail-border-radius);background-color:var(--thumbnail-bg-color)}.c-thumbnail.c-thumbnail--outline{border:1px solid var(--dt-color-border-default)}.c-thumbnail.c-thumbnail--disabled{opacity:.5}.c-thumbnail.c-thumbnail--backgroundSubtle{--thumbnail-bg-color: var(--dt-color-container-subtle)}.c-thumbnail.c-thumbnail--backgroundStrong{--thumbnail-bg-color: var(--dt-color-container-strong)}.c-thumbnail.c-thumbnail--backgroundDark{--thumbnail-bg-color: var(--dt-color-container-dark)}.c-thumbnail.c-thumbnail--backgroundInverse{--thumbnail-bg-color: var(--dt-color-container-inverse)}.c-thumbnail.c-thumbnail--backgroundInverseAlternative{--thumbnail-bg-color: var(--dt-color-container-inverse-alternative)}.c-thumbnail.c-thumbnail--padding{--thumbnail-img-border-radius: calc(var(--thumbnail-border-radius) - var(--thumbnail-padding));padding:var(--thumbnail-padding)}.c-thumbnail.c-thumbnail--4by3{height:calc(var(--thumbnail-size) * 3 / 4)}.c-thumbnail.c-thumbnail--16by9{height:calc(var(--thumbnail-size) * 9 / 16)}.c-thumbnail .c-thumbnail-img{width:100%;height:100%;border-radius:var(--thumbnail-img-border-radius);object-fit:var(--thumbnail-img-object-fit)}.c-thumbnail.c-thumbnail--defaultPlaceholder{--thumbnail-bg-color: var(--dt-color-container-default);--thumbnail-img-object-fit: fill;padding:var(--thumbnail-default-placeholder-padding)}", A = "data:image/svg+xml,%3csvg%20xmlns='http://www.w3.org/2000/svg'%20fill='none'%20viewBox='0%200%2033%2032'%3e%3cpath%20d='M32.399%2015.493c-.102-.255-1.495-2.753-4.081-5.888a.507.507%200%200%201-.119-.267%2048.162%2048.162%200%200%200-.778-5.436.88.88%200%200%200-.282-.467.928.928%200%200%200-.509-.221l-2.679-.323a.84.84%200%200%200-.071%200c-.15%200-.294.058-.401.161s-.166.243-.166.389v.906c0%20.009-.004.017-.011.023s-.015.01-.025.01c-.015-.003-.018-.006-.021-.008A37.89%2037.89%200%200%200%2017.829.395%202.43%202.43%200%200%200%2016.493%200c-.473%200-.936.138-1.328.395C5.887%205.956.782%2015.005.585%2015.493a.87.87%200%200%200%20.004.757.9.9%200%200%200%20.246.306.93.93%200%200%200%20.356.176l2.672.5c.177.047.335.144.454.279s.193.302.213.479c.023.457.527%2010.691%201.162%2013.345a.89.89%200%200%200%20.328.479c.161.12.358.186.561.185h.02l4.528-.084h.129c.079-.001.155-.032.211-.086s.087-.128.087-.205l-.306-5.093c0-.054-.007-.121-.01-.176a.54.54%200%200%200-.08-.254.56.56%200%200%200-.193-.188c-.407-.236-.747-.566-.992-.96s-.385-.841-.41-1.3c-.142-3.589-.211-7.735-.008-10.981.003-.138.062-.27.165-.366a.545.545%200%200%201%20.76.016c.099.1.152.234.149.372v.041c-.132%202.163-.142%204.72-.095%207.244a.61.61%200%200%200%20.195.435.65.65%200%200%200%20.454.174.65.65%200%200%200%20.448-.189.61.61%200%200%200%20.179-.441c-.048-2.54-.035-5.114.099-7.285.003-.138.062-.27.165-.366a.545.545%200%200%201%20.76.016c.099.1.152.234.149.372v.041c-.132%202.152-.142%204.694-.096%207.204a.61.61%200%200%200%20.194.435.65.65%200%200%200%20.454.175.65.65%200%200%200%20.448-.188.61.61%200%200%200%20.18-.441c-.047-2.529-.034-5.093.101-7.249.003-.138.063-.27.165-.366s.241-.148.383-.145.278.061.377.161.152.234.149.372v.041c-.193%203.154-.13%207.147%200%2010.651a.26.26%200%200%201%200%20.033v.086c0%20.455-.113.902-.331%201.305s-.533.747-.919%201.004a.54.54%200%200%200-.166.177.52.52%200%200%200-.07.229s-.067.538.179%203.144l.241%202.284c.009.067.043.128.095.172s.119.068.188.068h4.053l1.516.012c.07%200%20.137-.024.189-.069s.086-.107.094-.174c.35-3.123.434-4.879.434-4.879-.002-.075-.032-.146-.084-.201s-.123-.09-.199-.099l-1.843-.246c-.122-.015-.238-.064-.331-.142s-.161-.181-.195-.297a.83.83%200%200%201-.024-.275c.747-10.411%204.282-13.92%204.282-13.92a1.05%201.05%200%200%201%20.172-.144.575.575%200%200%201%20.491-.082.57.57%200%200%201%20.223.122.55.55%200%200%201%20.145.205.97.97%200%200%201%20.045.251c.306%203.272.157%208.842-.033%2013.186l-.353%206.583c0%20.057.023.112.065.152s.098.063.156.063l3.037.062h.021a.94.94%200%200%200%20.561-.186.892.892%200%200%200%20.328-.479c.635-2.654%201.134-12.887%201.161-13.344a.877.877%200%200%201%20.214-.479.92.92%200%200%201%20.453-.28l2.672-.5a.92.92%200%200%200%20.499-.317.873.873%200%200%200%20.194-.548.885.885%200%200%200-.101-.368z'%20fill='%23efedea'/%3e%3c/svg%3e";
|
|
40
|
+
var B = Object.defineProperty, i = (u, t, e, o) => {
|
|
41
|
+
for (var n = void 0, c = u.length - 1, d; c >= 0; c--)
|
|
42
|
+
(d = u[c]) && (n = d(t, e, n) || n);
|
|
43
|
+
return n && B(t, e, n), n;
|
|
43
44
|
};
|
|
44
|
-
const s = "pie-thumbnail",
|
|
45
|
+
const s = "pie-thumbnail", b = class b extends k {
|
|
45
46
|
constructor() {
|
|
46
|
-
super(...arguments), this.variant = r.variant, this.size = r.size, this.aspectRatio = r.aspectRatio, this.src = r.src, this.alt = r.alt, this.disabled = r.disabled, this.hasPadding = r.hasPadding, this.backgroundColor = r.backgroundColor, this.placeholder = r.placeholder;
|
|
47
|
+
super(...arguments), this.variant = r.variant, this.size = r.size, this.aspectRatio = r.aspectRatio, this.src = r.src, this.alt = r.alt, this.disabled = r.disabled, this.hasPadding = r.hasPadding, this.hideDefaultPlaceholder = r.hideDefaultPlaceholder, this.backgroundColor = r.backgroundColor, this.placeholder = r.placeholder, this._hasError = !1;
|
|
47
48
|
}
|
|
48
49
|
/**
|
|
49
|
-
*
|
|
50
|
-
|
|
50
|
+
* Determines if the default placeholder should be displayed.
|
|
51
|
+
*/
|
|
52
|
+
get _isDefaultPlaceholderVisible() {
|
|
53
|
+
const { _hasError: t, placeholder: e, hideDefaultPlaceholder: o } = this;
|
|
54
|
+
return t && !(e != null && e.src) && !o;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Returns the appropriate image props based on the following order:
|
|
58
|
+
* 1. If there is no error, return the provided image props.
|
|
59
|
+
* 2. If there is an error and a custom placeholder is provided, return the placeholder props.
|
|
60
|
+
* 3. If there is an error and no custom placeholder is provided, return the component default placeholder.
|
|
61
|
+
* 4. Otherwise, fall back to the provided src (resulting in a broken image).
|
|
62
|
+
*/
|
|
63
|
+
get _controlledSrc() {
|
|
64
|
+
var t;
|
|
65
|
+
return this._hasError ? (t = this.placeholder) != null && t.src ? this.placeholder.src : this.hideDefaultPlaceholder ? this.src : A : this.src;
|
|
66
|
+
}
|
|
67
|
+
get _controlledAlt() {
|
|
68
|
+
var t;
|
|
69
|
+
return this._hasError ? (t = this.placeholder) != null && t.src ? this.placeholder.alt ?? "" : this.hideDefaultPlaceholder ? this.alt : "" : this.alt;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Assigns CSS variables based on the size prop.
|
|
51
73
|
*/
|
|
52
74
|
_generateSizeStyles() {
|
|
53
75
|
const { size: t } = this;
|
|
54
|
-
let
|
|
55
|
-
return t <= 40 ?
|
|
76
|
+
let e = "--dt-radius-rounded-c", o = "--dt-spacing-d";
|
|
77
|
+
return t <= 40 ? (e = "--dt-radius-rounded-a", o = "--dt-spacing-a") : t <= 56 && (e = "--dt-radius-rounded-b", o = "--dt-spacing-b"), `
|
|
56
78
|
--thumbnail-size: ${t}px;
|
|
57
|
-
--thumbnail-border-radius: var(${
|
|
79
|
+
--thumbnail-border-radius: var(${e});
|
|
80
|
+
--thumbnail-default-placeholder-padding: var(${o});
|
|
58
81
|
`;
|
|
59
82
|
}
|
|
60
83
|
/**
|
|
61
|
-
* Handles
|
|
62
|
-
* with the placeholder props.
|
|
84
|
+
* Handles the image error event.
|
|
63
85
|
*/
|
|
64
86
|
_handleImageError() {
|
|
65
|
-
|
|
66
|
-
(t = this.placeholder) != null && t.src && this.setAttribute("src", this.placeholder.src), (a = this.placeholder) != null && a.alt && this.setAttribute("alt", this.placeholder.alt);
|
|
87
|
+
this._hasError = !0;
|
|
67
88
|
}
|
|
68
89
|
/**
|
|
69
|
-
*
|
|
90
|
+
* Checks the image load status and triggers error handling if needed.
|
|
70
91
|
* This is needed as the `onerror` event is not triggered in SSR.
|
|
71
92
|
*/
|
|
72
93
|
_checkImageError() {
|
|
73
94
|
if (this.img) {
|
|
74
|
-
const { complete: t, naturalHeight:
|
|
75
|
-
t &&
|
|
95
|
+
const { complete: t, naturalHeight: e } = this.img;
|
|
96
|
+
t && e === 0 && this._handleImageError.call(this);
|
|
76
97
|
}
|
|
77
98
|
}
|
|
78
99
|
firstUpdated() {
|
|
@@ -81,78 +102,86 @@ const s = "pie-thumbnail", h = class h extends f {
|
|
|
81
102
|
render() {
|
|
82
103
|
const {
|
|
83
104
|
variant: t,
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
disabled:
|
|
87
|
-
hasPadding:
|
|
88
|
-
|
|
89
|
-
|
|
105
|
+
_controlledSrc: e,
|
|
106
|
+
_controlledAlt: o,
|
|
107
|
+
disabled: n,
|
|
108
|
+
hasPadding: c,
|
|
109
|
+
_isDefaultPlaceholderVisible: d,
|
|
110
|
+
backgroundColor: p,
|
|
111
|
+
aspectRatio: f
|
|
90
112
|
} = this, v = {
|
|
91
113
|
"c-thumbnail": !0,
|
|
92
114
|
[`c-thumbnail--${t}`]: !0,
|
|
93
|
-
[`c-thumbnail--${
|
|
94
|
-
[
|
|
95
|
-
"c-thumbnail--disabled":
|
|
96
|
-
"c-thumbnail--padding":
|
|
115
|
+
[`c-thumbnail--${f}`]: !0,
|
|
116
|
+
[x[p]]: !0,
|
|
117
|
+
"c-thumbnail--disabled": n,
|
|
118
|
+
"c-thumbnail--padding": c,
|
|
119
|
+
"c-thumbnail--defaultPlaceholder": d
|
|
97
120
|
}, y = this._generateSizeStyles();
|
|
98
|
-
return
|
|
121
|
+
return _`
|
|
99
122
|
<div data-test-id="pie-thumbnail"
|
|
100
|
-
class="${
|
|
123
|
+
class="${E(v)}"
|
|
101
124
|
style="${y}">
|
|
102
125
|
<img
|
|
103
126
|
data-test-id="pie-thumbnail-img"
|
|
104
|
-
src="${
|
|
127
|
+
src="${e}"
|
|
128
|
+
alt="${o}"
|
|
105
129
|
class="c-thumbnail-img"
|
|
106
|
-
alt="${b}"
|
|
107
130
|
@error="${this._handleImageError}"
|
|
108
131
|
/>
|
|
109
132
|
</div>
|
|
110
133
|
`;
|
|
111
134
|
}
|
|
112
135
|
};
|
|
113
|
-
|
|
114
|
-
let
|
|
136
|
+
b.styles = S(j);
|
|
137
|
+
let a = b;
|
|
138
|
+
i([
|
|
139
|
+
l({ type: String }),
|
|
140
|
+
h(s, I, r.variant)
|
|
141
|
+
], a.prototype, "variant");
|
|
142
|
+
i([
|
|
143
|
+
l({ type: Number }),
|
|
144
|
+
h(s, R, r.size)
|
|
145
|
+
], a.prototype, "size");
|
|
115
146
|
i([
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
],
|
|
147
|
+
l({ type: String }),
|
|
148
|
+
h(s, $, r.aspectRatio)
|
|
149
|
+
], a.prototype, "aspectRatio");
|
|
119
150
|
i([
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
], e.prototype, "size");
|
|
151
|
+
l({ type: String })
|
|
152
|
+
], a.prototype, "src");
|
|
123
153
|
i([
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
], e.prototype, "aspectRatio");
|
|
154
|
+
l({ type: String })
|
|
155
|
+
], a.prototype, "alt");
|
|
127
156
|
i([
|
|
128
|
-
|
|
129
|
-
],
|
|
157
|
+
l({ type: Boolean })
|
|
158
|
+
], a.prototype, "disabled");
|
|
130
159
|
i([
|
|
131
|
-
|
|
132
|
-
],
|
|
160
|
+
l({ type: Boolean })
|
|
161
|
+
], a.prototype, "hasPadding");
|
|
133
162
|
i([
|
|
134
|
-
|
|
135
|
-
],
|
|
163
|
+
l({ type: Boolean })
|
|
164
|
+
], a.prototype, "hideDefaultPlaceholder");
|
|
136
165
|
i([
|
|
137
|
-
|
|
138
|
-
|
|
166
|
+
l({ type: String }),
|
|
167
|
+
h(s, D, r.backgroundColor)
|
|
168
|
+
], a.prototype, "backgroundColor");
|
|
139
169
|
i([
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
], e.prototype, "backgroundColor");
|
|
170
|
+
l({ type: Object })
|
|
171
|
+
], a.prototype, "placeholder");
|
|
143
172
|
i([
|
|
144
|
-
|
|
145
|
-
],
|
|
173
|
+
z("img")
|
|
174
|
+
], a.prototype, "img");
|
|
146
175
|
i([
|
|
147
|
-
C(
|
|
148
|
-
],
|
|
149
|
-
|
|
176
|
+
C()
|
|
177
|
+
], a.prototype, "_hasError");
|
|
178
|
+
P(s, a);
|
|
150
179
|
export {
|
|
151
|
-
|
|
180
|
+
a as PieThumbnail,
|
|
152
181
|
$ as aspectRatios,
|
|
153
|
-
|
|
154
|
-
|
|
182
|
+
x as backgroundColorClassNames,
|
|
183
|
+
D as backgroundColors,
|
|
155
184
|
r as defaultProps,
|
|
156
|
-
|
|
157
|
-
|
|
185
|
+
R as sizes,
|
|
186
|
+
I as variants
|
|
158
187
|
};
|
package/dist/react.d.ts
CHANGED
|
@@ -27,21 +27,34 @@ declare class PieThumbnail_2 extends LitElement implements ThumbnailProps {
|
|
|
27
27
|
alt: string;
|
|
28
28
|
disabled: boolean;
|
|
29
29
|
hasPadding: boolean;
|
|
30
|
+
hideDefaultPlaceholder: boolean;
|
|
30
31
|
backgroundColor: "default" | "subtle" | "strong" | "dark" | "inverse" | "inverse-alternative";
|
|
31
32
|
placeholder: ThumbnailProps['placeholder'];
|
|
32
33
|
private img;
|
|
34
|
+
private _hasError;
|
|
33
35
|
/**
|
|
34
|
-
*
|
|
35
|
-
|
|
36
|
+
* Determines if the default placeholder should be displayed.
|
|
37
|
+
*/
|
|
38
|
+
private get _isDefaultPlaceholderVisible();
|
|
39
|
+
/**
|
|
40
|
+
* Returns the appropriate image props based on the following order:
|
|
41
|
+
* 1. If there is no error, return the provided image props.
|
|
42
|
+
* 2. If there is an error and a custom placeholder is provided, return the placeholder props.
|
|
43
|
+
* 3. If there is an error and no custom placeholder is provided, return the component default placeholder.
|
|
44
|
+
* 4. Otherwise, fall back to the provided src (resulting in a broken image).
|
|
45
|
+
*/
|
|
46
|
+
private get _controlledSrc();
|
|
47
|
+
private get _controlledAlt();
|
|
48
|
+
/**
|
|
49
|
+
* Assigns CSS variables based on the size prop.
|
|
36
50
|
*/
|
|
37
51
|
private _generateSizeStyles;
|
|
38
52
|
/**
|
|
39
|
-
* Handles
|
|
40
|
-
* with the placeholder props.
|
|
53
|
+
* Handles the image error event.
|
|
41
54
|
*/
|
|
42
55
|
private _handleImageError;
|
|
43
56
|
/**
|
|
44
|
-
*
|
|
57
|
+
* Checks the image load status and triggers error handling if needed.
|
|
45
58
|
* This is needed as the `onerror` event is not triggered in SSR.
|
|
46
59
|
*/
|
|
47
60
|
private _checkImageError;
|
|
@@ -89,7 +102,11 @@ export declare interface ThumbnailProps {
|
|
|
89
102
|
*/
|
|
90
103
|
backgroundColor?: typeof backgroundColors[number];
|
|
91
104
|
/**
|
|
92
|
-
*
|
|
105
|
+
* When true, hides the component default placeholder on image load failure.
|
|
106
|
+
*/
|
|
107
|
+
hideDefaultPlaceholder?: boolean;
|
|
108
|
+
/**
|
|
109
|
+
* Overrides the component default placeholder with a custom one on image load failure.
|
|
93
110
|
*/
|
|
94
111
|
placeholder?: PlaceholderProps;
|
|
95
112
|
/**
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@justeattakeaway/pie-thumbnail",
|
|
3
3
|
"description": "PIE Design System Thumbnail built using Web Components",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.6.1",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"module": "dist/index.js",
|
|
@@ -24,8 +24,6 @@
|
|
|
24
24
|
"lint:style": "run -T stylelint ./src/**/*.{css,scss}",
|
|
25
25
|
"lint:style:fix": "yarn lint:style --fix",
|
|
26
26
|
"watch": "run -T vite build --watch",
|
|
27
|
-
"test": "echo \"Error: no test specified\" && exit 0",
|
|
28
|
-
"test:ci": "yarn test",
|
|
29
27
|
"test:browsers": "npx playwright test -c ./playwright-lit.config.ts",
|
|
30
28
|
"test:browsers:ci": "yarn test:browsers",
|
|
31
29
|
"test:visual": "run -T cross-env-shell PERCY_TOKEN=${PERCY_TOKEN_PIE_THUMBNAIL} percy exec --allowed-hostname cloudfront.net -- npx playwright test -c ./playwright-lit-visual.config.ts",
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 33 32"><path d="M32.399 15.493c-.102-.255-1.495-2.753-4.081-5.888a.507.507 0 0 1-.119-.267 48.162 48.162 0 0 0-.778-5.436.88.88 0 0 0-.282-.467.928.928 0 0 0-.509-.221l-2.679-.323a.84.84 0 0 0-.071 0c-.15 0-.294.058-.401.161s-.166.243-.166.389v.906c0 .009-.004.017-.011.023s-.015.01-.025.01c-.015-.003-.018-.006-.021-.008A37.89 37.89 0 0 0 17.829.395 2.43 2.43 0 0 0 16.493 0c-.473 0-.936.138-1.328.395C5.887 5.956.782 15.005.585 15.493a.87.87 0 0 0 .004.757.9.9 0 0 0 .246.306.93.93 0 0 0 .356.176l2.672.5c.177.047.335.144.454.279s.193.302.213.479c.023.457.527 10.691 1.162 13.345a.89.89 0 0 0 .328.479c.161.12.358.186.561.185h.02l4.528-.084h.129c.079-.001.155-.032.211-.086s.087-.128.087-.205l-.306-5.093c0-.054-.007-.121-.01-.176a.54.54 0 0 0-.08-.254.56.56 0 0 0-.193-.188c-.407-.236-.747-.566-.992-.96s-.385-.841-.41-1.3c-.142-3.589-.211-7.735-.008-10.981.003-.138.062-.27.165-.366a.545.545 0 0 1 .76.016c.099.1.152.234.149.372v.041c-.132 2.163-.142 4.72-.095 7.244a.61.61 0 0 0 .195.435.65.65 0 0 0 .454.174.65.65 0 0 0 .448-.189.61.61 0 0 0 .179-.441c-.048-2.54-.035-5.114.099-7.285.003-.138.062-.27.165-.366a.545.545 0 0 1 .76.016c.099.1.152.234.149.372v.041c-.132 2.152-.142 4.694-.096 7.204a.61.61 0 0 0 .194.435.65.65 0 0 0 .454.175.65.65 0 0 0 .448-.188.61.61 0 0 0 .18-.441c-.047-2.529-.034-5.093.101-7.249.003-.138.063-.27.165-.366s.241-.148.383-.145.278.061.377.161.152.234.149.372v.041c-.193 3.154-.13 7.147 0 10.651a.26.26 0 0 1 0 .033v.086c0 .455-.113.902-.331 1.305s-.533.747-.919 1.004a.54.54 0 0 0-.166.177.52.52 0 0 0-.07.229s-.067.538.179 3.144l.241 2.284c.009.067.043.128.095.172s.119.068.188.068h4.053l1.516.012c.07 0 .137-.024.189-.069s.086-.107.094-.174c.35-3.123.434-4.879.434-4.879-.002-.075-.032-.146-.084-.201s-.123-.09-.199-.099l-1.843-.246c-.122-.015-.238-.064-.331-.142s-.161-.181-.195-.297a.83.83 0 0 1-.024-.275c.747-10.411 4.282-13.92 4.282-13.92a1.05 1.05 0 0 1 .172-.144.575.575 0 0 1 .491-.082.57.57 0 0 1 .223.122.55.55 0 0 1 .145.205.97.97 0 0 1 .045.251c.306 3.272.157 8.842-.033 13.186l-.353 6.583c0 .057.023.112.065.152s.098.063.156.063l3.037.062h.021a.94.94 0 0 0 .561-.186.892.892 0 0 0 .328-.479c.635-2.654 1.134-12.887 1.161-13.344a.877.877 0 0 1 .214-.479.92.92 0 0 1 .453-.28l2.672-.5a.92.92 0 0 0 .499-.317.873.873 0 0 0 .194-.548.885.885 0 0 0-.101-.368z" fill="#efedea"/></svg>
|
package/src/defs.ts
CHANGED
|
@@ -63,7 +63,11 @@ export interface ThumbnailProps {
|
|
|
63
63
|
*/
|
|
64
64
|
backgroundColor?: typeof backgroundColors[number];
|
|
65
65
|
/**
|
|
66
|
-
*
|
|
66
|
+
* When true, hides the component default placeholder on image load failure.
|
|
67
|
+
*/
|
|
68
|
+
hideDefaultPlaceholder?: boolean;
|
|
69
|
+
/**
|
|
70
|
+
* Overrides the component default placeholder with a custom one on image load failure.
|
|
67
71
|
*/
|
|
68
72
|
placeholder?: PlaceholderProps;
|
|
69
73
|
/**
|
|
@@ -81,6 +85,7 @@ export const defaultProps: DefaultProps = {
|
|
|
81
85
|
alt: '',
|
|
82
86
|
disabled: false,
|
|
83
87
|
hasPadding: false,
|
|
88
|
+
hideDefaultPlaceholder: false,
|
|
84
89
|
backgroundColor: 'default',
|
|
85
90
|
aspectRatio: '1by1',
|
|
86
91
|
placeholder: {
|
package/src/index.ts
CHANGED
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
} from 'lit';
|
|
6
6
|
import { defineCustomElement, validPropertyValues } from '@justeattakeaway/pie-webc-core';
|
|
7
7
|
import { classMap } from 'lit/directives/class-map.js';
|
|
8
|
-
import { property, query } from 'lit/decorators.js';
|
|
8
|
+
import { property, query, state } from 'lit/decorators.js';
|
|
9
9
|
import {
|
|
10
10
|
type ThumbnailProps,
|
|
11
11
|
defaultProps,
|
|
@@ -16,6 +16,7 @@ import {
|
|
|
16
16
|
aspectRatios,
|
|
17
17
|
} from './defs';
|
|
18
18
|
import styles from './thumbnail.scss?inline';
|
|
19
|
+
import defaultPlaceholder from './default-placeholder.svg?inline';
|
|
19
20
|
|
|
20
21
|
// Valid values available to consumers
|
|
21
22
|
export * from './defs';
|
|
@@ -50,6 +51,9 @@ export class PieThumbnail extends LitElement implements ThumbnailProps {
|
|
|
50
51
|
@property({ type: Boolean })
|
|
51
52
|
public hasPadding = defaultProps.hasPadding;
|
|
52
53
|
|
|
54
|
+
@property({ type: Boolean })
|
|
55
|
+
public hideDefaultPlaceholder = defaultProps.hideDefaultPlaceholder;
|
|
56
|
+
|
|
53
57
|
@property({ type: String })
|
|
54
58
|
@validPropertyValues(componentSelector, backgroundColors, defaultProps.backgroundColor)
|
|
55
59
|
public backgroundColor = defaultProps.backgroundColor;
|
|
@@ -60,36 +64,69 @@ export class PieThumbnail extends LitElement implements ThumbnailProps {
|
|
|
60
64
|
@query('img')
|
|
61
65
|
private img!: HTMLImageElement;
|
|
62
66
|
|
|
67
|
+
@state()
|
|
68
|
+
private _hasError = false;
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Determines if the default placeholder should be displayed.
|
|
72
|
+
*/
|
|
73
|
+
private get _isDefaultPlaceholderVisible (): boolean {
|
|
74
|
+
const { _hasError, placeholder, hideDefaultPlaceholder } = this;
|
|
75
|
+
return _hasError && !placeholder?.src && !hideDefaultPlaceholder;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Returns the appropriate image props based on the following order:
|
|
80
|
+
* 1. If there is no error, return the provided image props.
|
|
81
|
+
* 2. If there is an error and a custom placeholder is provided, return the placeholder props.
|
|
82
|
+
* 3. If there is an error and no custom placeholder is provided, return the component default placeholder.
|
|
83
|
+
* 4. Otherwise, fall back to the provided src (resulting in a broken image).
|
|
84
|
+
*/
|
|
85
|
+
private get _controlledSrc (): string {
|
|
86
|
+
if (!this._hasError) return this.src;
|
|
87
|
+
if (this.placeholder?.src) return this.placeholder.src;
|
|
88
|
+
if (!this.hideDefaultPlaceholder) return defaultPlaceholder;
|
|
89
|
+
return this.src;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
private get _controlledAlt (): string {
|
|
93
|
+
if (!this._hasError) return this.alt;
|
|
94
|
+
if (this.placeholder?.src) return this.placeholder.alt ?? '';
|
|
95
|
+
if (!this.hideDefaultPlaceholder) return '';
|
|
96
|
+
return this.alt;
|
|
97
|
+
}
|
|
98
|
+
|
|
63
99
|
/**
|
|
64
|
-
* Assigns
|
|
65
|
-
* based on the size prop.
|
|
100
|
+
* Assigns CSS variables based on the size prop.
|
|
66
101
|
*/
|
|
67
102
|
private _generateSizeStyles (): string {
|
|
68
103
|
const { size } = this;
|
|
69
104
|
let borderRadius = '--dt-radius-rounded-c';
|
|
105
|
+
let defaultPlaceholderPadding = '--dt-spacing-d';
|
|
70
106
|
if (size <= 40) {
|
|
71
107
|
borderRadius = '--dt-radius-rounded-a';
|
|
108
|
+
defaultPlaceholderPadding = '--dt-spacing-a';
|
|
72
109
|
} else if (size <= 56) {
|
|
73
110
|
borderRadius = '--dt-radius-rounded-b';
|
|
111
|
+
defaultPlaceholderPadding = '--dt-spacing-b';
|
|
74
112
|
}
|
|
75
113
|
|
|
76
114
|
return `
|
|
77
115
|
--thumbnail-size: ${size}px;
|
|
78
116
|
--thumbnail-border-radius: var(${borderRadius});
|
|
117
|
+
--thumbnail-default-placeholder-padding: var(${defaultPlaceholderPadding});
|
|
79
118
|
`;
|
|
80
119
|
}
|
|
81
120
|
|
|
82
121
|
/**
|
|
83
|
-
* Handles
|
|
84
|
-
* with the placeholder props.
|
|
122
|
+
* Handles the image error event.
|
|
85
123
|
*/
|
|
86
|
-
private _handleImageError () {
|
|
87
|
-
|
|
88
|
-
if (this.placeholder?.alt) this.setAttribute('alt', this.placeholder.alt);
|
|
124
|
+
private _handleImageError (): void {
|
|
125
|
+
this._hasError = true;
|
|
89
126
|
}
|
|
90
127
|
|
|
91
128
|
/**
|
|
92
|
-
*
|
|
129
|
+
* Checks the image load status and triggers error handling if needed.
|
|
93
130
|
* This is needed as the `onerror` event is not triggered in SSR.
|
|
94
131
|
*/
|
|
95
132
|
private _checkImageError () {
|
|
@@ -107,10 +144,11 @@ export class PieThumbnail extends LitElement implements ThumbnailProps {
|
|
|
107
144
|
render () {
|
|
108
145
|
const {
|
|
109
146
|
variant,
|
|
110
|
-
|
|
111
|
-
|
|
147
|
+
_controlledSrc,
|
|
148
|
+
_controlledAlt,
|
|
112
149
|
disabled,
|
|
113
150
|
hasPadding,
|
|
151
|
+
_isDefaultPlaceholderVisible,
|
|
114
152
|
backgroundColor,
|
|
115
153
|
aspectRatio,
|
|
116
154
|
} = this;
|
|
@@ -122,6 +160,7 @@ export class PieThumbnail extends LitElement implements ThumbnailProps {
|
|
|
122
160
|
[backgroundColorClassNames[backgroundColor]]: true,
|
|
123
161
|
'c-thumbnail--disabled': disabled,
|
|
124
162
|
'c-thumbnail--padding': hasPadding,
|
|
163
|
+
'c-thumbnail--defaultPlaceholder': _isDefaultPlaceholderVisible,
|
|
125
164
|
};
|
|
126
165
|
|
|
127
166
|
const sizeStyles = this._generateSizeStyles();
|
|
@@ -132,9 +171,9 @@ export class PieThumbnail extends LitElement implements ThumbnailProps {
|
|
|
132
171
|
style="${sizeStyles}">
|
|
133
172
|
<img
|
|
134
173
|
data-test-id="pie-thumbnail-img"
|
|
135
|
-
src="${
|
|
174
|
+
src="${_controlledSrc}"
|
|
175
|
+
alt="${_controlledAlt}"
|
|
136
176
|
class="c-thumbnail-img"
|
|
137
|
-
alt="${alt}"
|
|
138
177
|
@error="${this._handleImageError}"
|
|
139
178
|
/>
|
|
140
179
|
</div>
|
package/src/thumbnail.scss
CHANGED
|
@@ -3,7 +3,9 @@
|
|
|
3
3
|
--thumbnail-border-radius: var(--dt-radius-rounded-b);
|
|
4
4
|
--thumbnail-bg-color: var(--dt-color-container-default);
|
|
5
5
|
--thumbnail-padding: calc(var(--dt-spacing-a) / 2);
|
|
6
|
+
--thumbnail-default-placeholder-padding: var(--dt-spacing-b);
|
|
6
7
|
--thumbnail-img-border-radius: unset;
|
|
8
|
+
--thumbnail-img-object-fit: cover;
|
|
7
9
|
|
|
8
10
|
display: flex;
|
|
9
11
|
justify-content: center;
|
|
@@ -60,6 +62,12 @@
|
|
|
60
62
|
width: 100%;
|
|
61
63
|
height: 100%;
|
|
62
64
|
border-radius: var(--thumbnail-img-border-radius);
|
|
63
|
-
object-fit:
|
|
65
|
+
object-fit: var(--thumbnail-img-object-fit);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
&.c-thumbnail--defaultPlaceholder {
|
|
69
|
+
--thumbnail-bg-color: var(--dt-color-container-default);
|
|
70
|
+
--thumbnail-img-object-fit: fill;
|
|
71
|
+
padding: var(--thumbnail-default-placeholder-padding);
|
|
64
72
|
}
|
|
65
73
|
}
|