svelte-remote-image 0.2.6 → 0.3.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/README.md +31 -32
- package/dist/components/Img.svelte +74 -0
- package/dist/components/Img.svelte.d.ts +24 -0
- package/dist/components/{Image.svelte → Picture.svelte} +7 -7
- package/dist/components/{Image.svelte.d.ts → Picture.svelte.d.ts} +6 -6
- package/dist/components/{image.type.d.ts → type.d.ts} +9 -2
- package/dist/index.d.ts +4 -3
- package/dist/index.js +3 -2
- package/package.json +3 -2
- /package/dist/components/{image.type.js → type.js} +0 -0
package/README.md
CHANGED
|
@@ -6,7 +6,7 @@ Display optimized, responsive and progressive images for Svelte.
|
|
|
6
6
|
With remote image URL of CDN or other means.
|
|
7
7
|
|
|
8
8
|
- Fade-in and blur on image reveal.
|
|
9
|
-
- An image URL can be set to
|
|
9
|
+
- An image URL can be set to fallback if an image cannot be retrieved from the source URL due to an error.
|
|
10
10
|
- A pre-rendered low-quality dataURI can be set as a placeholder.
|
|
11
11
|
|
|
12
12
|
|
|
@@ -21,13 +21,15 @@ $ npm i svelte-remote-image
|
|
|
21
21
|
And import components and types.
|
|
22
22
|
|
|
23
23
|
```
|
|
24
|
-
import {
|
|
24
|
+
import { Img, Picture, type ImgSrc, type PictureSrc } from "svelte-remote-image";
|
|
25
25
|
```
|
|
26
26
|
|
|
27
27
|
## How to use
|
|
28
28
|
|
|
29
29
|
Sample code.
|
|
30
30
|
|
|
31
|
+
### Img
|
|
32
|
+
|
|
31
33
|
```
|
|
32
34
|
<script lang="ts">
|
|
33
35
|
import { Image, type ImageSrc } from "svelte-remote-image";
|
|
@@ -36,46 +38,39 @@ Sample code.
|
|
|
36
38
|
const optimazerPrefix = 'https://nostr-image-optimizer.ocknamo.com/image/';
|
|
37
39
|
const originalImageUrl = 'https://ocknamo.com/static/b84d6366deec053ff3fa77df01a54464/dccd3/cat.webp'
|
|
38
40
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
};
|
|
41
|
+
const imgSrc: ImgSrc = {
|
|
42
|
+
w: 800,
|
|
43
|
+
img: `https://ocknamo.com/cat.jpg`,
|
|
44
|
+
srssets: [
|
|
45
|
+
{
|
|
46
|
+
src: `https://ocknamo.com/cat_1600.jpg`,
|
|
47
|
+
w: 1600,
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
src: `https://ocknamo.com/cat_800.jpg`,
|
|
51
|
+
w: 800,
|
|
52
|
+
},
|
|
53
|
+
],
|
|
54
|
+
fallback: ['https://ocknamo.com/cat_fallback.jpg'],
|
|
55
|
+
}
|
|
55
56
|
</script>
|
|
56
57
|
|
|
57
|
-
<
|
|
58
|
+
<Img src={imgSrc} style='max-width: 400px; max-width: 80%;' />
|
|
58
59
|
```
|
|
59
60
|
|
|
60
61
|
The image component renders into:
|
|
61
62
|
|
|
62
63
|
```
|
|
63
|
-
<
|
|
64
|
-
|
|
65
|
-
srcset="https://nostr-image-optimizer.ocknamo.com/image/width=1600,quality=50,format=webp/https://ocknamo.com/static/b84d6366deec053ff3fa77df01a54464/dccd3/cat.webp 1600w, https://nostr-image-optimizer.ocknamo.com/image/width=800,quality=50,format=webp/https://ocknamo.com/static/b84d6366deec053ff3fa77df01a54464/dccd3/cat.webp 800w"
|
|
66
|
-
type="image/webp">
|
|
67
|
-
<source
|
|
68
|
-
srcset="https://nostr-image-optimizer.ocknamo.com/image/width=1600,quality=50,format=jpeg/https://ocknamo.com/static/b84d6366deec053ff3fa77df01a54464/dccd3/cat.webp 1600w, https://nostr-image-optimizer.ocknamo.com/image/width=800,quality=50,format=jpeg/https://ocknamo.com/static/b84d6366deec053ff3fa77df01a54464/dccd3/cat.webp 800w"
|
|
69
|
-
type="image/jpeg"> <img width="800"
|
|
70
|
-
style="max-width: 100%; background-color: '#c5c5c5'; display: inline;"
|
|
71
|
-
class="image-blur-loaded"
|
|
72
|
-
src="https://nostr-image-optimizer.ocknamo.com/image/width=1600,quality=70,format=webp/https://ocknamo.com/static/b84d6366deec053ff3fa77df01a54464/dccd3/cat.webp"
|
|
73
|
-
alt="blog top" loading="lazy">
|
|
74
|
-
</picture>
|
|
64
|
+
<img id="svelte-remote-image--6188058" width="800" style="max-width: 80%; visibility: hidden;"
|
|
65
|
+
src="https://ocknamo.com/cat_fallback.jpg" srcset="" alt="" title="" loading="lazy" class="s-6LbhuE7J5MgN">
|
|
75
66
|
```
|
|
76
67
|
|
|
77
68
|
Inspired by [svelte-img](https://github.com/zerodevx/svelte-img?tab=readme-ov-file#remote-images-from-an-api).
|
|
78
69
|
|
|
70
|
+
### Picture
|
|
71
|
+
|
|
72
|
+
TBD
|
|
73
|
+
|
|
79
74
|
## Config
|
|
80
75
|
|
|
81
76
|
### ImageSrc
|
|
@@ -92,6 +87,10 @@ Image width.
|
|
|
92
87
|
|
|
93
88
|
Image height.
|
|
94
89
|
|
|
90
|
+
#### srssets: Srcset[]
|
|
91
|
+
|
|
92
|
+
Image sources for Img component.
|
|
93
|
+
|
|
95
94
|
#### webp?: Srcset[]
|
|
96
95
|
|
|
97
96
|
Image sources for webp.
|
|
@@ -104,7 +103,7 @@ Image sources for jpeg.
|
|
|
104
103
|
|
|
105
104
|
Image sources for png.
|
|
106
105
|
|
|
107
|
-
####
|
|
106
|
+
#### fallback: string[]
|
|
108
107
|
|
|
109
108
|
Failback image urls.
|
|
110
109
|
The order is important because the images are tested in order from the top of the array.
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
<script>import { browser } from "$app/environment";
|
|
2
|
+
import { afterUpdate } from "svelte";
|
|
3
|
+
export let src;
|
|
4
|
+
export let style;
|
|
5
|
+
export const alt = "";
|
|
6
|
+
export const title = "";
|
|
7
|
+
const imgId = `svelte-remote-image-${alt.replaceAll(" ", "-")}-${Math.round(Math.random() * 1e7)}`;
|
|
8
|
+
const getImgElement = () => browser ? document.getElementById(imgId) : null;
|
|
9
|
+
afterUpdate(async () => {
|
|
10
|
+
const img = getImgElement();
|
|
11
|
+
if (!img) {
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
if (img.naturalWidth !== 0 && img.naturalHeight !== 0) {
|
|
15
|
+
img.style.visibility = "visible";
|
|
16
|
+
} else {
|
|
17
|
+
handleImgError();
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
const handleImgError = (e) => {
|
|
21
|
+
if (e && e.type !== "error") {
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
if (!src.fallback) {
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
const img = getImgElement();
|
|
28
|
+
if (!img) {
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
img.style.visibility = "hidden";
|
|
32
|
+
let fallbackUrl = void 0;
|
|
33
|
+
const index = src.fallback.findIndex(
|
|
34
|
+
(url) => new URL(url).toString() === new URL(img.src).toString()
|
|
35
|
+
);
|
|
36
|
+
if (index === -1) {
|
|
37
|
+
fallbackUrl = src.fallback[0];
|
|
38
|
+
} else {
|
|
39
|
+
fallbackUrl = src.fallback[index + 1];
|
|
40
|
+
}
|
|
41
|
+
if (!fallbackUrl) {
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
src = {
|
|
45
|
+
...src,
|
|
46
|
+
img: fallbackUrl,
|
|
47
|
+
srcsets: []
|
|
48
|
+
};
|
|
49
|
+
};
|
|
50
|
+
const handleLoaded = (e) => {
|
|
51
|
+
const img = e.currentTarget;
|
|
52
|
+
img.style.visibility = "visible";
|
|
53
|
+
};
|
|
54
|
+
</script>
|
|
55
|
+
|
|
56
|
+
<img
|
|
57
|
+
id={imgId}
|
|
58
|
+
width={src.w}
|
|
59
|
+
height={src.h}
|
|
60
|
+
{style}
|
|
61
|
+
src={src.img}
|
|
62
|
+
srcset={src.srcsets ? src.srcsets.map((s) => `${s.src} ${s.w}w`).join(', ') : ''}
|
|
63
|
+
alt={alt}
|
|
64
|
+
title={title}
|
|
65
|
+
on:error={handleImgError}
|
|
66
|
+
on:load={handleLoaded}
|
|
67
|
+
loading="lazy"
|
|
68
|
+
/>
|
|
69
|
+
|
|
70
|
+
<style>
|
|
71
|
+
img {
|
|
72
|
+
visibility: hidden;
|
|
73
|
+
}
|
|
74
|
+
</style>
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { SvelteComponent } from "svelte";
|
|
2
|
+
import type { ImgSrc } from './type.js';
|
|
3
|
+
declare const __propDef: {
|
|
4
|
+
props: {
|
|
5
|
+
src: ImgSrc;
|
|
6
|
+
style: any;
|
|
7
|
+
alt?: string | undefined;
|
|
8
|
+
title?: string | undefined;
|
|
9
|
+
};
|
|
10
|
+
events: {
|
|
11
|
+
[evt: string]: CustomEvent<any>;
|
|
12
|
+
};
|
|
13
|
+
slots: {};
|
|
14
|
+
exports?: {} | undefined;
|
|
15
|
+
bindings?: string | undefined;
|
|
16
|
+
};
|
|
17
|
+
export type ImgProps = typeof __propDef.props;
|
|
18
|
+
export type ImgEvents = typeof __propDef.events;
|
|
19
|
+
export type ImgSlots = typeof __propDef.slots;
|
|
20
|
+
export default class Img extends SvelteComponent<ImgProps, ImgEvents, ImgSlots> {
|
|
21
|
+
get alt(): string;
|
|
22
|
+
get title(): string;
|
|
23
|
+
}
|
|
24
|
+
export {};
|
|
@@ -38,7 +38,7 @@ const handleImgError = (e) => {
|
|
|
38
38
|
if (e && e.type !== "error") {
|
|
39
39
|
return;
|
|
40
40
|
}
|
|
41
|
-
if (!src.
|
|
41
|
+
if (!src.fallback) {
|
|
42
42
|
return;
|
|
43
43
|
}
|
|
44
44
|
const img = getImgElement();
|
|
@@ -49,21 +49,21 @@ const handleImgError = (e) => {
|
|
|
49
49
|
if (!img.complete) {
|
|
50
50
|
return;
|
|
51
51
|
}
|
|
52
|
-
let
|
|
53
|
-
const index = src.
|
|
52
|
+
let fallbackUrl = void 0;
|
|
53
|
+
const index = src.fallback.findIndex(
|
|
54
54
|
(url) => new URL(url).toString() === new URL(img.src).toString()
|
|
55
55
|
);
|
|
56
56
|
if (index === -1) {
|
|
57
|
-
|
|
57
|
+
fallbackUrl = src.fallback[0];
|
|
58
58
|
} else {
|
|
59
|
-
|
|
59
|
+
fallbackUrl = src.fallback[index + 1];
|
|
60
60
|
}
|
|
61
|
-
if (!
|
|
61
|
+
if (!fallbackUrl) {
|
|
62
62
|
return;
|
|
63
63
|
}
|
|
64
64
|
src = {
|
|
65
65
|
...src,
|
|
66
|
-
img:
|
|
66
|
+
img: fallbackUrl,
|
|
67
67
|
webp: [],
|
|
68
68
|
jpeg: [],
|
|
69
69
|
png: [],
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { SvelteComponent } from "svelte";
|
|
2
|
-
import type {
|
|
2
|
+
import type { PictureSrc } from './type.js';
|
|
3
3
|
declare const __propDef: {
|
|
4
4
|
props: {
|
|
5
|
-
src:
|
|
5
|
+
src: PictureSrc;
|
|
6
6
|
style?: string | undefined;
|
|
7
7
|
alt?: string | undefined;
|
|
8
8
|
title?: string | undefined;
|
|
@@ -14,10 +14,10 @@ declare const __propDef: {
|
|
|
14
14
|
exports?: {} | undefined;
|
|
15
15
|
bindings?: string | undefined;
|
|
16
16
|
};
|
|
17
|
-
export type
|
|
18
|
-
export type
|
|
19
|
-
export type
|
|
20
|
-
export default class
|
|
17
|
+
export type PictureProps = typeof __propDef.props;
|
|
18
|
+
export type PictureEvents = typeof __propDef.events;
|
|
19
|
+
export type PictureSlots = typeof __propDef.slots;
|
|
20
|
+
export default class Picture extends SvelteComponent<PictureProps, PictureEvents, PictureSlots> {
|
|
21
21
|
get alt(): string;
|
|
22
22
|
get title(): string;
|
|
23
23
|
}
|
|
@@ -2,17 +2,24 @@ export interface Srcset {
|
|
|
2
2
|
src: string;
|
|
3
3
|
w: number;
|
|
4
4
|
}
|
|
5
|
-
export interface
|
|
5
|
+
export interface PictureSrc {
|
|
6
6
|
img: string;
|
|
7
7
|
w?: number;
|
|
8
8
|
h?: number;
|
|
9
9
|
webp?: Srcset[];
|
|
10
10
|
jpeg?: Srcset[];
|
|
11
11
|
png?: Srcset[];
|
|
12
|
-
|
|
12
|
+
fallback?: string[];
|
|
13
13
|
placeholder?: {
|
|
14
14
|
dataUri?: string;
|
|
15
15
|
color?: string;
|
|
16
16
|
};
|
|
17
17
|
blur?: boolean;
|
|
18
18
|
}
|
|
19
|
+
export interface ImgSrc {
|
|
20
|
+
img: string;
|
|
21
|
+
srcsets?: Srcset[];
|
|
22
|
+
w?: number;
|
|
23
|
+
h?: number;
|
|
24
|
+
fallback?: string[];
|
|
25
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
export * from './components/
|
|
2
|
-
import
|
|
1
|
+
export * from './components/type'
|
|
2
|
+
import Picture from './components/Picture.svelte'
|
|
3
|
+
import Img from './components/Picture.svelte'
|
|
3
4
|
|
|
4
|
-
export {
|
|
5
|
+
export { Picture, Img }
|
package/dist/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "svelte-remote-image",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"homepage": "https://github.com/ocknamo/svelte-remote-image",
|
|
6
6
|
"scripts": {
|
|
@@ -27,7 +27,8 @@
|
|
|
27
27
|
"!dist/**/*.spec.*"
|
|
28
28
|
],
|
|
29
29
|
"peerDependencies": {
|
|
30
|
-
"svelte": "^4.0.0"
|
|
30
|
+
"svelte": "^4.0.0",
|
|
31
|
+
"@sveltejs/kit": "^2.0.0"
|
|
31
32
|
},
|
|
32
33
|
"devDependencies": {
|
|
33
34
|
"@biomejs/biome": "^1.8.1",
|
|
File without changes
|