@slopmachine/react 0.1.25 → 0.2.0

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/CHANGELOG.md ADDED
@@ -0,0 +1,12 @@
1
+ # @slopmachine/react
2
+
3
+ ## 0.2.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 15b923d: Switch pipeline execution parameters to use pipelineId (with optional siloId) instead of pipelineKey.
8
+
9
+ ### Patch Changes
10
+
11
+ - Updated dependencies [15b923d]
12
+ - @slopmachine/core@0.2.0
package/README.md CHANGED
@@ -1,15 +1,15 @@
1
1
  # @slopmachine/react
2
2
 
3
- The official React SDK for Slop Machine. This package provides React components to easily integrate Slop Machine image generation into your applications.
3
+ The official React SDK for Slop Machine. This package provides high-performance, layout-stable React components to seamlessly integrate AI images, videos, and text into your web applications.
4
4
 
5
5
  ## Installation
6
6
 
7
7
  ```bash
8
- npm install @slopmachine/react
8
+ npm install @slopmachine/react @slopmachine/core
9
9
  # or
10
- yarn add @slopmachine/react
10
+ yarn add @slopmachine/react @slopmachine/core
11
11
  # or
12
- pnpm add @slopmachine/react
12
+ pnpm add @slopmachine/react @slopmachine/core
13
13
  ```
14
14
 
15
15
  ## Demo
@@ -18,37 +18,74 @@ https://docs.slopmachine.dev/demo-react/
18
18
 
19
19
  ## Usage
20
20
 
21
+ ### 1. Using Pre-Templated Buckets
22
+
21
23
  ```tsx
22
- import { SlopImage } from "@slopmachine/react";
24
+ import { SlopImage, SlopVideo, SlopText } from "@slopmachine/react";
23
25
 
24
- function App() {
26
+ function BucketExample() {
25
27
  return (
26
- <div style={{ width: "400px", height: "400px" }}>
28
+ <div>
29
+ {/* Dynamic Image */}
27
30
  <SlopImage
28
- prompt="A cute cat drinking coffee in a {style} style"
29
- aspectRatio="1:1"
30
- variables={{ style: "anime" }}
31
+ bucketId="my-bucket-id"
32
+ aspectRatio="16:9"
33
+ variables={{ style: "anime", character: "wizard" }}
34
+ className="rounded-lg shadow-md"
35
+ />
36
+
37
+ {/* Dynamic Video */}
38
+ <SlopVideo
39
+ bucketId="my-video-bucket"
40
+ aspectRatio="16:9"
41
+ duration={5}
42
+ autoPlay
43
+ loop
44
+ muted
45
+ />
46
+
47
+ {/* Dynamic Text / Story */}
48
+ <SlopText
49
+ bucketId="my-text-bucket"
50
+ variables={{ hero: "Arthur" }}
51
+ className="prose"
31
52
  />
32
53
  </div>
33
54
  );
34
55
  }
35
-
36
- export default App;
37
56
  ```
38
57
 
39
- ## API / Props
58
+ ### 2. Using Dynamic Multi-Step Pipelines
59
+
60
+ Pipelines give you full runtime control over the prompt and pipeline execution while persisting results directly to Slop Machine:
61
+
62
+ ```tsx
63
+ import { SlopImage, SlopVideo, SlopText } from "@slopmachine/react";
40
64
 
41
- ### `SlopImage`
65
+ function PipelineExample() {
66
+ return (
67
+ <div>
68
+ <SlopImage
69
+ pipelineId="pipe_live_abc123"
70
+ prompt="1960s retro robot eating synthetic pizza on Mars"
71
+ aspectRatio="1:1"
72
+ metadata={{ campaign: "retro_future_2026", userId: "u_101" }}
73
+ />
42
74
 
43
- The `SlopImage` component inherits from standard `React.ImgHTMLAttributes<HTMLImageElement>` (excluding `src` and `alt`) and accepts the following additional props:
75
+ <SlopVideo
76
+ pipelineId="pipe_live_def456"
77
+ prompt="A drone swooping through neon skyscrapers in heavy rain"
78
+ aspectRatio="9:16"
79
+ />
44
80
 
45
- | Prop | Type | Default | Description |
46
- | :------------ | :----------------------- | :----------- | :------------------------------------------------------ |
47
- | `prompt` | `string` | **Required** | The prompt to use for image generation. |
48
- | `aspectRatio` | `string` | `"1:1"` | The aspect ratio of the image (e.g. `"16:9"`, `"1:1"`). |
49
- | `variables` | `Record<string, string>` | `{}` | Variables to interpolate into the prompt. |
50
- | `model` | `string` | `undefined` | The AI model to use for generation. |
51
- | `baseUrl` | `string` | `undefined` | Custom base URL for the Slop Machine API. |
81
+ <SlopText
82
+ pipelineId="pipe_live_ghi789"
83
+ prompt="Write a whimsical product tagline for a cybernetic toaster"
84
+ />
85
+ </div>
86
+ );
87
+ }
88
+ ```
52
89
 
53
90
  ## License
54
91
 
package/dist/index.d.mts CHANGED
@@ -29,6 +29,7 @@ interface SlopImageProps extends Omit<React.ImgHTMLAttributes<HTMLImageElement>,
29
29
  *
30
30
  * @example
31
31
  * ```tsx
32
+ * // Using a Bucket
32
33
  * <SlopImage
33
34
  * bucketId="my-bucket"
34
35
  * resultId="some-result"
@@ -36,9 +37,17 @@ interface SlopImageProps extends Omit<React.ImgHTMLAttributes<HTMLImageElement>,
36
37
  * className="rounded-lg"
37
38
  * objectFit="cover"
38
39
  * />
40
+ *
41
+ * // Using a Pipeline with runtime prompt
42
+ * <SlopImage
43
+ * pipelineId="pipe_live_abc123"
44
+ * prompt="1960s retro robot eating pizza on Mars"
45
+ * aspectRatio="16:9"
46
+ * metadata={{ userId: "123" }}
47
+ * />
39
48
  * ```
40
49
  *
41
- * @version 0.1.25
50
+ * @version 0.2.0
42
51
  */
43
52
  declare const SlopImage: React.FC<SlopImageProps>;
44
53
 
@@ -61,6 +70,7 @@ interface SlopVideoProps extends Omit<React.VideoHTMLAttributes<HTMLVideoElement
61
70
  *
62
71
  * @example
63
72
  * ```tsx
73
+ * // Using a Bucket
64
74
  * <SlopVideo
65
75
  * bucketId="my-bucket"
66
76
  * resultId="some-result"
@@ -70,9 +80,17 @@ interface SlopVideoProps extends Omit<React.VideoHTMLAttributes<HTMLVideoElement
70
80
  * loop
71
81
  * muted
72
82
  * />
83
+ *
84
+ * // Using a Pipeline with runtime prompt
85
+ * <SlopVideo
86
+ * pipelineId="pipe_live_abc123"
87
+ * prompt="Drone shot of a cyberpunk city in rain"
88
+ * aspectRatio="16:9"
89
+ * metadata={{ campaign: "spring_launch" }}
90
+ * />
73
91
  * ```
74
92
  *
75
- * @version 0.1.25
93
+ * @version 0.2.0
76
94
  */
77
95
  declare const SlopVideo: React.FC<SlopVideoProps>;
78
96
 
@@ -94,15 +112,23 @@ interface SlopTextProps extends Omit<React.HTMLAttributes<HTMLDivElement>, "chil
94
112
  *
95
113
  * @example
96
114
  * ```tsx
115
+ * // Using a Bucket
97
116
  * <SlopText
98
117
  * bucketId="my-text-bucket"
99
118
  * fallback={<div>Loading story...</div>}
100
119
  * errorFallback={<div>Failed to load story</div>}
101
120
  * className="text-lg text-gray-800"
102
121
  * />
122
+ *
123
+ * // Using a Pipeline with runtime prompt
124
+ * <SlopText
125
+ * pipelineId="pipe_live_abc123"
126
+ * prompt="Write a whimsical haiku about quantum physics"
127
+ * metadata={{ userId: "123" }}
128
+ * />
103
129
  * ```
104
130
  *
105
- * @version 0.1.25
131
+ * @version 0.2.0
106
132
  */
107
133
  declare const SlopText: React.ForwardRefExoticComponent<SlopTextProps & React.RefAttributes<HTMLDivElement>>;
108
134
 
package/dist/index.d.ts CHANGED
@@ -29,6 +29,7 @@ interface SlopImageProps extends Omit<React.ImgHTMLAttributes<HTMLImageElement>,
29
29
  *
30
30
  * @example
31
31
  * ```tsx
32
+ * // Using a Bucket
32
33
  * <SlopImage
33
34
  * bucketId="my-bucket"
34
35
  * resultId="some-result"
@@ -36,9 +37,17 @@ interface SlopImageProps extends Omit<React.ImgHTMLAttributes<HTMLImageElement>,
36
37
  * className="rounded-lg"
37
38
  * objectFit="cover"
38
39
  * />
40
+ *
41
+ * // Using a Pipeline with runtime prompt
42
+ * <SlopImage
43
+ * pipelineId="pipe_live_abc123"
44
+ * prompt="1960s retro robot eating pizza on Mars"
45
+ * aspectRatio="16:9"
46
+ * metadata={{ userId: "123" }}
47
+ * />
39
48
  * ```
40
49
  *
41
- * @version 0.1.25
50
+ * @version 0.2.0
42
51
  */
43
52
  declare const SlopImage: React.FC<SlopImageProps>;
44
53
 
@@ -61,6 +70,7 @@ interface SlopVideoProps extends Omit<React.VideoHTMLAttributes<HTMLVideoElement
61
70
  *
62
71
  * @example
63
72
  * ```tsx
73
+ * // Using a Bucket
64
74
  * <SlopVideo
65
75
  * bucketId="my-bucket"
66
76
  * resultId="some-result"
@@ -70,9 +80,17 @@ interface SlopVideoProps extends Omit<React.VideoHTMLAttributes<HTMLVideoElement
70
80
  * loop
71
81
  * muted
72
82
  * />
83
+ *
84
+ * // Using a Pipeline with runtime prompt
85
+ * <SlopVideo
86
+ * pipelineId="pipe_live_abc123"
87
+ * prompt="Drone shot of a cyberpunk city in rain"
88
+ * aspectRatio="16:9"
89
+ * metadata={{ campaign: "spring_launch" }}
90
+ * />
73
91
  * ```
74
92
  *
75
- * @version 0.1.25
93
+ * @version 0.2.0
76
94
  */
77
95
  declare const SlopVideo: React.FC<SlopVideoProps>;
78
96
 
@@ -94,15 +112,23 @@ interface SlopTextProps extends Omit<React.HTMLAttributes<HTMLDivElement>, "chil
94
112
  *
95
113
  * @example
96
114
  * ```tsx
115
+ * // Using a Bucket
97
116
  * <SlopText
98
117
  * bucketId="my-text-bucket"
99
118
  * fallback={<div>Loading story...</div>}
100
119
  * errorFallback={<div>Failed to load story</div>}
101
120
  * className="text-lg text-gray-800"
102
121
  * />
122
+ *
123
+ * // Using a Pipeline with runtime prompt
124
+ * <SlopText
125
+ * pipelineId="pipe_live_abc123"
126
+ * prompt="Write a whimsical haiku about quantum physics"
127
+ * metadata={{ userId: "123" }}
128
+ * />
103
129
  * ```
104
130
  *
105
- * @version 0.1.25
131
+ * @version 0.2.0
106
132
  */
107
133
  declare const SlopText: React.ForwardRefExoticComponent<SlopTextProps & React.RefAttributes<HTMLDivElement>>;
108
134
 
package/dist/index.js CHANGED
@@ -48,6 +48,10 @@ function cn(...inputs) {
48
48
  }
49
49
  var SlopImage = ({
50
50
  bucketId,
51
+ pipelineId,
52
+ siloId,
53
+ prompt,
54
+ metadata,
51
55
  className,
52
56
  aspectRatio = "1:1",
53
57
  version,
@@ -61,11 +65,17 @@ var SlopImage = ({
61
65
  objectFit = "cover",
62
66
  imageClassName,
63
67
  style,
68
+ onLoad,
69
+ onError,
64
70
  ...props
65
71
  }) => {
66
72
  const rawSrc = (0, import_react.useMemo)(
67
73
  () => (0, import_core.buildImageUrl)({
68
74
  bucketId,
75
+ pipelineId,
76
+ siloId,
77
+ prompt,
78
+ metadata,
69
79
  aspectRatio,
70
80
  version,
71
81
  resultId,
@@ -77,6 +87,10 @@ var SlopImage = ({
77
87
  }),
78
88
  [
79
89
  bucketId,
90
+ pipelineId,
91
+ siloId,
92
+ prompt,
93
+ metadata,
80
94
  aspectRatio,
81
95
  version,
82
96
  resultId,
@@ -292,8 +306,15 @@ var SlopImage = ({
292
306
  {
293
307
  src,
294
308
  alt,
295
- onLoad: () => setIsLoading(false),
296
- onError: () => setIsLoading(false),
309
+ ...props,
310
+ onLoad: (e) => {
311
+ setIsLoading(false);
312
+ onLoad?.(e);
313
+ },
314
+ onError: (e) => {
315
+ setIsLoading(false);
316
+ onError?.(e);
317
+ },
297
318
  className: cn(
298
319
  "h-full w-full transition-opacity duration-500",
299
320
  isLoading ? "opacity-0" : "opacity-100",
@@ -305,8 +326,7 @@ var SlopImage = ({
305
326
  objectFit,
306
327
  transition: "opacity 500ms",
307
328
  opacity: isLoading ? 0 : 1
308
- },
309
- ...props
329
+ }
310
330
  },
311
331
  src
312
332
  )
@@ -327,6 +347,10 @@ function cn2(...inputs) {
327
347
  }
328
348
  var SlopVideo = ({
329
349
  bucketId,
350
+ pipelineId,
351
+ siloId,
352
+ prompt,
353
+ metadata,
330
354
  className,
331
355
  aspectRatio = "16:9",
332
356
  version,
@@ -342,11 +366,17 @@ var SlopVideo = ({
342
366
  loop = true,
343
367
  muted = true,
344
368
  playsInline = true,
369
+ onLoadedData,
370
+ onError,
345
371
  ...props
346
372
  }) => {
347
373
  const rawSrc = (0, import_react2.useMemo)(
348
374
  () => (0, import_core2.buildVideoUrl)({
349
375
  bucketId,
376
+ pipelineId,
377
+ siloId,
378
+ prompt,
379
+ metadata,
350
380
  aspectRatio,
351
381
  version,
352
382
  resultId,
@@ -359,6 +389,10 @@ var SlopVideo = ({
359
389
  }),
360
390
  [
361
391
  bucketId,
392
+ pipelineId,
393
+ siloId,
394
+ prompt,
395
+ metadata,
362
396
  aspectRatio,
363
397
  version,
364
398
  resultId,
@@ -579,8 +613,15 @@ var SlopVideo = ({
579
613
  loop,
580
614
  muted,
581
615
  playsInline,
582
- onLoadedData: () => setIsLoading(false),
583
- onError: () => setIsLoading(false),
616
+ ...props,
617
+ onLoadedData: (e) => {
618
+ setIsLoading(false);
619
+ onLoadedData?.(e);
620
+ },
621
+ onError: (e) => {
622
+ setIsLoading(false);
623
+ onError?.(e);
624
+ },
584
625
  className: cn2(
585
626
  "h-full w-full object-cover transition-opacity duration-500",
586
627
  isLoading ? "opacity-0" : "opacity-100"
@@ -591,8 +632,7 @@ var SlopVideo = ({
591
632
  objectFit: "cover",
592
633
  transition: "opacity 500ms",
593
634
  opacity: isLoading ? 0 : 1
594
- },
595
- ...props
635
+ }
596
636
  },
597
637
  src
598
638
  )
@@ -610,6 +650,10 @@ var import_jsx_runtime3 = require("react/jsx-runtime");
610
650
  var SlopText = import_react3.default.forwardRef(
611
651
  ({
612
652
  bucketId,
653
+ pipelineId,
654
+ siloId,
655
+ prompt,
656
+ metadata,
613
657
  version,
614
658
  resultId,
615
659
  variables,
@@ -622,21 +666,39 @@ var SlopText = import_react3.default.forwardRef(
622
666
  const [text, setText] = (0, import_react3.useState)(null);
623
667
  const [loading, setLoading] = (0, import_react3.useState)(true);
624
668
  const [error, setError] = (0, import_react3.useState)(null);
669
+ const rawUrl = (0, import_react3.useMemo)(
670
+ () => (0, import_core3.buildTextUrl)({
671
+ bucketId,
672
+ pipelineId,
673
+ siloId,
674
+ prompt,
675
+ metadata,
676
+ version,
677
+ resultId,
678
+ variables,
679
+ baseUrl,
680
+ attachments
681
+ }),
682
+ [
683
+ bucketId,
684
+ pipelineId,
685
+ siloId,
686
+ prompt,
687
+ JSON.stringify(metadata),
688
+ version,
689
+ resultId,
690
+ JSON.stringify(variables),
691
+ baseUrl,
692
+ JSON.stringify(attachments)
693
+ ]
694
+ );
625
695
  (0, import_react3.useEffect)(() => {
626
696
  let isMounted = true;
627
697
  const fetchText = async () => {
628
698
  try {
629
699
  setLoading(true);
630
700
  setError(null);
631
- const url = (0, import_core3.buildTextUrl)({
632
- bucketId,
633
- version,
634
- resultId,
635
- variables,
636
- baseUrl,
637
- attachments
638
- });
639
- const response = await fetch(url, { cache: "no-store" });
701
+ const response = await fetch(rawUrl, { cache: "no-store" });
640
702
  if (!response.ok) {
641
703
  let errorMessage = response.statusText;
642
704
  try {
@@ -669,14 +731,7 @@ var SlopText = import_react3.default.forwardRef(
669
731
  return () => {
670
732
  isMounted = false;
671
733
  };
672
- }, [
673
- bucketId,
674
- version,
675
- resultId,
676
- JSON.stringify(variables),
677
- JSON.stringify(attachments),
678
- baseUrl
679
- ]);
734
+ }, [rawUrl]);
680
735
  if (error && errorFallback) {
681
736
  return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_jsx_runtime3.Fragment, { children: errorFallback });
682
737
  }