@slopmachine/react 0.1.10 → 0.1.13

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/Agents.md ADDED
@@ -0,0 +1,34 @@
1
+ # React SDK Conventions
2
+
3
+ This document outlines the coding conventions and patterns used in the `@slopmachine/react` SDK. Future agents should adhere to these guidelines when making modifications or adding new components.
4
+
5
+ ## Dependencies and Styling
6
+
7
+ - **Class Merging:** Use `clsx` and `tailwind-merge` to construct and merge Tailwind CSS classes. A utility function `cn(...inputs: ClassValue[])` is typically used for this purpose.
8
+ - **Styling Approach:** Components use Tailwind CSS classes for styling. However, to ensure components remain robust even if the consumer's environment doesn't perfectly process all Tailwind classes, always include equivalent inline `style` properties as a fallback.
9
+ - **CSS Variables:** Use standard CSS variables for theme-related colors (e.g., `var(--muted, #f3f4f6)`).
10
+ - **Custom Animations/Styles:** If complex animations or specific scoped styles are needed that go beyond Tailwind utility classes, inject them using a scoped `<style>` block within the component.
11
+ - **Core Logic:** Import shared logic, utilities, and base types from `@slopmachine/core`.
12
+
13
+ ## Component Structure
14
+
15
+ - **Functional Components:** Define components as Functional Components (e.g., `React.FC<Props>`).
16
+ - **Prop Forwarding:** Spread the remaining props (`...props`) onto the primary underlying DOM element to allow consumers to pass standard HTML attributes (like `aria-` attributes, data attributes, etc.).
17
+
18
+ ## Prop Typing
19
+
20
+ - **Interfaces:** Define an explicit `Props` interface for each component.
21
+ - **Extending Standard Attributes:** Extend the appropriate React HTML attributes interface (e.g., `React.ImgHTMLAttributes<HTMLImageElement>`).
22
+ - **Overriding Attributes:** Use `Omit` to exclude standard attributes that are managed internally by the component or replaced by custom SDK options (e.g., `Omit<React.ImgHTMLAttributes<HTMLImageElement>, "src" | "alt">`).
23
+ - **Shared Types:** Extend or incorporate types from `@slopmachine/core` (like `SlopImageOptions`).
24
+
25
+ ## IntelliSense and Documentation
26
+
27
+ - **JSDoc Comments:** Always include descriptive JSDoc comments for components and their props to provide rich IntelliSense in IDEs.
28
+ - **Component Documentation:** Component JSDoc blocks should describe what the component does and include a clear `@example` block demonstrating usage, and optionally a `@version` tag if applicable.
29
+ - **Prop Documentation:** Every custom prop in a component's interface should have a JSDoc comment explaining its purpose, default behavior, and any edge cases. This is crucial for developer experience when consuming the SDK.
30
+
31
+ ## Exporting Patterns
32
+
33
+ - **Named Exports:** Use named exports for components and interfaces (e.g., `export const ComponentName = ...`). Avoid default exports.
34
+ - **Entry Point:** Ensure components and their prop types are exported from the package's main entry point if they are meant for public consumption.
package/README.md CHANGED
@@ -14,7 +14,7 @@ pnpm add @slopmachine/react
14
14
 
15
15
  ## Demo
16
16
 
17
- https://slopmachine-dev.github.io/slopmachine-sdk/
17
+ https://slopmachine-dev.github.io/slopmachine-sdk/demo-react/
18
18
 
19
19
  ## Usage
20
20
 
package/dist/index.d.mts CHANGED
@@ -1,9 +1,68 @@
1
1
  import React from 'react';
2
- import { SlopImageOptions } from '@slopmachine/core';
2
+ import { SlopImageOptions, ImageAspectRatio, SlopVideoOptions, VideoAspectRatio } from '@slopmachine/core';
3
+ export { ImageAspectRatio, SlopImageOptions, SlopVideoOptions, VideoAspectRatio } from '@slopmachine/core';
3
4
 
4
- interface SlopImageProps extends Omit<React.ImgHTMLAttributes<HTMLImageElement>, "src" | "alt">, SlopImageOptions {
5
+ interface SlopImageProps extends Omit<React.ImgHTMLAttributes<HTMLImageElement>, "src" | "alt">, Omit<SlopImageOptions, "aspectRatio"> {
6
+ /**
7
+ * The aspect ratio of the generated image. Defaults to "1:1".
8
+ */
9
+ aspectRatio?: ImageAspectRatio;
10
+ /**
11
+ * Custom React node to display while the image is loading.
12
+ * If not provided, a default spinner and shimmer effect will be shown.
13
+ */
5
14
  loader?: React.ReactNode;
6
15
  }
16
+ /**
17
+ * Renders an image generated by Slop Machine.
18
+ *
19
+ * This component automatically constructs the correct URL for the Slop Machine API,
20
+ * displays a loading skeleton or custom loader while fetching, and handles errors.
21
+ *
22
+ * @example
23
+ * ```tsx
24
+ * <SlopImage
25
+ * bucketId="my-bucket"
26
+ * resultId="some-result"
27
+ * aspectRatio="16:9"
28
+ * className="rounded-lg"
29
+ * />
30
+ * ```
31
+ *
32
+ * @version 0.1.13
33
+ */
7
34
  declare const SlopImage: React.FC<SlopImageProps>;
8
35
 
9
- export { SlopImage };
36
+ interface SlopVideoProps extends Omit<React.VideoHTMLAttributes<HTMLVideoElement>, "src">, Omit<SlopVideoOptions, "aspectRatio"> {
37
+ /**
38
+ * The aspect ratio of the generated video. Defaults to "16:9".
39
+ */
40
+ aspectRatio?: VideoAspectRatio;
41
+ /**
42
+ * Custom React node to display while the video is loading.
43
+ * If not provided, a default spinner and shimmer effect will be shown.
44
+ */
45
+ loader?: React.ReactNode;
46
+ }
47
+ /**
48
+ * Renders a video generated by Slop Machine.
49
+ *
50
+ * This component automatically constructs the correct URL for the Slop Machine API,
51
+ * displays a loading skeleton or custom loader while fetching, and handles errors.
52
+ *
53
+ * @example
54
+ * ```tsx
55
+ * <SlopVideo
56
+ * bucketId="my-bucket"
57
+ * resultId="some-result"
58
+ * aspectRatio="16:9"
59
+ * className="rounded-lg"
60
+ * autoPlay
61
+ * loop
62
+ * muted
63
+ * />
64
+ * ```
65
+ */
66
+ declare const SlopVideo: React.FC<SlopVideoProps>;
67
+
68
+ export { SlopImage, type SlopImageProps, SlopVideo, type SlopVideoProps };
package/dist/index.d.ts CHANGED
@@ -1,9 +1,68 @@
1
1
  import React from 'react';
2
- import { SlopImageOptions } from '@slopmachine/core';
2
+ import { SlopImageOptions, ImageAspectRatio, SlopVideoOptions, VideoAspectRatio } from '@slopmachine/core';
3
+ export { ImageAspectRatio, SlopImageOptions, SlopVideoOptions, VideoAspectRatio } from '@slopmachine/core';
3
4
 
4
- interface SlopImageProps extends Omit<React.ImgHTMLAttributes<HTMLImageElement>, "src" | "alt">, SlopImageOptions {
5
+ interface SlopImageProps extends Omit<React.ImgHTMLAttributes<HTMLImageElement>, "src" | "alt">, Omit<SlopImageOptions, "aspectRatio"> {
6
+ /**
7
+ * The aspect ratio of the generated image. Defaults to "1:1".
8
+ */
9
+ aspectRatio?: ImageAspectRatio;
10
+ /**
11
+ * Custom React node to display while the image is loading.
12
+ * If not provided, a default spinner and shimmer effect will be shown.
13
+ */
5
14
  loader?: React.ReactNode;
6
15
  }
16
+ /**
17
+ * Renders an image generated by Slop Machine.
18
+ *
19
+ * This component automatically constructs the correct URL for the Slop Machine API,
20
+ * displays a loading skeleton or custom loader while fetching, and handles errors.
21
+ *
22
+ * @example
23
+ * ```tsx
24
+ * <SlopImage
25
+ * bucketId="my-bucket"
26
+ * resultId="some-result"
27
+ * aspectRatio="16:9"
28
+ * className="rounded-lg"
29
+ * />
30
+ * ```
31
+ *
32
+ * @version 0.1.13
33
+ */
7
34
  declare const SlopImage: React.FC<SlopImageProps>;
8
35
 
9
- export { SlopImage };
36
+ interface SlopVideoProps extends Omit<React.VideoHTMLAttributes<HTMLVideoElement>, "src">, Omit<SlopVideoOptions, "aspectRatio"> {
37
+ /**
38
+ * The aspect ratio of the generated video. Defaults to "16:9".
39
+ */
40
+ aspectRatio?: VideoAspectRatio;
41
+ /**
42
+ * Custom React node to display while the video is loading.
43
+ * If not provided, a default spinner and shimmer effect will be shown.
44
+ */
45
+ loader?: React.ReactNode;
46
+ }
47
+ /**
48
+ * Renders a video generated by Slop Machine.
49
+ *
50
+ * This component automatically constructs the correct URL for the Slop Machine API,
51
+ * displays a loading skeleton or custom loader while fetching, and handles errors.
52
+ *
53
+ * @example
54
+ * ```tsx
55
+ * <SlopVideo
56
+ * bucketId="my-bucket"
57
+ * resultId="some-result"
58
+ * aspectRatio="16:9"
59
+ * className="rounded-lg"
60
+ * autoPlay
61
+ * loop
62
+ * muted
63
+ * />
64
+ * ```
65
+ */
66
+ declare const SlopVideo: React.FC<SlopVideoProps>;
67
+
68
+ export { SlopImage, type SlopImageProps, SlopVideo, type SlopVideoProps };
package/dist/index.js CHANGED
@@ -30,7 +30,8 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
30
30
  // src/index.ts
31
31
  var index_exports = {};
32
32
  __export(index_exports, {
33
- SlopImage: () => SlopImage
33
+ SlopImage: () => SlopImage,
34
+ SlopVideo: () => SlopVideo
34
35
  });
35
36
  module.exports = __toCommonJS(index_exports);
36
37
 
@@ -117,15 +118,17 @@ var SlopImage = ({
117
118
  }
118
119
  }
119
120
  ` }),
120
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
121
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className, style: props.style, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
121
122
  "div",
122
123
  {
123
- className: cn("relative overflow-hidden", className),
124
+ className: "slop-wrapper relative overflow-hidden w-full h-full",
124
125
  style: {
125
126
  aspectRatio: String(aspectRatio).replace(":", "/"),
126
127
  backgroundColor: "var(--muted, #f3f4f6)",
127
128
  position: "relative",
128
- overflow: "hidden"
129
+ overflow: "hidden",
130
+ width: "100%",
131
+ height: "100%"
129
132
  },
130
133
  children: [
131
134
  loader ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
@@ -285,10 +288,288 @@ var SlopImage = ({
285
288
  )
286
289
  ]
287
290
  }
288
- )
291
+ ) })
292
+ ] });
293
+ };
294
+
295
+ // src/components/SlopVideo.tsx
296
+ var import_react2 = require("react");
297
+ var import_clsx2 = require("clsx");
298
+ var import_tailwind_merge2 = require("tailwind-merge");
299
+ var import_core2 = require("@slopmachine/core");
300
+ var import_jsx_runtime2 = require("react/jsx-runtime");
301
+ function cn2(...inputs) {
302
+ return (0, import_tailwind_merge2.twMerge)((0, import_clsx2.clsx)(inputs));
303
+ }
304
+ var SlopVideo = ({
305
+ bucketId,
306
+ className,
307
+ aspectRatio = "16:9",
308
+ version,
309
+ resultId,
310
+ model,
311
+ variables = {},
312
+ duration,
313
+ baseUrl,
314
+ loader,
315
+ autoPlay = true,
316
+ loop = true,
317
+ muted = true,
318
+ playsInline = true,
319
+ ...props
320
+ }) => {
321
+ const rawSrc = (0, import_react2.useMemo)(
322
+ () => (0, import_core2.buildVideoUrl)({
323
+ bucketId,
324
+ aspectRatio,
325
+ version,
326
+ resultId,
327
+ variables,
328
+ duration,
329
+ baseUrl,
330
+ model
331
+ }),
332
+ [
333
+ bucketId,
334
+ aspectRatio,
335
+ version,
336
+ resultId,
337
+ variables,
338
+ duration,
339
+ baseUrl,
340
+ model
341
+ ]
342
+ );
343
+ const [src, setSrc] = (0, import_react2.useState)(rawSrc);
344
+ (0, import_react2.useEffect)(() => {
345
+ const timer = setTimeout(() => {
346
+ setSrc(rawSrc);
347
+ }, 100);
348
+ return () => clearTimeout(timer);
349
+ }, [rawSrc]);
350
+ const [isLoading, setIsLoading] = (0, import_react2.useState)(true);
351
+ const [currentSrc, setCurrentSrc] = (0, import_react2.useState)(src);
352
+ const videoRef = (0, import_react2.useRef)(null);
353
+ if (src !== currentSrc) {
354
+ setCurrentSrc(src);
355
+ setIsLoading(true);
356
+ }
357
+ (0, import_react2.useEffect)(() => {
358
+ if (!src) return;
359
+ fetch(src, { method: "HEAD" }).then(async (res) => {
360
+ if (!res.ok) {
361
+ try {
362
+ const errRes = await fetch(src);
363
+ const errJson = await errRes.json();
364
+ console.error("SlopVideo error:", res.status, errJson.error);
365
+ } catch (e) {
366
+ }
367
+ setIsLoading(false);
368
+ }
369
+ }).catch((err) => {
370
+ console.error(`Error fetching video from ${src}:`, err);
371
+ setIsLoading(false);
372
+ });
373
+ }, [src]);
374
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
375
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("style", { children: `
376
+ @keyframes slop-shimmer {
377
+ 0% {
378
+ background-position: 200% 0;
379
+ }
380
+ 100% {
381
+ background-position: -200% 0;
382
+ }
383
+ }
384
+ @keyframes slop-spin {
385
+ from {
386
+ transform: rotate(0deg);
387
+ }
388
+ to {
389
+ transform: rotate(360deg);
390
+ }
391
+ }
392
+ ` }),
393
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className, style: props.style, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
394
+ "div",
395
+ {
396
+ className: "slop-wrapper relative overflow-hidden w-full h-full",
397
+ style: {
398
+ aspectRatio: String(aspectRatio).replace(":", "/"),
399
+ backgroundColor: "var(--muted, #f3f4f6)",
400
+ position: "relative",
401
+ overflow: "hidden",
402
+ width: "100%",
403
+ height: "100%"
404
+ },
405
+ children: [
406
+ loader ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
407
+ "div",
408
+ {
409
+ className: cn2(
410
+ "absolute inset-0 z-10 flex items-center justify-center transition-opacity duration-300",
411
+ isLoading ? "opacity-100" : "opacity-0 pointer-events-none"
412
+ ),
413
+ style: {
414
+ position: "absolute",
415
+ top: 0,
416
+ left: 0,
417
+ right: 0,
418
+ bottom: 0,
419
+ zIndex: 10,
420
+ display: "flex",
421
+ alignItems: "center",
422
+ justifyContent: "center",
423
+ opacity: isLoading ? 1 : 0,
424
+ pointerEvents: isLoading ? "auto" : "none",
425
+ transition: "opacity 300ms ease-in-out"
426
+ },
427
+ children: loader
428
+ }
429
+ ) : /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
430
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
431
+ "div",
432
+ {
433
+ className: cn2(
434
+ "absolute inset-0 z-10 flex items-center justify-center bg-muted transition-opacity duration-300",
435
+ isLoading ? "opacity-100" : "opacity-0 pointer-events-none"
436
+ ),
437
+ style: {
438
+ position: "absolute",
439
+ top: 0,
440
+ left: 0,
441
+ right: 0,
442
+ bottom: 0,
443
+ zIndex: 10,
444
+ display: "flex",
445
+ alignItems: "center",
446
+ justifyContent: "center",
447
+ backgroundColor: "var(--muted, #f3f4f6)",
448
+ opacity: isLoading ? 1 : 0,
449
+ pointerEvents: isLoading ? "auto" : "none",
450
+ transition: "opacity 300ms ease-in-out"
451
+ },
452
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
453
+ "div",
454
+ {
455
+ className: "flex flex-col items-center gap-2",
456
+ style: {
457
+ display: "flex",
458
+ flexDirection: "column",
459
+ alignItems: "center",
460
+ gap: "0.5rem"
461
+ },
462
+ children: [
463
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
464
+ "svg",
465
+ {
466
+ className: "spinner size-6 text-muted-foreground",
467
+ xmlns: "http://www.w3.org/2000/svg",
468
+ fill: "none",
469
+ viewBox: "0 0 24 24",
470
+ style: {
471
+ width: "24px",
472
+ height: "24px",
473
+ color: "var(--muted-foreground, #6b7280)",
474
+ animation: "slop-spin 1s linear infinite"
475
+ },
476
+ children: [
477
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
478
+ "circle",
479
+ {
480
+ className: "opacity-25",
481
+ cx: "12",
482
+ cy: "12",
483
+ r: "10",
484
+ stroke: "currentColor",
485
+ strokeWidth: "4",
486
+ style: { opacity: 0.25 }
487
+ }
488
+ ),
489
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
490
+ "path",
491
+ {
492
+ className: "opacity-75",
493
+ fill: "currentColor",
494
+ 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",
495
+ style: { opacity: 0.75 }
496
+ }
497
+ )
498
+ ]
499
+ }
500
+ ),
501
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
502
+ "span",
503
+ {
504
+ className: "text-xs text-muted-foreground",
505
+ style: {
506
+ fontSize: "0.75rem",
507
+ color: "var(--muted-foreground, #6b7280)"
508
+ },
509
+ children: "Loading..."
510
+ }
511
+ )
512
+ ]
513
+ }
514
+ )
515
+ }
516
+ ),
517
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
518
+ "div",
519
+ {
520
+ className: cn2(
521
+ "shimmer-effect absolute inset-0 bg-gradient-to-r from-muted via-muted/50 to-muted",
522
+ isLoading ? "opacity-100" : "opacity-0"
523
+ ),
524
+ style: {
525
+ position: "absolute",
526
+ top: 0,
527
+ left: 0,
528
+ right: 0,
529
+ bottom: 0,
530
+ background: "linear-gradient(90deg, var(--muted, #f3f4f6) 0%, var(--muted-foreground, #e5e7eb) 50%, var(--muted, #f3f4f6) 100%)",
531
+ backgroundSize: "200% 100%",
532
+ animation: "slop-shimmer 2s ease-in-out infinite",
533
+ opacity: isLoading ? 1 : 0,
534
+ transition: "opacity 300ms"
535
+ }
536
+ }
537
+ )
538
+ ] }),
539
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
540
+ "video",
541
+ {
542
+ ref: videoRef,
543
+ src,
544
+ autoPlay,
545
+ loop,
546
+ muted,
547
+ playsInline,
548
+ onLoadedData: () => setIsLoading(false),
549
+ onError: () => setIsLoading(false),
550
+ className: cn2(
551
+ "h-full w-full object-cover transition-opacity duration-500",
552
+ isLoading ? "opacity-0" : "opacity-100"
553
+ ),
554
+ style: {
555
+ height: "100%",
556
+ width: "100%",
557
+ objectFit: "cover",
558
+ transition: "opacity 500ms",
559
+ opacity: isLoading ? 0 : 1
560
+ },
561
+ ...props
562
+ },
563
+ src
564
+ )
565
+ ]
566
+ }
567
+ ) })
289
568
  ] });
290
569
  };
291
570
  // Annotate the CommonJS export names for ESM import in node:
292
571
  0 && (module.exports = {
293
- SlopImage
572
+ SlopImage,
573
+ SlopVideo
294
574
  });
575
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/components/SlopImage.tsx","../src/components/SlopVideo.tsx"],"sourcesContent":["export { SlopImage, type SlopImageProps } from \"./components/SlopImage\";\nexport { SlopVideo, type SlopVideoProps } from \"./components/SlopVideo\";\nexport type {\n ImageAspectRatio,\n VideoAspectRatio,\n SlopImageOptions,\n SlopVideoOptions,\n} from \"@slopmachine/core\";\n","import React, { useMemo, useState } from \"react\";\nimport { clsx, type ClassValue } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\nimport {\n buildImageUrl,\n type SlopImageOptions,\n type ImageAspectRatio,\n} from \"@slopmachine/core\";\n\n// Utility for Tailwind classes\nfunction cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n\nexport interface SlopImageProps\n extends\n Omit<React.ImgHTMLAttributes<HTMLImageElement>, \"src\" | \"alt\">,\n Omit<SlopImageOptions, \"aspectRatio\"> {\n /**\n * The aspect ratio of the generated image. Defaults to \"1:1\".\n */\n aspectRatio?: ImageAspectRatio;\n /**\n * Custom React node to display while the image is loading.\n * If not provided, a default spinner and shimmer effect will be shown.\n */\n loader?: React.ReactNode;\n}\n\n/**\n * Renders an image generated by Slop Machine.\n *\n * This component automatically constructs the correct URL for the Slop Machine API,\n * displays a loading skeleton or custom loader while fetching, and handles errors.\n *\n * @example\n * ```tsx\n * <SlopImage\n * bucketId=\"my-bucket\"\n * resultId=\"some-result\"\n * aspectRatio=\"16:9\"\n * className=\"rounded-lg\"\n * />\n * ```\n *\n * @version 0.1.13\n */\nexport const SlopImage: React.FC<SlopImageProps> = ({\n bucketId,\n className,\n aspectRatio = \"1:1\",\n version,\n resultId,\n model,\n variables = {},\n baseUrl,\n loader,\n ...props\n}) => {\n // Construct API URL\n const rawSrc = useMemo(\n () =>\n buildImageUrl({\n bucketId,\n aspectRatio,\n version,\n resultId,\n variables,\n baseUrl,\n model,\n }),\n [bucketId, aspectRatio, version, resultId, variables, baseUrl, model],\n );\n\n const [src, setSrc] = useState(rawSrc);\n\n React.useEffect(() => {\n const timer = setTimeout(() => {\n setSrc(rawSrc);\n }, 100);\n return () => clearTimeout(timer);\n }, [rawSrc]);\n\n const alt = \"Generated image\";\n\n const [isLoading, setIsLoading] = useState(true);\n const [currentSrc, setCurrentSrc] = useState(src);\n\n if (src !== currentSrc) {\n setCurrentSrc(src);\n setIsLoading(true);\n }\n\n React.useEffect(() => {\n if (!src) return;\n\n fetch(src, { method: \"HEAD\" })\n .then(async (res) => {\n if (!res.ok) {\n // console.error(\n // `Failed to load image from ${src}. Status: ${res.status} ${res.statusText}`,\n // );\n try {\n const errRes = await fetch(src);\n const errJson = await errRes.json();\n console.error(\"SlopImage error:\", res.status, errJson.error);\n } catch (e) {\n // Failed to fetch or parse error details\n }\n setIsLoading(false);\n }\n })\n .catch((err) => {\n console.error(`Error fetching image from ${src}:`, err);\n setIsLoading(false);\n });\n }, [src]);\n\n return (\n <>\n <style>{`\n @keyframes slop-shimmer {\n 0% {\n background-position: 200% 0;\n }\n 100% {\n background-position: -200% 0;\n }\n }\n @keyframes slop-spin {\n from {\n transform: rotate(0deg);\n }\n to {\n transform: rotate(360deg);\n }\n }\n `}</style>\n <div className={className} style={props.style}>\n <div\n className=\"slop-wrapper relative overflow-hidden w-full h-full\"\n style={{\n aspectRatio: String(aspectRatio).replace(\":\", \"/\"),\n backgroundColor: \"var(--muted, #f3f4f6)\",\n position: \"relative\",\n overflow: \"hidden\",\n width: \"100%\",\n height: \"100%\",\n }}\n >\n {/* Loading UI */}\n {loader ? (\n <div\n className={cn(\n \"absolute inset-0 z-10 flex items-center justify-center transition-opacity duration-300\",\n isLoading ? \"opacity-100\" : \"opacity-0 pointer-events-none\",\n )}\n style={{\n position: \"absolute\",\n top: 0,\n left: 0,\n right: 0,\n bottom: 0,\n zIndex: 10,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n opacity: isLoading ? 1 : 0,\n pointerEvents: isLoading ? \"auto\" : \"none\",\n transition: \"opacity 300ms ease-in-out\",\n }}\n >\n {loader}\n </div>\n ) : (\n <>\n {/* Loading overlay */}\n <div\n className={cn(\n \"absolute inset-0 z-10 flex items-center justify-center bg-muted transition-opacity duration-300\",\n isLoading ? \"opacity-100\" : \"opacity-0 pointer-events-none\",\n )}\n style={{\n position: \"absolute\",\n top: 0,\n left: 0,\n right: 0,\n bottom: 0,\n zIndex: 10,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n backgroundColor: \"var(--muted, #f3f4f6)\",\n opacity: isLoading ? 1 : 0,\n pointerEvents: isLoading ? \"auto\" : \"none\",\n transition: \"opacity 300ms ease-in-out\",\n }}\n >\n <div\n className=\"flex flex-col items-center gap-2\"\n style={{\n display: \"flex\",\n flexDirection: \"column\",\n alignItems: \"center\",\n gap: \"0.5rem\",\n }}\n >\n <svg\n className=\"spinner size-6 text-muted-foreground\"\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n style={{\n width: \"24px\",\n height: \"24px\",\n color: \"var(--muted-foreground, #6b7280)\",\n animation: \"slop-spin 1s linear infinite\",\n }}\n >\n <circle\n className=\"opacity-25\"\n cx=\"12\"\n cy=\"12\"\n r=\"10\"\n stroke=\"currentColor\"\n strokeWidth=\"4\"\n style={{ opacity: 0.25 }}\n />\n <path\n className=\"opacity-75\"\n fill=\"currentColor\"\n 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\"\n style={{ opacity: 0.75 }}\n />\n </svg>\n <span\n className=\"text-xs text-muted-foreground\"\n style={{\n fontSize: \"0.75rem\",\n color: \"var(--muted-foreground, #6b7280)\",\n }}\n >\n Loading...\n </span>\n </div>\n </div>\n\n {/* Shimmer effect underneath */}\n <div\n className={cn(\n \"shimmer-effect absolute inset-0 bg-gradient-to-r from-muted via-muted/50 to-muted\",\n isLoading ? \"opacity-100\" : \"opacity-0\",\n )}\n style={{\n position: \"absolute\",\n top: 0,\n left: 0,\n right: 0,\n bottom: 0,\n background:\n \"linear-gradient(90deg, var(--muted, #f3f4f6) 0%, var(--muted-foreground, #e5e7eb) 50%, var(--muted, #f3f4f6) 100%)\",\n backgroundSize: \"200% 100%\",\n animation: \"slop-shimmer 2s ease-in-out infinite\",\n opacity: isLoading ? 1 : 0,\n transition: \"opacity 300ms\",\n }}\n />\n </>\n )}\n\n {/* Image */}\n <img\n key={src}\n src={src}\n alt={alt}\n onLoad={() => setIsLoading(false)}\n onError={() => setIsLoading(false)}\n className={cn(\n \"h-full w-full object-cover transition-opacity duration-500\",\n isLoading ? \"opacity-0\" : \"opacity-100\",\n )}\n style={{\n height: \"100%\",\n width: \"100%\",\n objectFit: \"cover\",\n transition: \"opacity 500ms\",\n opacity: isLoading ? 0 : 1,\n }}\n {...props}\n />\n </div>\n </div>\n </>\n );\n};\n","import React, { useMemo, useState, useRef, useEffect } from \"react\";\nimport { clsx, type ClassValue } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\nimport {\n buildVideoUrl,\n type SlopVideoOptions,\n type VideoAspectRatio,\n} from \"@slopmachine/core\";\n\n// Utility for Tailwind classes\nfunction cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n\nexport interface SlopVideoProps\n extends\n Omit<React.VideoHTMLAttributes<HTMLVideoElement>, \"src\">,\n Omit<SlopVideoOptions, \"aspectRatio\"> {\n /**\n * The aspect ratio of the generated video. Defaults to \"16:9\".\n */\n aspectRatio?: VideoAspectRatio;\n /**\n * Custom React node to display while the video is loading.\n * If not provided, a default spinner and shimmer effect will be shown.\n */\n loader?: React.ReactNode;\n}\n\n/**\n * Renders a video generated by Slop Machine.\n *\n * This component automatically constructs the correct URL for the Slop Machine API,\n * displays a loading skeleton or custom loader while fetching, and handles errors.\n *\n * @example\n * ```tsx\n * <SlopVideo\n * bucketId=\"my-bucket\"\n * resultId=\"some-result\"\n * aspectRatio=\"16:9\"\n * className=\"rounded-lg\"\n * autoPlay\n * loop\n * muted\n * />\n * ```\n */\nexport const SlopVideo: React.FC<SlopVideoProps> = ({\n bucketId,\n className,\n aspectRatio = \"16:9\",\n version,\n resultId,\n model,\n variables = {},\n duration,\n baseUrl,\n loader,\n autoPlay = true,\n loop = true,\n muted = true,\n playsInline = true,\n ...props\n}) => {\n // Construct API URL\n const rawSrc = useMemo(\n () =>\n buildVideoUrl({\n bucketId,\n aspectRatio,\n version,\n resultId,\n variables,\n duration,\n baseUrl,\n model,\n }),\n [\n bucketId,\n aspectRatio,\n version,\n resultId,\n variables,\n duration,\n baseUrl,\n model,\n ],\n );\n\n const [src, setSrc] = useState(rawSrc);\n\n useEffect(() => {\n const timer = setTimeout(() => {\n setSrc(rawSrc);\n }, 100);\n return () => clearTimeout(timer);\n }, [rawSrc]);\n\n const [isLoading, setIsLoading] = useState(true);\n const [currentSrc, setCurrentSrc] = useState(src);\n const videoRef = useRef<HTMLVideoElement>(null);\n\n if (src !== currentSrc) {\n setCurrentSrc(src);\n setIsLoading(true);\n }\n\n useEffect(() => {\n if (!src) return;\n\n fetch(src, { method: \"HEAD\" })\n .then(async (res) => {\n if (!res.ok) {\n try {\n const errRes = await fetch(src);\n const errJson = await errRes.json();\n console.error(\"SlopVideo error:\", res.status, errJson.error);\n } catch (e) {\n // Failed to fetch or parse error details\n }\n setIsLoading(false);\n }\n })\n .catch((err) => {\n console.error(`Error fetching video from ${src}:`, err);\n setIsLoading(false);\n });\n }, [src]);\n\n return (\n <>\n <style>{`\n @keyframes slop-shimmer {\n 0% {\n background-position: 200% 0;\n }\n 100% {\n background-position: -200% 0;\n }\n }\n @keyframes slop-spin {\n from {\n transform: rotate(0deg);\n }\n to {\n transform: rotate(360deg);\n }\n }\n `}</style>\n <div className={className} style={props.style}>\n <div\n className=\"slop-wrapper relative overflow-hidden w-full h-full\"\n style={{\n aspectRatio: String(aspectRatio).replace(\":\", \"/\"),\n backgroundColor: \"var(--muted, #f3f4f6)\",\n position: \"relative\",\n overflow: \"hidden\",\n width: \"100%\",\n height: \"100%\",\n }}\n >\n {/* Loading UI */}\n {loader ? (\n <div\n className={cn(\n \"absolute inset-0 z-10 flex items-center justify-center transition-opacity duration-300\",\n isLoading ? \"opacity-100\" : \"opacity-0 pointer-events-none\",\n )}\n style={{\n position: \"absolute\",\n top: 0,\n left: 0,\n right: 0,\n bottom: 0,\n zIndex: 10,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n opacity: isLoading ? 1 : 0,\n pointerEvents: isLoading ? \"auto\" : \"none\",\n transition: \"opacity 300ms ease-in-out\",\n }}\n >\n {loader}\n </div>\n ) : (\n <>\n {/* Loading overlay */}\n <div\n className={cn(\n \"absolute inset-0 z-10 flex items-center justify-center bg-muted transition-opacity duration-300\",\n isLoading ? \"opacity-100\" : \"opacity-0 pointer-events-none\",\n )}\n style={{\n position: \"absolute\",\n top: 0,\n left: 0,\n right: 0,\n bottom: 0,\n zIndex: 10,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n backgroundColor: \"var(--muted, #f3f4f6)\",\n opacity: isLoading ? 1 : 0,\n pointerEvents: isLoading ? \"auto\" : \"none\",\n transition: \"opacity 300ms ease-in-out\",\n }}\n >\n <div\n className=\"flex flex-col items-center gap-2\"\n style={{\n display: \"flex\",\n flexDirection: \"column\",\n alignItems: \"center\",\n gap: \"0.5rem\",\n }}\n >\n <svg\n className=\"spinner size-6 text-muted-foreground\"\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n style={{\n width: \"24px\",\n height: \"24px\",\n color: \"var(--muted-foreground, #6b7280)\",\n animation: \"slop-spin 1s linear infinite\",\n }}\n >\n <circle\n className=\"opacity-25\"\n cx=\"12\"\n cy=\"12\"\n r=\"10\"\n stroke=\"currentColor\"\n strokeWidth=\"4\"\n style={{ opacity: 0.25 }}\n />\n <path\n className=\"opacity-75\"\n fill=\"currentColor\"\n 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\"\n style={{ opacity: 0.75 }}\n />\n </svg>\n <span\n className=\"text-xs text-muted-foreground\"\n style={{\n fontSize: \"0.75rem\",\n color: \"var(--muted-foreground, #6b7280)\",\n }}\n >\n Loading...\n </span>\n </div>\n </div>\n\n {/* Shimmer effect underneath */}\n <div\n className={cn(\n \"shimmer-effect absolute inset-0 bg-gradient-to-r from-muted via-muted/50 to-muted\",\n isLoading ? \"opacity-100\" : \"opacity-0\",\n )}\n style={{\n position: \"absolute\",\n top: 0,\n left: 0,\n right: 0,\n bottom: 0,\n background:\n \"linear-gradient(90deg, var(--muted, #f3f4f6) 0%, var(--muted-foreground, #e5e7eb) 50%, var(--muted, #f3f4f6) 100%)\",\n backgroundSize: \"200% 100%\",\n animation: \"slop-shimmer 2s ease-in-out infinite\",\n opacity: isLoading ? 1 : 0,\n transition: \"opacity 300ms\",\n }}\n />\n </>\n )}\n\n {/* Video */}\n <video\n key={src}\n ref={videoRef}\n src={src}\n autoPlay={autoPlay}\n loop={loop}\n muted={muted}\n playsInline={playsInline}\n onLoadedData={() => setIsLoading(false)}\n onError={() => setIsLoading(false)}\n className={cn(\n \"h-full w-full object-cover transition-opacity duration-500\",\n isLoading ? \"opacity-0\" : \"opacity-100\",\n )}\n style={{\n height: \"100%\",\n width: \"100%\",\n objectFit: \"cover\",\n transition: \"opacity 500ms\",\n opacity: isLoading ? 0 : 1,\n }}\n {...props}\n />\n </div>\n </div>\n </>\n );\n};\n"],"mappings":"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","names":["React","import_react","import_clsx","import_tailwind_merge","import_core","import_jsx_runtime","cn"]}