unicornstudio-react
Version:
React component for embedding Unicorn.Studio interactive scenes with TypeScript support. Compatible with React (Vite) and Next.js.
1 lines • 23 kB
Source Map (JSON)
{"version":3,"sources":["../src/next/index.tsx","../src/next/hooks.ts","../src/shared/hooks.ts","../src/shared/constants.ts","../src/shared/utils.ts","../src/shared/styles.ts"],"sourcesContent":["\"use client\";\nimport { useRef, useState, useEffect } from \"react\";\nimport Script from \"next/script\";\nimport Image from \"next/image\";\nimport type { UnicornSceneProps } from \"../shared/types\";\nimport { useUnicornStudioScript, useUnicornScene } from \"./hooks\";\nimport { UNICORN_STUDIO_CDN_URL, DEFAULT_VALUES } from \"../shared/constants\";\nimport { unicornStyles } from \"../shared/styles\";\nimport { isWebGLSupported } from \"../shared/utils\";\n\nfunction UnicornScene({\n projectId,\n jsonFilePath,\n sdkUrl = UNICORN_STUDIO_CDN_URL,\n width = DEFAULT_VALUES.width,\n height = DEFAULT_VALUES.height,\n scale = DEFAULT_VALUES.scale,\n dpi = DEFAULT_VALUES.dpi,\n fps = DEFAULT_VALUES.fps,\n altText = DEFAULT_VALUES.altText,\n ariaLabel,\n className = DEFAULT_VALUES.className,\n lazyLoad = DEFAULT_VALUES.lazyLoad,\n production = DEFAULT_VALUES.production,\n placeholder,\n placeholderClassName,\n showPlaceholderOnError = DEFAULT_VALUES.showPlaceholderOnError,\n showPlaceholderWhileLoading = DEFAULT_VALUES.showPlaceholderWhileLoading,\n onLoad,\n onError,\n}: UnicornSceneProps) {\n const elementRef = useRef<HTMLDivElement>(null);\n const [isSceneLoaded, setIsSceneLoaded] = useState(false);\n const [webGLSupported, setWebGLSupported] = useState(true);\n\n const {\n isLoaded,\n error: scriptError,\n handleScriptLoad,\n handleScriptError,\n } = useUnicornStudioScript();\n const { error: sceneError } = useUnicornScene({\n elementRef,\n projectId,\n jsonFilePath,\n production,\n scale,\n dpi,\n fps,\n lazyLoad,\n altText,\n ariaLabel: ariaLabel || altText,\n isScriptLoaded: isLoaded,\n onLoad: () => {\n setIsSceneLoaded(true);\n onLoad?.();\n },\n onError,\n });\n\n const error = scriptError || sceneError;\n\n // Check WebGL support on mount\n useEffect(() => {\n setWebGLSupported(isWebGLSupported());\n }, []);\n\n // Determine if placeholder should be shown\n const showPlaceholder =\n (placeholder || placeholderClassName) &&\n (!webGLSupported ||\n (showPlaceholderWhileLoading && !isSceneLoaded) ||\n (showPlaceholderOnError && error));\n\n // Calculate dimensions for both container and image\n const numericWidth = typeof width === \"number\" ? width : 0;\n const numericHeight = typeof height === \"number\" ? height : 0;\n const useNumericDimensions =\n typeof width === \"number\" && typeof height === \"number\";\n\n // Build CSS custom properties for dynamic dimensions\n const customProperties = {\n \"--unicorn-width\": typeof width === \"number\" ? `${width}px` : width,\n \"--unicorn-height\": typeof height === \"number\" ? `${height}px` : height,\n } as React.CSSProperties;\n\n return (\n <>\n <Script\n src={sdkUrl}\n strategy={lazyLoad ? \"lazyOnload\" : \"afterInteractive\"}\n onLoad={handleScriptLoad}\n onError={handleScriptError}\n />\n\n <div\n ref={elementRef}\n style={{ ...unicornStyles.container, ...customProperties }}\n className={className}\n >\n {showPlaceholder && (placeholder || placeholderClassName) && (\n <div style={{ position: \"absolute\", inset: 0 }}>\n {typeof placeholder === \"string\" ? (\n useNumericDimensions ? (\n <Image\n src={placeholder}\n alt={altText}\n width={numericWidth}\n height={numericHeight}\n style={{ objectFit: \"cover\" }}\n priority\n />\n ) : (\n <Image\n src={placeholder}\n alt={altText}\n fill\n style={{ objectFit: \"cover\" }}\n priority\n />\n )\n ) : placeholder ? (\n placeholder\n ) : placeholderClassName ? (\n <div\n className={placeholderClassName}\n style={{ width: \"100%\", height: \"100%\" }}\n aria-label={altText}\n />\n ) : null}\n </div>\n )}\n {error && !showPlaceholder && (\n <div style={unicornStyles.errorWrapper}>\n <div style={unicornStyles.errorBox}>\n <p style={unicornStyles.errorTitle}>Error loading scene</p>\n <p style={unicornStyles.errorMessage}>{error.message}</p>\n </div>\n </div>\n )}\n </div>\n </>\n );\n}\n\nexport default UnicornScene;\nexport { UnicornScene };\n\n// Re-export types for convenience\nexport type { UnicornSceneProps } from \"../shared/types\";","import { useState, useCallback, useEffect } from \"react\";\n\nexport function useUnicornStudioScript() {\n const [isLoaded, setIsLoaded] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n\n const handleScriptLoad = useCallback(() => {\n // Only set to true if not already true to prevent duplicate triggers\n setIsLoaded(prev => {\n if (!prev && typeof window !== 'undefined' && (window as any).UnicornStudio) {\n setError(null);\n return true;\n }\n return prev;\n });\n }, []);\n\n const handleScriptError = useCallback(() => {\n setError(new Error(\"Failed to load UnicornStudio script\"));\n setIsLoaded(false);\n }, []);\n\n // Check if UnicornStudio is already available on mount\n useEffect(() => {\n if (typeof window !== 'undefined' && (window as any).UnicornStudio && !isLoaded) {\n setIsLoaded(true);\n setError(null);\n }\n }, [isLoaded]);\n\n return { isLoaded, error, handleScriptLoad, handleScriptError };\n}\n\n// Re-export shared hooks\nexport { useUnicornScene } from \"../shared/hooks\";\nexport type { UseUnicornSceneParams } from \"../shared/hooks\";\n","import { useEffect, useRef, useState, useCallback, useMemo } from \"react\";\nimport type {\n UnicornStudioScene,\n UnicornSceneConfig,\n ValidFPS,\n ScaleRange,\n} from \"./types\";\nimport { validateParameters } from \"./utils\";\n\n// Custom hook for scene management\nexport interface UseUnicornSceneParams {\n elementRef: React.RefObject<HTMLDivElement | null>;\n projectId?: string;\n jsonFilePath?: string;\n production?: boolean;\n scale: ScaleRange;\n dpi: number;\n fps: ValidFPS;\n lazyLoad: boolean;\n altText: string;\n ariaLabel: string;\n isScriptLoaded: boolean;\n onLoad?: () => void;\n onError?: (error: Error) => void;\n}\n\nexport function useUnicornScene({\n elementRef,\n projectId,\n jsonFilePath,\n production,\n scale,\n dpi,\n fps,\n lazyLoad,\n altText,\n ariaLabel,\n isScriptLoaded,\n onLoad,\n onError,\n}: UseUnicornSceneParams) {\n const sceneRef = useRef<UnicornStudioScene | null>(null);\n const [initError, setInitError] = useState<Error | null>(null);\n const hasAttemptedRef = useRef(false);\n const initializationKeyRef = useRef<string>(\"\");\n const isInitializingRef = useRef(false);\n\n // Validate parameters early and memoize the result to prevent loops\n const validationError = useMemo(() => {\n return validateParameters(scale, fps);\n }, [scale, fps]);\n\n const prevValidationError = useRef<string | null>(null);\n\n useEffect(() => {\n if (validationError !== prevValidationError.current) {\n prevValidationError.current = validationError;\n\n if (validationError) {\n const error = new Error(validationError);\n setInitError(error);\n onError?.(error);\n } else {\n setInitError(null);\n }\n }\n }, [validationError, onError]);\n\n const destroyScene = useCallback(() => {\n if (sceneRef.current?.destroy) {\n sceneRef.current.destroy();\n sceneRef.current = null;\n }\n isInitializingRef.current = false;\n }, []);\n\n const initializeScene = useCallback(async () => {\n if (!elementRef.current || !isScriptLoaded || validationError) return;\n\n // Prevent multiple concurrent initializations\n if (isInitializingRef.current) {\n console.log(\"Already initializing, skipping...\");\n return;\n }\n\n // Create a unique key for this configuration\n const currentKey = `${projectId || \"\"}-${jsonFilePath || \"\"}-${scale}-${dpi}-${fps}-${production ? \"prod\" : \"dev\"}`;\n\n // Check if we're already initialized with this exact configuration\n if (initializationKeyRef.current === currentKey && sceneRef.current) {\n console.log(\"Scene already initialized with this configuration, skipping...\");\n return;\n }\n\n // Update the initialization key and flag\n initializationKeyRef.current = currentKey;\n hasAttemptedRef.current = true;\n isInitializingRef.current = true;\n\n try {\n destroyScene();\n // Check if UnicornStudio is available\n if (!window.UnicornStudio?.addScene) {\n throw new Error(\"UnicornStudio.addScene not found\");\n }\n\n // Prepare scene configuration\n const sceneConfig: UnicornSceneConfig = {\n elementId:\n elementRef.current.id ||\n `unicorn-${Math.random().toString(36).slice(2, 11)}`,\n scale,\n dpi,\n fps,\n lazyLoad,\n altText,\n ariaLabel,\n production,\n };\n\n // Set the ID if it doesn't exist\n if (!elementRef.current.id) {\n elementRef.current.id = sceneConfig.elementId;\n }\n\n // Add project source\n if (jsonFilePath) {\n sceneConfig.filePath = jsonFilePath;\n } else if (projectId) {\n sceneConfig.projectId = projectId;\n } else {\n throw new Error(\"No project ID or JSON file path provided\");\n }\n\n // Initialize the scene using the dynamic method with a timeout\n // This prevents infinite retries from the Unicorn Studio library\n let timeoutId: NodeJS.Timeout | undefined;\n const timeoutPromise = new Promise<never>((_, reject) => {\n timeoutId = setTimeout(\n () => reject(new Error(\"Scene initialization timeout\")),\n 15000\n );\n });\n\n const cleanup = () => {\n if (timeoutId) {\n clearTimeout(timeoutId);\n }\n };\n\n try {\n const scene = await Promise.race([\n window.UnicornStudio.addScene(sceneConfig),\n timeoutPromise,\n ]);\n\n cleanup();\n\n if (scene) {\n sceneRef.current = scene;\n hasAttemptedRef.current = false; // Reset on success\n setInitError(null); // Clear any previous errors\n isInitializingRef.current = false;\n onLoad?.();\n } else {\n isInitializingRef.current = false;\n throw new Error(\"Failed to initialize scene\");\n }\n } catch (error) {\n cleanup();\n throw error;\n }\n } catch (error) {\n const err = error instanceof Error ? error : new Error(\"Unknown error\");\n\n // Sanitize error messages to not expose URLs\n let sanitizedMessage = err.message;\n if (\n sanitizedMessage.includes(\"404\") ||\n sanitizedMessage.includes(\"Failed to fetch\")\n ) {\n sanitizedMessage = \"Resource not found\";\n } else if (\n sanitizedMessage.includes(\"Network\") ||\n sanitizedMessage.includes(\"network\")\n ) {\n sanitizedMessage = \"Network error occurred\";\n } else if (sanitizedMessage.includes(\"timeout\")) {\n sanitizedMessage = \"Loading timeout\";\n }\n\n const sanitizedError = new Error(sanitizedMessage);\n setInitError(sanitizedError);\n isInitializingRef.current = false;\n onError?.(sanitizedError);\n }\n }, [\n elementRef,\n isScriptLoaded,\n jsonFilePath,\n projectId,\n production,\n scale,\n dpi,\n fps,\n lazyLoad,\n altText,\n ariaLabel,\n destroyScene,\n onLoad,\n onError,\n validationError,\n ]);\n\n useEffect(() => {\n if (isScriptLoaded) {\n void initializeScene();\n }\n }, [isScriptLoaded, initializeScene]);\n\n // Cleanup only on unmount\n useEffect(() => {\n return destroyScene;\n }, [destroyScene]);\n\n // Reset state when projectId or jsonFilePath changes\n useEffect(() => {\n const newKey = `${projectId || \"\"}-${jsonFilePath || \"\"}-${scale}-${dpi}-${fps}-${production ? \"prod\" : \"dev\"}`;\n if (initializationKeyRef.current !== newKey) {\n hasAttemptedRef.current = false;\n setInitError(null);\n isInitializingRef.current = false;\n initializationKeyRef.current = \"\"; // Reset the key to allow fresh initialization\n }\n }, [projectId, jsonFilePath, scale, dpi, fps, production]);\n\n return { error: initError };\n}\n","import type { ValidFPS, ScaleRange } from \"./types\";\n\n// UnicornStudio configuration constants\nexport const UNICORN_STUDIO_VERSION = \"1.5.2\";\nexport const UNICORN_STUDIO_CDN_URL = `https://cdn.jsdelivr.net/gh/hiunicornstudio/unicornstudio.js@v${UNICORN_STUDIO_VERSION}/dist/unicornStudio.umd.js`;\n\n// Default values for UnicornScene props\nexport const DEFAULT_VALUES = {\n width: \"100%\" as const,\n height: \"100%\" as const,\n scale: 1 as ScaleRange, // 0.25 to 1.0\n production: true,\n dpi: 1.5,\n fps: 60 as ValidFPS, // 15, 24, 30, 60, or 120\n altText: \"Scene\",\n className: \"\",\n lazyLoad: true,\n showPlaceholderOnError: true,\n showPlaceholderWhileLoading: true,\n} as const;\n\nexport const VALID_FPS = [15, 24, 30, 60, 120] as const;\n","import { VALID_FPS } from \"./constants\";\nimport type { ScaleRange, ValidFPS } from \"./types\";\n\nexport function isWebGLSupported(): boolean {\n if (typeof window === \"undefined\") return true; // Assume supported during SSR\n\n try {\n const canvas = document.createElement(\"canvas\");\n const gl =\n canvas.getContext(\"webgl\") || canvas.getContext(\"experimental-webgl\");\n return !!gl;\n } catch (e) {\n return false;\n }\n}\n\nexport function validateFPS(fps: number): fps is ValidFPS {\n return VALID_FPS.includes(fps as ValidFPS);\n}\n\nexport function validateScale(scale: number): scale is ScaleRange {\n return scale >= 0.25 && scale <= 1.0;\n}\n\nexport function validateParameters(scale: number, fps: number): string | null {\n if (!validateScale(scale)) {\n return `Invalid scale: ${scale}. Scale must be between 0.25 and 1.0`;\n }\n if (!validateFPS(fps)) {\n return `Invalid fps: ${fps}. FPS must be one of: 15, 24, 30, 60, 120`;\n }\n return null;\n}\n","export const unicornStyles = {\n container: {\n position: \"relative\" as const,\n width: \"var(--unicorn-width)\",\n height: \"var(--unicorn-height)\",\n },\n errorWrapper: {\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n height: \"100%\",\n },\n errorBox: {\n textAlign: \"center\" as const,\n padding: \"1rem\",\n borderRadius: \"0.5rem\",\n backgroundColor: \"rgb(254 242 242)\",\n color: \"rgb(239 68 68)\",\n },\n errorTitle: {\n fontWeight: \"600\",\n marginBottom: \"0.25rem\",\n },\n errorMessage: {\n fontSize: \"0.875rem\",\n marginTop: \"0.25rem\",\n },\n};\n"],"mappings":"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","names":["useRef","useState","useEffect","useState","useCallback","useEffect","useState","useCallback","useEffect","useRef","useState","useEffect"]}