Skip to content

Commit

Permalink
Merge pull request #913 from simonihmig/wc-async-blurhash
Browse files Browse the repository at this point in the history
Load blurhash script lazily in web component
  • Loading branch information
simonihmig authored Jan 11, 2025
2 parents 4a825d6 + 97b60b0 commit c3c134c
Show file tree
Hide file tree
Showing 6 changed files with 711 additions and 904 deletions.
5 changes: 5 additions & 0 deletions .changeset/eleven-mangos-join.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@responsive-image/wc': patch
---

Load blurhash script lazily in web component
2 changes: 2 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,8 @@ jobs:
cache: 'pnpm'
- name: Install Dependencies
run: pnpm install --no-lockfile
- name: Install Playwright
run: pnpx playwright install --with-deps
- name: TurboRepo local server
uses: felixmosh/turborepo-gh-artifacts@v3
with:
Expand Down
1 change: 1 addition & 0 deletions packages/wc/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
"test:watch": "vitest watch"
},
"dependencies": {
"@lit/task": "^1.0.2",
"@responsive-image/core": "workspace:^",
"blurhash": "^2.0.0",
"lit": "^3.1.4"
Expand Down
57 changes: 28 additions & 29 deletions packages/wc/src/responsive-image.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
import { html, css, LitElement, nothing } from 'lit';
import { customElement, property, state } from 'lit/decorators.js';
import { Task, TaskStatus } from '@lit/task';
import {
type ImageType,
type LqipBlurhash,
type ImageData,
type ImageType,
type Lqip,
env,
getDestinationWidthBySize,
} from '@responsive-image/core';
import { ClassInfo, classMap } from 'lit/directives/class-map.js';
import { css, html, LitElement, nothing } from 'lit';
import { customElement, property, state } from 'lit/decorators.js';
import { type ClassInfo, classMap } from 'lit/directives/class-map.js';
import { ifDefined } from 'lit/directives/if-defined.js';
import { decode2url } from '@responsive-image/core/blurhash/decode';
import { StyleInfo, styleMap } from 'lit/directives/style-map.js';
import { type StyleInfo, styleMap } from 'lit/directives/style-map.js';

interface ImageSource {
srcset: string;
Expand Down Expand Up @@ -172,24 +172,22 @@ export class ResponsiveImage extends LitElement {
return this.src.imageUrlFor(this.imgWidth ?? 640);
}

get hasLqipBlurhash(): boolean {
return this.src.lqip?.type === 'blurhash';
}
private blurhashTask = new Task(this, {
task: async ([lqip]: readonly [Lqip | undefined]) => {
if (lqip?.type !== 'blurhash' || this.complete) {
return '';
}

get showLqipBlurhash(): boolean {
return !this.complete && this.hasLqipBlurhash;
}
const { hash, width, height } = lqip;
const { decode2url } = await import(
'@responsive-image/core/blurhash/decode'
);
const uri = decode2url(hash, width, height);

get lqipBlurhash(): string | undefined {
if (!this.hasLqipBlurhash) {
return undefined;
}

const { hash, width, height } = this.src.lqip as LqipBlurhash;
const uri = decode2url(hash, width, height);

return `url("${uri}")`;
}
return uri;
},
args: () => [this.src.lqip],
});

render() {
const { lqip } = this.src;
Expand All @@ -204,12 +202,13 @@ export class ResponsiveImage extends LitElement {
(lqip?.type === 'color' || lqip?.type === 'inline') && !this.complete,
};

const styles: StyleInfo = this.showLqipBlurhash
? {
backgroundImage: this.lqipBlurhash,
backgroundSize: 'cover',
}
: {};
const styles: StyleInfo =
this.blurhashTask.status === TaskStatus.COMPLETE && !this.complete
? {
backgroundImage: `url("${this.blurhashTask.value}")`,
backgroundSize: 'cover',
}
: {};

return html`
<picture>
Expand Down
6 changes: 6 additions & 0 deletions packages/wc/test/responsive-image.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -571,6 +571,12 @@ describe('ResponsiveImage', () => {
expect(imgEl).toBeDefined();
expect(imgEl!.complete).toBe(false);

await waitUntil(
() => imgEl!.style.backgroundImage.startsWith('url'),
undefined,
{ interval: 1, timeout: 5000 },
);

expect(imgEl!.style.backgroundImage, 'it has a background PNG').to.match(
/data:image\/png/,
);
Expand Down
Loading

0 comments on commit c3c134c

Please sign in to comment.