@slopmachine/svelte 0.1.1 → 0.1.2
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/package.json +1 -1
- package/src/SlopImage.svelte +66 -21
package/package.json
CHANGED
package/src/SlopImage.svelte
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
buildImageUrl,
|
|
4
|
+
interpolatePrompt,
|
|
5
|
+
type SlopImageOptions,
|
|
6
|
+
} from "@slopmachine/core";
|
|
3
7
|
|
|
4
|
-
interface Props extends
|
|
8
|
+
interface Props extends SlopImageOptions {
|
|
5
9
|
class?: string;
|
|
6
10
|
}
|
|
7
11
|
|
|
@@ -18,9 +22,22 @@
|
|
|
18
22
|
|
|
19
23
|
let isLoading = $state(true);
|
|
20
24
|
|
|
21
|
-
let
|
|
25
|
+
let computedSrc = $derived(
|
|
26
|
+
buildImageUrl({ bucketId, prompt, aspectRatio, variables, baseUrl, model }),
|
|
27
|
+
);
|
|
28
|
+
let src = $state("");
|
|
22
29
|
let prevSrc = $state("");
|
|
23
|
-
let alt = $derived(interpolatePrompt(
|
|
30
|
+
let alt = $derived(interpolatePrompt(prompt, variables) ?? "Generated image");
|
|
31
|
+
|
|
32
|
+
$effect(() => {
|
|
33
|
+
const timeout = setTimeout(() => {
|
|
34
|
+
if (src !== computedSrc) {
|
|
35
|
+
src = computedSrc;
|
|
36
|
+
}
|
|
37
|
+
}, 50);
|
|
38
|
+
|
|
39
|
+
return () => clearTimeout(timeout);
|
|
40
|
+
});
|
|
24
41
|
|
|
25
42
|
$effect(() => {
|
|
26
43
|
if (src !== prevSrc) {
|
|
@@ -31,24 +48,33 @@
|
|
|
31
48
|
|
|
32
49
|
$effect(() => {
|
|
33
50
|
if (src) {
|
|
34
|
-
|
|
51
|
+
const abortController = new AbortController();
|
|
52
|
+
fetch(src, { method: "HEAD", signal: abortController.signal })
|
|
35
53
|
.then(async (res) => {
|
|
36
54
|
if (!res.ok) {
|
|
37
55
|
// console.error(`Failed to load image from ${src}. Status: ${res.status} ${res.statusText}`);
|
|
38
56
|
try {
|
|
39
|
-
const errRes = await fetch(src
|
|
57
|
+
const errRes = await fetch(src, {
|
|
58
|
+
signal: abortController.signal,
|
|
59
|
+
});
|
|
40
60
|
const errJson = await errRes.json();
|
|
41
|
-
console.error("SlopImage error:",res.status, errJson.error);
|
|
42
|
-
} catch (e) {
|
|
43
|
-
|
|
61
|
+
console.error("SlopImage error:", res.status, errJson.error);
|
|
62
|
+
} catch (e: any) {
|
|
63
|
+
if (e.name !== "AbortError") {
|
|
64
|
+
// Failed to fetch or parse error details
|
|
65
|
+
}
|
|
44
66
|
}
|
|
45
67
|
isLoading = false;
|
|
46
68
|
}
|
|
47
69
|
})
|
|
48
70
|
.catch((err) => {
|
|
49
|
-
|
|
50
|
-
|
|
71
|
+
if (err.name !== "AbortError") {
|
|
72
|
+
console.error(`Error fetching image from ${src}:`, err);
|
|
73
|
+
isLoading = false;
|
|
74
|
+
}
|
|
51
75
|
});
|
|
76
|
+
|
|
77
|
+
return () => abortController.abort();
|
|
52
78
|
}
|
|
53
79
|
});
|
|
54
80
|
|
|
@@ -74,7 +100,8 @@
|
|
|
74
100
|
fill="none"
|
|
75
101
|
viewBox="0 0 24 24"
|
|
76
102
|
>
|
|
77
|
-
<circle cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"
|
|
103
|
+
<circle cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"
|
|
104
|
+
></circle>
|
|
78
105
|
<path
|
|
79
106
|
fill="currentColor"
|
|
80
107
|
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
|
|
@@ -107,7 +134,10 @@
|
|
|
107
134
|
|
|
108
135
|
.loading-overlay {
|
|
109
136
|
position: absolute;
|
|
110
|
-
top: 0;
|
|
137
|
+
top: 0;
|
|
138
|
+
left: 0;
|
|
139
|
+
right: 0;
|
|
140
|
+
bottom: 0;
|
|
111
141
|
z-index: 10;
|
|
112
142
|
display: flex;
|
|
113
143
|
align-items: center;
|
|
@@ -129,8 +159,12 @@
|
|
|
129
159
|
color: var(--muted-foreground, #6b7280);
|
|
130
160
|
animation: slop-spin 1s linear infinite;
|
|
131
161
|
}
|
|
132
|
-
.spinner circle {
|
|
133
|
-
|
|
162
|
+
.spinner circle {
|
|
163
|
+
opacity: 0.25;
|
|
164
|
+
}
|
|
165
|
+
.spinner path {
|
|
166
|
+
opacity: 0.75;
|
|
167
|
+
}
|
|
134
168
|
|
|
135
169
|
.spinner-container span {
|
|
136
170
|
font-size: 0.75rem;
|
|
@@ -139,7 +173,10 @@
|
|
|
139
173
|
|
|
140
174
|
.shimmer-effect {
|
|
141
175
|
position: absolute;
|
|
142
|
-
top: 0;
|
|
176
|
+
top: 0;
|
|
177
|
+
left: 0;
|
|
178
|
+
right: 0;
|
|
179
|
+
bottom: 0;
|
|
143
180
|
background: linear-gradient(
|
|
144
181
|
90deg,
|
|
145
182
|
var(--muted, #f3f4f6) 0%,
|
|
@@ -163,12 +200,20 @@
|
|
|
163
200
|
}
|
|
164
201
|
|
|
165
202
|
@keyframes slop-shimmer {
|
|
166
|
-
0% {
|
|
167
|
-
|
|
203
|
+
0% {
|
|
204
|
+
background-position: 200% 0;
|
|
205
|
+
}
|
|
206
|
+
100% {
|
|
207
|
+
background-position: -200% 0;
|
|
208
|
+
}
|
|
168
209
|
}
|
|
169
210
|
|
|
170
211
|
@keyframes slop-spin {
|
|
171
|
-
from {
|
|
172
|
-
|
|
212
|
+
from {
|
|
213
|
+
transform: rotate(0deg);
|
|
214
|
+
}
|
|
215
|
+
to {
|
|
216
|
+
transform: rotate(360deg);
|
|
217
|
+
}
|
|
173
218
|
}
|
|
174
|
-
</style>
|
|
219
|
+
</style>
|