@slopmachine/react 0.8.1 → 1.0.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 +38 -0
- package/dist/index.d.mts +29 -10
- package/dist/index.d.ts +29 -10
- package/dist/index.js +65 -61
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +70 -64
- package/dist/index.mjs.map +1 -1
- package/package.json +11 -11
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/components/SlopImage.tsx","../src/components/ErrorOverlay.tsx","../src/components/SlopVideo.tsx","../src/components/SlopText.tsx"],"sourcesContent":["export { SlopImage, type SlopImageProps } from \"./components/SlopImage\";\nexport { SlopVideo, type SlopVideoProps } from \"./components/SlopVideo\";\nexport { SlopText, type SlopTextProps } from \"./components/SlopText\";\nexport type { SlopErrorFallback } from \"./components/ErrorOverlay\";\n\nexport type {\n ImageAspectRatio,\n VideoAspectRatio,\n SlopImageOptions,\n SlopVideoOptions,\n SlopTextOptions,\n ResultRating,\n RateResultOptions,\n RateResultResponse,\n} from \"@slopmachine/core\";\n\nexport {\n preloadImage,\n preloadVideo,\n preloadText,\n rateResult,\n SlopMachineError,\n} from \"@slopmachine/core\";\n","import React, { useEffect, useMemo, useRef, useState } from \"react\";\nimport { clsx, type ClassValue } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\nimport {\n buildImageUrl,\n createRenderUrlMonitor,\n type SlopMachineError,\n type SlopImageOptions,\n type ImageAspectRatio,\n} from \"@slopmachine/core\";\nimport { ErrorOverlay, type SlopErrorFallback } from \"./ErrorOverlay\";\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 * Content to display if the image fails to generate or load.\n * Pass a node, or a function that receives the `SlopMachineError` and returns a node.\n * If not provided, a default error message is shown in place of the image.\n */\n errorFallback?: SlopErrorFallback;\n /**\n * Called once per URL when the image fails to generate or load.\n * `error.status` holds the HTTP status when the API reported the failure.\n */\n onGenerationError?: (error: SlopMachineError) => void;\n /**\n * How the image should be resized to fit its container. Defaults to \"cover\".\n */\n objectFit?: React.CSSProperties[\"objectFit\"];\n /**\n * Additional CSS classes to apply directly to the `<img />` element.\n */\n imageClassName?: string;\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 * // Using a Bucket\n * <SlopImage\n * bucketId=\"my-bucket\"\n * resultId=\"some-result\"\n * aspectRatio=\"16:9\"\n * className=\"rounded-lg\"\n * objectFit=\"cover\"\n * />\n *\n * // Using a Pipeline with runtime prompt\n * <SlopImage\n * pipelineId=\"pipe_live_abc123\"\n * prompt=\"1960s retro robot eating pizza on Mars\"\n * aspectRatio=\"16:9\"\n * metadata={{ userId: \"123\" }}\n * />\n * ```\n *\n * @version 0.8.1\n */\nexport const SlopImage: React.FC<SlopImageProps> = ({\n bucketId,\n pipelineId,\n siloId,\n prompt,\n metadata,\n className,\n aspectRatio = \"1:1\",\n model,\n version,\n resultId,\n variables = {},\n baseUrl,\n original,\n attachments,\n loader,\n errorFallback,\n onGenerationError,\n objectFit = \"cover\",\n imageClassName,\n style,\n onLoad,\n onError,\n ...props\n}) => {\n // Construct API URL\n const rawSrc = useMemo(\n () =>\n buildImageUrl({\n bucketId,\n pipelineId,\n siloId,\n prompt,\n metadata,\n aspectRatio,\n model,\n version,\n resultId,\n variables,\n baseUrl,\n original,\n attachments,\n }),\n [\n bucketId,\n pipelineId,\n siloId,\n prompt,\n metadata,\n aspectRatio,\n model,\n version,\n resultId,\n variables,\n baseUrl,\n original,\n attachments,\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 alt = \"Image produced by Slop Machine (slopmachine.dev)\";\n\n const [isLoading, setIsLoading] = useState(true);\n const [error, setError] = useState<SlopMachineError | null>(null);\n const [currentSrc, setCurrentSrc] = useState(src);\n if (src !== currentSrc) {\n setCurrentSrc(src);\n setIsLoading(true);\n setError(null);\n }\n\n // Keep the latest callback without re-running effects when it changes identity\n const onGenerationErrorRef = useRef(onGenerationError);\n useEffect(() => {\n onGenerationErrorRef.current = onGenerationError;\n });\n\n // Shares one URL check between the HEAD probe and the media element's error event\n const monitor = useMemo(\n () =>\n createRenderUrlMonitor((err) => {\n console.error(\"SlopImage error:\", err.status ?? \"\", err.message);\n setIsLoading(false);\n setError(err);\n onGenerationErrorRef.current?.(err);\n }),\n [],\n );\n\n useEffect(() => {\n if (!src) return;\n monitor.watch(src);\n return () => monitor.stop();\n }, [src, monitor]);\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={style}>\n <div\n className=\"slop-wrapper relative overflow-hidden w-full h-full\"\n style={{\n aspectRatio: String(aspectRatio).replace(\":\", \"/\"),\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 {error && (\n <ErrorOverlay\n error={error}\n errorFallback={errorFallback}\n label=\"Failed to load image\"\n />\n )}\n\n {/* Image */}\n <img\n key={src}\n src={src}\n alt={alt}\n {...props}\n onLoad={(e) => {\n setIsLoading(false);\n onLoad?.(e);\n }}\n onError={(e) => {\n monitor.mediaFailed(src, \"Failed to load image\");\n onError?.(e);\n }}\n aria-hidden={error ? true : props[\"aria-hidden\"]}\n className={cn(\n \"h-full w-full transition-opacity duration-500\",\n isLoading || error ? \"opacity-0\" : \"opacity-100\",\n imageClassName,\n )}\n style={{\n height: \"100%\",\n width: \"100%\",\n objectFit,\n transition: \"opacity 500ms\",\n opacity: isLoading || error ? 0 : 1,\n }}\n />\n </div>\n </div>\n </>\n );\n};\n","import React from \"react\";\nimport type { SlopMachineError } from \"@slopmachine/core\";\n\n/**\n * Content to render when generation or loading fails. Either a node, or a\n * function that receives the error and returns a node.\n */\nexport type SlopErrorFallback =\n React.ReactNode | ((error: SlopMachineError) => React.ReactNode);\n\ninterface ErrorOverlayProps {\n error: SlopMachineError;\n errorFallback?: SlopErrorFallback;\n /**\n * Message shown by the default error UI, e.g. \"Failed to load image\".\n */\n label: string;\n}\n\nconst overlayStyle: React.CSSProperties = {\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};\n\n/**\n * Internal overlay shown over the media slot when generation or loading fails.\n * Renders the consumer's `errorFallback` if provided, otherwise a default message.\n */\nexport const ErrorOverlay: React.FC<ErrorOverlayProps> = ({\n error,\n errorFallback,\n label,\n}) => {\n if (errorFallback !== undefined) {\n return (\n <div\n className=\"absolute inset-0 z-10 flex items-center justify-center\"\n style={overlayStyle}\n >\n {typeof errorFallback === \"function\"\n ? errorFallback(error)\n : errorFallback}\n </div>\n );\n }\n\n return (\n <div\n className=\"absolute inset-0 z-10 flex items-center justify-center bg-muted\"\n style={{ ...overlayStyle, backgroundColor: \"var(--muted, #f3f4f6)\" }}\n title={error.message}\n >\n <div\n className=\"flex flex-col items-center gap-2 text-muted-foreground\"\n style={{\n display: \"flex\",\n flexDirection: \"column\",\n alignItems: \"center\",\n gap: \"0.5rem\",\n color: \"var(--muted-foreground, #6b7280)\",\n }}\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n style={{ width: \"24px\", height: \"24px\" }}\n >\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n <line x1=\"12\" y1=\"8\" x2=\"12\" y2=\"12\" />\n <line x1=\"12\" y1=\"16\" x2=\"12.01\" y2=\"16\" />\n </svg>\n <span className=\"text-xs\" style={{ fontSize: \"0.75rem\" }}>\n {label}\n </span>\n </div>\n </div>\n );\n};\n","import React, { useEffect, useMemo, useRef, useState } from \"react\";\nimport { clsx, type ClassValue } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\nimport {\n buildVideoUrl,\n createRenderUrlMonitor,\n type SlopMachineError,\n type SlopVideoOptions,\n type VideoAspectRatio,\n} from \"@slopmachine/core\";\nimport { ErrorOverlay, type SlopErrorFallback } from \"./ErrorOverlay\";\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 * Content to display if the video fails to generate or load.\n * Pass a node, or a function that receives the `SlopMachineError` and returns a node.\n * If not provided, a default error message is shown in place of the video.\n */\n errorFallback?: SlopErrorFallback;\n /**\n * Called once per URL when the video fails to generate or load.\n * `error.status` holds the HTTP status when the API reported the failure.\n */\n onGenerationError?: (error: SlopMachineError) => void;\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 * // Using a Bucket\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 * // Using a Pipeline with runtime prompt\n * <SlopVideo\n * pipelineId=\"pipe_live_abc123\"\n * prompt=\"Drone shot of a cyberpunk city in rain\"\n * aspectRatio=\"16:9\"\n * metadata={{ campaign: \"spring_launch\" }}\n * />\n * ```\n *\n * @version 0.8.1\n */\nexport const SlopVideo: React.FC<SlopVideoProps> = ({\n bucketId,\n pipelineId,\n siloId,\n prompt,\n metadata,\n className,\n aspectRatio = \"16:9\",\n version,\n resultId,\n variables = {},\n duration,\n baseUrl,\n original,\n attachments,\n loader,\n errorFallback,\n onGenerationError,\n autoPlay = true,\n loop = true,\n muted = true,\n playsInline = true,\n onLoadedData,\n onError,\n ...props\n}) => {\n // Construct API URL\n const rawSrc = useMemo(\n () =>\n buildVideoUrl({\n bucketId,\n pipelineId,\n siloId,\n prompt,\n metadata,\n aspectRatio,\n version,\n resultId,\n variables,\n duration,\n baseUrl,\n original,\n attachments,\n }),\n [\n bucketId,\n pipelineId,\n siloId,\n prompt,\n metadata,\n aspectRatio,\n version,\n resultId,\n variables,\n duration,\n baseUrl,\n original,\n attachments,\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 [error, setError] = useState<SlopMachineError | null>(null);\n const [currentSrc, setCurrentSrc] = useState(src);\n const videoRef = useRef<HTMLVideoElement>(null);\n if (src !== currentSrc) {\n setCurrentSrc(src);\n setIsLoading(true);\n setError(null);\n }\n\n // Keep the latest callback without re-running effects when it changes identity\n const onGenerationErrorRef = useRef(onGenerationError);\n useEffect(() => {\n onGenerationErrorRef.current = onGenerationError;\n });\n\n // Shares one URL check between the HEAD probe and the media element's error event\n const monitor = useMemo(\n () =>\n createRenderUrlMonitor((err) => {\n console.error(\"SlopVideo error:\", err.status ?? \"\", err.message);\n setIsLoading(false);\n setError(err);\n onGenerationErrorRef.current?.(err);\n }),\n [],\n );\n\n useEffect(() => {\n if (!src) return;\n monitor.watch(src);\n return () => monitor.stop();\n }, [src, monitor]);\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 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 {error && (\n <ErrorOverlay\n error={error}\n errorFallback={errorFallback}\n label=\"Failed to load video\"\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 {...props}\n onLoadedData={(e) => {\n setIsLoading(false);\n onLoadedData?.(e);\n }}\n onError={(e) => {\n monitor.mediaFailed(src, \"Failed to load video\");\n onError?.(e);\n }}\n aria-hidden={error ? true : props[\"aria-hidden\"]}\n className={cn(\n \"h-full w-full object-cover transition-opacity duration-500\",\n isLoading || error ? \"opacity-0\" : \"opacity-100\",\n )}\n style={{\n height: \"100%\",\n width: \"100%\",\n objectFit: \"cover\",\n transition: \"opacity 500ms\",\n opacity: isLoading || error ? 0 : 1,\n }}\n />\n </div>\n </div>\n </>\n );\n};\n","import React, { useEffect, useMemo, useState } from \"react\";\nimport {\n buildTextUrl,\n renderMarkdown,\n type SlopTextOptions,\n} from \"@slopmachine/core\";\n\nexport interface SlopTextProps\n extends\n Omit<React.HTMLAttributes<HTMLDivElement>, \"children\">,\n SlopTextOptions {\n /**\n * Optional loading component to show while the text is being generated\n */\n fallback?: React.ReactNode;\n /**\n * Optional error component to show if the text generation fails\n */\n errorFallback?: React.ReactNode;\n}\n\n/**\n * Renders text generated by Slop Machine.\n *\n * This component automatically constructs the correct URL for the Slop Machine API,\n * fetches the generated text, and displays it with optional loading and error states.\n *\n * @example\n * ```tsx\n * // Using a Bucket\n * <SlopText\n * bucketId=\"my-text-bucket\"\n * fallback={<div>Loading story...</div>}\n * errorFallback={<div>Failed to load story</div>}\n * className=\"text-lg text-gray-800\"\n * />\n *\n * // Using a Pipeline with runtime prompt\n * <SlopText\n * pipelineId=\"pipe_live_abc123\"\n * prompt=\"Write a whimsical haiku about quantum physics\"\n * metadata={{ userId: \"123\" }}\n * />\n * ```\n *\n * @version 0.8.1\n */\nexport const SlopText = React.forwardRef<HTMLDivElement, SlopTextProps>(\n (\n {\n bucketId,\n pipelineId,\n siloId,\n prompt,\n metadata,\n version,\n resultId,\n model,\n variables,\n baseUrl,\n attachments,\n fallback,\n errorFallback,\n ...props\n },\n ref,\n ) => {\n const [text, setText] = useState<string | null>(null);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<Error | null>(null);\n\n const rawUrl = useMemo(\n () =>\n buildTextUrl({\n bucketId,\n pipelineId,\n siloId,\n prompt,\n metadata,\n version,\n resultId,\n model,\n variables,\n baseUrl,\n attachments,\n }),\n [\n bucketId,\n pipelineId,\n siloId,\n prompt,\n JSON.stringify(metadata),\n version,\n resultId,\n model,\n JSON.stringify(variables),\n baseUrl,\n JSON.stringify(attachments),\n ],\n );\n\n useEffect(() => {\n let isMounted = true;\n\n const fetchText = async () => {\n try {\n setLoading(true);\n setError(null);\n\n // Fetch the URL to get the content, following redirects automatically\n const response = await fetch(rawUrl, { cache: \"no-store\" });\n if (!response.ok) {\n let errorMessage = response.statusText;\n try {\n const errorText = await response.text();\n const errorData = JSON.parse(errorText);\n if (errorData.error) {\n errorMessage = errorData.error;\n }\n } catch (e) {\n // Ignore JSON parse errors if the response isn't JSON\n }\n throw new Error(`Failed to fetch text: ${errorMessage}`);\n }\n const content = await response.text();\n if (isMounted) {\n setText(content);\n }\n } catch (err) {\n if (isMounted) {\n const finalError =\n err instanceof Error ? err : new Error(\"Failed to generate text\");\n console.error(finalError);\n setError(finalError);\n }\n } finally {\n if (isMounted) {\n setLoading(false);\n }\n }\n };\n\n fetchText();\n\n return () => {\n isMounted = false;\n };\n }, [rawUrl]);\n\n if (error && errorFallback) {\n return <>{errorFallback}</>;\n }\n\n if (loading) {\n if (fallback) {\n return <>{fallback}</>;\n }\n return (\n <div className={props.className} style={props.style}>\n <style>{`\n @keyframes slop-shimmer {\n 0% { background-position: 200% 0; }\n 100% { background-position: -200% 0; }\n }\n @keyframes slop-spin {\n from { transform: rotate(0deg); }\n to { transform: rotate(360deg); }\n }\n `}</style>\n <div\n className=\"slop-wrapper relative overflow-hidden w-full\"\n style={{\n position: \"relative\",\n overflow: \"hidden\",\n width: \"100%\",\n minHeight: \"100px\",\n }}\n >\n {/* Loading overlay */}\n <div\n className=\"absolute inset-0 z-10 flex items-center justify-center bg-muted transition-opacity duration-300\"\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 }}\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=\"shimmer-effect absolute inset-0 bg-gradient-to-r from-muted via-muted/50 to-muted\"\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 }}\n />\n </div>\n </div>\n );\n }\n\n return (\n <div\n ref={ref}\n {...props}\n dangerouslySetInnerHTML={{\n __html: text ? renderMarkdown(text) : \"\",\n }}\n />\n );\n },\n);\n\nSlopText.displayName = \"SlopText\";\n"],"mappings":"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","names":["import_jsx_runtime","import_react","import_clsx","import_tailwind_merge","import_core","import_jsx_runtime","cn","import_react","import_core","import_jsx_runtime","React","import_core"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/components/SlopImage.tsx","../src/components/ErrorOverlay.tsx","../src/components/SlopVideo.tsx","../src/components/SlopText.tsx"],"sourcesContent":["export { SlopImage, type SlopImageProps } from \"./components/SlopImage\";\nexport { SlopVideo, type SlopVideoProps } from \"./components/SlopVideo\";\nexport { SlopText, type SlopTextProps } from \"./components/SlopText\";\nexport type { SlopErrorFallback } from \"./components/ErrorOverlay\";\n\nexport type {\n ImageAspectRatio,\n VideoAspectRatio,\n SlopImageOptions,\n SlopVideoOptions,\n SlopTextOptions,\n} from \"@slopmachine/core\";\n\nexport {\n preloadImage,\n preloadVideo,\n preloadText,\n SlopMachineError,\n} from \"@slopmachine/core\";\n","import React, { useEffect, useMemo, useRef, useState } from \"react\";\nimport { clsx, type ClassValue } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\nimport {\n buildImageUrl,\n createRenderUrlMonitor,\n type SlopMachineError,\n type SlopImageOptions,\n type ImageAspectRatio,\n} from \"@slopmachine/core\";\nimport { ErrorOverlay, type SlopErrorFallback } from \"./ErrorOverlay\";\n\nconst DEFAULT_ALT = \"Image produced by Slop Machine (slopmachine.dev)\";\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\">,\n Omit<SlopImageOptions, \"aspectRatio\"> {\n /**\n * The aspect ratio of the generated image. Defaults to \"1:1\".\n */\n aspectRatio?: ImageAspectRatio;\n /**\n * Alternative text describing the image, for screen readers and when the image\n * can't be shown. Defaults to \"Image produced by Slop Machine (slopmachine.dev)\".\n * Describe what the image shows, or pass `\"\"` if it's purely decorative.\n */\n alt?: string;\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 * Content to display if the image fails to generate or load.\n * Pass a node, or a function that receives the `SlopMachineError` and returns a node.\n * If not provided, a default error message is shown in place of the image.\n */\n errorFallback?: SlopErrorFallback;\n /**\n * Called once per URL when the image fails to generate or load.\n * `error.status` holds the HTTP status when the API reported the failure.\n */\n onGenerationError?: (error: SlopMachineError) => void;\n /**\n * How the image should be resized to fit its container. Defaults to \"cover\".\n */\n objectFit?: React.CSSProperties[\"objectFit\"];\n /**\n * Additional CSS classes to apply directly to the `<img />` element.\n */\n imageClassName?: string;\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 * // Using a Bucket\n * <SlopImage\n * bucketId=\"my-bucket\"\n * resultId=\"some-result\"\n * aspectRatio=\"16:9\"\n * className=\"rounded-lg\"\n * objectFit=\"cover\"\n * />\n *\n * // Using a Pipeline with runtime prompt\n * <SlopImage\n * pipelineId=\"pipe_live_abc123\"\n * prompt=\"1960s retro robot eating pizza on Mars\"\n * aspectRatio=\"16:9\"\n * metadata={{ userId: \"123\" }}\n * />\n * ```\n *\n * @version 1.0.0\n */\nexport const SlopImage: React.FC<SlopImageProps> = ({\n bucketId,\n pipelineId,\n siloId,\n prompt,\n metadata,\n className,\n aspectRatio = \"1:1\",\n alt = DEFAULT_ALT,\n model,\n version,\n resultId,\n variables = {},\n baseUrl,\n original,\n attachments,\n loader,\n errorFallback,\n onGenerationError,\n objectFit = \"cover\",\n imageClassName,\n style,\n onLoad,\n onError,\n ...props\n}) => {\n // Construct API URL\n const rawSrc = useMemo(\n () =>\n buildImageUrl({\n bucketId,\n pipelineId,\n siloId,\n prompt,\n metadata,\n aspectRatio,\n model,\n version,\n resultId,\n variables,\n baseUrl,\n original,\n attachments,\n }),\n [\n bucketId,\n pipelineId,\n siloId,\n prompt,\n metadata,\n aspectRatio,\n model,\n version,\n resultId,\n variables,\n baseUrl,\n original,\n attachments,\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 [error, setError] = useState<SlopMachineError | null>(null);\n const [currentSrc, setCurrentSrc] = useState(src);\n if (src !== currentSrc) {\n setCurrentSrc(src);\n setIsLoading(true);\n setError(null);\n }\n\n // Keep the latest callback without re-running effects when it changes identity\n const onGenerationErrorRef = useRef(onGenerationError);\n useEffect(() => {\n onGenerationErrorRef.current = onGenerationError;\n });\n\n // Shares one URL check between the HEAD probe and the media element's error event\n const monitor = useMemo(\n () =>\n createRenderUrlMonitor((err) => {\n console.error(\"SlopImage error:\", err.status ?? \"\", err.message);\n setIsLoading(false);\n setError(err);\n onGenerationErrorRef.current?.(err);\n }),\n [],\n );\n\n useEffect(() => {\n if (!src) return;\n monitor.watch(src);\n return () => monitor.stop();\n }, [src, monitor]);\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={style}>\n <div\n className=\"slop-wrapper relative overflow-hidden w-full h-full\"\n style={{\n aspectRatio: String(aspectRatio).replace(\":\", \"/\"),\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(--slop-muted, 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:\n \"var(--slop-muted-foreground, 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:\n \"var(--slop-muted-foreground, 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(--slop-muted, var(--muted, #f3f4f6)) 0%, var(--slop-shimmer, var(--muted-foreground, #e5e7eb)) 50%, var(--slop-muted, 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 {error && (\n <ErrorOverlay\n error={error}\n errorFallback={errorFallback}\n label=\"Failed to load image\"\n />\n )}\n\n {/* Image */}\n <img\n key={src}\n src={src}\n alt={alt}\n {...props}\n onLoad={(e) => {\n setIsLoading(false);\n onLoad?.(e);\n }}\n onError={(e) => {\n monitor.mediaFailed(src, \"Failed to load image\");\n onError?.(e);\n }}\n aria-hidden={error ? true : props[\"aria-hidden\"]}\n className={cn(\n \"h-full w-full transition-opacity duration-500\",\n isLoading || error ? \"opacity-0\" : \"opacity-100\",\n imageClassName,\n )}\n style={{\n height: \"100%\",\n width: \"100%\",\n objectFit,\n transition: \"opacity 500ms\",\n opacity: isLoading || error ? 0 : 1,\n }}\n />\n </div>\n </div>\n </>\n );\n};\n","import React from \"react\";\nimport type { SlopMachineError } from \"@slopmachine/core\";\n\n/**\n * Content to render when generation or loading fails. Either a node, or a\n * function that receives the error and returns a node.\n */\nexport type SlopErrorFallback =\n React.ReactNode | ((error: SlopMachineError) => React.ReactNode);\n\ninterface ErrorOverlayProps {\n error: SlopMachineError;\n errorFallback?: SlopErrorFallback;\n /**\n * Message shown by the default error UI, e.g. \"Failed to load image\".\n */\n label: string;\n}\n\nconst overlayStyle: React.CSSProperties = {\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};\n\n/**\n * Internal overlay shown over the media slot when generation or loading fails.\n * Renders the consumer's `errorFallback` if provided, otherwise a default message.\n */\nexport const ErrorOverlay: React.FC<ErrorOverlayProps> = ({\n error,\n errorFallback,\n label,\n}) => {\n if (errorFallback !== undefined) {\n return (\n <div\n className=\"absolute inset-0 z-10 flex items-center justify-center\"\n style={overlayStyle}\n >\n {typeof errorFallback === \"function\"\n ? errorFallback(error)\n : errorFallback}\n </div>\n );\n }\n\n return (\n <div\n className=\"absolute inset-0 z-10 flex items-center justify-center bg-muted\"\n style={{\n ...overlayStyle,\n backgroundColor: \"var(--slop-muted, var(--muted, #f3f4f6))\",\n }}\n title={error.message}\n >\n <div\n className=\"flex flex-col items-center gap-2 text-muted-foreground\"\n style={{\n display: \"flex\",\n flexDirection: \"column\",\n alignItems: \"center\",\n gap: \"0.5rem\",\n color:\n \"var(--slop-muted-foreground, var(--muted-foreground, #6b7280))\",\n }}\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n style={{ width: \"24px\", height: \"24px\" }}\n >\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n <line x1=\"12\" y1=\"8\" x2=\"12\" y2=\"12\" />\n <line x1=\"12\" y1=\"16\" x2=\"12.01\" y2=\"16\" />\n </svg>\n <span className=\"text-xs\" style={{ fontSize: \"0.75rem\" }}>\n {label}\n </span>\n </div>\n </div>\n );\n};\n","import React, { useEffect, useMemo, useRef, useState } from \"react\";\nimport { clsx, type ClassValue } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\nimport {\n buildVideoUrl,\n createRenderUrlMonitor,\n type SlopMachineError,\n type SlopVideoOptions,\n type VideoAspectRatio,\n} from \"@slopmachine/core\";\nimport { ErrorOverlay, type SlopErrorFallback } from \"./ErrorOverlay\";\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 * How the video should be resized to fit its container. Defaults to \"cover\".\n */\n objectFit?: React.CSSProperties[\"objectFit\"];\n /**\n * Content to display if the video fails to generate or load.\n * Pass a node, or a function that receives the `SlopMachineError` and returns a node.\n * If not provided, a default error message is shown in place of the video.\n */\n errorFallback?: SlopErrorFallback;\n /**\n * Called once per URL when the video fails to generate or load.\n * `error.status` holds the HTTP status when the API reported the failure.\n */\n onGenerationError?: (error: SlopMachineError) => void;\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 * // Using a Bucket\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 * // Using a Pipeline with runtime prompt\n * <SlopVideo\n * pipelineId=\"pipe_live_abc123\"\n * prompt=\"Drone shot of a cyberpunk city in rain\"\n * aspectRatio=\"16:9\"\n * metadata={{ campaign: \"spring_launch\" }}\n * />\n * ```\n *\n * @version 1.0.0\n */\nexport const SlopVideo: React.FC<SlopVideoProps> = ({\n bucketId,\n pipelineId,\n siloId,\n prompt,\n metadata,\n className,\n aspectRatio = \"16:9\",\n version,\n resultId,\n variables = {},\n duration,\n baseUrl,\n original,\n attachments,\n loader,\n objectFit = \"cover\",\n errorFallback,\n onGenerationError,\n autoPlay = true,\n loop = true,\n muted = true,\n playsInline = true,\n onLoadedData,\n onError,\n ...props\n}) => {\n // Construct API URL\n const rawSrc = useMemo(\n () =>\n buildVideoUrl({\n bucketId,\n pipelineId,\n siloId,\n prompt,\n metadata,\n aspectRatio,\n version,\n resultId,\n variables,\n duration,\n baseUrl,\n original,\n attachments,\n }),\n [\n bucketId,\n pipelineId,\n siloId,\n prompt,\n metadata,\n aspectRatio,\n version,\n resultId,\n variables,\n duration,\n baseUrl,\n original,\n attachments,\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 [error, setError] = useState<SlopMachineError | null>(null);\n const [currentSrc, setCurrentSrc] = useState(src);\n const videoRef = useRef<HTMLVideoElement>(null);\n if (src !== currentSrc) {\n setCurrentSrc(src);\n setIsLoading(true);\n setError(null);\n }\n\n // Keep the latest callback without re-running effects when it changes identity\n const onGenerationErrorRef = useRef(onGenerationError);\n useEffect(() => {\n onGenerationErrorRef.current = onGenerationError;\n });\n\n // Shares one URL check between the HEAD probe and the media element's error event\n const monitor = useMemo(\n () =>\n createRenderUrlMonitor((err) => {\n console.error(\"SlopVideo error:\", err.status ?? \"\", err.message);\n setIsLoading(false);\n setError(err);\n onGenerationErrorRef.current?.(err);\n }),\n [],\n );\n\n useEffect(() => {\n if (!src) return;\n monitor.watch(src);\n return () => monitor.stop();\n }, [src, monitor]);\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 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(--slop-muted, 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:\n \"var(--slop-muted-foreground, 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:\n \"var(--slop-muted-foreground, 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(--slop-muted, var(--muted, #f3f4f6)) 0%, var(--slop-shimmer, var(--muted-foreground, #e5e7eb)) 50%, var(--slop-muted, 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 {error && (\n <ErrorOverlay\n error={error}\n errorFallback={errorFallback}\n label=\"Failed to load video\"\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 {...props}\n onLoadedData={(e) => {\n setIsLoading(false);\n onLoadedData?.(e);\n }}\n onError={(e) => {\n monitor.mediaFailed(src, \"Failed to load video\");\n onError?.(e);\n }}\n aria-hidden={error ? true : props[\"aria-hidden\"]}\n className={cn(\n \"h-full w-full transition-opacity duration-500\",\n isLoading || error ? \"opacity-0\" : \"opacity-100\",\n )}\n style={{\n height: \"100%\",\n width: \"100%\",\n objectFit,\n transition: \"opacity 500ms\",\n opacity: isLoading || error ? 0 : 1,\n }}\n />\n </div>\n </div>\n </>\n );\n};\n","import React, { useEffect, useMemo, useRef, useState } from \"react\";\nimport {\n buildTextUrl,\n fetchRenderedText,\n renderMarkdown,\n SlopMachineError,\n type SlopTextOptions,\n} from \"@slopmachine/core\";\nimport { ErrorOverlay, type SlopErrorFallback } from \"./ErrorOverlay\";\n\nexport interface SlopTextProps\n extends\n Omit<React.HTMLAttributes<HTMLDivElement>, \"children\">,\n SlopTextOptions {\n /**\n * Optional loading component to show while the text is being generated.\n * If not provided, a default spinner and shimmer effect will be shown.\n */\n fallback?: React.ReactNode;\n /**\n * Content to display if the text fails to generate or load.\n * Pass a node, or a function that receives the `SlopMachineError` and returns a node.\n * If not provided, a default error message is shown.\n */\n errorFallback?: SlopErrorFallback;\n /**\n * Called once per URL when the text fails to generate or load.\n * `error.status` holds the HTTP status when the API reported the failure.\n */\n onGenerationError?: (error: SlopMachineError) => void;\n}\n\n/**\n * Renders text generated by Slop Machine.\n *\n * This component automatically constructs the correct URL for the Slop Machine API,\n * fetches the generated text, and displays it with optional loading and error states.\n *\n * @example\n * ```tsx\n * // Using a Bucket\n * <SlopText\n * bucketId=\"my-text-bucket\"\n * fallback={<div>Loading story...</div>}\n * errorFallback={(error) => <div>Failed to load story: {error.message}</div>}\n * className=\"text-lg text-gray-800\"\n * />\n *\n * // Using a Pipeline with runtime prompt\n * <SlopText\n * pipelineId=\"pipe_live_abc123\"\n * prompt=\"Write a whimsical haiku about quantum physics\"\n * metadata={{ userId: \"123\" }}\n * />\n * ```\n *\n * @version 1.0.0\n */\nexport const SlopText = React.forwardRef<HTMLDivElement, SlopTextProps>(\n (\n {\n bucketId,\n pipelineId,\n siloId,\n prompt,\n metadata,\n version,\n resultId,\n model,\n variables,\n baseUrl,\n attachments,\n fallback,\n errorFallback,\n onGenerationError,\n ...props\n },\n ref,\n ) => {\n const [text, setText] = useState<string | null>(null);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<SlopMachineError | null>(null);\n\n const rawUrl = useMemo(\n () =>\n buildTextUrl({\n bucketId,\n pipelineId,\n siloId,\n prompt,\n metadata,\n version,\n resultId,\n model,\n variables,\n baseUrl,\n attachments,\n }),\n [\n bucketId,\n pipelineId,\n siloId,\n prompt,\n JSON.stringify(metadata),\n version,\n resultId,\n model,\n JSON.stringify(variables),\n baseUrl,\n JSON.stringify(attachments),\n ],\n );\n\n // Keep the latest callback without re-running the fetch when it changes identity\n const onGenerationErrorRef = useRef(onGenerationError);\n useEffect(() => {\n onGenerationErrorRef.current = onGenerationError;\n });\n\n useEffect(() => {\n // Cancels the request if the URL changes or the component unmounts,\n // so a slow response for an old URL can never replace newer text\n const controller = new AbortController();\n setLoading(true);\n setError(null);\n\n fetchRenderedText(rawUrl, { signal: controller.signal })\n .then((content) => {\n setText(content);\n setLoading(false);\n })\n .catch((err) => {\n if (controller.signal.aborted) return;\n const finalError =\n err instanceof SlopMachineError\n ? err\n : new SlopMachineError(\"Failed to load text\");\n console.error(\n \"SlopText error:\",\n finalError.status ?? \"\",\n finalError.message,\n );\n setError(finalError);\n setLoading(false);\n onGenerationErrorRef.current?.(finalError);\n });\n\n return () => controller.abort();\n }, [rawUrl]);\n\n if (error) {\n if (errorFallback !== undefined) {\n return (\n <>\n {typeof errorFallback === \"function\"\n ? errorFallback(error)\n : errorFallback}\n </>\n );\n }\n return (\n <div ref={ref} {...props}>\n <div\n className=\"slop-wrapper relative overflow-hidden w-full\"\n style={{\n position: \"relative\",\n overflow: \"hidden\",\n width: \"100%\",\n minHeight: \"100px\",\n }}\n >\n <ErrorOverlay error={error} label=\"Failed to load text\" />\n </div>\n </div>\n );\n }\n\n if (loading) {\n if (fallback) {\n return <>{fallback}</>;\n }\n return (\n <div className={props.className} style={props.style}>\n <style>{`\n @keyframes slop-shimmer {\n 0% { background-position: 200% 0; }\n 100% { background-position: -200% 0; }\n }\n @keyframes slop-spin {\n from { transform: rotate(0deg); }\n to { transform: rotate(360deg); }\n }\n `}</style>\n <div\n className=\"slop-wrapper relative overflow-hidden w-full\"\n style={{\n position: \"relative\",\n overflow: \"hidden\",\n width: \"100%\",\n minHeight: \"100px\",\n }}\n >\n {/* Loading overlay */}\n <div\n className=\"absolute inset-0 z-10 flex items-center justify-center bg-muted transition-opacity duration-300\"\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(--slop-muted, var(--muted, #f3f4f6))\",\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:\n \"var(--slop-muted-foreground, 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:\n \"var(--slop-muted-foreground, var(--muted-foreground, #6b7280))\",\n }}\n >\n Loading...\n </span>\n </div>\n </div>\n\n {/* Shimmer effect underneath */}\n <div\n className=\"shimmer-effect absolute inset-0 bg-gradient-to-r from-muted via-muted/50 to-muted\"\n style={{\n position: \"absolute\",\n top: 0,\n left: 0,\n right: 0,\n bottom: 0,\n background:\n \"linear-gradient(90deg, var(--slop-muted, var(--muted, #f3f4f6)) 0%, var(--slop-shimmer, var(--muted-foreground, #e5e7eb)) 50%, var(--slop-muted, var(--muted, #f3f4f6)) 100%)\",\n backgroundSize: \"200% 100%\",\n animation: \"slop-shimmer 2s ease-in-out infinite\",\n }}\n />\n </div>\n </div>\n );\n }\n\n return (\n <div\n ref={ref}\n {...props}\n dangerouslySetInnerHTML={{\n __html: text ? renderMarkdown(text) : \"\",\n }}\n />\n );\n },\n);\n\nSlopText.displayName = \"SlopText\";\n"],"mappings":"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","names":["import_jsx_runtime","import_react","import_clsx","import_tailwind_merge","import_core","import_jsx_runtime","cn","import_react","import_core","import_jsx_runtime","React","import_core"]}
|
package/dist/index.mjs
CHANGED
|
@@ -41,7 +41,10 @@ var ErrorOverlay = ({
|
|
|
41
41
|
"div",
|
|
42
42
|
{
|
|
43
43
|
className: "absolute inset-0 z-10 flex items-center justify-center bg-muted",
|
|
44
|
-
style: {
|
|
44
|
+
style: {
|
|
45
|
+
...overlayStyle,
|
|
46
|
+
backgroundColor: "var(--slop-muted, var(--muted, #f3f4f6))"
|
|
47
|
+
},
|
|
45
48
|
title: error.message,
|
|
46
49
|
children: /* @__PURE__ */ jsxs(
|
|
47
50
|
"div",
|
|
@@ -52,7 +55,7 @@ var ErrorOverlay = ({
|
|
|
52
55
|
flexDirection: "column",
|
|
53
56
|
alignItems: "center",
|
|
54
57
|
gap: "0.5rem",
|
|
55
|
-
color: "var(--muted-foreground, #6b7280)"
|
|
58
|
+
color: "var(--slop-muted-foreground, var(--muted-foreground, #6b7280))"
|
|
56
59
|
},
|
|
57
60
|
children: [
|
|
58
61
|
/* @__PURE__ */ jsxs(
|
|
@@ -84,6 +87,7 @@ var ErrorOverlay = ({
|
|
|
84
87
|
|
|
85
88
|
// src/components/SlopImage.tsx
|
|
86
89
|
import { Fragment, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
90
|
+
var DEFAULT_ALT = "Image produced by Slop Machine (slopmachine.dev)";
|
|
87
91
|
function cn(...inputs) {
|
|
88
92
|
return twMerge(clsx(inputs));
|
|
89
93
|
}
|
|
@@ -95,6 +99,7 @@ var SlopImage = ({
|
|
|
95
99
|
metadata,
|
|
96
100
|
className,
|
|
97
101
|
aspectRatio = "1:1",
|
|
102
|
+
alt = DEFAULT_ALT,
|
|
98
103
|
model,
|
|
99
104
|
version,
|
|
100
105
|
resultId,
|
|
@@ -151,7 +156,6 @@ var SlopImage = ({
|
|
|
151
156
|
}, 100);
|
|
152
157
|
return () => clearTimeout(timer);
|
|
153
158
|
}, [rawSrc]);
|
|
154
|
-
const alt = "Image produced by Slop Machine (slopmachine.dev)";
|
|
155
159
|
const [isLoading, setIsLoading] = useState(true);
|
|
156
160
|
const [error, setError] = useState(null);
|
|
157
161
|
const [currentSrc, setCurrentSrc] = useState(src);
|
|
@@ -250,7 +254,7 @@ var SlopImage = ({
|
|
|
250
254
|
display: "flex",
|
|
251
255
|
alignItems: "center",
|
|
252
256
|
justifyContent: "center",
|
|
253
|
-
backgroundColor: "var(--muted, #f3f4f6)",
|
|
257
|
+
backgroundColor: "var(--slop-muted, var(--muted, #f3f4f6))",
|
|
254
258
|
opacity: isLoading ? 1 : 0,
|
|
255
259
|
pointerEvents: isLoading ? "auto" : "none",
|
|
256
260
|
transition: "opacity 300ms ease-in-out"
|
|
@@ -276,7 +280,7 @@ var SlopImage = ({
|
|
|
276
280
|
style: {
|
|
277
281
|
width: "24px",
|
|
278
282
|
height: "24px",
|
|
279
|
-
color: "var(--muted-foreground, #6b7280)",
|
|
283
|
+
color: "var(--slop-muted-foreground, var(--muted-foreground, #6b7280))",
|
|
280
284
|
animation: "slop-spin 1s linear infinite"
|
|
281
285
|
},
|
|
282
286
|
children: [
|
|
@@ -310,7 +314,7 @@ var SlopImage = ({
|
|
|
310
314
|
className: "text-xs text-muted-foreground",
|
|
311
315
|
style: {
|
|
312
316
|
fontSize: "0.75rem",
|
|
313
|
-
color: "var(--muted-foreground, #6b7280)"
|
|
317
|
+
color: "var(--slop-muted-foreground, var(--muted-foreground, #6b7280))"
|
|
314
318
|
},
|
|
315
319
|
children: "Loading..."
|
|
316
320
|
}
|
|
@@ -333,7 +337,7 @@ var SlopImage = ({
|
|
|
333
337
|
left: 0,
|
|
334
338
|
right: 0,
|
|
335
339
|
bottom: 0,
|
|
336
|
-
background: "linear-gradient(90deg, var(--muted, #f3f4f6) 0%, var(--muted-foreground, #e5e7eb) 50%, var(--muted, #f3f4f6) 100%)",
|
|
340
|
+
background: "linear-gradient(90deg, var(--slop-muted, var(--muted, #f3f4f6)) 0%, var(--slop-shimmer, var(--muted-foreground, #e5e7eb)) 50%, var(--slop-muted, var(--muted, #f3f4f6)) 100%)",
|
|
337
341
|
backgroundSize: "200% 100%",
|
|
338
342
|
animation: "slop-shimmer 2s ease-in-out infinite",
|
|
339
343
|
opacity: isLoading ? 1 : 0,
|
|
@@ -414,6 +418,7 @@ var SlopVideo = ({
|
|
|
414
418
|
original,
|
|
415
419
|
attachments,
|
|
416
420
|
loader,
|
|
421
|
+
objectFit = "cover",
|
|
417
422
|
errorFallback,
|
|
418
423
|
onGenerationError,
|
|
419
424
|
autoPlay = true,
|
|
@@ -562,7 +567,7 @@ var SlopVideo = ({
|
|
|
562
567
|
display: "flex",
|
|
563
568
|
alignItems: "center",
|
|
564
569
|
justifyContent: "center",
|
|
565
|
-
backgroundColor: "var(--muted, #f3f4f6)",
|
|
570
|
+
backgroundColor: "var(--slop-muted, var(--muted, #f3f4f6))",
|
|
566
571
|
opacity: isLoading ? 1 : 0,
|
|
567
572
|
pointerEvents: isLoading ? "auto" : "none",
|
|
568
573
|
transition: "opacity 300ms ease-in-out"
|
|
@@ -588,7 +593,7 @@ var SlopVideo = ({
|
|
|
588
593
|
style: {
|
|
589
594
|
width: "24px",
|
|
590
595
|
height: "24px",
|
|
591
|
-
color: "var(--muted-foreground, #6b7280)",
|
|
596
|
+
color: "var(--slop-muted-foreground, var(--muted-foreground, #6b7280))",
|
|
592
597
|
animation: "slop-spin 1s linear infinite"
|
|
593
598
|
},
|
|
594
599
|
children: [
|
|
@@ -622,7 +627,7 @@ var SlopVideo = ({
|
|
|
622
627
|
className: "text-xs text-muted-foreground",
|
|
623
628
|
style: {
|
|
624
629
|
fontSize: "0.75rem",
|
|
625
|
-
color: "var(--muted-foreground, #6b7280)"
|
|
630
|
+
color: "var(--slop-muted-foreground, var(--muted-foreground, #6b7280))"
|
|
626
631
|
},
|
|
627
632
|
children: "Loading..."
|
|
628
633
|
}
|
|
@@ -645,7 +650,7 @@ var SlopVideo = ({
|
|
|
645
650
|
left: 0,
|
|
646
651
|
right: 0,
|
|
647
652
|
bottom: 0,
|
|
648
|
-
background: "linear-gradient(90deg, var(--muted, #f3f4f6) 0%, var(--muted-foreground, #e5e7eb) 50%, var(--muted, #f3f4f6) 100%)",
|
|
653
|
+
background: "linear-gradient(90deg, var(--slop-muted, var(--muted, #f3f4f6)) 0%, var(--slop-shimmer, var(--muted-foreground, #e5e7eb)) 50%, var(--slop-muted, var(--muted, #f3f4f6)) 100%)",
|
|
649
654
|
backgroundSize: "200% 100%",
|
|
650
655
|
animation: "slop-shimmer 2s ease-in-out infinite",
|
|
651
656
|
opacity: isLoading ? 1 : 0,
|
|
@@ -682,13 +687,13 @@ var SlopVideo = ({
|
|
|
682
687
|
},
|
|
683
688
|
"aria-hidden": error ? true : props["aria-hidden"],
|
|
684
689
|
className: cn2(
|
|
685
|
-
"h-full w-full
|
|
690
|
+
"h-full w-full transition-opacity duration-500",
|
|
686
691
|
isLoading || error ? "opacity-0" : "opacity-100"
|
|
687
692
|
),
|
|
688
693
|
style: {
|
|
689
694
|
height: "100%",
|
|
690
695
|
width: "100%",
|
|
691
|
-
objectFit
|
|
696
|
+
objectFit,
|
|
692
697
|
transition: "opacity 500ms",
|
|
693
698
|
opacity: isLoading || error ? 0 : 1
|
|
694
699
|
}
|
|
@@ -702,10 +707,12 @@ var SlopVideo = ({
|
|
|
702
707
|
};
|
|
703
708
|
|
|
704
709
|
// src/components/SlopText.tsx
|
|
705
|
-
import React3, { useEffect as useEffect3, useMemo as useMemo3, useState as useState3 } from "react";
|
|
710
|
+
import React3, { useEffect as useEffect3, useMemo as useMemo3, useRef as useRef3, useState as useState3 } from "react";
|
|
706
711
|
import {
|
|
707
712
|
buildTextUrl,
|
|
708
|
-
|
|
713
|
+
fetchRenderedText,
|
|
714
|
+
renderMarkdown,
|
|
715
|
+
SlopMachineError
|
|
709
716
|
} from "@slopmachine/core";
|
|
710
717
|
import { Fragment as Fragment3, jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
711
718
|
var SlopText = React3.forwardRef(
|
|
@@ -723,6 +730,7 @@ var SlopText = React3.forwardRef(
|
|
|
723
730
|
attachments,
|
|
724
731
|
fallback,
|
|
725
732
|
errorFallback,
|
|
733
|
+
onGenerationError,
|
|
726
734
|
...props
|
|
727
735
|
}, ref) => {
|
|
728
736
|
const [text, setText] = useState3(null);
|
|
@@ -756,48 +764,48 @@ var SlopText = React3.forwardRef(
|
|
|
756
764
|
JSON.stringify(attachments)
|
|
757
765
|
]
|
|
758
766
|
);
|
|
767
|
+
const onGenerationErrorRef = useRef3(onGenerationError);
|
|
759
768
|
useEffect3(() => {
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
} catch (err) {
|
|
783
|
-
if (isMounted) {
|
|
784
|
-
const finalError = err instanceof Error ? err : new Error("Failed to generate text");
|
|
785
|
-
console.error(finalError);
|
|
786
|
-
setError(finalError);
|
|
787
|
-
}
|
|
788
|
-
} finally {
|
|
789
|
-
if (isMounted) {
|
|
790
|
-
setLoading(false);
|
|
791
|
-
}
|
|
792
|
-
}
|
|
793
|
-
};
|
|
794
|
-
fetchText();
|
|
795
|
-
return () => {
|
|
796
|
-
isMounted = false;
|
|
797
|
-
};
|
|
769
|
+
onGenerationErrorRef.current = onGenerationError;
|
|
770
|
+
});
|
|
771
|
+
useEffect3(() => {
|
|
772
|
+
const controller = new AbortController();
|
|
773
|
+
setLoading(true);
|
|
774
|
+
setError(null);
|
|
775
|
+
fetchRenderedText(rawUrl, { signal: controller.signal }).then((content) => {
|
|
776
|
+
setText(content);
|
|
777
|
+
setLoading(false);
|
|
778
|
+
}).catch((err) => {
|
|
779
|
+
if (controller.signal.aborted) return;
|
|
780
|
+
const finalError = err instanceof SlopMachineError ? err : new SlopMachineError("Failed to load text");
|
|
781
|
+
console.error(
|
|
782
|
+
"SlopText error:",
|
|
783
|
+
finalError.status ?? "",
|
|
784
|
+
finalError.message
|
|
785
|
+
);
|
|
786
|
+
setError(finalError);
|
|
787
|
+
setLoading(false);
|
|
788
|
+
onGenerationErrorRef.current?.(finalError);
|
|
789
|
+
});
|
|
790
|
+
return () => controller.abort();
|
|
798
791
|
}, [rawUrl]);
|
|
799
|
-
if (error
|
|
800
|
-
|
|
792
|
+
if (error) {
|
|
793
|
+
if (errorFallback !== void 0) {
|
|
794
|
+
return /* @__PURE__ */ jsx4(Fragment3, { children: typeof errorFallback === "function" ? errorFallback(error) : errorFallback });
|
|
795
|
+
}
|
|
796
|
+
return /* @__PURE__ */ jsx4("div", { ref, ...props, children: /* @__PURE__ */ jsx4(
|
|
797
|
+
"div",
|
|
798
|
+
{
|
|
799
|
+
className: "slop-wrapper relative overflow-hidden w-full",
|
|
800
|
+
style: {
|
|
801
|
+
position: "relative",
|
|
802
|
+
overflow: "hidden",
|
|
803
|
+
width: "100%",
|
|
804
|
+
minHeight: "100px"
|
|
805
|
+
},
|
|
806
|
+
children: /* @__PURE__ */ jsx4(ErrorOverlay, { error, label: "Failed to load text" })
|
|
807
|
+
}
|
|
808
|
+
) });
|
|
801
809
|
}
|
|
802
810
|
if (loading) {
|
|
803
811
|
if (fallback) {
|
|
@@ -839,7 +847,7 @@ var SlopText = React3.forwardRef(
|
|
|
839
847
|
display: "flex",
|
|
840
848
|
alignItems: "center",
|
|
841
849
|
justifyContent: "center",
|
|
842
|
-
backgroundColor: "var(--muted, #f3f4f6)"
|
|
850
|
+
backgroundColor: "var(--slop-muted, var(--muted, #f3f4f6))"
|
|
843
851
|
},
|
|
844
852
|
children: /* @__PURE__ */ jsxs4(
|
|
845
853
|
"div",
|
|
@@ -862,7 +870,7 @@ var SlopText = React3.forwardRef(
|
|
|
862
870
|
style: {
|
|
863
871
|
width: "24px",
|
|
864
872
|
height: "24px",
|
|
865
|
-
color: "var(--muted-foreground, #6b7280)",
|
|
873
|
+
color: "var(--slop-muted-foreground, var(--muted-foreground, #6b7280))",
|
|
866
874
|
animation: "slop-spin 1s linear infinite"
|
|
867
875
|
},
|
|
868
876
|
children: [
|
|
@@ -896,7 +904,7 @@ var SlopText = React3.forwardRef(
|
|
|
896
904
|
className: "text-xs text-muted-foreground",
|
|
897
905
|
style: {
|
|
898
906
|
fontSize: "0.75rem",
|
|
899
|
-
color: "var(--muted-foreground, #6b7280)"
|
|
907
|
+
color: "var(--slop-muted-foreground, var(--muted-foreground, #6b7280))"
|
|
900
908
|
},
|
|
901
909
|
children: "Loading..."
|
|
902
910
|
}
|
|
@@ -916,7 +924,7 @@ var SlopText = React3.forwardRef(
|
|
|
916
924
|
left: 0,
|
|
917
925
|
right: 0,
|
|
918
926
|
bottom: 0,
|
|
919
|
-
background: "linear-gradient(90deg, var(--muted, #f3f4f6) 0%, var(--muted-foreground, #e5e7eb) 50%, var(--muted, #f3f4f6) 100%)",
|
|
927
|
+
background: "linear-gradient(90deg, var(--slop-muted, var(--muted, #f3f4f6)) 0%, var(--slop-shimmer, var(--muted-foreground, #e5e7eb)) 50%, var(--slop-muted, var(--muted, #f3f4f6)) 100%)",
|
|
920
928
|
backgroundSize: "200% 100%",
|
|
921
929
|
animation: "slop-shimmer 2s ease-in-out infinite"
|
|
922
930
|
}
|
|
@@ -946,17 +954,15 @@ import {
|
|
|
946
954
|
preloadImage,
|
|
947
955
|
preloadVideo,
|
|
948
956
|
preloadText,
|
|
949
|
-
|
|
950
|
-
SlopMachineError
|
|
957
|
+
SlopMachineError as SlopMachineError2
|
|
951
958
|
} from "@slopmachine/core";
|
|
952
959
|
export {
|
|
953
960
|
SlopImage,
|
|
954
|
-
SlopMachineError,
|
|
961
|
+
SlopMachineError2 as SlopMachineError,
|
|
955
962
|
SlopText,
|
|
956
963
|
SlopVideo,
|
|
957
964
|
preloadImage,
|
|
958
965
|
preloadText,
|
|
959
|
-
preloadVideo
|
|
960
|
-
rateResult
|
|
966
|
+
preloadVideo
|
|
961
967
|
};
|
|
962
968
|
//# sourceMappingURL=index.mjs.map
|