@internetarchive/collection-browser 0.1.8 → 0.2.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.
Files changed (51) hide show
  1. package/.github/workflows/gh-pages-main.yml +39 -0
  2. package/.github/workflows/npm-publish.yml +39 -0
  3. package/.github/workflows/pr-preview.yml +38 -0
  4. package/README.md +21 -2
  5. package/dist/{demo → src}/app-root.d.ts +0 -0
  6. package/dist/{demo → src}/app-root.js +0 -0
  7. package/dist/src/app-root.js.map +1 -0
  8. package/dist/src/collection-browser.d.ts +6 -0
  9. package/dist/src/collection-browser.js +49 -25
  10. package/dist/src/collection-browser.js.map +1 -1
  11. package/dist/src/styles/{index.d.ts → item-image-styles.d.ts} +0 -0
  12. package/dist/src/styles/{index.js → item-image-styles.js} +20 -25
  13. package/dist/src/styles/item-image-styles.js.map +1 -0
  14. package/dist/src/tiles/grid/account-tile.js +2 -0
  15. package/dist/src/tiles/grid/account-tile.js.map +1 -1
  16. package/dist/src/tiles/grid/item-tile.js +13 -11
  17. package/dist/src/tiles/grid/item-tile.js.map +1 -1
  18. package/dist/src/tiles/item-image.d.ts +17 -13
  19. package/dist/src/tiles/item-image.js +63 -244
  20. package/dist/src/tiles/item-image.js.map +1 -1
  21. package/dist/src/tiles/list/tile-list-compact.d.ts +1 -0
  22. package/dist/src/tiles/list/tile-list-compact.js +2 -0
  23. package/dist/src/tiles/list/tile-list-compact.js.map +1 -1
  24. package/dist/src/tiles/list/tile-list.d.ts +2 -1
  25. package/dist/src/tiles/list/tile-list.js +2 -0
  26. package/dist/src/tiles/list/tile-list.js.map +1 -1
  27. package/{demo/index.html → index.html} +1 -3
  28. package/package.json +13 -7
  29. package/{demo → src}/app-root.ts +0 -0
  30. package/src/collection-browser.ts +51 -25
  31. package/src/styles/item-image-styles.ts +97 -0
  32. package/src/tiles/grid/account-tile.ts +2 -0
  33. package/src/tiles/grid/item-tile.ts +7 -6
  34. package/src/tiles/item-image.ts +68 -255
  35. package/src/tiles/item-tile-image.ts +61 -0
  36. package/src/tiles/list/tile-list-compact.ts +4 -0
  37. package/src/tiles/list/tile-list.ts +6 -1
  38. package/tsconfig.json +1 -1
  39. package/vite.config.ts +22 -0
  40. package/web-dev-server.config.mjs +1 -1
  41. package/dist/.nojekyll +0 -0
  42. package/dist/app-root.js +0 -816
  43. package/dist/demo/app-root.js.map +0 -1
  44. package/dist/index.html +0 -23
  45. package/dist/src/styles/index.js.map +0 -1
  46. package/dist/src/tiles/image/item-image.d.ts +0 -18
  47. package/dist/src/tiles/image/item-image.js +0 -210
  48. package/dist/src/tiles/image/item-image.js.map +0 -1
  49. package/dist/src/tiles/image/waveform-image.d.ts +0 -16
  50. package/dist/src/tiles/image/waveform-image.js +0 -168
  51. package/dist/src/tiles/image/waveform-image.js.map +0 -1
package/package.json CHANGED
@@ -3,18 +3,21 @@
3
3
  "description": "The Internet Archive Collection Browser.",
4
4
  "license": "AGPL-3.0-only",
5
5
  "author": "Internet Archive",
6
- "version": "0.1.8",
6
+ "version": "0.2.0",
7
7
  "main": "dist/index.js",
8
8
  "module": "dist/index.js",
9
9
  "scripts": {
10
- "start": "tsc && concurrently -k -r \"tsc --watch --preserveWatchOutput\" \"wds\"",
11
- "build": "tsc",
12
- "prepare": "tsc && husky install",
10
+ "start": "yarn run prepare && concurrently -k -r \"tsc --watch --preserveWatchOutput\" \"wds\"",
11
+ "prepare:ghpages": "rimraf ghpages && yarn run prepare && vite build",
12
+ "prepare": "rimraf dist && tsc && husky install",
13
13
  "lint": "eslint --ext .ts,.html . --ignore-path .gitignore && prettier \"**/*.ts\" --check --ignore-path .gitignore",
14
14
  "format": "eslint --ext .ts,.html . --fix --ignore-path .gitignore && prettier \"**/*.ts\" --write --ignore-path .gitignore",
15
15
  "circular": "madge --circular --extensions ts .",
16
16
  "test": "tsc && yarn run lint && yarn run circular && wtr --coverage",
17
- "test:watch": "tsc && concurrently -k -r \"tsc --watch --preserveWatchOutput\" \"wtr --watch\""
17
+ "test:watch": "tsc && concurrently -k -r \"tsc --watch --preserveWatchOutput\" \"wtr --watch\"",
18
+ "deploy": "yarn run deploy:run -e $(git branch --show-current)",
19
+ "deploy:run": "yarn run prepare:ghpages && touch ghpages/.nojekyll && yarn run deploy:gh",
20
+ "deploy:gh": "gh-pages -t -d ghpages -m \"Build for $(git log --pretty=format:\"%h %an %ai %s\" -n1) [skip ci]\""
18
21
  },
19
22
  "types": "dist/index.d.ts",
20
23
  "dependencies": {
@@ -23,6 +26,7 @@
23
26
  "@internetarchive/field-parsers": "^0.1.3",
24
27
  "@internetarchive/histogram-date-range": "^0.1.6",
25
28
  "@internetarchive/infinite-scroller": "^0.1.2",
29
+ "@internetarchive/local-cache": "^0.2.1",
26
30
  "@internetarchive/search-service": "^0.3.4",
27
31
  "@internetarchive/shared-resize-observer": "^0.2.0",
28
32
  "@lit/localize": "^0.11.2",
@@ -31,7 +35,6 @@
31
35
  "typescript-cookie": "^1.0.3"
32
36
  },
33
37
  "devDependencies": {
34
- "@internetarchive/local-cache": "^0.2.1",
35
38
  "@internetarchive/result-type": "^0.0.1",
36
39
  "@open-wc/eslint-config": "^7.0.0",
37
40
  "@open-wc/testing": "^3.0.3",
@@ -46,12 +49,15 @@
46
49
  "eslint-plugin-import": "^2.25.3",
47
50
  "eslint-plugin-lit-a11y": "^2.2.0",
48
51
  "eslint-plugin-wc": "^1.3.2",
52
+ "gh-pages": "^4.0.0",
49
53
  "husky": "^7.0.0",
50
54
  "madge": "^5.0.1",
51
55
  "prettier": "^2.4.1",
56
+ "rimraf": "^3.0.2",
52
57
  "sinon": "^12.0.1",
53
58
  "tslib": "^2.3.1",
54
- "typescript": "^4.4.4"
59
+ "typescript": "^4.4.4",
60
+ "vite": "^2.9.9"
55
61
  },
56
62
  "publishConfig": {
57
63
  "access": "public"
File without changes
@@ -162,6 +162,12 @@ export class CollectionBrowser
162
162
  */
163
163
  private endOfDataReached = false;
164
164
 
165
+ /**
166
+ * When page width resizes from desktop to mobile, set true to
167
+ * disable expand/collapse transition when loading.
168
+ */
169
+ private isResizeToMobile = false;
170
+
165
171
  private placeholderCellTemplate = html`<collection-browser-loading-tile></collection-browser-loading-tile>`;
166
172
 
167
173
  private tileModelAtCellIndex(index: number): TileModel | undefined {
@@ -241,31 +247,12 @@ export class CollectionBrowser
241
247
  render() {
242
248
  return html`
243
249
  <div id="content-container" class=${this.mobileView ? 'mobile' : ''}>
244
- <div id="left-column" class="column">
250
+ <div
251
+ id="left-column"
252
+ class="column${this.isResizeToMobile ? ' preload' : ''}"
253
+ >
245
254
  <div id="mobile-header-container">
246
- ${this.mobileView
247
- ? html`
248
- <div id="mobile-filter-collapse">
249
- <h1
250
- @click=${() => {
251
- this.mobileFacetsVisible = !this.mobileFacetsVisible;
252
- }}
253
- @keyup=${() => {
254
- this.mobileFacetsVisible = !this.mobileFacetsVisible;
255
- }}
256
- >
257
- <span
258
- class="collapser ${this.mobileFacetsVisible
259
- ? 'open'
260
- : ''}"
261
- >
262
- ${chevronIcon}
263
- </span>
264
- Filters
265
- </h1>
266
- </div>
267
- `
268
- : nothing}
255
+ ${this.mobileView ? this.mobileFacetsTemplate : nothing}
269
256
  <div id="results-total">
270
257
  <span id="big-results-count"
271
258
  >${this.totalResults !== undefined
@@ -382,6 +369,28 @@ export class CollectionBrowser
382
369
  return this.facetsLoading || this.fullYearAggregationLoading;
383
370
  }
384
371
 
372
+ private get mobileFacetsTemplate() {
373
+ return html`
374
+ <div id="mobile-filter-collapse">
375
+ <h1
376
+ @click=${() => {
377
+ this.isResizeToMobile = false;
378
+ this.mobileFacetsVisible = !this.mobileFacetsVisible;
379
+ }}
380
+ @keyup=${() => {
381
+ this.isResizeToMobile = false;
382
+ this.mobileFacetsVisible = !this.mobileFacetsVisible;
383
+ }}
384
+ >
385
+ <span class="collapser ${this.mobileFacetsVisible ? 'open' : ''}">
386
+ ${chevronIcon}
387
+ </span>
388
+ Filters
389
+ </h1>
390
+ </div>
391
+ `;
392
+ }
393
+
385
394
  private get facetsTemplate() {
386
395
  return html`
387
396
  ${this.facetsLoading ? this.loadingTemplate : nothing}
@@ -513,8 +522,13 @@ export class CollectionBrowser
513
522
  }
514
523
 
515
524
  handleResize(entry: ResizeObserverEntry): void {
525
+ const previousView = this.mobileView;
516
526
  if (entry.target === this.contentContainer) {
517
- this.mobileView = entry.contentRect.width < 600;
527
+ this.mobileView = entry.contentRect.width < this.mobileBreakpoint;
528
+ // If changing from desktop to mobile disable transition
529
+ if (this.mobileView && !previousView) {
530
+ this.isResizeToMobile = true;
531
+ }
518
532
  }
519
533
  }
520
534
 
@@ -1101,6 +1115,18 @@ export class CollectionBrowser
1101
1115
  display: block;
1102
1116
  }
1103
1117
 
1118
+ /**
1119
+ * When page width resizes from desktop to mobile, use this class to
1120
+ * disable expand/collapse transition when loading.
1121
+ */
1122
+ .preload * {
1123
+ transition: none !important;
1124
+ -webkit-transition: none !important;
1125
+ -moz-transition: none !important;
1126
+ -ms-transition: none !important;
1127
+ -o-transition: none !important;
1128
+ }
1129
+
1104
1130
  #content-container {
1105
1131
  display: flex;
1106
1132
  }
@@ -0,0 +1,97 @@
1
+ import { css } from 'lit';
2
+
3
+ /**
4
+ * Base item-image styles
5
+ */
6
+ export const baseItemImageStyles = css`
7
+ .drop-shadow {
8
+ filter: drop-shadow(1px 1px 2px rgba(0, 0, 0, 0.8));
9
+ overflow: hidden;
10
+ }
11
+
12
+ .list-box {
13
+ width: 100%;
14
+ height: 100%;
15
+ overflow: hidden;
16
+ box-sizing: border-box;
17
+ display: flex;
18
+ position: relative;
19
+ }
20
+
21
+ .contain {
22
+ object-fit: contain;
23
+ }
24
+
25
+ .cover {
26
+ object-fit: cover;
27
+ }
28
+
29
+ .blur {
30
+ filter: blur(15px);
31
+ width: 100%;
32
+ transform: scale(1.1);
33
+ }
34
+ `;
35
+
36
+ /**
37
+ * Waveform styles
38
+ */
39
+ export const waveformGradientStyles = css`
40
+ .waveform {
41
+ mix-blend-mode: screen;
42
+ }
43
+
44
+ .waveform-grad0 {
45
+ background: linear-gradient(
46
+ hsl(340, 80%, 55%),
47
+ hsl(0, 80%, 33%) 35%,
48
+ hsl(0, 80%, 22%) 70%,
49
+ hsl(0, 0%, 0%)
50
+ );
51
+ }
52
+
53
+ .waveform-grad1 {
54
+ background: linear-gradient(
55
+ hsl(300, 80%, 55%),
56
+ hsl(330, 80%, 33%) 35%,
57
+ hsl(330, 80%, 22%) 70%,
58
+ hsl(0, 0%, 0%)
59
+ );
60
+ }
61
+
62
+ .waveform-grad2 {
63
+ background: linear-gradient(
64
+ hsl(200, 80%, 55%),
65
+ hsl(230, 80%, 33%) 35%,
66
+ hsl(230, 80%, 22%) 70%,
67
+ hsl(0, 0%, 0%)
68
+ );
69
+ }
70
+
71
+ .waveform-grad3 {
72
+ background: linear-gradient(
73
+ hsl(160, 80%, 55%),
74
+ hsl(190, 80%, 33%) 35%,
75
+ hsl(190, 80%, 22%) 70%,
76
+ hsl(0, 0%, 0%)
77
+ );
78
+ }
79
+
80
+ .waveform-grad4 {
81
+ background: linear-gradient(
82
+ hsl(250, 80%, 55%),
83
+ hsl(280, 80%, 33%) 35%,
84
+ hsl(280, 80%, 22%) 70%,
85
+ hsl(0, 0%, 0%)
86
+ );
87
+ }
88
+
89
+ .waveform-grad5 {
90
+ background: linear-gradient(
91
+ hsl(280, 80%, 55%),
92
+ hsl(310, 80%, 33%) 35%,
93
+ hsl(310, 80%, 22%) 70%,
94
+ hsl(0, 0%, 0%)
95
+ );
96
+ }
97
+ `;
@@ -125,6 +125,7 @@ export class AccountTile extends LitElement {
125
125
  height: 25px;
126
126
  display: flex;
127
127
  justify-content: space-evenly;
128
+ line-height: initial;
128
129
  }
129
130
 
130
131
  #patron-icon {
@@ -141,6 +142,7 @@ export class AccountTile extends LitElement {
141
142
  display: -webkit-box;
142
143
  -webkit-box-orient: vertical;
143
144
  word-wrap: break-word;
145
+ word-break: break-all;
144
146
  line-height: 2rem;
145
147
  text-align: center;
146
148
  }
@@ -1,5 +1,5 @@
1
1
  /* eslint-disable import/no-duplicates */
2
- import { css, CSSResultGroup, html, LitElement } from 'lit';
2
+ import { css, CSSResultGroup, html, LitElement, nothing } from 'lit';
3
3
  import { customElement, property } from 'lit/decorators.js';
4
4
 
5
5
  import { TileModel } from '../../models';
@@ -19,20 +19,21 @@ export class ItemTile extends LitElement {
19
19
  @property({ type: String }) baseImageUrl?: string;
20
20
 
21
21
  render() {
22
- const itemTitle = this.model?.title || '';
23
- const itemCreator = this.model?.creator || '-';
24
-
22
+ const itemTitle = this.model?.title || nothing;
23
+ const itemCreator = this.model?.creator;
25
24
  return html`
26
25
  <div id="container">
27
26
  <div id="title-image-container">
28
- <h1 id="item-title" title=${itemTitle}>${this.model?.title}</h1>
27
+ <h1 id="item-title" title=${itemTitle}>${itemTitle}</h1>
29
28
  <div id="item-image-container">
30
29
  <item-image .model=${this.model} .baseImageUrl=${this.baseImageUrl}>
31
30
  </item-image>
32
31
  </div>
33
32
  <div class="item-creator">
34
33
  <div class="truncated">
35
- <span><strong>By:&nbsp;</strong>${itemCreator}</span>
34
+ ${itemCreator
35
+ ? html`<span>by&nbsp;${itemCreator}</span>`
36
+ : nothing}
36
37
  </div>
37
38
  </div>
38
39
  </div>
@@ -1,9 +1,14 @@
1
- import { css, CSSResultGroup, html, nothing, LitElement } from 'lit';
1
+ import { css, CSSResultGroup, html, LitElement } from 'lit';
2
2
  import { customElement, property, query, state } from 'lit/decorators.js';
3
- import { ifDefined } from 'lit/directives/if-defined.js';
4
- import { restrictedIcon } from '../assets/img/icons/restricted';
3
+ import { ClassInfo, classMap } from 'lit/directives/class-map.js';
4
+
5
5
  import { TileModel } from '../models';
6
6
 
7
+ import {
8
+ baseItemImageStyles,
9
+ waveformGradientStyles,
10
+ } from '../styles/item-image-styles';
11
+
7
12
  @customElement('item-image')
8
13
  export class ItemImage extends LitElement {
9
14
  @property({ type: Object }) model?: TileModel;
@@ -14,128 +19,38 @@ export class ItemImage extends LitElement {
14
19
 
15
20
  @property({ type: Boolean }) isCompactTile = false;
16
21
 
22
+ @property({ type: Boolean }) loggedIn = false;
23
+
17
24
  @state() private isWaveform = false;
18
25
 
19
- @query('.item-image') private itemImageWaveform!: HTMLImageElement;
26
+ @query('img') private baseImage!: HTMLImageElement;
20
27
 
21
28
  render() {
22
29
  return html`
23
- <div class=${ifDefined(this.imageBoxClass)}>
24
- ${this.model?.mediatype === 'audio'
25
- ? this.waveformTemplate
26
- : this.itemImageTemplate}
27
- </div>
28
- `;
29
- }
30
-
31
- private get imageSrc() {
32
- return `${this.baseImageUrl}/services/img/${this.model?.identifier}`;
33
- }
34
-
35
- // Templates
36
- private get itemImageTemplate() {
37
- return html`
38
- ${this.isListTile ? this.listImageTemplate : this.tileImageTemplate}
39
- `;
40
- }
41
-
42
- private get tileImageTemplate() {
43
- return html`
44
- <div
45
- class=${this.imageClass}
46
- style="background-image:url(${this.imageSrc})"
47
- ></div>
48
- ${this.tileActionTemplate}
49
- `;
50
- }
51
-
52
- private get listImageTemplate() {
53
- if (!this.model) {
54
- return nothing;
55
- }
56
- return html`
57
- <img src="${this.imageSrc}" alt="" class="${this.listImageClass}" />
58
- ${this.restrictedIconTemplate}
59
- `;
60
- }
61
-
62
- private get waveformTemplate() {
63
- return html`
64
- <div class=${this.boxWaveformClass}>
30
+ <div class=${classMap(this.itemBaseClass)}>
65
31
  <img
66
- class=${this.itemImageWaveformClass}
32
+ class=${classMap(this.itemImageClass)}
67
33
  src="${this.imageSrc}"
68
- alt="${ifDefined(this.model?.title)}"
69
- @load=${this.onLoadItemImageCheck}
34
+ alt=""
35
+ @load=${this.onLoad}
70
36
  />
71
37
  </div>
72
38
  `;
73
39
  }
74
40
 
75
- private get restrictedIconTemplate() {
76
- if (!this.model?.contentWarning) {
77
- return nothing;
78
- }
79
- return html` ${restrictedIcon} `;
80
- }
81
-
82
- private get tileActionTemplate() {
83
- if (!this.model?.contentWarning) {
84
- return nothing;
85
- }
86
- return html`
87
- <div class="tile-action no-preview">Content may be inappropriate</div>
88
- `;
89
- }
90
-
91
- private onLoadItemImageCheck() {
92
- const aspectRatio =
93
- this.itemImageWaveform.naturalWidth /
94
- this.itemImageWaveform.naturalHeight;
95
- if (aspectRatio === 4) {
96
- this.isWaveform = true;
97
- }
98
- }
99
-
100
- // Classes
101
- private get imageClass() {
102
- return `item-image ${
103
- this.model?.contentWarning ? 'deemphasize' : 'default'
104
- }`;
105
- }
106
-
107
- private get listImageClass() {
108
- return `list-image ${this.model?.mediatype}${
109
- this.isCompactTile ? ' compact' : ''
110
- }`;
111
- }
112
-
113
- private get imageBoxClass() {
114
- if (this.isListTile) {
115
- return `list-image-box${
116
- this.model?.contentWarning ? ' deemphasize' : ''
117
- }`;
118
- }
119
- if (this.model?.contentWarning) {
120
- return 'item-image-box';
121
- }
122
- return undefined;
123
- }
124
-
125
- private get boxWaveformClass() {
126
- return `item-audio${this.isWaveform ? ` ${this.hashBasedGradient}` : ''}`;
127
- }
128
-
129
- private get itemImageWaveformClass() {
130
- return `item-image${this.isWaveform ? ' waveform' : ''}`;
41
+ /**
42
+ * Helpers
43
+ */
44
+ private get imageSrc() {
45
+ return `${this.baseImageUrl}/services/img/${this.model?.identifier}`;
131
46
  }
132
47
 
133
48
  private get hashBasedGradient() {
134
49
  if (!this.model?.identifier) {
135
- return 'grad1';
50
+ return 'waveform-grad0';
136
51
  }
137
52
  const gradient = this.hashStrToInt(this.model.identifier) % 6; // returns 0-5
138
- return `grad${gradient}`;
53
+ return `waveform-grad${gradient}`;
139
54
  }
140
55
 
141
56
  private hashStrToInt(str: string): number {
@@ -144,154 +59,52 @@ export class ItemImage extends LitElement {
144
59
  .reduce((acc: number, char: string) => acc + char.charCodeAt(0), 0);
145
60
  }
146
61
 
147
- static get styles(): CSSResultGroup {
148
- return css`
149
- .item-image-box {
150
- width: 16rem;
151
- height: 16rem;
152
- overflow: hidden;
153
- position: relative;
154
- box-shadow: 1px 1px 2px 0px;
155
- display: flex;
156
- }
157
-
158
- .item-image {
159
- width: 16rem;
160
- height: 16rem;
161
- object-fit: contain;
162
- background-repeat: no-repeat;
163
- background-position: center center;
164
- position: relative;
165
- -webkit-appearance: none;
166
- overflow: visible;
167
- }
168
-
169
- .list-image-box.deemphasize {
170
- border: 1px solid #767676;
171
- }
172
-
173
- .list-image-box {
174
- width: 100%;
175
- height: 100%;
176
- overflow: hidden;
177
- box-sizing: border-box;
178
- display: flex;
179
- position: relative;
180
- }
181
-
182
- .list-image {
183
- width: 100%;
184
- height: 100%;
185
- overflow: hidden;
186
- }
187
-
188
- img.list-image {
189
- overflow: hidden;
190
- object-fit: contain;
191
- border-radius: var(--border-radius, 0);
192
- -webkit-border-radius: var(--border-radius, 0);
193
- -moz-border-radius: var(--border-radius, 0);
194
- }
195
-
196
- img.list-image.compact {
197
- object-fit: cover;
198
- }
199
-
200
- .waveform {
201
- mix-blend-mode: screen;
202
- }
203
-
204
- .default {
205
- background-size: contain;
206
- filter: drop-shadow(1px 1px 2px rgba(0, 0, 0, 0.8));
207
- }
208
-
209
- .deemphasize .list-image,
210
- .deemphasize.item-image {
211
- background-size: contain;
212
- filter: blur(15px);
213
- z-index: 1;
214
- }
215
-
216
- .deemphasize svg {
217
- padding: 25%;
218
- z-index: 2;
219
- position: absolute;
220
- }
221
-
222
- .tile-action {
223
- border: 1px solid currentColor;
224
- border-radius: 1px;
225
- padding: 5px;
226
- font-weight: 500;
227
- width: auto;
228
- position: absolute;
229
- z-index: 2;
230
- display: flex;
231
- top: 5.5rem;
232
- }
233
-
234
- .no-preview {
235
- background-color: #fffecb;
236
- color: #2c2c2c;
237
- font-size: 1.4rem;
238
- line-height: 2rem;
239
- text-align: center;
240
- }
241
-
242
- .grad0 {
243
- background: linear-gradient(
244
- hsl(340, 80%, 55%),
245
- hsl(0, 80%, 33%) 35%,
246
- hsl(0, 80%, 22%) 70%,
247
- hsl(0, 0%, 0%)
248
- );
249
- }
250
-
251
- .grad1 {
252
- background: linear-gradient(
253
- hsl(300, 80%, 55%),
254
- hsl(330, 80%, 33%) 35%,
255
- hsl(330, 80%, 22%) 70%,
256
- hsl(0, 0%, 0%)
257
- );
258
- }
259
-
260
- .grad2 {
261
- background: linear-gradient(
262
- hsl(200, 80%, 55%),
263
- hsl(230, 80%, 33%) 35%,
264
- hsl(230, 80%, 22%) 70%,
265
- hsl(0, 0%, 0%)
266
- );
267
- }
268
-
269
- .grad3 {
270
- background: linear-gradient(
271
- hsl(160, 80%, 55%),
272
- hsl(190, 80%, 33%) 35%,
273
- hsl(190, 80%, 22%) 70%,
274
- hsl(0, 0%, 0%)
275
- );
276
- }
277
-
278
- .grad4 {
279
- background: linear-gradient(
280
- hsl(250, 80%, 55%),
281
- hsl(280, 80%, 33%) 35%,
282
- hsl(280, 80%, 22%) 70%,
283
- hsl(0, 0%, 0%)
284
- );
285
- }
62
+ /**
63
+ * Classes
64
+ */
65
+ private get itemBaseClass(): ClassInfo {
66
+ return {
67
+ 'drop-shadow': true,
68
+ 'list-box': this.isListTile,
69
+ [this.hashBasedGradient]: this.isWaveform,
70
+ };
71
+ }
72
+
73
+ private get itemImageClass(): ClassInfo {
74
+ return {
75
+ contain: !this.isCompactTile,
76
+ cover: this.isCompactTile,
77
+ blur: this.model?.contentWarning || false,
78
+ waveform: this.isWaveform,
79
+ };
80
+ }
81
+
82
+ /**
83
+ * Event listener sets isWaveform true if image is waveform
84
+ */
85
+ private onLoad() {
86
+ if (
87
+ (this.model?.mediatype === 'audio' ||
88
+ this.model?.mediatype === 'etree') &&
89
+ this.baseImage.naturalWidth / this.baseImage.naturalHeight === 4
90
+ ) {
91
+ this.isWaveform = true;
92
+ }
93
+ }
286
94
 
287
- .grad5 {
288
- background: linear-gradient(
289
- hsl(280, 80%, 55%),
290
- hsl(310, 80%, 33%) 35%,
291
- hsl(310, 80%, 22%) 70%,
292
- hsl(0, 0%, 0%)
293
- );
294
- }
295
- `;
95
+ /**
96
+ * CSS
97
+ */
98
+ static get styles(): CSSResultGroup {
99
+ return [
100
+ baseItemImageStyles,
101
+ waveformGradientStyles,
102
+ css`
103
+ img {
104
+ height: var(--imgHeight, 16rem);
105
+ width: var(--imgWidth, 16rem);
106
+ }
107
+ `,
108
+ ];
296
109
  }
297
110
  }