@slopmachine/react 0.1.0 → 0.1.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 CHANGED
@@ -12,6 +12,10 @@ yarn add @slopmachine/react
12
12
  pnpm add @slopmachine/react
13
13
  ```
14
14
 
15
+ ## Demo
16
+
17
+ https://slopmachine-dev.github.io/slopmachine-sdk/
18
+
15
19
  ## Usage
16
20
 
17
21
  ```tsx
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",
@@ -43,8 +54,15 @@ var SlopImage = ({
43
54
  ...props
44
55
  }) => {
45
56
  const src = (0, import_react.useMemo)(
46
- () => (0, import_core.buildImageUrl)({ prompt, aspectRatio, variables, baseUrl, model }),
47
- [prompt, aspectRatio, variables, baseUrl, model]
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
  );
49
67
  const alt = (0, import_react.useMemo)(
50
68
  () => (0, import_core.interpolatePrompt)(prompt, variables) ?? "Generated image",
@@ -56,6 +74,23 @@ var SlopImage = ({
56
74
  setCurrentSrc(src);
57
75
  setIsLoading(true);
58
76
  }
77
+ import_react.default.useEffect(() => {
78
+ if (!src) return;
79
+ fetch(src, { method: "HEAD" }).then(async (res) => {
80
+ if (!res.ok) {
81
+ try {
82
+ const errRes = await fetch(src);
83
+ const errJson = await errRes.json();
84
+ console.error("SlopImage error:", res.status, errJson.error);
85
+ } catch (e) {
86
+ }
87
+ setIsLoading(false);
88
+ }
89
+ }).catch((err) => {
90
+ console.error(`Error fetching image from ${src}:`, err);
91
+ setIsLoading(false);
92
+ });
93
+ }, [src]);
59
94
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
60
95
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("style", { children: `
61
96
  @keyframes slop-shimmer {
@@ -200,6 +235,7 @@ var SlopImage = ({
200
235
  src,
201
236
  alt,
202
237
  onLoad: () => setIsLoading(false),
238
+ onError: () => setIsLoading(false),
203
239
  className: cn(
204
240
  "h-full w-full object-cover transition-opacity duration-500",
205
241
  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",
@@ -20,8 +21,15 @@ var SlopImage = ({
20
21
  ...props
21
22
  }) => {
22
23
  const src = useMemo(
23
- () => buildImageUrl({ prompt, aspectRatio, variables, baseUrl, model }),
24
- [prompt, aspectRatio, variables, baseUrl, model]
24
+ () => buildImageUrl({
25
+ bucketId,
26
+ prompt,
27
+ aspectRatio,
28
+ variables,
29
+ baseUrl,
30
+ model
31
+ }),
32
+ [bucketId, prompt, aspectRatio, variables, baseUrl, model]
25
33
  );
26
34
  const alt = useMemo(
27
35
  () => interpolatePrompt(prompt, variables) ?? "Generated image",
@@ -33,6 +41,23 @@ var SlopImage = ({
33
41
  setCurrentSrc(src);
34
42
  setIsLoading(true);
35
43
  }
44
+ React.useEffect(() => {
45
+ if (!src) return;
46
+ fetch(src, { method: "HEAD" }).then(async (res) => {
47
+ if (!res.ok) {
48
+ try {
49
+ const errRes = await fetch(src);
50
+ const errJson = await errRes.json();
51
+ console.error("SlopImage error:", res.status, errJson.error);
52
+ } catch (e) {
53
+ }
54
+ setIsLoading(false);
55
+ }
56
+ }).catch((err) => {
57
+ console.error(`Error fetching image from ${src}:`, err);
58
+ setIsLoading(false);
59
+ });
60
+ }, [src]);
36
61
  return /* @__PURE__ */ jsxs(Fragment, { children: [
37
62
  /* @__PURE__ */ jsx("style", { children: `
38
63
  @keyframes slop-shimmer {
@@ -177,6 +202,7 @@ var SlopImage = ({
177
202
  src,
178
203
  alt,
179
204
  onLoad: () => setIsLoading(false),
205
+ onError: () => setIsLoading(false),
180
206
  className: cn(
181
207
  "h-full w-full object-cover transition-opacity duration-500",
182
208
  isLoading ? "opacity-0" : "opacity-100"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@slopmachine/react",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "The official React SDK for Slop Machine",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
@@ -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",
@@ -29,8 +30,16 @@ export const SlopImage: React.FC<SlopImageProps> = ({
29
30
  }) => {
30
31
  // Construct API URL
31
32
  const src = useMemo(
32
- () => buildImageUrl({ prompt, aspectRatio, variables, baseUrl, model }),
33
- [prompt, aspectRatio, variables, baseUrl, model],
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
 
36
45
  const alt = useMemo(
@@ -46,6 +55,31 @@ export const SlopImage: React.FC<SlopImageProps> = ({
46
55
  setIsLoading(true);
47
56
  }
48
57
 
58
+ React.useEffect(() => {
59
+ if (!src) return;
60
+
61
+ fetch(src, { method: "HEAD" })
62
+ .then(async (res) => {
63
+ if (!res.ok) {
64
+ // console.error(
65
+ // `Failed to load image from ${src}. Status: ${res.status} ${res.statusText}`,
66
+ // );
67
+ try {
68
+ const errRes = await fetch(src);
69
+ const errJson = await errRes.json();
70
+ console.error("SlopImage error:", res.status, errJson.error);
71
+ } catch (e) {
72
+ // Failed to fetch or parse error details
73
+ }
74
+ setIsLoading(false);
75
+ }
76
+ })
77
+ .catch((err) => {
78
+ console.error(`Error fetching image from ${src}:`, err);
79
+ setIsLoading(false);
80
+ });
81
+ }, [src]);
82
+
49
83
  return (
50
84
  <>
51
85
  <style>{`
@@ -73,7 +107,8 @@ export const SlopImage: React.FC<SlopImageProps> = ({
73
107
  backgroundColor: "var(--muted, #f3f4f6)",
74
108
  position: "relative",
75
109
  overflow: "hidden",
76
- }}>
110
+ }}
111
+ >
77
112
  {/* Loading overlay */}
78
113
  <div
79
114
  className={cn(
@@ -94,7 +129,8 @@ export const SlopImage: React.FC<SlopImageProps> = ({
94
129
  opacity: isLoading ? 1 : 0,
95
130
  pointerEvents: isLoading ? "auto" : "none",
96
131
  transition: "opacity 300ms ease-in-out",
97
- }}>
132
+ }}
133
+ >
98
134
  <div
99
135
  className="flex flex-col items-center gap-2"
100
136
  style={{
@@ -102,7 +138,8 @@ export const SlopImage: React.FC<SlopImageProps> = ({
102
138
  flexDirection: "column",
103
139
  alignItems: "center",
104
140
  gap: "0.5rem",
105
- }}>
141
+ }}
142
+ >
106
143
  <svg
107
144
  className="spinner size-6 text-muted-foreground"
108
145
  xmlns="http://www.w3.org/2000/svg"
@@ -113,7 +150,8 @@ export const SlopImage: React.FC<SlopImageProps> = ({
113
150
  height: "24px",
114
151
  color: "var(--muted-foreground, #6b7280)",
115
152
  animation: "slop-spin 1s linear infinite",
116
- }}>
153
+ }}
154
+ >
117
155
  <circle
118
156
  className="opacity-25"
119
157
  cx="12"
@@ -135,7 +173,8 @@ export const SlopImage: React.FC<SlopImageProps> = ({
135
173
  style={{
136
174
  fontSize: "0.75rem",
137
175
  color: "var(--muted-foreground, #6b7280)",
138
- }}>
176
+ }}
177
+ >
139
178
  Loading...
140
179
  </span>
141
180
  </div>
@@ -168,6 +207,7 @@ export const SlopImage: React.FC<SlopImageProps> = ({
168
207
  src={src}
169
208
  alt={alt}
170
209
  onLoad={() => setIsLoading(false)}
210
+ onError={() => setIsLoading(false)}
171
211
  className={cn(
172
212
  "h-full w-full object-cover transition-opacity duration-500",
173
213
  isLoading ? "opacity-0" : "opacity-100",