@slopmachine/react 0.1.0 → 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/README.md +4 -0
- package/dist/index.js +47 -4
- package/dist/index.mjs +37 -4
- package/package.json +1 -1
- package/src/components/SlopImage.tsx +57 -8
package/README.md
CHANGED
package/dist/index.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
2
3
|
var __defProp = Object.defineProperty;
|
|
3
4
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
5
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
5
7
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
8
|
var __export = (target, all) => {
|
|
7
9
|
for (var name in all)
|
|
@@ -15,6 +17,14 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
15
17
|
}
|
|
16
18
|
return to;
|
|
17
19
|
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
18
28
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
29
|
|
|
20
30
|
// src/index.ts
|
|
@@ -25,7 +35,7 @@ __export(index_exports, {
|
|
|
25
35
|
module.exports = __toCommonJS(index_exports);
|
|
26
36
|
|
|
27
37
|
// src/components/SlopImage.tsx
|
|
28
|
-
var import_react = require("react");
|
|
38
|
+
var import_react = __toESM(require("react"));
|
|
29
39
|
var import_clsx = require("clsx");
|
|
30
40
|
var import_tailwind_merge = require("tailwind-merge");
|
|
31
41
|
var import_core = require("@slopmachine/core");
|
|
@@ -34,6 +44,7 @@ function cn(...inputs) {
|
|
|
34
44
|
return (0, import_tailwind_merge.twMerge)((0, import_clsx.clsx)(inputs));
|
|
35
45
|
}
|
|
36
46
|
var SlopImage = ({
|
|
47
|
+
bucketId,
|
|
37
48
|
prompt,
|
|
38
49
|
className,
|
|
39
50
|
aspectRatio = "1:1",
|
|
@@ -42,10 +53,24 @@ var SlopImage = ({
|
|
|
42
53
|
baseUrl,
|
|
43
54
|
...props
|
|
44
55
|
}) => {
|
|
45
|
-
const
|
|
46
|
-
() => (0, import_core.buildImageUrl)({
|
|
47
|
-
|
|
56
|
+
const rawSrc = (0, import_react.useMemo)(
|
|
57
|
+
() => (0, import_core.buildImageUrl)({
|
|
58
|
+
bucketId,
|
|
59
|
+
prompt,
|
|
60
|
+
aspectRatio,
|
|
61
|
+
variables,
|
|
62
|
+
baseUrl,
|
|
63
|
+
model
|
|
64
|
+
}),
|
|
65
|
+
[bucketId, prompt, aspectRatio, variables, baseUrl, model]
|
|
48
66
|
);
|
|
67
|
+
const [src, setSrc] = (0, import_react.useState)(rawSrc);
|
|
68
|
+
import_react.default.useEffect(() => {
|
|
69
|
+
const timer = setTimeout(() => {
|
|
70
|
+
setSrc(rawSrc);
|
|
71
|
+
}, 100);
|
|
72
|
+
return () => clearTimeout(timer);
|
|
73
|
+
}, [rawSrc]);
|
|
49
74
|
const alt = (0, import_react.useMemo)(
|
|
50
75
|
() => (0, import_core.interpolatePrompt)(prompt, variables) ?? "Generated image",
|
|
51
76
|
[prompt, variables]
|
|
@@ -56,6 +81,23 @@ var SlopImage = ({
|
|
|
56
81
|
setCurrentSrc(src);
|
|
57
82
|
setIsLoading(true);
|
|
58
83
|
}
|
|
84
|
+
import_react.default.useEffect(() => {
|
|
85
|
+
if (!src) return;
|
|
86
|
+
fetch(src, { method: "HEAD" }).then(async (res) => {
|
|
87
|
+
if (!res.ok) {
|
|
88
|
+
try {
|
|
89
|
+
const errRes = await fetch(src);
|
|
90
|
+
const errJson = await errRes.json();
|
|
91
|
+
console.error("SlopImage error:", res.status, errJson.error);
|
|
92
|
+
} catch (e) {
|
|
93
|
+
}
|
|
94
|
+
setIsLoading(false);
|
|
95
|
+
}
|
|
96
|
+
}).catch((err) => {
|
|
97
|
+
console.error(`Error fetching image from ${src}:`, err);
|
|
98
|
+
setIsLoading(false);
|
|
99
|
+
});
|
|
100
|
+
}, [src]);
|
|
59
101
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
60
102
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("style", { children: `
|
|
61
103
|
@keyframes slop-shimmer {
|
|
@@ -200,6 +242,7 @@ var SlopImage = ({
|
|
|
200
242
|
src,
|
|
201
243
|
alt,
|
|
202
244
|
onLoad: () => setIsLoading(false),
|
|
245
|
+
onError: () => setIsLoading(false),
|
|
203
246
|
className: cn(
|
|
204
247
|
"h-full w-full object-cover transition-opacity duration-500",
|
|
205
248
|
isLoading ? "opacity-0" : "opacity-100"
|
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/components/SlopImage.tsx
|
|
2
|
-
import { useMemo, useState } from "react";
|
|
2
|
+
import React, { useMemo, useState } from "react";
|
|
3
3
|
import { clsx } from "clsx";
|
|
4
4
|
import { twMerge } from "tailwind-merge";
|
|
5
5
|
import {
|
|
@@ -11,6 +11,7 @@ function cn(...inputs) {
|
|
|
11
11
|
return twMerge(clsx(inputs));
|
|
12
12
|
}
|
|
13
13
|
var SlopImage = ({
|
|
14
|
+
bucketId,
|
|
14
15
|
prompt,
|
|
15
16
|
className,
|
|
16
17
|
aspectRatio = "1:1",
|
|
@@ -19,10 +20,24 @@ var SlopImage = ({
|
|
|
19
20
|
baseUrl,
|
|
20
21
|
...props
|
|
21
22
|
}) => {
|
|
22
|
-
const
|
|
23
|
-
() => buildImageUrl({
|
|
24
|
-
|
|
23
|
+
const rawSrc = useMemo(
|
|
24
|
+
() => buildImageUrl({
|
|
25
|
+
bucketId,
|
|
26
|
+
prompt,
|
|
27
|
+
aspectRatio,
|
|
28
|
+
variables,
|
|
29
|
+
baseUrl,
|
|
30
|
+
model
|
|
31
|
+
}),
|
|
32
|
+
[bucketId, prompt, aspectRatio, variables, baseUrl, model]
|
|
25
33
|
);
|
|
34
|
+
const [src, setSrc] = useState(rawSrc);
|
|
35
|
+
React.useEffect(() => {
|
|
36
|
+
const timer = setTimeout(() => {
|
|
37
|
+
setSrc(rawSrc);
|
|
38
|
+
}, 100);
|
|
39
|
+
return () => clearTimeout(timer);
|
|
40
|
+
}, [rawSrc]);
|
|
26
41
|
const alt = useMemo(
|
|
27
42
|
() => interpolatePrompt(prompt, variables) ?? "Generated image",
|
|
28
43
|
[prompt, variables]
|
|
@@ -33,6 +48,23 @@ var SlopImage = ({
|
|
|
33
48
|
setCurrentSrc(src);
|
|
34
49
|
setIsLoading(true);
|
|
35
50
|
}
|
|
51
|
+
React.useEffect(() => {
|
|
52
|
+
if (!src) return;
|
|
53
|
+
fetch(src, { method: "HEAD" }).then(async (res) => {
|
|
54
|
+
if (!res.ok) {
|
|
55
|
+
try {
|
|
56
|
+
const errRes = await fetch(src);
|
|
57
|
+
const errJson = await errRes.json();
|
|
58
|
+
console.error("SlopImage error:", res.status, errJson.error);
|
|
59
|
+
} catch (e) {
|
|
60
|
+
}
|
|
61
|
+
setIsLoading(false);
|
|
62
|
+
}
|
|
63
|
+
}).catch((err) => {
|
|
64
|
+
console.error(`Error fetching image from ${src}:`, err);
|
|
65
|
+
setIsLoading(false);
|
|
66
|
+
});
|
|
67
|
+
}, [src]);
|
|
36
68
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
37
69
|
/* @__PURE__ */ jsx("style", { children: `
|
|
38
70
|
@keyframes slop-shimmer {
|
|
@@ -177,6 +209,7 @@ var SlopImage = ({
|
|
|
177
209
|
src,
|
|
178
210
|
alt,
|
|
179
211
|
onLoad: () => setIsLoading(false),
|
|
212
|
+
onError: () => setIsLoading(false),
|
|
180
213
|
className: cn(
|
|
181
214
|
"h-full w-full object-cover transition-opacity duration-500",
|
|
182
215
|
isLoading ? "opacity-0" : "opacity-100"
|
package/package.json
CHANGED
|
@@ -19,6 +19,7 @@ interface SlopImageProps
|
|
|
19
19
|
SlopImageOptions {}
|
|
20
20
|
|
|
21
21
|
export const SlopImage: React.FC<SlopImageProps> = ({
|
|
22
|
+
bucketId,
|
|
22
23
|
prompt,
|
|
23
24
|
className,
|
|
24
25
|
aspectRatio = "1:1",
|
|
@@ -28,11 +29,28 @@ export const SlopImage: React.FC<SlopImageProps> = ({
|
|
|
28
29
|
...props
|
|
29
30
|
}) => {
|
|
30
31
|
// Construct API URL
|
|
31
|
-
const
|
|
32
|
-
() =>
|
|
33
|
-
|
|
32
|
+
const rawSrc = useMemo(
|
|
33
|
+
() =>
|
|
34
|
+
buildImageUrl({
|
|
35
|
+
bucketId,
|
|
36
|
+
prompt,
|
|
37
|
+
aspectRatio,
|
|
38
|
+
variables,
|
|
39
|
+
baseUrl,
|
|
40
|
+
model,
|
|
41
|
+
}),
|
|
42
|
+
[bucketId, prompt, aspectRatio, variables, baseUrl, model],
|
|
34
43
|
);
|
|
35
44
|
|
|
45
|
+
const [src, setSrc] = useState(rawSrc);
|
|
46
|
+
|
|
47
|
+
React.useEffect(() => {
|
|
48
|
+
const timer = setTimeout(() => {
|
|
49
|
+
setSrc(rawSrc);
|
|
50
|
+
}, 100);
|
|
51
|
+
return () => clearTimeout(timer);
|
|
52
|
+
}, [rawSrc]);
|
|
53
|
+
|
|
36
54
|
const alt = useMemo(
|
|
37
55
|
() => interpolatePrompt(prompt, variables) ?? "Generated image",
|
|
38
56
|
[prompt, variables],
|
|
@@ -46,6 +64,31 @@ export const SlopImage: React.FC<SlopImageProps> = ({
|
|
|
46
64
|
setIsLoading(true);
|
|
47
65
|
}
|
|
48
66
|
|
|
67
|
+
React.useEffect(() => {
|
|
68
|
+
if (!src) return;
|
|
69
|
+
|
|
70
|
+
fetch(src, { method: "HEAD" })
|
|
71
|
+
.then(async (res) => {
|
|
72
|
+
if (!res.ok) {
|
|
73
|
+
// console.error(
|
|
74
|
+
// `Failed to load image from ${src}. Status: ${res.status} ${res.statusText}`,
|
|
75
|
+
// );
|
|
76
|
+
try {
|
|
77
|
+
const errRes = await fetch(src);
|
|
78
|
+
const errJson = await errRes.json();
|
|
79
|
+
console.error("SlopImage error:", res.status, errJson.error);
|
|
80
|
+
} catch (e) {
|
|
81
|
+
// Failed to fetch or parse error details
|
|
82
|
+
}
|
|
83
|
+
setIsLoading(false);
|
|
84
|
+
}
|
|
85
|
+
})
|
|
86
|
+
.catch((err) => {
|
|
87
|
+
console.error(`Error fetching image from ${src}:`, err);
|
|
88
|
+
setIsLoading(false);
|
|
89
|
+
});
|
|
90
|
+
}, [src]);
|
|
91
|
+
|
|
49
92
|
return (
|
|
50
93
|
<>
|
|
51
94
|
<style>{`
|
|
@@ -73,7 +116,8 @@ export const SlopImage: React.FC<SlopImageProps> = ({
|
|
|
73
116
|
backgroundColor: "var(--muted, #f3f4f6)",
|
|
74
117
|
position: "relative",
|
|
75
118
|
overflow: "hidden",
|
|
76
|
-
}}
|
|
119
|
+
}}
|
|
120
|
+
>
|
|
77
121
|
{/* Loading overlay */}
|
|
78
122
|
<div
|
|
79
123
|
className={cn(
|
|
@@ -94,7 +138,8 @@ export const SlopImage: React.FC<SlopImageProps> = ({
|
|
|
94
138
|
opacity: isLoading ? 1 : 0,
|
|
95
139
|
pointerEvents: isLoading ? "auto" : "none",
|
|
96
140
|
transition: "opacity 300ms ease-in-out",
|
|
97
|
-
}}
|
|
141
|
+
}}
|
|
142
|
+
>
|
|
98
143
|
<div
|
|
99
144
|
className="flex flex-col items-center gap-2"
|
|
100
145
|
style={{
|
|
@@ -102,7 +147,8 @@ export const SlopImage: React.FC<SlopImageProps> = ({
|
|
|
102
147
|
flexDirection: "column",
|
|
103
148
|
alignItems: "center",
|
|
104
149
|
gap: "0.5rem",
|
|
105
|
-
}}
|
|
150
|
+
}}
|
|
151
|
+
>
|
|
106
152
|
<svg
|
|
107
153
|
className="spinner size-6 text-muted-foreground"
|
|
108
154
|
xmlns="http://www.w3.org/2000/svg"
|
|
@@ -113,7 +159,8 @@ export const SlopImage: React.FC<SlopImageProps> = ({
|
|
|
113
159
|
height: "24px",
|
|
114
160
|
color: "var(--muted-foreground, #6b7280)",
|
|
115
161
|
animation: "slop-spin 1s linear infinite",
|
|
116
|
-
}}
|
|
162
|
+
}}
|
|
163
|
+
>
|
|
117
164
|
<circle
|
|
118
165
|
className="opacity-25"
|
|
119
166
|
cx="12"
|
|
@@ -135,7 +182,8 @@ export const SlopImage: React.FC<SlopImageProps> = ({
|
|
|
135
182
|
style={{
|
|
136
183
|
fontSize: "0.75rem",
|
|
137
184
|
color: "var(--muted-foreground, #6b7280)",
|
|
138
|
-
}}
|
|
185
|
+
}}
|
|
186
|
+
>
|
|
139
187
|
Loading...
|
|
140
188
|
</span>
|
|
141
189
|
</div>
|
|
@@ -168,6 +216,7 @@ export const SlopImage: React.FC<SlopImageProps> = ({
|
|
|
168
216
|
src={src}
|
|
169
217
|
alt={alt}
|
|
170
218
|
onLoad={() => setIsLoading(false)}
|
|
219
|
+
onError={() => setIsLoading(false)}
|
|
171
220
|
className={cn(
|
|
172
221
|
"h-full w-full object-cover transition-opacity duration-500",
|
|
173
222
|
isLoading ? "opacity-0" : "opacity-100",
|