@buildcores/render-client 1.6.0 → 1.7.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/README.md +34 -0
- package/dist/api.d.ts +2 -1
- package/dist/hooks/useSpriteRender.d.ts +8 -0
- package/dist/index.d.ts +88 -2
- package/dist/index.esm.js +154 -43
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +154 -43
- package/dist/index.js.map +1 -1
- package/dist/types.d.ts +64 -0
- package/package.json +1 -1
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../src/hooks/useSpriteScrubbing.ts","../src/hooks/useProgressOneSecond.ts","../src/hooks/useContinuousSpin.ts","../src/api.ts","../src/types.ts","../src/hooks/useBuildRender.ts","../src/hooks/useSpriteRender.ts","../src/components/LoadingErrorOverlay.tsx","../src/components/DragIcon.tsx","../src/components/InstructionTooltip.tsx","../src/hooks/useZoomPan.ts","../src/BuildRender.tsx","../src/hooks/useVideoScrubbing.ts","../src/BuildRenderVideo.tsx"],"sourcesContent":["import {\n useState,\n useRef,\n useEffect,\n useCallback,\n type RefObject,\n} from \"react\";\n\n// Helper to extract clientX from mouse or touch events\nconst getClientX = (e: MouseEvent | TouchEvent): number => {\n return \"touches\" in e ? e.touches[0].clientX : e.clientX;\n};\n\n// Helper to calculate new frame with circular wrapping\nexport const calculateCircularFrame = (\n startFrame: number,\n deltaX: number,\n sensitivity: number,\n totalFrames: number\n): number => {\n const frameDelta = deltaX * sensitivity;\n let newFrame = startFrame + frameDelta;\n\n // Make it circular - wrap around when going past boundaries\n newFrame = newFrame % totalFrames;\n if (newFrame < 0) {\n newFrame += totalFrames;\n }\n\n return newFrame;\n};\n\ninterface UseSpiteScrubbingOptions {\n mouseSensitivity?: number;\n touchSensitivity?: number;\n onFrameChange?: (frame: number) => void;\n}\n\nexport const useSpriteScrubbing = (\n canvasRef: RefObject<HTMLCanvasElement | null>,\n totalFrames: number,\n options: UseSpiteScrubbingOptions = {}\n) => {\n const {\n mouseSensitivity = 0.1,\n touchSensitivity = 0.1,\n onFrameChange,\n } = options;\n\n const [isDragging, setIsDragging] = useState(false);\n const [dragStartX, setDragStartX] = useState(0);\n const [dragStartFrame, setDragStartFrame] = useState(0);\n const hasDragged = useRef(false);\n const currentFrame = useRef(0);\n\n // Helper to start dragging (common logic for mouse and touch)\n const startDrag = useCallback(\n (clientX: number, event: Event) => {\n if (!canvasRef.current) return;\n\n setIsDragging(true);\n setDragStartX(clientX);\n setDragStartFrame(currentFrame.current);\n hasDragged.current = true;\n event.preventDefault();\n },\n [canvasRef]\n );\n\n // Helper to handle drag movement (common logic for mouse and touch)\n const handleDragMove = useCallback(\n (clientX: number, sensitivity: number) => {\n if (!isDragging || !canvasRef.current) return;\n\n const deltaX = clientX - dragStartX;\n\n const newFrame = calculateCircularFrame(\n dragStartFrame,\n deltaX, // Positive for natural \"spin right\" feel\n sensitivity,\n totalFrames\n );\n\n currentFrame.current = newFrame;\n\n // Call the frame change callback if provided\n if (onFrameChange) {\n onFrameChange(newFrame);\n }\n\n return newFrame;\n },\n [isDragging, dragStartX, dragStartFrame, totalFrames, onFrameChange]\n );\n\n // Helper to end dragging (common logic for mouse and touch)\n const endDrag = useCallback(() => {\n setIsDragging(false);\n }, []);\n\n const handleMouseDown = useCallback(\n (e: React.MouseEvent) => {\n startDrag(e.clientX, e.nativeEvent);\n },\n [startDrag]\n );\n\n const handleTouchStart = useCallback(\n (e: React.TouchEvent) => {\n startDrag(e.touches[0].clientX, e.nativeEvent);\n },\n [startDrag]\n );\n\n const handleDocumentMouseMove = useCallback(\n (e: MouseEvent) => {\n return handleDragMove(getClientX(e), mouseSensitivity);\n },\n [handleDragMove, mouseSensitivity]\n );\n\n const handleDocumentTouchMove = useCallback(\n (e: TouchEvent) => {\n return handleDragMove(getClientX(e), touchSensitivity);\n },\n [handleDragMove, touchSensitivity]\n );\n\n const handleDocumentMouseUp = useCallback(() => {\n endDrag();\n }, [endDrag]);\n\n const handleDocumentTouchEnd = useCallback(() => {\n endDrag();\n }, [endDrag]);\n\n // Add document-level event listeners when dragging starts\n useEffect(() => {\n if (isDragging) {\n document.addEventListener(\"mousemove\", handleDocumentMouseMove);\n document.addEventListener(\"mouseup\", handleDocumentMouseUp);\n document.addEventListener(\"touchmove\", handleDocumentTouchMove);\n document.addEventListener(\"touchend\", handleDocumentTouchEnd);\n\n return () => {\n document.removeEventListener(\"mousemove\", handleDocumentMouseMove);\n document.removeEventListener(\"mouseup\", handleDocumentMouseUp);\n document.removeEventListener(\"touchmove\", handleDocumentTouchMove);\n document.removeEventListener(\"touchend\", handleDocumentTouchEnd);\n };\n }\n }, [\n isDragging,\n handleDocumentMouseMove,\n handleDocumentMouseUp,\n handleDocumentTouchMove,\n handleDocumentTouchEnd,\n ]);\n\n return {\n isDragging,\n handleMouseDown,\n handleTouchStart,\n hasDragged,\n currentFrame: currentFrame.current,\n setCurrentFrame: (frame: number) => {\n currentFrame.current = frame;\n },\n };\n};\n","import { useAnimationFrame } from \"framer-motion\";\nimport { useRef, useState } from \"react\";\n\nexport function useBouncePatternProgress(enabled = true) {\n const [value, setValue] = useState(0);\n const [isBouncing, setIsBouncing] = useState(false);\n const start = useRef<number | null>(null);\n\n useAnimationFrame((t) => {\n if (!enabled) {\n // Reset animation when disabled\n if (start.current !== null) {\n start.current = null;\n setValue(0);\n setIsBouncing(false);\n }\n return;\n }\n\n if (start.current === null) start.current = t;\n\n const elapsed = (t - start.current) % 3000; // 3s full cycle\n\n let progress = 0;\n const bouncing = elapsed < 1000; // Bouncing during first 1 second\n\n if (elapsed < 500) {\n // 0 → 1\n progress = elapsed / 500;\n } else if (elapsed < 1000) {\n // 1 → 0\n progress = 1 - (elapsed - 500) / 500;\n } else {\n // Pause at 0 for 2 seconds\n progress = 0;\n }\n\n setValue(progress);\n setIsBouncing(bouncing);\n });\n\n return { value, isBouncing };\n}\n","import { useAnimationFrame } from \"framer-motion\";\nimport { useRef, useState, useEffect } from \"react\";\n\nexport interface ContinuousSpinResult {\n /** Current frame index (integer part) */\n frame: number;\n /** Next frame index for interpolation */\n nextFrame: number;\n /** Blend factor between frames (0-1), used for cross-fade interpolation */\n blend: number;\n}\n\n/**\n * Hook for continuous 360° spin animation with smooth interpolation support.\n * \n * @param enabled - Whether the animation is enabled\n * @param duration - Duration in ms for one full rotation (default: 10000ms = 10 seconds)\n * @param totalFrames - Total number of frames in the sprite (default: 72)\n * @returns Object with current frame, next frame, and blend factor for smooth interpolation\n */\nexport function useContinuousSpin(\n enabled = true,\n duration = 10000,\n totalFrames = 72\n): ContinuousSpinResult {\n const [result, setResult] = useState<ContinuousSpinResult>({ \n frame: 0, \n nextFrame: 1, \n blend: 0 \n });\n const startTime = useRef<number | null>(null);\n \n // Use refs to avoid stale closures in useAnimationFrame\n const totalFramesRef = useRef(totalFrames);\n const durationRef = useRef(duration);\n \n // Keep refs in sync with props\n useEffect(() => {\n totalFramesRef.current = totalFrames;\n }, [totalFrames]);\n \n useEffect(() => {\n durationRef.current = duration;\n }, [duration]);\n\n useAnimationFrame((time) => {\n if (!enabled) {\n if (startTime.current !== null) {\n startTime.current = null;\n }\n return;\n }\n\n if (startTime.current === null) {\n startTime.current = time;\n }\n\n const elapsed = time - startTime.current;\n const currentDuration = durationRef.current;\n const currentTotalFrames = totalFramesRef.current;\n \n // Calculate progress through the full rotation (0 to 1)\n const progress = (elapsed % currentDuration) / currentDuration;\n // Convert to fractional frame position\n const exactFrame = progress * currentTotalFrames;\n const currentFrame = Math.floor(exactFrame) % currentTotalFrames;\n const nextFrame = (currentFrame + 1) % currentTotalFrames;\n // Blend is the fractional part - how far between current and next frame\n const blend = exactFrame - Math.floor(exactFrame);\n \n setResult({ frame: currentFrame, nextFrame, blend });\n });\n\n return result;\n}\n","import { \n RenderBuildRequest, \n AvailablePartsResponse, \n ApiConfig, \n PartCategory, \n GetAvailablePartsOptions,\n BuildResponse,\n PartsResponse,\n RenderByShareCodeOptions,\n RenderByShareCodeJobResponse,\n RenderByShareCodeResponse,\n} from \"./types\";\n\n// API Configuration\nconst API_BASE_URL = \"https://www.renderapi.buildcores.com\";\n\n// API Endpoints\nexport const API_ENDPOINTS = {\n RENDER_BUILD_EXPERIMENTAL: \"/render-build-experimental\",\n RENDER_BUILD: \"/render-build\",\n AVAILABLE_PARTS: \"/available-parts\",\n BUILD: \"/build\",\n PARTS: \"/parts\",\n RENDER_BY_SHARE_CODE: \"/render-by-share-code\",\n} as const;\n\n// API Response Types\nexport interface RenderBuildResponse {\n /**\n * The rendered MP4 video as a Blob (when format is \"video\")\n */\n video: Blob;\n /**\n * Optional metadata about the render\n */\n metadata?: {\n duration?: number;\n size?: number;\n format?: string;\n };\n}\n\n// Async render job types (new endpoints)\nexport interface RenderJobCreateResponse {\n job_id: string;\n status: \"queued\" | \"processing\" | \"completed\" | \"error\";\n}\n\nexport interface RenderJobStatusResponse {\n job_id: string;\n status: \"queued\" | \"processing\" | \"completed\" | \"error\";\n url?: string | null;\n video_url?: string | null;\n sprite_url?: string | null;\n error?: string | null;\n end_time?: string | null;\n}\n\nexport interface RenderBuildAsyncResponse {\n /** Final URL to the rendered MP4 (or sprite) asset */\n videoUrl: string;\n}\n\nexport interface RenderSpriteResponse {\n /**\n * The rendered sprite sheet as a Blob (when format is \"sprite\")\n */\n sprite: Blob;\n /**\n * Sprite sheet metadata\n */\n metadata?: {\n cols?: number;\n rows?: number;\n totalFrames?: number;\n size?: number;\n format?: string;\n };\n}\n\n// API Functions (definitions only - not implemented yet)\nexport interface RenderAPIService {\n /**\n * Submit a render build request\n * @param parts - The parts configuration for the build\n * @param config - API configuration (environment, auth token) - required\n * @returns Promise with the rendered MP4 video\n */\n renderBuildExperimental(\n parts: RenderBuildRequest,\n config: ApiConfig\n ): Promise<RenderBuildResponse>;\n\n /**\n * Get available parts for building\n * @param config - API configuration (environment, auth token) - required\n * @returns Promise with available parts by category\n */\n getAvailableParts(\n category: PartCategory,\n config: ApiConfig,\n options?: GetAvailablePartsOptions\n ): Promise<AvailablePartsResponse>;\n}\n\n// API URL helpers\nexport const buildApiUrl = (endpoint: string, config: ApiConfig): string => {\n const baseUrl = `${API_BASE_URL}${endpoint}`;\n if (config.environment) {\n const separator = endpoint.includes(\"?\") ? \"&\" : \"?\";\n return `${baseUrl}${separator}environment=${config.environment}`;\n }\n return baseUrl;\n};\n\n// Helper to build request headers with auth token\nexport const buildHeaders = (config: ApiConfig): Record<string, string> => {\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n accept: \"application/json\",\n };\n\n if (config.authToken) {\n headers[\"Authorization\"] = `Bearer ${config.authToken}`;\n }\n\n return headers;\n};\n\nconst sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));\n\n// API Implementation\nexport const renderBuildExperimental = async (\n request: RenderBuildRequest,\n config: ApiConfig\n): Promise<RenderBuildResponse> => {\n const requestWithFormat = {\n ...request,\n format: request.format || \"video\", // Default to video format\n // Include width and height if provided\n ...(request.width !== undefined ? { width: request.width } : {}),\n ...(request.height !== undefined ? { height: request.height } : {}),\n // Include profile if provided\n ...(request.profile ? { profile: request.profile } : {}),\n };\n\n const response = await fetch(\n buildApiUrl(API_ENDPOINTS.RENDER_BUILD_EXPERIMENTAL, config),\n {\n method: \"POST\",\n headers: buildHeaders(config),\n body: JSON.stringify(requestWithFormat),\n }\n );\n\n if (!response.ok) {\n throw new Error(\n `Render build failed: ${response.status} ${response.statusText}`\n );\n }\n\n const video = await response.blob();\n\n return {\n video,\n metadata: {\n size: video.size,\n format: \"video/mp4\",\n },\n };\n};\n\n// New async endpoints implementation\nexport const createRenderBuildJob = async (\n request: RenderBuildRequest,\n config: ApiConfig\n): Promise<RenderJobCreateResponse> => {\n const body = {\n parts: request.parts,\n // If provided, forward format; default handled server-side but we keep explicit default\n ...(request.format ? { format: request.format } : {}),\n // Include width and height if provided\n ...(request.width !== undefined ? { width: request.width } : {}),\n ...(request.height !== undefined ? { height: request.height } : {}),\n // Include profile if provided\n ...(request.profile ? { profile: request.profile } : {}),\n // Include composition settings\n ...(request.showGrid !== undefined ? { showGrid: request.showGrid } : {}),\n ...(request.cameraOffsetX !== undefined ? { cameraOffsetX: request.cameraOffsetX } : {}),\n ...(request.gridSettings ? { gridSettings: request.gridSettings } : {}),\n // Include frame quality for sprite rendering\n ...(request.frameQuality ? { frameQuality: request.frameQuality } : {}),\n // Include camera zoom for render-time scaling\n ...(request.cameraZoom !== undefined ? { cameraZoom: request.cameraZoom } : {}),\n };\n\n const response = await fetch(buildApiUrl(API_ENDPOINTS.RENDER_BUILD, config), {\n method: \"POST\",\n headers: buildHeaders(config),\n body: JSON.stringify(body),\n });\n\n if (!response.ok) {\n throw new Error(`Create render job failed: ${response.status} ${response.statusText}`);\n }\n\n const data = (await response.json()) as RenderJobCreateResponse;\n if (!data?.job_id) {\n throw new Error(\"Create render job failed: missing job_id in response\");\n }\n return data;\n};\n\nexport const getRenderBuildStatus = async (\n jobId: string,\n config: ApiConfig\n): Promise<RenderJobStatusResponse> => {\n const url = buildApiUrl(`${API_ENDPOINTS.RENDER_BUILD}/${encodeURIComponent(jobId)}`, config);\n const response = await fetch(url, {\n method: \"GET\",\n headers: buildHeaders(config),\n });\n\n if (response.status === 404) {\n throw new Error(\"Render job not found\");\n }\n if (!response.ok) {\n throw new Error(`Get render job status failed: ${response.status} ${response.statusText}`);\n }\n\n return (await response.json()) as RenderJobStatusResponse;\n};\n\nexport const renderBuild = async (\n request: RenderBuildRequest,\n config: ApiConfig,\n options?: { pollIntervalMs?: number; timeoutMs?: number }\n): Promise<RenderBuildAsyncResponse> => {\n const pollIntervalMs = options?.pollIntervalMs ?? 1500;\n const timeoutMs = options?.timeoutMs ?? 120_000; // 2 minutes default\n\n const { job_id } = await createRenderBuildJob(request, config);\n\n const start = Date.now();\n // Poll until completed or error or timeout\n for (;;) {\n const status = await getRenderBuildStatus(job_id, config);\n if (status.status === \"completed\") {\n const requestedFormat = request.format ?? \"video\";\n const finalUrl =\n (requestedFormat === \"sprite\"\n ? status.sprite_url || status.url || undefined\n : status.video_url || status.url || undefined);\n if (!finalUrl) {\n throw new Error(\"Render job completed but no URL returned\");\n }\n return { videoUrl: finalUrl };\n }\n if (status.status === \"error\") {\n throw new Error(status.error || \"Render job failed\");\n }\n\n if (Date.now() - start > timeoutMs) {\n throw new Error(\"Timed out waiting for render job to complete\");\n }\n\n await sleep(pollIntervalMs);\n }\n};\n\nexport const renderSpriteExperimental = async (\n request: RenderBuildRequest,\n config: ApiConfig\n): Promise<RenderSpriteResponse> => {\n const requestWithFormat = {\n ...request,\n format: \"sprite\",\n // Include width and height if provided\n ...(request.width !== undefined ? { width: request.width } : {}),\n ...(request.height !== undefined ? { height: request.height } : {}),\n // Include profile if provided\n ...(request.profile ? { profile: request.profile } : {}),\n };\n\n const response = await fetch(\n buildApiUrl(API_ENDPOINTS.RENDER_BUILD_EXPERIMENTAL, config),\n {\n method: \"POST\",\n headers: buildHeaders(config),\n body: JSON.stringify(requestWithFormat),\n }\n );\n\n if (!response.ok) {\n throw new Error(\n `Render sprite failed: ${response.status} ${response.statusText}`\n );\n }\n\n const sprite = await response.blob();\n\n return {\n sprite,\n metadata: {\n cols: 12, // Default sprite grid - could be returned from API\n rows: 6,\n totalFrames: 72,\n size: sprite.size,\n format: \"image/webp\",\n },\n };\n};\n\nexport const getAvailableParts = async (\n category: PartCategory,\n config: ApiConfig,\n options?: GetAvailablePartsOptions\n): Promise<AvailablePartsResponse> => {\n const base = buildApiUrl(API_ENDPOINTS.AVAILABLE_PARTS, config);\n const params = new URLSearchParams();\n params.set(\"category\", category);\n if (typeof options?.limit === \"number\") params.set(\"limit\", String(options.limit));\n if (typeof options?.skip === \"number\") params.set(\"skip\", String(options.skip));\n const separator = base.includes(\"?\") ? \"&\" : \"?\";\n const url = `${base}${separator}${params.toString()}`;\n\n const response = await fetch(url, {\n method: \"GET\",\n headers: buildHeaders(config),\n });\n\n if (!response.ok) {\n throw new Error(\n `Get available parts failed: ${response.status} ${response.statusText}`\n );\n }\n\n return (await response.json()) as AvailablePartsResponse;\n};\n\n// ============================================\n// Build and Parts API Functions\n// ============================================\n\n/**\n * Fetch a build by its share code.\n * Returns build metadata and parts organized by category.\n *\n * @param shareCode - The share code of the build to fetch\n * @param config - API configuration (environment, auth token)\n * @returns Promise with build details including parts\n *\n * @example\n * ```tsx\n * const build = await getBuildByShareCode('abc123xyz', {\n * environment: 'prod',\n * authToken: 'your-api-key'\n * });\n *\n * console.log(build.name); // \"My Gaming PC\"\n * console.log(build.parts.CPU); // [\"7xjqsomhr\"]\n *\n * // Use the parts directly with BuildRender\n * <BuildRender parts={{ parts: build.parts }} size={500} apiConfig={config} />\n * ```\n */\nexport const getBuildByShareCode = async (\n shareCode: string,\n config: ApiConfig\n): Promise<BuildResponse> => {\n const url = buildApiUrl(`${API_ENDPOINTS.BUILD}/${encodeURIComponent(shareCode)}`, config);\n\n const response = await fetch(url, {\n method: \"GET\",\n headers: buildHeaders(config),\n });\n\n if (response.status === 404) {\n throw new Error(\"Build not found\");\n }\n\n if (!response.ok) {\n throw new Error(\n `Get build by share code failed: ${response.status} ${response.statusText}`\n );\n }\n\n return (await response.json()) as BuildResponse;\n};\n\n/**\n * Fetch part details by their BuildCores IDs.\n *\n * @param partIds - Array of BuildCores part IDs to fetch\n * @param config - API configuration (environment, auth token)\n * @returns Promise with part details\n *\n * @example\n * ```tsx\n * const response = await getPartsByIds(['7xjqsomhr', 'z7pyphm9k'], {\n * environment: 'prod',\n * authToken: 'your-api-key'\n * });\n *\n * response.parts.forEach(part => {\n * console.log(`${part.name} (${part.category})`);\n * });\n * ```\n */\nexport const getPartsByIds = async (\n partIds: string[],\n config: ApiConfig\n): Promise<PartsResponse> => {\n const url = buildApiUrl(API_ENDPOINTS.PARTS, config);\n\n const response = await fetch(url, {\n method: \"POST\",\n headers: buildHeaders(config),\n body: JSON.stringify({ ids: partIds }),\n });\n\n if (!response.ok) {\n throw new Error(\n `Get parts by IDs failed: ${response.status} ${response.statusText}`\n );\n }\n\n return (await response.json()) as PartsResponse;\n};\n\n/**\n * Create a render job for a build by its share code.\n * Returns the job ID for polling status.\n *\n * @param shareCode - The share code of the build to render\n * @param config - API configuration (environment, auth token)\n * @param options - Render options (format, dimensions, profile)\n * @returns Promise with job creation response\n */\nexport const createRenderByShareCodeJob = async (\n shareCode: string,\n config: ApiConfig,\n options?: Omit<RenderByShareCodeOptions, \"pollIntervalMs\" | \"timeoutMs\">\n): Promise<RenderByShareCodeJobResponse> => {\n const url = buildApiUrl(API_ENDPOINTS.RENDER_BY_SHARE_CODE, config);\n\n const body = {\n shareCode,\n ...(options?.format ? { format: options.format } : {}),\n ...(options?.width !== undefined ? { width: options.width } : {}),\n ...(options?.height !== undefined ? { height: options.height } : {}),\n ...(options?.profile ? { profile: options.profile } : {}),\n ...(options?.showGrid !== undefined ? { showGrid: options.showGrid } : {}),\n ...(options?.cameraOffsetX !== undefined ? { cameraOffsetX: options.cameraOffsetX } : {}),\n ...(options?.gridSettings ? { gridSettings: options.gridSettings } : {}),\n ...(options?.frameQuality ? { frameQuality: options.frameQuality } : {}),\n ...(options?.cameraZoom !== undefined ? { cameraZoom: options.cameraZoom } : {}),\n };\n\n const response = await fetch(url, {\n method: \"POST\",\n headers: buildHeaders(config),\n body: JSON.stringify(body),\n });\n\n if (response.status === 404) {\n throw new Error(\"Build not found\");\n }\n\n if (!response.ok) {\n throw new Error(\n `Create render job failed: ${response.status} ${response.statusText}`\n );\n }\n\n const data = (await response.json()) as RenderByShareCodeJobResponse;\n if (!data?.job_id) {\n throw new Error(\"Create render job failed: missing job_id in response\");\n }\n\n return data;\n};\n\n/**\n * Render a build by its share code.\n * This is a convenience function that creates a render job and polls until completion.\n *\n * @param shareCode - The share code of the build to render\n * @param config - API configuration (environment, auth token)\n * @param options - Render options including polling configuration\n * @returns Promise with the final render URL\n *\n * @example\n * ```tsx\n * // Simple usage - just pass share code\n * const result = await renderByShareCode('abc123xyz', {\n * environment: 'prod',\n * authToken: 'your-api-key'\n * });\n * console.log(result.videoUrl); // URL to rendered video\n *\n * // With custom options\n * const result = await renderByShareCode('abc123xyz', config, {\n * format: 'sprite',\n * width: 1920,\n * height: 1080,\n * profile: 'cinematic',\n * timeoutMs: 180000 // 3 minute timeout\n * });\n * ```\n */\nexport const renderByShareCode = async (\n shareCode: string,\n config: ApiConfig,\n options?: RenderByShareCodeOptions\n): Promise<RenderByShareCodeResponse> => {\n const pollIntervalMs = options?.pollIntervalMs ?? 1500;\n const timeoutMs = options?.timeoutMs ?? 120_000; // 2 minutes default\n\n const { job_id } = await createRenderByShareCodeJob(shareCode, config, options);\n\n const start = Date.now();\n // Poll until completed or error or timeout\n for (;;) {\n const status = await getRenderBuildStatus(job_id, config);\n \n if (status.status === \"completed\") {\n const requestedFormat = options?.format ?? \"video\";\n const finalUrl =\n requestedFormat === \"sprite\"\n ? status.sprite_url || status.url || undefined\n : status.video_url || status.url || undefined;\n \n if (!finalUrl) {\n throw new Error(\"Render job completed but no URL returned\");\n }\n return { videoUrl: finalUrl };\n }\n \n if (status.status === \"error\") {\n throw new Error(status.error || \"Render job failed\");\n }\n\n if (Date.now() - start > timeoutMs) {\n throw new Error(\"Timed out waiting for render job to complete\");\n }\n\n await sleep(pollIntervalMs);\n }\n};\n\n// Export the base URL for external use\nexport { API_BASE_URL };\n","export interface BuildRenderVideoProps {\n /**\n * Parts configuration for the build render.\n *\n * This object defines which PC components should be included in the 3D render.\n * Each part category contains an array with a single part ID that will be rendered.\n *\n * **Current Limitation**: Only 1 part per category is supported. Arrays must contain\n * exactly one part ID per category. Future versions will support multiple parts per category.\n *\n * @example\n * ```tsx\n * const parts = {\n * parts: {\n * CPU: [\"7xjqsomhr\"], // AMD Ryzen 7 9800X3D\n * GPU: [\"z7pyphm9k\"], // ASUS GeForce RTX 5080 ASTRAL\n * RAM: [\"dpl1iyvb5\"], // PNY DDR5\n * Motherboard: [\"iwin2u9vx\"], // Asus ROG STRIX X870E-E GAMING WIFI\n * PSU: [\"m4kilv190\"], // LIAN LI 1300W\n * Storage: [\"0bkvs17po\"], // SAMSUNG 990 EVO\n * PCCase: [\"qq9jamk7c\"], // MONTECH KING 95 PRO\n * CPUCooler: [\"62d8zelr5\"], // ARCTIC LIQUID FREEZER 360\n * }\n * };\n *\n * <BuildRender parts={parts} size={300} />\n * ```\n *\n * @example Minimal build (only required components)\n * ```tsx\n * const parts = {\n * parts: {\n * CPU: [\"7xjqsomhr\"], // Single CPU required\n * Motherboard: [\"iwin2u9vx\"], // Single motherboard required\n * PCCase: [\"qq9jamk7c\"], // Single case required\n * }\n * };\n * ```\n *\n * Note: Part IDs must correspond to valid components in the BuildCores database.\n * Use the available parts API to get valid part IDs for each category.\n */\n parts: RenderBuildRequest;\n\n /**\n * Width and height in pixels. If only `size` is provided, both width and height use it.\n * If `width`/`height` are provided, they override `size` individually.\n */\n width?: number;\n height?: number;\n size?: number;\n\n /**\n * API configuration for environment and authentication.\n * This is required to make API calls to the BuildCores rendering service.\n *\n * @example\n * ```tsx\n * <BuildRender\n * parts={parts}\n * size={300}\n * apiConfig={{\n * environment: 'staging',\n * authToken: 'your-auth-token'\n * }}\n * />\n * ```\n */\n apiConfig: ApiConfig;\n\n /**\n * Options to configure the internal useBuildRender hook\n * (e.g., choose async vs experimental rendering flow)\n */\n useBuildRenderOptions?: {\n mode?: \"async\" | \"experimental\";\n };\n\n /**\n * Optional mouse sensitivity for dragging (default: 0.005).\n *\n * Controls how responsive the 3D model rotation is to mouse movements.\n * Lower values make rotation slower and more precise, higher values make it faster.\n *\n * @example\n * ```tsx\n * <BuildRender\n * parts={parts}\n * size={300}\n * mouseSensitivity={0.003} // Slower, more precise\n * />\n *\n * <BuildRender\n * parts={parts}\n * size={300}\n * mouseSensitivity={0.01} // Faster rotation\n * />\n * ```\n *\n * @default 0.005\n */\n mouseSensitivity?: number;\n\n /**\n * Optional touch sensitivity for dragging (default: 0.01).\n *\n * Controls how responsive the 3D model rotation is to touch gestures on mobile devices.\n * Generally set higher than mouseSensitivity for better touch experience.\n *\n * @example\n * ```tsx\n * <BuildRender\n * parts={parts}\n * size={300}\n * touchSensitivity={0.008} // Slower touch rotation\n * />\n *\n * <BuildRender\n * parts={parts}\n * size={300}\n * touchSensitivity={0.015} // Faster touch rotation\n * />\n * ```\n *\n * @default 0.01\n */\n touchSensitivity?: number;\n}\n\nexport interface BuildRenderProps {\n /**\n * Parts configuration for the sprite render.\n *\n * This object defines which PC components should be included in the 3D sprite render.\n * Each part category contains an array with a single part ID that will be rendered.\n *\n * **Note**: If `shareCode` is provided, it will be used instead of `parts`.\n * Using `shareCode` preserves the build's interactive state (including case fan slot placements).\n *\n * **Current Limitation**: Only 1 part per category is supported. Arrays must contain\n * exactly one part ID per category. Future versions will support multiple parts per category.\n *\n * @example\n * ```tsx\n * const parts = {\n * parts: {\n * CPU: [\"7xjqsomhr\"], // AMD Ryzen 7 9800X3D\n * GPU: [\"z7pyphm9k\"], // ASUS GeForce RTX 5080 ASTRAL\n * RAM: [\"dpl1iyvb5\"], // PNY DDR5\n * Motherboard: [\"iwin2u9vx\"], // Asus ROG STRIX X870E-E GAMING WIFI\n * PSU: [\"m4kilv190\"], // LIAN LI 1300W\n * Storage: [\"0bkvs17po\"], // SAMSUNG 990 EVO\n * PCCase: [\"qq9jamk7c\"], // MONTECH KING 95 PRO\n * CPUCooler: [\"62d8zelr5\"], // ARCTIC LIQUID FREEZER 360\n * }\n * };\n *\n * <SpriteRender parts={parts} size={300} />\n * ```\n */\n parts?: RenderBuildRequest;\n\n /**\n * Share code of an existing build to render.\n *\n * When provided, the build will be rendered using its existing interactive state,\n * which includes case fan slot placements. This is preferred over `parts` when\n * rendering builds that have already been configured with case fans.\n *\n * If both `shareCode` and `parts` are provided, `shareCode` takes precedence.\n *\n * @example\n * ```tsx\n * <BuildRender\n * shareCode=\"abc123xyz\"\n * size={500}\n * apiConfig={{ environment: 'prod', authToken: 'your-token' }}\n * />\n * ```\n */\n shareCode?: string;\n\n /**\n * Width and height in pixels. If only `size` is provided, both width and height use it.\n * If `width`/`height` are provided, they override `size` individually.\n */\n width?: number;\n height?: number;\n size?: number;\n\n /**\n * API configuration for environment and authentication.\n * This is required to make API calls to the BuildCores rendering service.\n *\n * @example\n * ```tsx\n * <SpriteRender\n * parts={parts}\n * size={300}\n * apiConfig={{\n * environment: 'staging',\n * authToken: 'your-auth-token'\n * }}\n * />\n * ```\n */\n apiConfig: ApiConfig;\n\n /**\n * Options to configure the internal useSpriteRender hook\n * (e.g., choose async vs experimental rendering flow)\n */\n useSpriteRenderOptions?: {\n mode?: \"async\" | \"experimental\";\n };\n\n /**\n * Optional mouse sensitivity for dragging (default: 0.05).\n *\n * Controls how responsive the 3D model rotation is to mouse movements.\n * Lower values make rotation slower and more precise, higher values make it faster.\n *\n * @default 0.2\n */\n mouseSensitivity?: number;\n\n /**\n * Optional touch sensitivity for dragging (default: 0.02).\n *\n * Controls how responsive the 3D model rotation is to touch gestures on mobile devices.\n * Generally set similar to mouseSensitivity for consistent experience.\n *\n * @default 0.2\n */\n touchSensitivity?: number;\n\n /**\n * Show grid in render.\n * Works for both parts and shareCode rendering.\n */\n showGrid?: boolean;\n\n /**\n * Camera offset X for composition.\n * Positive values shift the build to the right, leaving room for text overlay on the left.\n * Works for both parts and shareCode rendering.\n */\n cameraOffsetX?: number;\n\n /**\n * Grid appearance settings for thicker/more visible grid in renders.\n * Works for both parts and shareCode rendering.\n */\n gridSettings?: GridSettings;\n\n /**\n * Animation mode for the auto-rotation.\n * \n * - **bounce**: (default) Quick back-and-forth partial rotation with pauses\n * - **spin360**: Slow continuous 360° rotation\n * \n * @example\n * ```tsx\n * // Continuous slow spin (good for showcases)\n * <BuildRender\n * shareCode=\"abc123\"\n * animationMode=\"spin360\"\n * spinDuration={12000} // 12 seconds per full rotation\n * />\n * ```\n * \n * @default \"bounce\"\n */\n animationMode?: 'bounce' | 'spin360';\n\n /**\n * Duration in milliseconds for one full 360° rotation.\n * Only applies when `animationMode` is \"spin360\".\n * \n * @example\n * ```tsx\n * <BuildRender\n * shareCode=\"abc123\"\n * animationMode=\"spin360\"\n * spinDuration={15000} // 15 seconds per rotation\n * />\n * ```\n * \n * @default 10000 (10 seconds)\n */\n spinDuration?: number;\n\n /**\n * Whether to enable user interaction (drag to rotate, scroll to zoom).\n * \n * When set to `false`:\n * - Drag-to-rotate is disabled\n * - Scroll-to-zoom is disabled\n * - Cursor shows as \"pointer\" instead of \"grab\"\n * - Click events pass through (useful for wrapping in a link)\n * \n * @example\n * ```tsx\n * // Non-interactive showcase with link\n * <a href=\"https://buildcores.com/build/abc123\">\n * <BuildRender\n * shareCode=\"abc123\"\n * animationMode=\"spin360\"\n * interactive={false}\n * />\n * </a>\n * ```\n * \n * @default true\n */\n interactive?: boolean;\n\n /**\n * Frame quality for sprite renders.\n * - **standard**: 72 frames (default) - good balance of quality and file size\n * - **high**: 144 frames - smoother animation, larger file size (~2x file size)\n * \n * @example\n * ```tsx\n * <BuildRender\n * shareCode=\"abc123\"\n * frameQuality=\"high\" // 144 frames for smoother rotation\n * />\n * ```\n * \n * @default \"standard\"\n */\n frameQuality?: 'standard' | 'high';\n\n /**\n * Initial zoom level for the build.\n * Range: 0.5 (50%) to 2.5 (250%). Values less than 1 make the build appear smaller,\n * values greater than 1 make it appear larger.\n * \n * @example\n * ```tsx\n * <BuildRender\n * shareCode=\"abc123\"\n * zoom={0.7} // 70% size - build appears smaller\n * />\n * \n * <BuildRender\n * shareCode=\"abc123\"\n * zoom={1.5} // 150% size - build appears larger\n * />\n * ```\n * \n * @default 1\n */\n zoom?: number;\n\n /**\n * Camera zoom level for server-side rendering.\n * Values > 1 move the camera further away (build appears smaller in the sprite).\n * Values < 1 move the camera closer (build appears larger in the sprite).\n * \n * Use this for higher quality scaled-down renders vs client-side zoom scaling.\n * Range: 0.5 to 2.0\n * \n * @example\n * ```tsx\n * <BuildRender\n * shareCode=\"abc123\"\n * cameraZoom={1.3} // Camera 30% further away - smaller build in sprite\n * />\n * ```\n * \n * @default 1\n */\n cameraZoom?: number;\n}\n\n// API Types\n\n/**\n * API configuration for environment and authentication\n */\nexport interface ApiConfig {\n /**\n * Environment to use for API requests\n * - 'staging': Development/testing environment\n * - 'prod': Production environment\n *\n * @example\n * ```tsx\n * const config: ApiConfig = {\n * environment: 'staging',\n * authToken: 'your-bearer-token'\n * };\n * ```\n */\n environment?: \"staging\" | \"prod\";\n\n /**\n * Bearer token for API authentication\n *\n * @example\n * ```tsx\n * const config: ApiConfig = {\n * environment: 'prod',\n * authToken: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...'\n * };\n * ```\n */\n authToken?: string;\n}\n\n/**\n * Enum defining all available PC part categories that can be rendered.\n *\n * Each category represents a different type of computer component that can be\n * included in the 3D build visualization.\n *\n * @example\n * ```tsx\n * // All available categories\n * const categories = [\n * PartCategory.CPU, // \"CPU\"\n * PartCategory.GPU, // \"GPU\"\n * PartCategory.RAM, // \"RAM\"\n * PartCategory.Motherboard,// \"Motherboard\"\n * PartCategory.PSU, // \"PSU\"\n * PartCategory.Storage, // \"Storage\"\n * PartCategory.PCCase, // \"PCCase\"\n * PartCategory.CPUCooler, // \"CPUCooler\"\n * ];\n * ```\n */\nexport enum PartCategory {\n /** Central Processing Unit - The main processor */\n CPU = \"CPU\",\n /** Graphics Processing Unit - Video card for rendering */\n GPU = \"GPU\",\n /** Random Access Memory - System memory modules */\n RAM = \"RAM\",\n /** Main circuit board that connects all components */\n Motherboard = \"Motherboard\",\n /** Power Supply Unit - Provides power to all components */\n PSU = \"PSU\",\n /** Storage devices like SSDs, HDDs, NVMe drives */\n Storage = \"Storage\",\n /** PC Case - The enclosure that houses all components */\n PCCase = \"PCCase\",\n /** CPU Cooler - Air or liquid cooling for the processor */\n CPUCooler = \"CPUCooler\",\n /** Case Fans - Additional cooling fans for the case */\n CaseFan = \"CaseFan\",\n}\n\n/**\n * Request structure for rendering a PC build.\n *\n * This interface defines the parts configuration that will be sent to the\n * rendering service to generate a 3D visualization of a PC build.\n *\n * **Current Limitation**: Only one part per category is supported. Each category\n * array must contain exactly one part ID. Future versions will support multiple\n * parts per category for comparison views.\n *\n * @example Basic build configuration\n * ```tsx\n * const buildRequest: RenderBuildRequest = {\n * parts: {\n * CPU: [\"7xjqsomhr\"], // AMD Ryzen 7 9800X3D\n * GPU: [\"z7pyphm9k\"], // ASUS GeForce RTX 5080 ASTRAL\n * RAM: [\"dpl1iyvb5\"], // PNY DDR5\n * Motherboard: [\"iwin2u9vx\"], // Asus ROG STRIX X870E-E GAMING WIFI\n * PSU: [\"m4kilv190\"], // LIAN LI 1300W\n * Storage: [\"0bkvs17po\"], // SAMSUNG 990 EVO\n * PCCase: [\"qq9jamk7c\"], // MONTECH KING 95 PRO\n * CPUCooler: [\"62d8zelr5\"], // ARCTIC LIQUID FREEZER 360\n * },\n * format: \"video\" // Request video format\n * };\n * ```\n *\n * @example Sprite format request\n * ```tsx\n * const spriteRequest: RenderBuildRequest = {\n * parts: {\n * CPU: [\"7xjqsomhr\"], // AMD Ryzen 7 9800X3D\n * GPU: [\"z7pyphm9k\"], // ASUS GeForce RTX 5080 ASTRAL\n * RAM: [\"dpl1iyvb5\"], // PNY DDR5\n * Motherboard: [\"iwin2u9vx\"], // Asus ROG STRIX X870E-E GAMING WIFI\n * },\n * format: \"sprite\" // Request sprite sheet format\n * };\n * ```\n */\nexport interface RenderBuildRequest {\n /**\n * Object mapping part categories to arrays of part IDs.\n *\n * **Current Requirements**:\n * - Keys are part categories (CPU, GPU, RAM, etc.)\n * - Values are arrays containing exactly one part ID string\n * - All categories are optional - include only the parts you want to render\n * - Part IDs must be valid identifiers from the BuildCores parts database\n *\n * **Future Enhancement**: Multiple parts per category will be supported for comparison views.\n *\n * @see PartCategory for all available categories\n * @see AvailablePartsResponse for getting valid part IDs\n */\n parts: {\n [K in PartCategory]?: string[];\n };\n\n /**\n * Output format for the rendered build.\n *\n * - \"video\": Returns an MP4 video file for video-based 360° rotation\n * - \"sprite\": Returns a sprite sheet image for frame-based 360° rotation\n *\n * @default \"video\"\n */\n format?: \"video\" | \"sprite\";\n\n /**\n * Desired canvas pixel width (256-2000).\n * Must be provided together with height.\n *\n * @example\n * ```tsx\n * const request: RenderBuildRequest = {\n * parts: { CPU: [\"7xjqsomhr\"] },\n * width: 1920,\n * height: 1080\n * };\n * ```\n */\n width?: number;\n\n /**\n * Desired canvas pixel height (256-2000).\n * Must be provided together with width.\n *\n * @example\n * ```tsx\n * const request: RenderBuildRequest = {\n * parts: { CPU: [\"7xjqsomhr\"] },\n * width: 1920,\n * height: 1080\n * };\n * ```\n */\n height?: number;\n\n /**\n * Render quality profile that controls visual effects and rendering speed.\n *\n * - **cinematic**: All effects enabled (shadows, ambient occlusion, bloom) for highest quality\n * - **flat**: No effects for clean, simple product shots\n * - **fast**: Minimal rendering for fastest processing speed\n *\n * @example\n * ```tsx\n * const request: RenderBuildRequest = {\n * parts: { CPU: [\"7xjqsomhr\"] },\n * profile: 'cinematic' // High quality with all effects\n * };\n * ```\n *\n * @example Fast rendering\n * ```tsx\n * const request: RenderBuildRequest = {\n * parts: { CPU: [\"7xjqsomhr\"] },\n * profile: 'fast' // Quick render, minimal effects\n * };\n * ```\n */\n profile?: 'cinematic' | 'flat' | 'fast';\n\n /**\n * Whether to show the 3D grid in the render.\n * Defaults to true for cinematic profile, false otherwise.\n */\n showGrid?: boolean;\n\n /**\n * Horizontal offset for the camera view.\n * Positive values shift the build to the right, leaving room for text overlay on the left.\n * Range: -0.3 to 0.3\n */\n cameraOffsetX?: number;\n\n /**\n * Custom grid appearance settings.\n * Only applies when showGrid is true.\n */\n gridSettings?: GridSettings;\n\n /**\n * Frame quality for sprite renders.\n * - **standard**: 72 frames (default) - good balance of quality and file size\n * - **high**: 144 frames - smoother animation, larger file size\n * \n * @default \"standard\"\n */\n frameQuality?: 'standard' | 'high';\n\n /**\n * Camera zoom level for server-side rendering.\n * Values > 1 move the camera further away (build appears smaller in the sprite).\n * Values < 1 move the camera closer (build appears larger in the sprite).\n * Range: 0.5 to 2.0\n * \n * @default 1\n */\n cameraZoom?: number;\n}\n\n/**\n * Response structure containing all available parts for each category.\n *\n * This type represents the response from the available parts API endpoint,\n * providing arrays of valid part IDs for each component category.\n *\n * @example Using available parts response\n * ```tsx\n * const availableParts: AvailablePartsResponse = {\n * CPU: [\n * { id: \"7xjqsomhr\", name: \"AMD Ryzen 7 9800X3D\", image: \"https://...\" },\n * { id: \"x2thvstj3\", name: \"AMD Ryzen 7 9700X\", image: \"https://...\" },\n * ],\n * GPU: [\n * { id: \"z7pyphm9k\", name: \"ASUS GeForce RTX 5080 ASTRAL\", image: \"https://...\" },\n * { id: \"4a0mjb360\", name: \"PNY GeForce RTX 5060 Ti 16GB\", image: \"https://...\" },\n * ],\n * // ... all other categories\n * };\n *\n * // Select one part per category for current build request\n * const buildRequest: RenderBuildRequest = {\n * parts: {\n * CPU: [availableParts.CPU[0].id], // Select first available CPU ID\n * GPU: [availableParts.GPU[1].id], // Select second available GPU ID\n * RAM: [availableParts.RAM[0].id], // Select first available RAM ID\n * }\n * };\n * ```\n *\n * @example Dynamic part selection\n * ```tsx\n * // Function to create build with user-selected parts\n * const createBuild = (selectedPartIds: Record<string, string>) => {\n * const buildRequest: RenderBuildRequest = {\n * parts: {\n * CPU: [selectedPartIds.cpu], // Single selected CPU ID\n * GPU: [selectedPartIds.gpu], // Single selected GPU ID\n * RAM: [selectedPartIds.ram], // Single selected RAM ID\n * // ... other single selections\n * }\n * };\n * return buildRequest;\n * };\n * ```\n */\n/**\n * Individual part information with details\n */\nexport interface PartDetails {\n /** Unique part identifier */\n id: string;\n /** Human-readable part name */\n name: string;\n /** URL to part image */\n image: string;\n}\n\n/**\n * Pagination metadata for available parts responses\n */\nexport interface AvailablePartsPagination {\n /** Total number of parts available for this category */\n total: number;\n /** Number of parts returned in this response */\n limit: number;\n /** Number of parts skipped */\n skip: number;\n /** Whether there are more parts available */\n hasNext: boolean;\n /** Whether there are previous parts available */\n hasPrev: boolean;\n}\n\n/**\n * Response envelope for the available parts endpoint.\n * Returns parts for the requested category under `data` keyed by category name.\n */\nexport interface AvailablePartsResponse {\n /**\n * Parts grouped by category. Only the requested category key is expected\n * to be present in the response.\n */\n data: Partial<Record<PartCategory, PartDetails[]>>;\n /** The requested category */\n category: PartCategory;\n /** Optional pagination information */\n pagination?: AvailablePartsPagination;\n}\n\n/**\n * Query options for fetching available parts\n */\nexport interface GetAvailablePartsOptions {\n /** Number of parts to return (default 20, min 1, max 100) */\n limit?: number;\n /** Number of parts to skip for pagination (default 0) */\n skip?: number;\n}\n\n// ============================================\n// Build and Parts API Types\n// ============================================\n\n/**\n * Extended part details including category information\n */\nexport interface PartDetailsWithCategory {\n /** Unique part identifier (BuildCores ID) */\n id: string;\n /** Human-readable part name */\n name: string;\n /** URL to part image (may be null) */\n image: string | null;\n /** Part category */\n category: PartCategory;\n}\n\n/**\n * Response from the get build by share code endpoint.\n * Contains build metadata and parts organized by category.\n *\n * @example\n * ```tsx\n * const build = await getBuildByShareCode('abc123xyz', config);\n * console.log(build.name); // \"My Gaming PC\"\n * console.log(build.parts.CPU); // [\"7xjqsomhr\"]\n * console.log(build.partDetails.CPU[0].name); // \"AMD Ryzen 7 9800X3D\"\n * ```\n */\nexport interface BuildResponse {\n /** The share code of the build */\n shareCode: string;\n /** Build name/title */\n name: string;\n /** Build description */\n description: string;\n /**\n * Part IDs mapped by category.\n * Use these IDs directly with RenderBuildRequest.\n */\n parts: {\n [K in PartCategory]?: string[];\n };\n /**\n * Detailed part information mapped by category.\n * Includes name, image URL, and category for each part.\n */\n partDetails: {\n [K in PartCategory]?: PartDetailsWithCategory[];\n };\n /**\n * Whether the case in this build has an interactive 3D model available.\n * If false, the build cannot be rendered in 3D.\n */\n hasInteractiveModel: boolean;\n}\n\n/**\n * Response from the get parts by IDs endpoint.\n *\n * @example\n * ```tsx\n * const response = await getPartsByIds(['7xjqsomhr', 'z7pyphm9k'], config);\n * response.parts.forEach(part => {\n * console.log(`${part.name} (${part.category})`);\n * });\n * ```\n */\nexport interface PartsResponse {\n /** Array of part details */\n parts: PartDetailsWithCategory[];\n}\n\n/**\n * Grid appearance settings for renders\n */\nexport interface GridSettings {\n /** Grid cell line thickness (default: 0.6) */\n cellThickness?: number;\n /** Grid section line thickness (default: 1.2) */\n sectionThickness?: number;\n /** Grid color as hex string (default: #6f6f6f) */\n color?: string;\n /** Distance at which grid starts to fade (default: 3) */\n fadeDistance?: number;\n /** Render order for depth sorting (default: 0, use -1 to render before other objects) */\n renderOrder?: number;\n}\n\n/**\n * Options for rendering a build by share code\n */\nexport interface RenderByShareCodeOptions {\n /** Output format - video (MP4) or sprite (WebP sprite sheet) */\n format?: \"video\" | \"sprite\";\n /** Desired canvas pixel width (256-8192) */\n width?: number;\n /** Desired canvas pixel height (256-8192) */\n height?: number;\n /** Render quality profile */\n profile?: \"cinematic\" | \"flat\" | \"fast\";\n /** Show grid in render (default: true for cinematic profile) */\n showGrid?: boolean;\n /** Camera offset X for composition (positive = shift build right to leave room for text overlay) */\n cameraOffsetX?: number;\n /** Grid appearance settings (for thicker/more visible grid in renders) */\n gridSettings?: GridSettings;\n /** Frame quality - 'standard' (72 frames) or 'high' (144 frames for smoother animation) */\n frameQuality?: 'standard' | 'high';\n /** Camera zoom level for rendering. Values > 1 move camera further (build appears smaller). Range: 0.5 to 2.0 */\n cameraZoom?: number;\n /** Polling interval in milliseconds (default: 1500) */\n pollIntervalMs?: number;\n /** Timeout in milliseconds (default: 120000 = 2 minutes) */\n timeoutMs?: number;\n}\n\n/**\n * Response from the render by share code endpoint (job creation).\n */\nexport interface RenderByShareCodeJobResponse {\n /** Unique job identifier for polling status */\n job_id: string;\n /** Current job status */\n status: \"queued\" | \"processing\" | \"completed\" | \"error\";\n /** The share code of the build being rendered */\n share_code: string;\n}\n\n/**\n * Final response after render by share code completes.\n *\n * @example\n * ```tsx\n * const result = await renderByShareCode('abc123xyz', config);\n * // Use result.videoUrl to display the rendered video\n * ```\n */\nexport interface RenderByShareCodeResponse {\n /** URL to the rendered video or sprite sheet */\n videoUrl: string;\n}\n","import { useState, useEffect, useCallback, useRef } from \"react\";\nimport { RenderBuildRequest, PartCategory, ApiConfig } from \"../types\";\nimport { renderBuild, renderBuildExperimental } from \"../api\";\n\n/**\n * Compares two RenderBuildRequest objects for equality by checking if the same IDs\n * are present in each category array, regardless of order.\n */\nexport const arePartsEqual = (\n parts1: RenderBuildRequest,\n parts2: RenderBuildRequest\n): boolean => {\n const categories = Object.values(PartCategory);\n\n for (const category of categories) {\n const arr1 = parts1.parts[category] || [];\n const arr2 = parts2.parts[category] || [];\n\n // Check if arrays have the same length\n if (arr1.length !== arr2.length) {\n return false;\n }\n\n // Check if arrays contain the same elements (order doesn't matter)\n const set1 = new Set(arr1);\n const set2 = new Set(arr2);\n\n if (set1.size !== set2.size) {\n return false;\n }\n\n for (const id of set1) {\n if (!set2.has(id)) {\n return false;\n }\n }\n }\n\n return true;\n};\n\nexport interface UseBuildRenderReturn {\n videoSrc: string | null;\n isRenderingBuild: boolean;\n renderError: string | null;\n}\n\nexport interface UseBuildRenderOptions {\n /**\n * Choose which backend flow to use\n * - 'async' (default): uses /render-build and polls /render-build/{jobId}\n * - 'experimental': uses /render-build-experimental and returns Blob\n */\n mode?: \"async\" | \"experimental\";\n}\n\nexport const useBuildRender = (\n parts: RenderBuildRequest,\n apiConfig: ApiConfig,\n onLoadStart?: () => void,\n options?: UseBuildRenderOptions\n): UseBuildRenderReturn => {\n const [videoSrc, setVideoSrc] = useState<string | null>(null);\n const [isRenderingBuild, setIsRenderingBuild] = useState(false);\n const [renderError, setRenderError] = useState<string | null>(null);\n const previousPartsRef = useRef<RenderBuildRequest | null>(null);\n\n const fetchRenderBuild = useCallback(\n async (currentParts: RenderBuildRequest) => {\n try {\n setIsRenderingBuild(true);\n setRenderError(null);\n onLoadStart?.();\n\n const mode = options?.mode ?? \"async\";\n if (mode === \"experimental\") {\n const response = await renderBuildExperimental(currentParts, apiConfig);\n const objectUrl = URL.createObjectURL(response.video);\n setVideoSrc((prevSrc: string | null) => {\n if (prevSrc && prevSrc.startsWith(\"blob:\")) {\n URL.revokeObjectURL(prevSrc);\n }\n return objectUrl;\n });\n } else {\n const { videoUrl } = await renderBuild(currentParts, apiConfig);\n // Clean up previous object URL (if any) before setting new one\n setVideoSrc((prevSrc: string | null) => {\n if (prevSrc && prevSrc.startsWith(\"blob:\")) {\n URL.revokeObjectURL(prevSrc);\n }\n return videoUrl;\n });\n }\n } catch (error) {\n setRenderError(\n error instanceof Error ? error.message : \"Failed to render build\"\n );\n } finally {\n setIsRenderingBuild(false);\n }\n },\n [apiConfig, onLoadStart, options?.mode]\n );\n\n // Effect to call API when parts content changes (using custom equality check)\n useEffect(() => {\n const shouldFetch =\n previousPartsRef.current === null ||\n !arePartsEqual(previousPartsRef.current, parts);\n\n if (shouldFetch) {\n previousPartsRef.current = parts;\n fetchRenderBuild(parts);\n }\n }, [parts, fetchRenderBuild]);\n\n // Cleanup effect for component unmount\n useEffect(() => {\n return () => {\n if (videoSrc && videoSrc.startsWith(\"blob:\")) {\n URL.revokeObjectURL(videoSrc);\n }\n };\n }, [videoSrc]);\n\n return {\n videoSrc,\n isRenderingBuild,\n renderError,\n };\n};\n","import { useState, useEffect, useCallback, useRef } from \"react\";\nimport { RenderBuildRequest, ApiConfig } from \"../types\";\nimport { renderSpriteExperimental, renderBuild, renderByShareCode } from \"../api\";\nimport { arePartsEqual } from \"./useBuildRender\";\n\nexport interface UseSpriteRenderReturn {\n spriteSrc: string | null;\n isRenderingSprite: boolean;\n renderError: string | null;\n spriteMetadata: {\n cols: number;\n rows: number;\n totalFrames: number;\n } | null;\n}\n\nexport interface UseSpriteRenderOptions {\n /**\n * Choose which backend flow to use\n * - 'async' (default): uses /render-build and polls /render-build/{jobId} with format 'sprite'\n * - 'experimental': uses /render-build-experimental and returns Blob\n */\n mode?: \"async\" | \"experimental\";\n}\n\n/**\n * Grid settings for render composition\n */\nexport interface RenderGridSettings {\n cellThickness?: number;\n sectionThickness?: number;\n color?: string;\n fadeDistance?: number;\n renderOrder?: number;\n}\n\n/**\n * Input for sprite rendering - either parts (creates new build) or shareCode (uses existing build)\n */\nexport type SpriteRenderInput = \n | { \n type: 'parts'; \n parts: RenderBuildRequest;\n showGrid?: boolean;\n cameraOffsetX?: number;\n cameraZoom?: number;\n gridSettings?: RenderGridSettings;\n frameQuality?: 'standard' | 'high';\n }\n | { \n type: 'shareCode'; \n shareCode: string; \n profile?: 'cinematic' | 'flat' | 'fast';\n showGrid?: boolean;\n cameraOffsetX?: number;\n cameraZoom?: number;\n gridSettings?: RenderGridSettings;\n frameQuality?: 'standard' | 'high';\n };\n\nexport const useSpriteRender = (\n input: RenderBuildRequest | SpriteRenderInput,\n apiConfig: ApiConfig,\n onLoadStart?: () => void,\n options?: UseSpriteRenderOptions\n): UseSpriteRenderReturn => {\n const [spriteSrc, setSpriteSrc] = useState<string | null>(null);\n const [isRenderingSprite, setIsRenderingSprite] = useState(false);\n const [renderError, setRenderError] = useState<string | null>(null);\n const [spriteMetadata, setSpriteMetadata] = useState<{\n cols: number;\n rows: number;\n totalFrames: number;\n } | null>(null);\n const previousInputRef = useRef<RenderBuildRequest | SpriteRenderInput | null>(null);\n\n // Normalize input to SpriteRenderInput format\n const normalizedInput: SpriteRenderInput = \n 'type' in input ? input : { type: 'parts', parts: input };\n\n const fetchRenderSprite = useCallback(\n async (currentInput: SpriteRenderInput) => {\n try {\n setIsRenderingSprite(true);\n setRenderError(null);\n onLoadStart?.();\n\n // Handle share code rendering - uses existing build with proper interactive state\n if (currentInput.type === 'shareCode') {\n const { videoUrl: spriteUrl } = await renderByShareCode(\n currentInput.shareCode,\n apiConfig,\n { \n format: 'sprite', \n profile: currentInput.profile,\n showGrid: currentInput.showGrid,\n cameraOffsetX: currentInput.cameraOffsetX,\n cameraZoom: currentInput.cameraZoom,\n gridSettings: currentInput.gridSettings,\n frameQuality: currentInput.frameQuality\n }\n );\n\n // Set metadata BEFORE sprite URL to avoid race condition\n // (image load starts immediately when spriteSrc changes)\n const rows = currentInput.frameQuality === 'high' ? 12 : 6;\n setSpriteMetadata({ cols: 12, rows, totalFrames: 12 * rows });\n\n setSpriteSrc((prevSrc) => {\n if (prevSrc && prevSrc.startsWith(\"blob:\")) {\n URL.revokeObjectURL(prevSrc);\n }\n return spriteUrl;\n });\n return;\n }\n\n // Handle parts-based rendering (creates new build)\n const currentParts = currentInput.parts;\n const mode = options?.mode ?? \"async\";\n const frameQuality = currentInput.frameQuality;\n const rows = frameQuality === 'high' ? 12 : 6;\n \n if (mode === \"experimental\") {\n const response = await renderSpriteExperimental(\n {\n ...currentParts,\n showGrid: currentInput.showGrid,\n cameraOffsetX: currentInput.cameraOffsetX,\n cameraZoom: currentInput.cameraZoom,\n gridSettings: currentInput.gridSettings,\n frameQuality,\n },\n apiConfig\n );\n const objectUrl = URL.createObjectURL(response.sprite);\n\n // Set sprite metadata BEFORE sprite URL to avoid race condition\n setSpriteMetadata({\n cols: response.metadata?.cols || 12,\n rows: response.metadata?.rows || rows,\n totalFrames: response.metadata?.totalFrames || 12 * rows,\n });\n\n // Clean up previous sprite URL before setting new one\n setSpriteSrc((prevSrc) => {\n if (prevSrc && prevSrc.startsWith(\"blob:\")) {\n URL.revokeObjectURL(prevSrc);\n }\n return objectUrl;\n });\n } else {\n // Async job-based flow: request sprite format and use returned URL\n const { videoUrl: spriteUrl } = await renderBuild(\n { \n ...currentParts, \n format: \"sprite\",\n showGrid: currentInput.showGrid,\n cameraOffsetX: currentInput.cameraOffsetX,\n cameraZoom: currentInput.cameraZoom,\n gridSettings: currentInput.gridSettings,\n frameQuality,\n },\n apiConfig\n );\n\n // Set metadata BEFORE sprite URL to avoid race condition\n setSpriteMetadata({ cols: 12, rows, totalFrames: 12 * rows });\n\n setSpriteSrc((prevSrc) => {\n if (prevSrc && prevSrc.startsWith(\"blob:\")) {\n URL.revokeObjectURL(prevSrc);\n }\n return spriteUrl;\n });\n }\n } catch (error) {\n setRenderError(\n error instanceof Error ? error.message : \"Failed to render sprite\"\n );\n } finally {\n setIsRenderingSprite(false);\n }\n },\n [apiConfig, onLoadStart, options?.mode]\n );\n\n // Check if inputs are equal\n const areInputsEqual = (a: SpriteRenderInput | null, b: SpriteRenderInput): boolean => {\n if (!a) return false;\n if (a.type !== b.type) return false;\n if (a.type === 'shareCode' && b.type === 'shareCode') {\n // Compare grid settings (shallow comparison of properties)\n const gridSettingsEqual = \n JSON.stringify(a.gridSettings ?? {}) === JSON.stringify(b.gridSettings ?? {});\n return a.shareCode === b.shareCode && \n a.profile === b.profile &&\n a.showGrid === b.showGrid &&\n a.cameraOffsetX === b.cameraOffsetX &&\n a.cameraZoom === b.cameraZoom &&\n a.frameQuality === b.frameQuality &&\n gridSettingsEqual;\n }\n if (a.type === 'parts' && b.type === 'parts') {\n // Compare grid settings (shallow comparison of properties)\n const gridSettingsEqual = \n JSON.stringify(a.gridSettings ?? {}) === JSON.stringify(b.gridSettings ?? {});\n return arePartsEqual(a.parts, b.parts) &&\n a.showGrid === b.showGrid &&\n a.cameraOffsetX === b.cameraOffsetX &&\n a.cameraZoom === b.cameraZoom &&\n a.frameQuality === b.frameQuality &&\n gridSettingsEqual;\n }\n return false;\n };\n\n // Effect to call API when input changes\n useEffect(() => {\n const shouldFetch = !areInputsEqual(previousInputRef.current as SpriteRenderInput | null, normalizedInput);\n\n if (shouldFetch) {\n previousInputRef.current = normalizedInput;\n fetchRenderSprite(normalizedInput);\n }\n }, [normalizedInput, fetchRenderSprite]);\n\n // Cleanup effect for component unmount\n useEffect(() => {\n return () => {\n if (spriteSrc && spriteSrc.startsWith(\"blob:\")) {\n URL.revokeObjectURL(spriteSrc);\n }\n };\n }, [spriteSrc]);\n\n return {\n spriteSrc,\n isRenderingSprite,\n renderError,\n spriteMetadata,\n };\n};","import React from \"react\";\n\ninterface LoadingErrorOverlayProps {\n isVisible: boolean;\n renderError?: string;\n size: number;\n}\n\nexport const LoadingErrorOverlay: React.FC<LoadingErrorOverlayProps> = ({\n isVisible,\n renderError,\n size,\n}) => {\n if (!isVisible) return null;\n\n return (\n <div\n style={{\n position: \"absolute\",\n top: 0,\n left: 0,\n right: 0,\n bottom: 0,\n backgroundColor: \"rgba(0, 0, 0, 1)\",\n display: \"flex\",\n flexDirection: \"column\",\n alignItems: \"center\",\n justifyContent: \"center\",\n color: \"white\",\n zIndex: 10,\n }}\n >\n {renderError ? (\n <>\n <div\n style={{ marginBottom: \"20px\", fontSize: \"18px\", color: \"white\" }}\n >\n Render Failed\n </div>\n <div\n style={{\n fontSize: \"14px\",\n textAlign: \"center\",\n maxWidth: size * 0.8,\n color: \"white\",\n }}\n >\n {renderError}\n </div>\n </>\n ) : (\n <>\n <div\n style={{ marginBottom: \"20px\", fontSize: \"18px\", color: \"white\" }}\n >\n {\"Loading Build...\"}\n </div>\n </>\n )}\n </div>\n );\n};\n","import React from \"react\";\n\ninterface DragIconProps {\n width?: number;\n height?: number;\n className?: string;\n style?: React.CSSProperties;\n}\n\nexport const DragIcon: React.FC<DragIconProps> = ({\n width = 24,\n height = 24,\n className,\n style,\n ...props\n}) => {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n id=\"Layer_1\"\n width={width}\n height={height}\n data-name=\"Layer 1\"\n viewBox=\"0 0 24 24\"\n className={className}\n style={style}\n {...props}\n >\n <defs>\n <style>\n {\n \".cls-1{fill:none;stroke:currentColor;stroke-miterlimit:10;stroke-width:1.91px}\"\n }\n </style>\n </defs>\n <path\n d=\"m11.05 22.5-5.14-5.14a2 2 0 0 1-.59-1.43 2 2 0 0 1 2-2 2 2 0 0 1 1.43.59l1.32 1.32V6.38a2 2 0 0 1 1.74-2 1.89 1.89 0 0 1 1.52.56 1.87 1.87 0 0 1 .56 1.34V12l5 .72a1.91 1.91 0 0 1 1.64 1.89 17.18 17.18 0 0 1-1.82 7.71l-.09.18M19.64 7.23l2.86-2.87-2.86-2.86M15.82 4.36h6.68M4.36 7.23 1.5 4.36 4.36 1.5M8.18 4.36H1.5\"\n className=\"cls-1\"\n />\n </svg>\n );\n};\n","import React from \"react\";\nimport { DragIcon } from \"./DragIcon\";\n\ninterface InstructionTooltipProps {\n isVisible: boolean;\n progressValue: number;\n instructionIcon?: string;\n}\n\nexport const InstructionTooltip: React.FC<InstructionTooltipProps> = ({\n isVisible,\n progressValue,\n instructionIcon,\n}) => {\n if (!isVisible) {\n return null;\n }\n\n return (\n <div\n style={{\n position: \"absolute\",\n top: \"50%\",\n left: \"50%\",\n transform: `translate(-50%, -50%) translateX(${progressValue * 50}px)`,\n backgroundColor: \"rgba(0, 0, 0, 0.8)\",\n color: \"white\",\n padding: \"12px\",\n borderRadius: \"8px\",\n pointerEvents: \"none\",\n zIndex: 5,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n }}\n >\n {instructionIcon ? (\n <img\n src={instructionIcon}\n alt=\"drag to view 360\"\n style={{\n width: \"24px\",\n height: \"24px\",\n filter: \"invert(1)\", // Makes the icon white\n }}\n />\n ) : (\n <DragIcon\n width={24}\n height={24}\n style={{\n color: \"white\",\n }}\n />\n )}\n </div>\n );\n};\n","import {\n useCallback,\n useEffect,\n useRef,\n useState,\n type TouchEvent as ReactTouchEvent,\n type WheelEvent as ReactWheelEvent,\n} from \"react\";\n\ninterface UseZoomOptions {\n displayWidth?: number;\n displayHeight?: number;\n minScale?: number;\n maxScale?: number;\n initialScale?: number;\n}\n\ninterface UseZoomReturn {\n scale: number;\n isPinching: boolean;\n handleWheel: (event: ReactWheelEvent<Element>) => void;\n handleTouchStart: (event: ReactTouchEvent<HTMLCanvasElement>) => boolean;\n reset: () => void;\n}\n\nconst clamp = (value: number, min: number, max: number) =>\n Math.min(Math.max(value, min), max);\n\nconst getTouchDistance = (touches: TouchList | React.TouchList) => {\n const first = touches[0];\n const second = touches[1];\n if (!first || !second) return 0;\n return Math.hypot(\n second.clientX - first.clientX,\n second.clientY - first.clientY\n );\n};\n\nexport const useZoomPan = ({\n displayWidth,\n displayHeight,\n minScale = 0.5,\n maxScale = 2.5,\n initialScale = 1,\n}: UseZoomOptions = {}): UseZoomReturn => {\n const [scale, setScale] = useState(initialScale);\n const [isPinching, setIsPinching] = useState(false);\n\n const scaleRef = useRef(initialScale);\n const pinchDataRef = useRef({\n initialDistance: 0,\n initialScale: 1,\n });\n\n const setScaleSafe = useCallback(\n (next: number) => {\n const clamped = clamp(next, minScale, maxScale);\n if (clamped === scaleRef.current) return;\n\n scaleRef.current = clamped;\n setScale(clamped);\n },\n [minScale, maxScale]\n );\n\n const handleWheel = useCallback(\n (event: ReactWheelEvent<Element>) => {\n event.preventDefault();\n event.stopPropagation();\n\n const deltaY =\n event.deltaMode === 1\n ? event.deltaY * 16\n : event.deltaMode === 2\n ? event.deltaY * (displayHeight ?? 300)\n : event.deltaY;\n\n const zoomFactor = Math.exp(-deltaY * 0.0015);\n const nextScale = scaleRef.current * zoomFactor;\n setScaleSafe(nextScale);\n },\n [setScaleSafe, displayHeight]\n );\n\n const handleTouchStart = useCallback(\n (event: ReactTouchEvent<HTMLCanvasElement>) => {\n if (event.touches.length < 2) {\n return false;\n }\n\n const distance = getTouchDistance(event.touches);\n if (!distance) {\n return false;\n }\n\n pinchDataRef.current = {\n initialDistance: distance,\n initialScale: scaleRef.current,\n };\n setIsPinching(true);\n event.preventDefault();\n return true;\n },\n []\n );\n\n useEffect(() => {\n if (!isPinching) return;\n\n const handleMove = (event: TouchEvent) => {\n if (event.touches.length < 2) return;\n const distance = getTouchDistance(event.touches);\n if (!distance || pinchDataRef.current.initialDistance === 0) return;\n\n const scaleFactor =\n distance / pinchDataRef.current.initialDistance;\n const nextScale = pinchDataRef.current.initialScale * scaleFactor;\n setScaleSafe(nextScale);\n event.preventDefault();\n };\n\n const handleEnd = (event: TouchEvent) => {\n if (event.touches.length < 2) {\n setIsPinching(false);\n }\n };\n\n window.addEventListener(\"touchmove\", handleMove, { passive: false });\n window.addEventListener(\"touchend\", handleEnd);\n window.addEventListener(\"touchcancel\", handleEnd);\n\n return () => {\n window.removeEventListener(\"touchmove\", handleMove);\n window.removeEventListener(\"touchend\", handleEnd);\n window.removeEventListener(\"touchcancel\", handleEnd);\n };\n }, [isPinching, setScaleSafe]);\n\n const reset = useCallback(() => {\n scaleRef.current = initialScale;\n setScale(initialScale);\n }, [initialScale]);\n\n return {\n scale,\n isPinching,\n handleWheel,\n handleTouchStart,\n reset,\n };\n};\n\n","import { useRef, useState, useCallback, useEffect, useMemo } from \"react\";\nimport { useSpriteScrubbing } from \"./hooks/useSpriteScrubbing\";\nimport { useBouncePatternProgress } from \"./hooks/useProgressOneSecond\";\nimport { useContinuousSpin } from \"./hooks/useContinuousSpin\";\nimport { useSpriteRender, SpriteRenderInput } from \"./hooks/useSpriteRender\";\nimport { BuildRenderProps } from \"./types\";\nimport { LoadingErrorOverlay } from \"./components/LoadingErrorOverlay\";\nimport { InstructionTooltip } from \"./components/InstructionTooltip\";\nimport { useZoomPan } from \"./hooks/useZoomPan\";\nimport type { WheelEvent as ReactWheelEvent } from \"react\";\n\nexport const BuildRender: React.FC<BuildRenderProps> = ({\n parts,\n shareCode,\n width,\n height,\n size,\n apiConfig,\n useSpriteRenderOptions,\n mouseSensitivity = 0.2,\n touchSensitivity = 0.2,\n showGrid,\n cameraOffsetX,\n cameraZoom,\n gridSettings,\n animationMode = 'bounce',\n spinDuration = 10000,\n interactive = true,\n frameQuality,\n zoom = 1,\n}) => {\n const canvasRef = useRef<HTMLCanvasElement | null>(null);\n const containerRef = useRef<HTMLDivElement | null>(null);\n const [img, setImg] = useState<HTMLImageElement | null>(null);\n const [isLoading, setIsLoading] = useState(true);\n const [bouncingAllowed, setBouncingAllowed] = useState(false);\n\n const displayW = width ?? size ?? 300;\n const displayH = height ?? size ?? 300;\n\n // Build the render input - prefer shareCode if provided (preserves interactive state like case fan slots)\n const renderInput: SpriteRenderInput = useMemo(() => {\n if (shareCode) {\n return { \n type: 'shareCode', \n shareCode, \n profile: parts?.profile,\n showGrid,\n cameraOffsetX,\n cameraZoom,\n gridSettings,\n frameQuality,\n };\n }\n return { \n type: 'parts', \n parts: parts!,\n showGrid,\n cameraOffsetX,\n cameraZoom,\n gridSettings,\n frameQuality,\n };\n }, [shareCode, parts, showGrid, cameraOffsetX, cameraZoom, gridSettings, frameQuality]);\n\n // Use custom hook for sprite rendering\n const { spriteSrc, isRenderingSprite, renderError, spriteMetadata } =\n useSpriteRender(renderInput, apiConfig, undefined, useSpriteRenderOptions);\n\n const total = spriteMetadata ? spriteMetadata.totalFrames : 72;\n\n // Animation hooks - only one will be active based on animationMode\n const { value: progressValue, isBouncing } =\n useBouncePatternProgress(bouncingAllowed && animationMode === 'bounce');\n \n const spinResult = useContinuousSpin(\n bouncingAllowed && animationMode === 'spin360',\n spinDuration,\n total\n );\n const cols = spriteMetadata ? spriteMetadata.cols : 12;\n const rows = spriteMetadata ? spriteMetadata.rows : 6;\n const frameRef = useRef(0);\n\n const {\n scale,\n handleWheel: handleZoomWheel,\n handleTouchStart: handleZoomTouchStart,\n reset: resetZoom,\n } = useZoomPan({\n displayWidth: displayW,\n displayHeight: displayH,\n initialScale: zoom,\n });\n\n // Image/frame sizes - only calculate if image dimensions match expected metadata\n // This prevents using stale image with new metadata during transitions\n const frameW = img ? img.width / cols : 0;\n const frameH = img ? img.height / rows : 0;\n \n // Track expected rows to detect stale images\n const expectedRowsRef = useRef(rows);\n expectedRowsRef.current = rows;\n\n // ---- Load sprite image ----\n useEffect(() => {\n if (!spriteSrc) {\n setImg(null);\n setIsLoading(true);\n return;\n }\n\n // Clear current image immediately when source changes to prevent \n // using old image with new metadata\n setImg(null);\n setIsLoading(true);\n setBouncingAllowed(false);\n \n const i = new Image();\n i.decoding = \"async\";\n i.loading = \"eager\";\n i.src = spriteSrc;\n i.onload = () => {\n // Only set the image if rows haven't changed since we started loading\n // This prevents race conditions where metadata updates mid-load\n setImg(i);\n setIsLoading(false);\n // Start bouncing animation after delay\n setTimeout(() => {\n setBouncingAllowed(true);\n }, 2000);\n };\n i.onerror = () => {\n setImg(null);\n setIsLoading(false);\n };\n \n // Cleanup: if this effect re-runs (due to spriteSrc or rows change), \n // the new effect will clear the image\n return () => {\n // Abort loading if component updates before load completes\n i.onload = null;\n i.onerror = null;\n };\n }, [spriteSrc, rows]);\n\n // ---- Drawing function with optional cross-fade interpolation ----\n const draw = useCallback(\n (frameIndex: number, nextFrameIndex?: number, blend?: number) => {\n const cnv = canvasRef.current;\n if (!cnv || !img || !frameW || !frameH) return;\n\n const ctx = cnv.getContext(\"2d\");\n if (!ctx) return;\n\n // Backing store sized for HiDPI; CSS size stays `size`\n const dpr = Math.max(1, window.devicePixelRatio || 1);\n const targetW = Math.round(displayW * dpr);\n const targetH = Math.round(displayH * dpr);\n if (cnv.width !== targetW || cnv.height !== targetH) {\n cnv.width = targetW;\n cnv.height = targetH;\n }\n\n // Calculate destination dimensions (letterboxing)\n const sw = Math.round(frameW);\n const sh = Math.round(frameH);\n const frameAspect = sw / sh;\n const canvasAspect = targetW / targetH;\n\n let drawW: number, drawH: number;\n if (frameAspect > canvasAspect) {\n drawW = targetW;\n drawH = targetW / frameAspect;\n } else {\n drawH = targetH;\n drawW = targetH * frameAspect;\n }\n\n // Apply zoom scale\n drawW *= scale;\n drawH *= scale;\n\n // Center in canvas\n const drawX = (targetW - drawW) / 2;\n const drawY = (targetH - drawH) / 2;\n\n ctx.clearRect(0, 0, targetW, targetH);\n ctx.imageSmoothingEnabled = true;\n ctx.imageSmoothingQuality = \"high\";\n\n // Helper to draw a specific frame\n const drawFrame = (frameIdx: number, opacity: number) => {\n let n = Math.round(frameIdx) % total;\n if (n < 0) n += total;\n \n const r = Math.floor(n / cols);\n const c = n % cols;\n const sx = Math.round(c * frameW);\n const sy = Math.round(r * frameH);\n\n ctx.globalAlpha = opacity;\n ctx.drawImage(img, sx, sy, sw, sh, drawX, drawY, drawW, drawH);\n };\n\n // Cross-fade interpolation for smooth animation\n if (nextFrameIndex !== undefined && blend !== undefined && blend > 0.01) {\n // Draw current frame at full opacity first\n drawFrame(frameIndex, 1);\n // Then overlay next frame with blend opacity for smooth transition\n drawFrame(nextFrameIndex, blend);\n ctx.globalAlpha = 1; // Reset\n } else {\n // Single frame draw (no interpolation)\n drawFrame(frameIndex, 1);\n }\n },\n [img, frameW, frameH, displayW, displayH, cols, rows, total, scale]\n );\n\n const { isDragging, handleMouseDown, handleTouchStart, hasDragged } =\n useSpriteScrubbing(canvasRef, total, {\n mouseSensitivity,\n touchSensitivity,\n onFrameChange: (newFrame: number) => {\n frameRef.current = newFrame;\n draw(newFrame);\n },\n });\n\n const handleLoadStartInternal = useCallback(() => {\n setIsLoading(true);\n setBouncingAllowed(false);\n }, []);\n\n // Auto-rotate when animation is allowed and user hasn't manually dragged\n useEffect(() => {\n if ((interactive && hasDragged.current) || !img) return;\n\n if (animationMode === 'spin360') {\n // Continuous 360 spin with cross-fade interpolation for smoothness\n frameRef.current = spinResult.frame;\n draw(spinResult.frame, spinResult.nextFrame, spinResult.blend);\n } else {\n // Bounce animation (no interpolation needed - it pauses between movements)\n const frame = ((progressValue / 5) * total) % total;\n frameRef.current = frame;\n draw(frame);\n }\n }, [progressValue, spinResult, hasDragged, img, total, draw, animationMode, interactive]);\n\n // Reset zoom when sprite changes or container size updates\n useEffect(() => {\n resetZoom();\n }, [spriteSrc, displayW, displayH, resetZoom]);\n\n // Add native wheel event listener to prevent scrolling AND handle zoom (only when interactive)\n useEffect(() => {\n const container = containerRef.current;\n if (!container || !interactive) return;\n\n const handleNativeWheel = (event: WheelEvent) => {\n event.preventDefault();\n event.stopPropagation();\n \n // Manually trigger zoom since we're preventing the React event\n const deltaY =\n event.deltaMode === 1\n ? event.deltaY * 16\n : event.deltaMode === 2\n ? event.deltaY * (displayH ?? 300)\n : event.deltaY;\n\n const zoomFactor = Math.exp(-deltaY * 0.0015);\n const nextScale = scale * zoomFactor;\n \n // We need to call the zoom handler directly\n // Create a synthetic React event-like object\n const syntheticEvent = {\n preventDefault: () => {},\n stopPropagation: () => {},\n deltaY: event.deltaY,\n deltaMode: event.deltaMode,\n currentTarget: container,\n } as any;\n \n handleZoomWheel(syntheticEvent);\n hasDragged.current = true;\n };\n\n // Add listener to container to catch all wheel events\n container.addEventListener('wheel', handleNativeWheel, { passive: false });\n\n return () => {\n container.removeEventListener('wheel', handleNativeWheel);\n };\n }, [handleZoomWheel, scale, displayH, interactive]);\n\n // Initial draw once image is ready or zoom changes\n useEffect(() => {\n if (img && !isLoading) {\n draw(frameRef.current);\n }\n }, [img, isLoading, draw]);\n\n const handleCanvasTouchStart = useCallback(\n (event: React.TouchEvent<HTMLCanvasElement>) => {\n if (handleZoomTouchStart(event)) {\n hasDragged.current = true;\n return;\n }\n\n handleTouchStart(event);\n },\n [handleZoomTouchStart, handleTouchStart, hasDragged]\n );\n\n const handleCanvasWheel = useCallback(\n (event: ReactWheelEvent<Element>) => {\n hasDragged.current = true;\n handleZoomWheel(event);\n },\n [handleZoomWheel, hasDragged]\n );\n\n return (\n <div\n ref={containerRef}\n style={{\n position: \"relative\",\n width: displayW,\n height: displayH,\n backgroundColor: \"black\",\n overflow: \"hidden\",\n }}\n >\n {img && (\n <canvas\n ref={canvasRef}\n onMouseDown={interactive ? handleMouseDown : undefined}\n onTouchStart={interactive ? handleCanvasTouchStart : undefined}\n style={{\n width: displayW,\n height: displayH,\n cursor: interactive ? (isDragging ? \"grabbing\" : \"grab\") : \"pointer\",\n touchAction: interactive ? \"none\" : \"auto\",\n display: \"block\",\n userSelect: \"none\",\n WebkitUserSelect: \"none\",\n WebkitTouchCallout: \"none\",\n pointerEvents: interactive ? \"auto\" : \"none\", // Allow click-through when not interactive\n }}\n role=\"img\"\n aria-label=\"360° viewer\"\n onContextMenu={interactive ? (e) => e.preventDefault() : undefined}\n />\n )}\n\n <LoadingErrorOverlay\n isVisible={isLoading || isRenderingSprite || !!renderError}\n renderError={renderError || undefined}\n size={Math.min(displayW, displayH)}\n />\n\n <InstructionTooltip\n isVisible={\n interactive &&\n animationMode === 'bounce' &&\n !isLoading &&\n !isRenderingSprite &&\n !renderError &&\n isBouncing &&\n !hasDragged.current\n }\n progressValue={progressValue}\n />\n </div>\n );\n};\n","import {\n useState,\n useRef,\n useEffect,\n useCallback,\n type RefObject,\n} from \"react\";\n\n// Helper to extract clientX from mouse or touch events\nconst getClientX = (e: MouseEvent | TouchEvent): number => {\n return \"touches\" in e ? e.touches[0].clientX : e.clientX;\n};\n\n// Helper to calculate new video time with circular wrapping\nexport const calculateCircularTime = (\n startTime: number,\n deltaX: number,\n sensitivity: number,\n duration: number\n): number => {\n const timeDelta = deltaX * sensitivity;\n let newTime = startTime + timeDelta;\n\n // Make it circular - wrap around when going past boundaries\n newTime = newTime % duration;\n if (newTime < 0) {\n newTime += duration;\n }\n\n return newTime;\n};\n\ninterface UseVideoScrubbingOptions {\n mouseSensitivity?: number;\n touchSensitivity?: number;\n progressSensitivity?: number;\n useProgressScrubbing?: boolean;\n}\n\nexport const useVideoScrubbing = (\n videoRef: RefObject<HTMLVideoElement | null>,\n options: UseVideoScrubbingOptions = {}\n) => {\n const { mouseSensitivity = 0.01, touchSensitivity = 0.01 } = options;\n\n const [isDragging, setIsDragging] = useState(false);\n const [dragStartX, setDragStartX] = useState(0);\n const [dragStartTime, setDragStartTime] = useState(0);\n const hasDragged = useRef(false);\n\n // Helper to start dragging (common logic for mouse and touch)\n const startDrag = useCallback(\n (clientX: number, event: Event) => {\n if (!videoRef.current) return;\n\n setIsDragging(true);\n setDragStartX(clientX);\n setDragStartTime(videoRef.current.currentTime);\n hasDragged.current = true;\n event.preventDefault();\n },\n [videoRef]\n );\n\n // Helper to handle drag movement (common logic for mouse and touch)\n const handleDragMove = useCallback(\n (clientX: number, sensitivity: number) => {\n if (!isDragging || !videoRef.current) return;\n\n const deltaX = clientX - dragStartX;\n const duration = videoRef.current.duration || 0;\n\n if (duration > 0) {\n const newTime = calculateCircularTime(\n dragStartTime,\n deltaX,\n sensitivity,\n duration\n );\n videoRef.current.currentTime = newTime;\n }\n },\n [isDragging, dragStartX, dragStartTime, videoRef]\n );\n\n // Helper to end dragging (common logic for mouse and touch)\n const endDrag = useCallback(() => {\n setIsDragging(false);\n }, []);\n\n const handleMouseDown = useCallback(\n (e: React.MouseEvent) => {\n startDrag(e.clientX, e.nativeEvent);\n },\n [startDrag]\n );\n\n const handleTouchStart = useCallback(\n (e: React.TouchEvent) => {\n startDrag(e.touches[0].clientX, e.nativeEvent);\n },\n [startDrag]\n );\n\n const handleDocumentMouseMove = useCallback(\n (e: MouseEvent) => {\n handleDragMove(getClientX(e), mouseSensitivity);\n },\n [handleDragMove, mouseSensitivity]\n );\n\n const handleDocumentTouchMove = useCallback(\n (e: TouchEvent) => {\n handleDragMove(getClientX(e), touchSensitivity);\n },\n [handleDragMove, touchSensitivity]\n );\n\n const handleDocumentMouseUp = useCallback(() => {\n endDrag();\n }, [endDrag]);\n\n const handleDocumentTouchEnd = useCallback(() => {\n endDrag();\n }, [endDrag]);\n\n // Add document-level event listeners when dragging starts\n useEffect(() => {\n if (isDragging) {\n document.addEventListener(\"mousemove\", handleDocumentMouseMove);\n document.addEventListener(\"mouseup\", handleDocumentMouseUp);\n document.addEventListener(\"touchmove\", handleDocumentTouchMove);\n document.addEventListener(\"touchend\", handleDocumentTouchEnd);\n\n return () => {\n document.removeEventListener(\"mousemove\", handleDocumentMouseMove);\n document.removeEventListener(\"mouseup\", handleDocumentMouseUp);\n document.removeEventListener(\"touchmove\", handleDocumentTouchMove);\n document.removeEventListener(\"touchend\", handleDocumentTouchEnd);\n };\n }\n }, [\n isDragging,\n handleDocumentMouseMove,\n handleDocumentMouseUp,\n handleDocumentTouchMove,\n handleDocumentTouchEnd,\n ]);\n\n return {\n isDragging,\n handleMouseDown,\n handleTouchStart,\n hasDragged,\n };\n};\n","import { useRef, useState, useCallback, useEffect } from \"react\";\nimport {\n calculateCircularTime,\n useVideoScrubbing,\n} from \"./hooks/useVideoScrubbing\";\nimport { useBouncePatternProgress } from \"./hooks/useProgressOneSecond\";\nimport { useBuildRender } from \"./hooks/useBuildRender\";\nimport { BuildRenderVideoProps } from \"./types\";\nimport { LoadingErrorOverlay } from \"./components/LoadingErrorOverlay\";\nimport { InstructionTooltip } from \"./components/InstructionTooltip\";\n\nexport const BuildRenderVideo: React.FC<BuildRenderVideoProps> = ({\n parts,\n width,\n height,\n size,\n apiConfig,\n useBuildRenderOptions,\n mouseSensitivity = 0.01,\n touchSensitivity = 0.01,\n}) => {\n const videoRef = useRef<HTMLVideoElement | null>(null);\n const [isLoading, setIsLoading] = useState(true);\n const [bouncingAllowed, setBouncingAllowed] = useState(false);\n\n const displayW = width ?? size ?? 300;\n const displayH = height ?? size ?? 300;\n\n // Use custom hook for build rendering\n const { videoSrc, isRenderingBuild, renderError } = useBuildRender(\n parts,\n apiConfig,\n undefined,\n useBuildRenderOptions\n );\n\n const { value: progressValue, isBouncing } =\n useBouncePatternProgress(bouncingAllowed);\n\n const { isDragging, handleMouseDown, handleTouchStart, hasDragged } =\n useVideoScrubbing(videoRef, {\n mouseSensitivity,\n touchSensitivity,\n });\n\n const handleLoadStartInternal = useCallback(() => {\n setIsLoading(true);\n setBouncingAllowed(false);\n }, []);\n\n const handleCanPlayInternal = useCallback(() => {\n setIsLoading(false);\n // Start bouncing animation after delay\n setTimeout(() => {\n setBouncingAllowed(true);\n }, 2000);\n }, []);\n\n useEffect(() => {\n if (hasDragged.current || !videoRef.current) return;\n\n const duration = videoRef.current.duration;\n if (!isFinite(duration)) return;\n\n const time = calculateCircularTime(0, progressValue, 0.5, duration);\n\n if (isFinite(time)) {\n videoRef.current.currentTime = time;\n }\n }, [progressValue, hasDragged]);\n\n return (\n <div style={{ position: \"relative\", width: displayW, height: displayH }}>\n {videoSrc && (\n <video\n key={videoSrc} // Force React to recreate video element when src changes\n ref={videoRef}\n src={videoSrc} // Set src directly on video element\n width={displayW}\n height={displayH}\n autoPlay={true}\n preload=\"metadata\"\n muted\n playsInline\n controls={false}\n disablePictureInPicture\n controlsList=\"nodownload nofullscreen noremoteplayback\"\n {...({ \"x-webkit-airplay\": \"deny\" } as any)}\n onMouseDown={handleMouseDown}\n onTouchStart={handleTouchStart}\n onLoadStart={handleLoadStartInternal}\n onCanPlay={handleCanPlayInternal}\n onLoadedData={() => {\n if (videoRef.current) {\n videoRef.current.pause();\n }\n }}\n style={\n {\n cursor: isDragging ? \"grabbing\" : \"grab\",\n touchAction: \"none\", // Prevents default touch behaviors like scrolling\n display: \"block\",\n // Completely hide video controls on all browsers including mobile\n WebkitMediaControls: \"none\",\n MozMediaControls: \"none\",\n OMediaControls: \"none\",\n msMediaControls: \"none\",\n mediaControls: \"none\",\n // Additional iOS-specific properties\n WebkitTouchCallout: \"none\",\n WebkitUserSelect: \"none\",\n userSelect: \"none\",\n } as React.CSSProperties\n }\n >\n Your browser does not support the video tag.\n </video>\n )}\n\n <LoadingErrorOverlay\n isVisible={isLoading || isRenderingBuild || !!renderError}\n renderError={renderError || undefined}\n size={Math.min(displayW, displayH)}\n />\n\n <InstructionTooltip\n isVisible={\n !isLoading &&\n !isRenderingBuild &&\n !renderError &&\n isBouncing &&\n !hasDragged.current\n }\n progressValue={progressValue}\n />\n </div>\n );\n};\n"],"names":["getClientX","useState","useRef","useCallback","useEffect","useAnimationFrame","PartCategory","_jsx","_jsxs","_Fragment","useMemo"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/hooks/useSpriteScrubbing.ts","../src/hooks/useProgressOneSecond.ts","../src/hooks/useContinuousSpin.ts","../src/api.ts","../src/types.ts","../src/hooks/useBuildRender.ts","../src/hooks/useSpriteRender.ts","../src/components/LoadingErrorOverlay.tsx","../src/components/DragIcon.tsx","../src/components/InstructionTooltip.tsx","../src/hooks/useZoomPan.ts","../src/BuildRender.tsx","../src/hooks/useVideoScrubbing.ts","../src/BuildRenderVideo.tsx"],"sourcesContent":["import {\n useState,\n useRef,\n useEffect,\n useCallback,\n type RefObject,\n} from \"react\";\n\n// Helper to extract clientX from mouse or touch events\nconst getClientX = (e: MouseEvent | TouchEvent): number => {\n return \"touches\" in e ? e.touches[0].clientX : e.clientX;\n};\n\n// Helper to calculate new frame with circular wrapping\nexport const calculateCircularFrame = (\n startFrame: number,\n deltaX: number,\n sensitivity: number,\n totalFrames: number\n): number => {\n const frameDelta = deltaX * sensitivity;\n let newFrame = startFrame + frameDelta;\n\n // Make it circular - wrap around when going past boundaries\n newFrame = newFrame % totalFrames;\n if (newFrame < 0) {\n newFrame += totalFrames;\n }\n\n return newFrame;\n};\n\ninterface UseSpiteScrubbingOptions {\n mouseSensitivity?: number;\n touchSensitivity?: number;\n onFrameChange?: (frame: number) => void;\n}\n\nexport const useSpriteScrubbing = (\n canvasRef: RefObject<HTMLCanvasElement | null>,\n totalFrames: number,\n options: UseSpiteScrubbingOptions = {}\n) => {\n const {\n mouseSensitivity = 0.1,\n touchSensitivity = 0.1,\n onFrameChange,\n } = options;\n\n const [isDragging, setIsDragging] = useState(false);\n const [dragStartX, setDragStartX] = useState(0);\n const [dragStartFrame, setDragStartFrame] = useState(0);\n const hasDragged = useRef(false);\n const currentFrame = useRef(0);\n\n // Helper to start dragging (common logic for mouse and touch)\n const startDrag = useCallback(\n (clientX: number, event: Event) => {\n if (!canvasRef.current) return;\n\n setIsDragging(true);\n setDragStartX(clientX);\n setDragStartFrame(currentFrame.current);\n hasDragged.current = true;\n event.preventDefault();\n },\n [canvasRef]\n );\n\n // Helper to handle drag movement (common logic for mouse and touch)\n const handleDragMove = useCallback(\n (clientX: number, sensitivity: number) => {\n if (!isDragging || !canvasRef.current) return;\n\n const deltaX = clientX - dragStartX;\n\n const newFrame = calculateCircularFrame(\n dragStartFrame,\n deltaX, // Positive for natural \"spin right\" feel\n sensitivity,\n totalFrames\n );\n\n currentFrame.current = newFrame;\n\n // Call the frame change callback if provided\n if (onFrameChange) {\n onFrameChange(newFrame);\n }\n\n return newFrame;\n },\n [isDragging, dragStartX, dragStartFrame, totalFrames, onFrameChange]\n );\n\n // Helper to end dragging (common logic for mouse and touch)\n const endDrag = useCallback(() => {\n setIsDragging(false);\n }, []);\n\n const handleMouseDown = useCallback(\n (e: React.MouseEvent) => {\n startDrag(e.clientX, e.nativeEvent);\n },\n [startDrag]\n );\n\n const handleTouchStart = useCallback(\n (e: React.TouchEvent) => {\n startDrag(e.touches[0].clientX, e.nativeEvent);\n },\n [startDrag]\n );\n\n const handleDocumentMouseMove = useCallback(\n (e: MouseEvent) => {\n return handleDragMove(getClientX(e), mouseSensitivity);\n },\n [handleDragMove, mouseSensitivity]\n );\n\n const handleDocumentTouchMove = useCallback(\n (e: TouchEvent) => {\n return handleDragMove(getClientX(e), touchSensitivity);\n },\n [handleDragMove, touchSensitivity]\n );\n\n const handleDocumentMouseUp = useCallback(() => {\n endDrag();\n }, [endDrag]);\n\n const handleDocumentTouchEnd = useCallback(() => {\n endDrag();\n }, [endDrag]);\n\n // Add document-level event listeners when dragging starts\n useEffect(() => {\n if (isDragging) {\n document.addEventListener(\"mousemove\", handleDocumentMouseMove);\n document.addEventListener(\"mouseup\", handleDocumentMouseUp);\n document.addEventListener(\"touchmove\", handleDocumentTouchMove);\n document.addEventListener(\"touchend\", handleDocumentTouchEnd);\n\n return () => {\n document.removeEventListener(\"mousemove\", handleDocumentMouseMove);\n document.removeEventListener(\"mouseup\", handleDocumentMouseUp);\n document.removeEventListener(\"touchmove\", handleDocumentTouchMove);\n document.removeEventListener(\"touchend\", handleDocumentTouchEnd);\n };\n }\n }, [\n isDragging,\n handleDocumentMouseMove,\n handleDocumentMouseUp,\n handleDocumentTouchMove,\n handleDocumentTouchEnd,\n ]);\n\n return {\n isDragging,\n handleMouseDown,\n handleTouchStart,\n hasDragged,\n currentFrame: currentFrame.current,\n setCurrentFrame: (frame: number) => {\n currentFrame.current = frame;\n },\n };\n};\n","import { useAnimationFrame } from \"framer-motion\";\nimport { useRef, useState } from \"react\";\n\nexport function useBouncePatternProgress(enabled = true) {\n const [value, setValue] = useState(0);\n const [isBouncing, setIsBouncing] = useState(false);\n const start = useRef<number | null>(null);\n\n useAnimationFrame((t) => {\n if (!enabled) {\n // Reset animation when disabled\n if (start.current !== null) {\n start.current = null;\n setValue(0);\n setIsBouncing(false);\n }\n return;\n }\n\n if (start.current === null) start.current = t;\n\n const elapsed = (t - start.current) % 3000; // 3s full cycle\n\n let progress = 0;\n const bouncing = elapsed < 1000; // Bouncing during first 1 second\n\n if (elapsed < 500) {\n // 0 → 1\n progress = elapsed / 500;\n } else if (elapsed < 1000) {\n // 1 → 0\n progress = 1 - (elapsed - 500) / 500;\n } else {\n // Pause at 0 for 2 seconds\n progress = 0;\n }\n\n setValue(progress);\n setIsBouncing(bouncing);\n });\n\n return { value, isBouncing };\n}\n","import { useAnimationFrame } from \"framer-motion\";\nimport { useRef, useState, useEffect } from \"react\";\n\nexport interface ContinuousSpinResult {\n /** Current frame index (integer part) */\n frame: number;\n /** Next frame index for interpolation */\n nextFrame: number;\n /** Blend factor between frames (0-1), used for cross-fade interpolation */\n blend: number;\n}\n\n/**\n * Hook for continuous 360° spin animation with smooth interpolation support.\n * \n * @param enabled - Whether the animation is enabled\n * @param duration - Duration in ms for one full rotation (default: 10000ms = 10 seconds)\n * @param totalFrames - Total number of frames in the sprite (default: 72)\n * @returns Object with current frame, next frame, and blend factor for smooth interpolation\n */\nexport function useContinuousSpin(\n enabled = true,\n duration = 10000,\n totalFrames = 72\n): ContinuousSpinResult {\n const [result, setResult] = useState<ContinuousSpinResult>({ \n frame: 0, \n nextFrame: 1, \n blend: 0 \n });\n const startTime = useRef<number | null>(null);\n \n // Use refs to avoid stale closures in useAnimationFrame\n const totalFramesRef = useRef(totalFrames);\n const durationRef = useRef(duration);\n \n // Keep refs in sync with props\n useEffect(() => {\n totalFramesRef.current = totalFrames;\n }, [totalFrames]);\n \n useEffect(() => {\n durationRef.current = duration;\n }, [duration]);\n\n useAnimationFrame((time) => {\n if (!enabled) {\n if (startTime.current !== null) {\n startTime.current = null;\n }\n return;\n }\n\n if (startTime.current === null) {\n startTime.current = time;\n }\n\n const elapsed = time - startTime.current;\n const currentDuration = durationRef.current;\n const currentTotalFrames = totalFramesRef.current;\n \n // Calculate progress through the full rotation (0 to 1)\n const progress = (elapsed % currentDuration) / currentDuration;\n // Convert to fractional frame position\n const exactFrame = progress * currentTotalFrames;\n const currentFrame = Math.floor(exactFrame) % currentTotalFrames;\n const nextFrame = (currentFrame + 1) % currentTotalFrames;\n // Blend is the fractional part - how far between current and next frame\n const blend = exactFrame - Math.floor(exactFrame);\n \n setResult({ frame: currentFrame, nextFrame, blend });\n });\n\n return result;\n}\n","import { \n RenderBuildRequest, \n AvailablePartsResponse, \n ApiConfig, \n PartCategory, \n GetAvailablePartsOptions,\n BuildResponse,\n PartsResponse,\n RenderByShareCodeOptions,\n RenderByShareCodeJobResponse,\n RenderByShareCodeResponse,\n} from \"./types\";\n\n// API Configuration\nconst API_BASE_URL = \"https://www.renderapi.buildcores.com\";\n\n// API Endpoints\nexport const API_ENDPOINTS = {\n RENDER_BUILD_EXPERIMENTAL: \"/render-build-experimental\",\n RENDER_BUILD: \"/render-build\",\n AVAILABLE_PARTS: \"/available-parts\",\n BUILD: \"/build\",\n PARTS: \"/parts\",\n RENDER_BY_SHARE_CODE: \"/render-by-share-code\",\n} as const;\n\n// API Response Types\nexport interface RenderBuildResponse {\n /**\n * The rendered MP4 video as a Blob (when format is \"video\")\n */\n video: Blob;\n /**\n * Optional metadata about the render\n */\n metadata?: {\n duration?: number;\n size?: number;\n format?: string;\n };\n}\n\n// Async render job types (new endpoints)\nexport interface RenderJobCreateResponse {\n job_id: string;\n status: \"queued\" | \"processing\" | \"completed\" | \"error\";\n}\n\nexport interface RenderJobStatusResponse {\n job_id: string;\n status: \"queued\" | \"processing\" | \"completed\" | \"error\";\n url?: string | null;\n video_url?: string | null;\n sprite_url?: string | null;\n screenshot_url?: string | null;\n error?: string | null;\n end_time?: string | null;\n}\n\nexport interface RenderBuildAsyncResponse {\n /** Final URL to the rendered MP4 (or sprite) asset */\n videoUrl: string;\n}\n\nexport interface RenderSpriteResponse {\n /**\n * The rendered sprite sheet as a Blob (when format is \"sprite\")\n */\n sprite: Blob;\n /**\n * Sprite sheet metadata\n */\n metadata?: {\n cols?: number;\n rows?: number;\n totalFrames?: number;\n size?: number;\n format?: string;\n };\n}\n\n// API Functions (definitions only - not implemented yet)\nexport interface RenderAPIService {\n /**\n * Submit a render build request\n * @param parts - The parts configuration for the build\n * @param config - API configuration (environment, auth token) - required\n * @returns Promise with the rendered MP4 video\n */\n renderBuildExperimental(\n parts: RenderBuildRequest,\n config: ApiConfig\n ): Promise<RenderBuildResponse>;\n\n /**\n * Get available parts for building\n * @param config - API configuration (environment, auth token) - required\n * @returns Promise with available parts by category\n */\n getAvailableParts(\n category: PartCategory,\n config: ApiConfig,\n options?: GetAvailablePartsOptions\n ): Promise<AvailablePartsResponse>;\n}\n\n// API URL helpers\nexport const buildApiUrl = (endpoint: string, config: ApiConfig): string => {\n const baseUrl = `${API_BASE_URL}${endpoint}`;\n if (config.environment) {\n const separator = endpoint.includes(\"?\") ? \"&\" : \"?\";\n return `${baseUrl}${separator}environment=${config.environment}`;\n }\n return baseUrl;\n};\n\ntype SessionTokenSupplier = NonNullable<ApiConfig[\"getRenderSessionToken\"]>;\ntype SessionTokenCacheEntry = {\n token: string;\n expiresAtMs: number;\n};\n\nconst SESSION_TOKEN_REFRESH_WINDOW_MS = 15_000;\nconst sessionTokenCache = new WeakMap<SessionTokenSupplier, SessionTokenCacheEntry>();\n\nconst resolveAuthMode = (config: ApiConfig): \"legacy\" | \"session\" =>\n config.authMode ?? (config.getRenderSessionToken ? \"session\" : \"legacy\");\n\nconst isSessionAuthMode = (config: ApiConfig): boolean => resolveAuthMode(config) === \"session\";\n\nconst parseExpiresAtMs = (expiresAt: string): number => {\n const parsed = Date.parse(expiresAt);\n if (!Number.isFinite(parsed)) {\n throw new Error(\"Invalid session token expiry (expiresAt)\");\n }\n return parsed;\n};\n\nconst resolveSessionToken = async (config: ApiConfig, forceRefresh: boolean): Promise<string> => {\n const supplier = config.getRenderSessionToken;\n if (!supplier) {\n throw new Error(\"authMode=session requires getRenderSessionToken\");\n }\n\n const cached = sessionTokenCache.get(supplier);\n const now = Date.now();\n if (\n !forceRefresh &&\n cached &&\n cached.expiresAtMs - SESSION_TOKEN_REFRESH_WINDOW_MS > now\n ) {\n return cached.token;\n }\n\n const session = await supplier();\n if (!session?.token || !session?.expiresAt) {\n throw new Error(\"getRenderSessionToken must return { token, expiresAt }\");\n }\n\n const expiresAtMs = parseExpiresAtMs(session.expiresAt);\n sessionTokenCache.set(supplier, {\n token: session.token,\n expiresAtMs,\n });\n return session.token;\n};\n\nconst resolveAuthToken = async (config: ApiConfig, forceRefresh: boolean): Promise<string | undefined> => {\n if (isSessionAuthMode(config)) {\n return resolveSessionToken(config, forceRefresh);\n }\n return config.authToken;\n};\n\n// Helper to build request headers with auth token\nexport const buildHeaders = (\n config: ApiConfig,\n authTokenOverride?: string\n): Record<string, string> => {\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n accept: \"application/json\",\n };\n\n const authToken = authTokenOverride ?? config.authToken;\n if (authToken) {\n headers[\"Authorization\"] = `Bearer ${authToken}`;\n }\n\n return headers;\n};\n\nconst fetchWithApiAuth = async (\n url: string,\n init: RequestInit,\n config: ApiConfig\n): Promise<Response> => {\n const firstToken = await resolveAuthToken(config, false);\n const firstResponse = await fetch(url, {\n ...init,\n headers: buildHeaders(config, firstToken),\n });\n\n if (!isSessionAuthMode(config) || firstResponse.status !== 401) {\n return firstResponse;\n }\n\n const refreshedToken = await resolveAuthToken(config, true);\n return fetch(url, {\n ...init,\n headers: buildHeaders(config, refreshedToken),\n });\n};\n\nconst sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));\n\n// API Implementation\nexport const renderBuildExperimental = async (\n request: RenderBuildRequest,\n config: ApiConfig\n): Promise<RenderBuildResponse> => {\n const requestWithFormat = {\n ...request,\n format: request.format || \"video\", // Default to video format\n // Include width and height if provided\n ...(request.width !== undefined ? { width: request.width } : {}),\n ...(request.height !== undefined ? { height: request.height } : {}),\n // Include profile if provided\n ...(request.profile ? { profile: request.profile } : {}),\n ...(request.scene ? { scene: request.scene } : {}),\n ...(request.showBackground !== undefined ? { showBackground: request.showBackground } : {}),\n ...(request.showGrid !== undefined ? { showGrid: request.showGrid } : {}),\n ...(request.winterMode !== undefined ? { winterMode: request.winterMode } : {}),\n ...(request.springMode !== undefined ? { springMode: request.springMode } : {}),\n };\n\n const response = await fetchWithApiAuth(\n buildApiUrl(API_ENDPOINTS.RENDER_BUILD_EXPERIMENTAL, config),\n {\n method: \"POST\",\n body: JSON.stringify(requestWithFormat),\n },\n config\n );\n\n if (!response.ok) {\n throw new Error(\n `Render build failed: ${response.status} ${response.statusText}`\n );\n }\n\n const video = await response.blob();\n\n return {\n video,\n metadata: {\n size: video.size,\n format: \"video/mp4\",\n },\n };\n};\n\n// New async endpoints implementation\nexport const createRenderBuildJob = async (\n request: RenderBuildRequest,\n config: ApiConfig\n): Promise<RenderJobCreateResponse> => {\n const body = {\n parts: request.parts,\n // If provided, forward format; default handled server-side but we keep explicit default\n ...(request.format ? { format: request.format } : {}),\n // Include width and height if provided\n ...(request.width !== undefined ? { width: request.width } : {}),\n ...(request.height !== undefined ? { height: request.height } : {}),\n // Include profile if provided\n ...(request.profile ? { profile: request.profile } : {}),\n ...(request.scene ? { scene: request.scene } : {}),\n ...(request.showBackground !== undefined ? { showBackground: request.showBackground } : {}),\n // Include composition settings\n ...(request.showGrid !== undefined ? { showGrid: request.showGrid } : {}),\n ...(request.winterMode !== undefined ? { winterMode: request.winterMode } : {}),\n ...(request.springMode !== undefined ? { springMode: request.springMode } : {}),\n ...(request.cameraOffsetX !== undefined ? { cameraOffsetX: request.cameraOffsetX } : {}),\n ...(request.gridSettings ? { gridSettings: request.gridSettings } : {}),\n // Include frame quality for sprite rendering\n ...(request.frameQuality ? { frameQuality: request.frameQuality } : {}),\n // Include camera zoom for render-time scaling\n ...(request.cameraZoom !== undefined ? { cameraZoom: request.cameraZoom } : {}),\n };\n\n const response = await fetchWithApiAuth(\n buildApiUrl(API_ENDPOINTS.RENDER_BUILD, config),\n {\n method: \"POST\",\n body: JSON.stringify(body),\n },\n config\n );\n\n if (!response.ok) {\n throw new Error(`Create render job failed: ${response.status} ${response.statusText}`);\n }\n\n const data = (await response.json()) as RenderJobCreateResponse;\n if (!data?.job_id) {\n throw new Error(\"Create render job failed: missing job_id in response\");\n }\n return data;\n};\n\nexport const getRenderBuildStatus = async (\n jobId: string,\n config: ApiConfig\n): Promise<RenderJobStatusResponse> => {\n const url = buildApiUrl(`${API_ENDPOINTS.RENDER_BUILD}/${encodeURIComponent(jobId)}`, config);\n const response = await fetchWithApiAuth(\n url,\n { method: \"GET\" },\n config\n );\n\n if (response.status === 404) {\n throw new Error(\"Render job not found\");\n }\n if (!response.ok) {\n throw new Error(`Get render job status failed: ${response.status} ${response.statusText}`);\n }\n\n return (await response.json()) as RenderJobStatusResponse;\n};\n\nexport const renderBuild = async (\n request: RenderBuildRequest,\n config: ApiConfig,\n options?: { pollIntervalMs?: number; timeoutMs?: number }\n): Promise<RenderBuildAsyncResponse> => {\n const pollIntervalMs = options?.pollIntervalMs ?? 1500;\n const timeoutMs = options?.timeoutMs ?? 120_000; // 2 minutes default\n\n const { job_id } = await createRenderBuildJob(request, config);\n\n const start = Date.now();\n // Poll until completed or error or timeout\n for (;;) {\n const status = await getRenderBuildStatus(job_id, config);\n if (status.status === \"completed\") {\n const requestedFormat = request.format ?? \"video\";\n const finalUrl =\n (requestedFormat === \"sprite\"\n ? status.sprite_url || status.url || undefined\n : status.video_url || status.url || undefined);\n if (!finalUrl) {\n throw new Error(\"Render job completed but no URL returned\");\n }\n return { videoUrl: finalUrl };\n }\n if (status.status === \"error\") {\n throw new Error(status.error || \"Render job failed\");\n }\n\n if (Date.now() - start > timeoutMs) {\n throw new Error(\"Timed out waiting for render job to complete\");\n }\n\n await sleep(pollIntervalMs);\n }\n};\n\nexport const renderSpriteExperimental = async (\n request: RenderBuildRequest,\n config: ApiConfig\n): Promise<RenderSpriteResponse> => {\n const requestWithFormat = {\n ...request,\n format: \"sprite\",\n // Include width and height if provided\n ...(request.width !== undefined ? { width: request.width } : {}),\n ...(request.height !== undefined ? { height: request.height } : {}),\n // Include profile if provided\n ...(request.profile ? { profile: request.profile } : {}),\n ...(request.scene ? { scene: request.scene } : {}),\n ...(request.showBackground !== undefined ? { showBackground: request.showBackground } : {}),\n ...(request.showGrid !== undefined ? { showGrid: request.showGrid } : {}),\n ...(request.winterMode !== undefined ? { winterMode: request.winterMode } : {}),\n ...(request.springMode !== undefined ? { springMode: request.springMode } : {}),\n };\n\n const response = await fetchWithApiAuth(\n buildApiUrl(API_ENDPOINTS.RENDER_BUILD_EXPERIMENTAL, config),\n {\n method: \"POST\",\n body: JSON.stringify(requestWithFormat),\n },\n config\n );\n\n if (!response.ok) {\n throw new Error(\n `Render sprite failed: ${response.status} ${response.statusText}`\n );\n }\n\n const sprite = await response.blob();\n\n return {\n sprite,\n metadata: {\n cols: 12, // Default sprite grid - could be returned from API\n rows: 6,\n totalFrames: 72,\n size: sprite.size,\n format: \"image/webp\",\n },\n };\n};\n\nexport const getAvailableParts = async (\n category: PartCategory,\n config: ApiConfig,\n options?: GetAvailablePartsOptions\n): Promise<AvailablePartsResponse> => {\n const base = buildApiUrl(API_ENDPOINTS.AVAILABLE_PARTS, config);\n const params = new URLSearchParams();\n params.set(\"category\", category);\n if (typeof options?.limit === \"number\") params.set(\"limit\", String(options.limit));\n if (typeof options?.skip === \"number\") params.set(\"skip\", String(options.skip));\n const separator = base.includes(\"?\") ? \"&\" : \"?\";\n const url = `${base}${separator}${params.toString()}`;\n\n const response = await fetchWithApiAuth(\n url,\n { method: \"GET\" },\n config\n );\n\n if (!response.ok) {\n throw new Error(\n `Get available parts failed: ${response.status} ${response.statusText}`\n );\n }\n\n return (await response.json()) as AvailablePartsResponse;\n};\n\n// ============================================\n// Build and Parts API Functions\n// ============================================\n\n/**\n * Fetch a build by its share code.\n * Returns build metadata and parts organized by category.\n *\n * @param shareCode - The share code of the build to fetch\n * @param config - API configuration (environment, auth token)\n * @returns Promise with build details including parts\n *\n * @example\n * ```tsx\n * const build = await getBuildByShareCode('abc123xyz', {\n * environment: 'prod',\n * authToken: 'your-api-key'\n * });\n *\n * console.log(build.name); // \"My Gaming PC\"\n * console.log(build.parts.CPU); // [\"7xjqsomhr\"]\n *\n * // Use the parts directly with BuildRender\n * <BuildRender parts={{ parts: build.parts }} size={500} apiConfig={config} />\n * ```\n */\nexport const getBuildByShareCode = async (\n shareCode: string,\n config: ApiConfig\n): Promise<BuildResponse> => {\n const url = buildApiUrl(`${API_ENDPOINTS.BUILD}/${encodeURIComponent(shareCode)}`, config);\n\n const response = await fetchWithApiAuth(\n url,\n { method: \"GET\" },\n config\n );\n\n if (response.status === 404) {\n throw new Error(\"Build not found\");\n }\n\n if (!response.ok) {\n throw new Error(\n `Get build by share code failed: ${response.status} ${response.statusText}`\n );\n }\n\n return (await response.json()) as BuildResponse;\n};\n\n/**\n * Fetch part details by their BuildCores IDs.\n *\n * @param partIds - Array of BuildCores part IDs to fetch\n * @param config - API configuration (environment, auth token)\n * @returns Promise with part details\n *\n * @example\n * ```tsx\n * const response = await getPartsByIds(['7xjqsomhr', 'z7pyphm9k'], {\n * environment: 'prod',\n * authToken: 'your-api-key'\n * });\n *\n * response.parts.forEach(part => {\n * console.log(`${part.name} (${part.category})`);\n * });\n * ```\n */\nexport const getPartsByIds = async (\n partIds: string[],\n config: ApiConfig\n): Promise<PartsResponse> => {\n const url = buildApiUrl(API_ENDPOINTS.PARTS, config);\n\n const response = await fetchWithApiAuth(\n url,\n {\n method: \"POST\",\n body: JSON.stringify({ ids: partIds }),\n },\n config\n );\n\n if (!response.ok) {\n throw new Error(\n `Get parts by IDs failed: ${response.status} ${response.statusText}`\n );\n }\n\n return (await response.json()) as PartsResponse;\n};\n\n/**\n * Create a render job for a build by its share code.\n * Returns the job ID for polling status.\n *\n * @param shareCode - The share code of the build to render\n * @param config - API configuration (environment, auth token)\n * @param options - Render options (format, dimensions, profile)\n * @returns Promise with job creation response\n */\nexport const createRenderByShareCodeJob = async (\n shareCode: string,\n config: ApiConfig,\n options?: Omit<RenderByShareCodeOptions, \"pollIntervalMs\" | \"timeoutMs\">\n): Promise<RenderByShareCodeJobResponse> => {\n const url = buildApiUrl(API_ENDPOINTS.RENDER_BY_SHARE_CODE, config);\n\n const body = {\n shareCode,\n ...(options?.format ? { format: options.format } : {}),\n ...(options?.width !== undefined ? { width: options.width } : {}),\n ...(options?.height !== undefined ? { height: options.height } : {}),\n ...(options?.profile ? { profile: options.profile } : {}),\n ...(options?.scene ? { scene: options.scene } : {}),\n ...(options?.showBackground !== undefined ? { showBackground: options.showBackground } : {}),\n ...(options?.showGrid !== undefined ? { showGrid: options.showGrid } : {}),\n ...(options?.winterMode !== undefined ? { winterMode: options.winterMode } : {}),\n ...(options?.springMode !== undefined ? { springMode: options.springMode } : {}),\n ...(options?.cameraOffsetX !== undefined ? { cameraOffsetX: options.cameraOffsetX } : {}),\n ...(options?.gridSettings ? { gridSettings: options.gridSettings } : {}),\n ...(options?.frameQuality ? { frameQuality: options.frameQuality } : {}),\n ...(options?.cameraZoom !== undefined ? { cameraZoom: options.cameraZoom } : {}),\n };\n\n const response = await fetchWithApiAuth(\n url,\n {\n method: \"POST\",\n body: JSON.stringify(body),\n },\n config\n );\n\n if (response.status === 404) {\n throw new Error(\"Build not found\");\n }\n\n if (!response.ok) {\n throw new Error(\n `Create render job failed: ${response.status} ${response.statusText}`\n );\n }\n\n const data = (await response.json()) as RenderByShareCodeJobResponse;\n if (!data?.job_id) {\n throw new Error(\"Create render job failed: missing job_id in response\");\n }\n\n return data;\n};\n\n/**\n * Render a build by its share code.\n * This is a convenience function that creates a render job and polls until completion.\n *\n * @param shareCode - The share code of the build to render\n * @param config - API configuration (environment, auth token)\n * @param options - Render options including polling configuration\n * @returns Promise with the final render URL\n *\n * @example\n * ```tsx\n * // Simple usage - just pass share code\n * const result = await renderByShareCode('abc123xyz', {\n * environment: 'prod',\n * authToken: 'your-api-key'\n * });\n * console.log(result.videoUrl); // URL to rendered video\n *\n * // With custom options\n * const result = await renderByShareCode('abc123xyz', config, {\n * format: 'sprite',\n * width: 1920,\n * height: 1080,\n * profile: 'cinematic',\n * timeoutMs: 180000 // 3 minute timeout\n * });\n * ```\n */\nexport const renderByShareCode = async (\n shareCode: string,\n config: ApiConfig,\n options?: RenderByShareCodeOptions\n): Promise<RenderByShareCodeResponse> => {\n const pollIntervalMs = options?.pollIntervalMs ?? 1500;\n const timeoutMs = options?.timeoutMs ?? 120_000; // 2 minutes default\n\n const { job_id } = await createRenderByShareCodeJob(shareCode, config, options);\n\n const start = Date.now();\n // Poll until completed or error or timeout\n for (;;) {\n const status = await getRenderBuildStatus(job_id, config);\n \n if (status.status === \"completed\") {\n const requestedFormat = options?.format ?? \"video\";\n const finalUrl =\n requestedFormat === \"sprite\"\n ? status.sprite_url || status.url || undefined\n : status.video_url || status.url || undefined;\n \n if (!finalUrl) {\n throw new Error(\"Render job completed but no URL returned\");\n }\n return { videoUrl: finalUrl };\n }\n \n if (status.status === \"error\") {\n throw new Error(status.error || \"Render job failed\");\n }\n\n if (Date.now() - start > timeoutMs) {\n throw new Error(\"Timed out waiting for render job to complete\");\n }\n\n await sleep(pollIntervalMs);\n }\n};\n\n// Export the base URL for external use\nexport { API_BASE_URL };\n","export interface BuildRenderVideoProps {\n /**\n * Parts configuration for the build render.\n *\n * This object defines which PC components should be included in the 3D render.\n * Each part category contains an array with a single part ID that will be rendered.\n *\n * **Current Limitation**: Only 1 part per category is supported. Arrays must contain\n * exactly one part ID per category. Future versions will support multiple parts per category.\n *\n * @example\n * ```tsx\n * const parts = {\n * parts: {\n * CPU: [\"7xjqsomhr\"], // AMD Ryzen 7 9800X3D\n * GPU: [\"z7pyphm9k\"], // ASUS GeForce RTX 5080 ASTRAL\n * RAM: [\"dpl1iyvb5\"], // PNY DDR5\n * Motherboard: [\"iwin2u9vx\"], // Asus ROG STRIX X870E-E GAMING WIFI\n * PSU: [\"m4kilv190\"], // LIAN LI 1300W\n * Storage: [\"0bkvs17po\"], // SAMSUNG 990 EVO\n * PCCase: [\"qq9jamk7c\"], // MONTECH KING 95 PRO\n * CPUCooler: [\"62d8zelr5\"], // ARCTIC LIQUID FREEZER 360\n * }\n * };\n *\n * <BuildRender parts={parts} size={300} />\n * ```\n *\n * @example Minimal build (only required components)\n * ```tsx\n * const parts = {\n * parts: {\n * CPU: [\"7xjqsomhr\"], // Single CPU required\n * Motherboard: [\"iwin2u9vx\"], // Single motherboard required\n * PCCase: [\"qq9jamk7c\"], // Single case required\n * }\n * };\n * ```\n *\n * Note: Part IDs must correspond to valid components in the BuildCores database.\n * Use the available parts API to get valid part IDs for each category.\n */\n parts: RenderBuildRequest;\n\n /**\n * Width and height in pixels. If only `size` is provided, both width and height use it.\n * If `width`/`height` are provided, they override `size` individually.\n */\n width?: number;\n height?: number;\n size?: number;\n\n /**\n * API configuration for environment and authentication.\n * This is required to make API calls to the BuildCores rendering service.\n *\n * @example\n * ```tsx\n * <BuildRender\n * parts={parts}\n * size={300}\n * apiConfig={{\n * environment: 'staging',\n * authToken: 'your-auth-token'\n * }}\n * />\n * ```\n */\n apiConfig: ApiConfig;\n\n /**\n * Options to configure the internal useBuildRender hook\n * (e.g., choose async vs experimental rendering flow)\n */\n useBuildRenderOptions?: {\n mode?: \"async\" | \"experimental\";\n };\n\n /**\n * Optional mouse sensitivity for dragging (default: 0.005).\n *\n * Controls how responsive the 3D model rotation is to mouse movements.\n * Lower values make rotation slower and more precise, higher values make it faster.\n *\n * @example\n * ```tsx\n * <BuildRender\n * parts={parts}\n * size={300}\n * mouseSensitivity={0.003} // Slower, more precise\n * />\n *\n * <BuildRender\n * parts={parts}\n * size={300}\n * mouseSensitivity={0.01} // Faster rotation\n * />\n * ```\n *\n * @default 0.005\n */\n mouseSensitivity?: number;\n\n /**\n * Optional touch sensitivity for dragging (default: 0.01).\n *\n * Controls how responsive the 3D model rotation is to touch gestures on mobile devices.\n * Generally set higher than mouseSensitivity for better touch experience.\n *\n * @example\n * ```tsx\n * <BuildRender\n * parts={parts}\n * size={300}\n * touchSensitivity={0.008} // Slower touch rotation\n * />\n *\n * <BuildRender\n * parts={parts}\n * size={300}\n * touchSensitivity={0.015} // Faster touch rotation\n * />\n * ```\n *\n * @default 0.01\n */\n touchSensitivity?: number;\n}\n\nexport interface BuildRenderProps {\n /**\n * Parts configuration for the sprite render.\n *\n * This object defines which PC components should be included in the 3D sprite render.\n * Each part category contains an array with a single part ID that will be rendered.\n *\n * **Note**: If `shareCode` is provided, it will be used instead of `parts`.\n * Using `shareCode` preserves the build's interactive state (including case fan slot placements).\n *\n * **Current Limitation**: Only 1 part per category is supported. Arrays must contain\n * exactly one part ID per category. Future versions will support multiple parts per category.\n *\n * @example\n * ```tsx\n * const parts = {\n * parts: {\n * CPU: [\"7xjqsomhr\"], // AMD Ryzen 7 9800X3D\n * GPU: [\"z7pyphm9k\"], // ASUS GeForce RTX 5080 ASTRAL\n * RAM: [\"dpl1iyvb5\"], // PNY DDR5\n * Motherboard: [\"iwin2u9vx\"], // Asus ROG STRIX X870E-E GAMING WIFI\n * PSU: [\"m4kilv190\"], // LIAN LI 1300W\n * Storage: [\"0bkvs17po\"], // SAMSUNG 990 EVO\n * PCCase: [\"qq9jamk7c\"], // MONTECH KING 95 PRO\n * CPUCooler: [\"62d8zelr5\"], // ARCTIC LIQUID FREEZER 360\n * }\n * };\n *\n * <SpriteRender parts={parts} size={300} />\n * ```\n */\n parts?: RenderBuildRequest;\n\n /**\n * Share code of an existing build to render.\n *\n * When provided, the build will be rendered using its existing interactive state,\n * which includes case fan slot placements. This is preferred over `parts` when\n * rendering builds that have already been configured with case fans.\n *\n * If both `shareCode` and `parts` are provided, `shareCode` takes precedence.\n *\n * @example\n * ```tsx\n * <BuildRender\n * shareCode=\"abc123xyz\"\n * size={500}\n * apiConfig={{ environment: 'prod', authToken: 'your-token' }}\n * />\n * ```\n */\n shareCode?: string;\n\n /**\n * Width and height in pixels. If only `size` is provided, both width and height use it.\n * If `width`/`height` are provided, they override `size` individually.\n */\n width?: number;\n height?: number;\n size?: number;\n\n /**\n * API configuration for environment and authentication.\n * This is required to make API calls to the BuildCores rendering service.\n *\n * @example\n * ```tsx\n * <SpriteRender\n * parts={parts}\n * size={300}\n * apiConfig={{\n * environment: 'staging',\n * authToken: 'your-auth-token'\n * }}\n * />\n * ```\n */\n apiConfig: ApiConfig;\n\n /**\n * Options to configure the internal useSpriteRender hook\n * (e.g., choose async vs experimental rendering flow)\n */\n useSpriteRenderOptions?: {\n mode?: \"async\" | \"experimental\";\n };\n\n /**\n * Optional mouse sensitivity for dragging (default: 0.05).\n *\n * Controls how responsive the 3D model rotation is to mouse movements.\n * Lower values make rotation slower and more precise, higher values make it faster.\n *\n * @default 0.2\n */\n mouseSensitivity?: number;\n\n /**\n * Optional touch sensitivity for dragging (default: 0.02).\n *\n * Controls how responsive the 3D model rotation is to touch gestures on mobile devices.\n * Generally set similar to mouseSensitivity for consistent experience.\n *\n * @default 0.2\n */\n touchSensitivity?: number;\n\n /**\n * Show grid in render.\n * Works for both parts and shareCode rendering.\n */\n showGrid?: boolean;\n\n /**\n * Environment scene preset for rendering.\n */\n scene?: RenderScene;\n\n /**\n * Whether to show the environment background.\n */\n showBackground?: boolean;\n\n /**\n * Enable winter mode effects.\n * Mutually exclusive with springMode.\n */\n winterMode?: boolean;\n\n /**\n * Enable spring mode effects.\n * Mutually exclusive with winterMode.\n */\n springMode?: boolean;\n\n /**\n * Camera offset X for composition.\n * Positive values shift the build to the right, leaving room for text overlay on the left.\n * Works for both parts and shareCode rendering.\n */\n cameraOffsetX?: number;\n\n /**\n * Grid appearance settings for thicker/more visible grid in renders.\n * Works for both parts and shareCode rendering.\n */\n gridSettings?: GridSettings;\n\n /**\n * Animation mode for the auto-rotation.\n * \n * - **bounce**: (default) Quick back-and-forth partial rotation with pauses\n * - **spin360**: Slow continuous 360° rotation\n * \n * @example\n * ```tsx\n * // Continuous slow spin (good for showcases)\n * <BuildRender\n * shareCode=\"abc123\"\n * animationMode=\"spin360\"\n * spinDuration={12000} // 12 seconds per full rotation\n * />\n * ```\n * \n * @default \"bounce\"\n */\n animationMode?: 'bounce' | 'spin360';\n\n /**\n * Duration in milliseconds for one full 360° rotation.\n * Only applies when `animationMode` is \"spin360\".\n * \n * @example\n * ```tsx\n * <BuildRender\n * shareCode=\"abc123\"\n * animationMode=\"spin360\"\n * spinDuration={15000} // 15 seconds per rotation\n * />\n * ```\n * \n * @default 10000 (10 seconds)\n */\n spinDuration?: number;\n\n /**\n * Whether to enable user interaction (drag to rotate, scroll to zoom).\n * \n * When set to `false`:\n * - Drag-to-rotate is disabled\n * - Scroll-to-zoom is disabled\n * - Cursor shows as \"pointer\" instead of \"grab\"\n * - Click events pass through (useful for wrapping in a link)\n * \n * @example\n * ```tsx\n * // Non-interactive showcase with link\n * <a href=\"https://buildcores.com/build/abc123\">\n * <BuildRender\n * shareCode=\"abc123\"\n * animationMode=\"spin360\"\n * interactive={false}\n * />\n * </a>\n * ```\n * \n * @default true\n */\n interactive?: boolean;\n\n /**\n * Frame quality for sprite renders.\n * - **standard**: 72 frames (default) - good balance of quality and file size\n * - **high**: 144 frames - smoother animation, larger file size (~2x file size)\n * \n * @example\n * ```tsx\n * <BuildRender\n * shareCode=\"abc123\"\n * frameQuality=\"high\" // 144 frames for smoother rotation\n * />\n * ```\n * \n * @default \"standard\"\n */\n frameQuality?: 'standard' | 'high';\n\n /**\n * Initial zoom level for the build.\n * Range: 0.5 (50%) to 2.5 (250%). Values less than 1 make the build appear smaller,\n * values greater than 1 make it appear larger.\n * \n * @example\n * ```tsx\n * <BuildRender\n * shareCode=\"abc123\"\n * zoom={0.7} // 70% size - build appears smaller\n * />\n * \n * <BuildRender\n * shareCode=\"abc123\"\n * zoom={1.5} // 150% size - build appears larger\n * />\n * ```\n * \n * @default 1\n */\n zoom?: number;\n\n /**\n * Camera zoom level for server-side rendering.\n * Values > 1 move the camera further away (build appears smaller in the sprite).\n * Values < 1 move the camera closer (build appears larger in the sprite).\n * \n * Use this for higher quality scaled-down renders vs client-side zoom scaling.\n * Range: 0.5 to 2.0\n * \n * @example\n * ```tsx\n * <BuildRender\n * shareCode=\"abc123\"\n * cameraZoom={1.3} // Camera 30% further away - smaller build in sprite\n * />\n * ```\n * \n * @default 1\n */\n cameraZoom?: number;\n}\n\n// API Types\n\n/**\n * API configuration for environment and authentication\n */\nexport interface ApiConfig {\n /**\n * Environment to use for API requests\n * - 'staging': Development/testing environment\n * - 'prod': Production environment\n *\n * @example\n * ```tsx\n * const config: ApiConfig = {\n * environment: 'staging',\n * authToken: 'your-bearer-token'\n * };\n * ```\n */\n environment?: \"staging\" | \"prod\";\n\n /**\n * Bearer token for API authentication\n *\n * @example\n * ```tsx\n * const config: ApiConfig = {\n * environment: 'prod',\n * authToken: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...'\n * };\n * ```\n */\n authToken?: string;\n\n /**\n * Auth mode for API requests.\n * - legacy: Sends `authToken` directly as bearer token.\n * - session: Uses `getRenderSessionToken` to fetch short-lived delegated tokens.\n *\n * @default \"legacy\"\n */\n authMode?: 'legacy' | 'session';\n\n /**\n * Session token supplier used when `authMode` is \"session\".\n * Should call your backend endpoint that brokers BuildCores session tokens.\n */\n getRenderSessionToken?: () => Promise<{\n token: string;\n expiresAt: string;\n }>;\n}\n\n/**\n * Enum defining all available PC part categories that can be rendered.\n *\n * Each category represents a different type of computer component that can be\n * included in the 3D build visualization.\n *\n * @example\n * ```tsx\n * // All available categories\n * const categories = [\n * PartCategory.CPU, // \"CPU\"\n * PartCategory.GPU, // \"GPU\"\n * PartCategory.RAM, // \"RAM\"\n * PartCategory.Motherboard,// \"Motherboard\"\n * PartCategory.PSU, // \"PSU\"\n * PartCategory.Storage, // \"Storage\"\n * PartCategory.PCCase, // \"PCCase\"\n * PartCategory.CPUCooler, // \"CPUCooler\"\n * ];\n * ```\n */\nexport enum PartCategory {\n /** Central Processing Unit - The main processor */\n CPU = \"CPU\",\n /** Graphics Processing Unit - Video card for rendering */\n GPU = \"GPU\",\n /** Random Access Memory - System memory modules */\n RAM = \"RAM\",\n /** Main circuit board that connects all components */\n Motherboard = \"Motherboard\",\n /** Power Supply Unit - Provides power to all components */\n PSU = \"PSU\",\n /** Storage devices like SSDs, HDDs, NVMe drives */\n Storage = \"Storage\",\n /** PC Case - The enclosure that houses all components */\n PCCase = \"PCCase\",\n /** CPU Cooler - Air or liquid cooling for the processor */\n CPUCooler = \"CPUCooler\",\n /** Case Fans - Additional cooling fans for the case */\n CaseFan = \"CaseFan\",\n}\n\n/**\n * Request structure for rendering a PC build.\n *\n * This interface defines the parts configuration that will be sent to the\n * rendering service to generate a 3D visualization of a PC build.\n *\n * **Current Limitation**: Only one part per category is supported. Each category\n * array must contain exactly one part ID. Future versions will support multiple\n * parts per category for comparison views.\n *\n * @example Basic build configuration\n * ```tsx\n * const buildRequest: RenderBuildRequest = {\n * parts: {\n * CPU: [\"7xjqsomhr\"], // AMD Ryzen 7 9800X3D\n * GPU: [\"z7pyphm9k\"], // ASUS GeForce RTX 5080 ASTRAL\n * RAM: [\"dpl1iyvb5\"], // PNY DDR5\n * Motherboard: [\"iwin2u9vx\"], // Asus ROG STRIX X870E-E GAMING WIFI\n * PSU: [\"m4kilv190\"], // LIAN LI 1300W\n * Storage: [\"0bkvs17po\"], // SAMSUNG 990 EVO\n * PCCase: [\"qq9jamk7c\"], // MONTECH KING 95 PRO\n * CPUCooler: [\"62d8zelr5\"], // ARCTIC LIQUID FREEZER 360\n * },\n * format: \"video\" // Request video format\n * };\n * ```\n *\n * @example Sprite format request\n * ```tsx\n * const spriteRequest: RenderBuildRequest = {\n * parts: {\n * CPU: [\"7xjqsomhr\"], // AMD Ryzen 7 9800X3D\n * GPU: [\"z7pyphm9k\"], // ASUS GeForce RTX 5080 ASTRAL\n * RAM: [\"dpl1iyvb5\"], // PNY DDR5\n * Motherboard: [\"iwin2u9vx\"], // Asus ROG STRIX X870E-E GAMING WIFI\n * },\n * format: \"sprite\" // Request sprite sheet format\n * };\n * ```\n */\nexport interface RenderBuildRequest {\n /**\n * Object mapping part categories to arrays of part IDs.\n *\n * **Current Requirements**:\n * - Keys are part categories (CPU, GPU, RAM, etc.)\n * - Values are arrays containing exactly one part ID string\n * - All categories are optional - include only the parts you want to render\n * - Part IDs must be valid identifiers from the BuildCores parts database\n *\n * **Future Enhancement**: Multiple parts per category will be supported for comparison views.\n *\n * @see PartCategory for all available categories\n * @see AvailablePartsResponse for getting valid part IDs\n */\n parts: {\n [K in PartCategory]?: string[];\n };\n\n /**\n * Output format for the rendered build.\n *\n * - \"video\": Returns an MP4 video file for video-based 360° rotation\n * - \"sprite\": Returns a sprite sheet image for frame-based 360° rotation\n *\n * @default \"video\"\n */\n format?: \"video\" | \"sprite\";\n\n /**\n * Desired canvas pixel width (256-2000).\n * Must be provided together with height.\n *\n * @example\n * ```tsx\n * const request: RenderBuildRequest = {\n * parts: { CPU: [\"7xjqsomhr\"] },\n * width: 1920,\n * height: 1080\n * };\n * ```\n */\n width?: number;\n\n /**\n * Desired canvas pixel height (256-2000).\n * Must be provided together with width.\n *\n * @example\n * ```tsx\n * const request: RenderBuildRequest = {\n * parts: { CPU: [\"7xjqsomhr\"] },\n * width: 1920,\n * height: 1080\n * };\n * ```\n */\n height?: number;\n\n /**\n * Render quality profile that controls visual effects and rendering speed.\n *\n * - **cinematic**: All effects enabled (shadows, ambient occlusion, bloom) for highest quality\n * - **flat**: No effects for clean, simple product shots\n * - **fast**: Minimal rendering for fastest processing speed\n *\n * @example\n * ```tsx\n * const request: RenderBuildRequest = {\n * parts: { CPU: [\"7xjqsomhr\"] },\n * profile: 'cinematic' // High quality with all effects\n * };\n * ```\n *\n * @example Fast rendering\n * ```tsx\n * const request: RenderBuildRequest = {\n * parts: { CPU: [\"7xjqsomhr\"] },\n * profile: 'fast' // Quick render, minimal effects\n * };\n * ```\n */\n profile?: 'cinematic' | 'flat' | 'fast';\n\n /**\n * Whether to show the 3D grid in the render.\n * Defaults to true for cinematic profile, false otherwise.\n */\n showGrid?: boolean;\n\n /**\n * Environment scene preset.\n */\n scene?: RenderScene;\n\n /**\n * Whether to show the environment background.\n */\n showBackground?: boolean;\n\n /**\n * Enable winter mode effects.\n * Mutually exclusive with springMode.\n */\n winterMode?: boolean;\n\n /**\n * Enable spring mode effects.\n * Mutually exclusive with winterMode.\n */\n springMode?: boolean;\n\n /**\n * Horizontal offset for the camera view.\n * Positive values shift the build to the right, leaving room for text overlay on the left.\n * Range: -0.3 to 0.3\n */\n cameraOffsetX?: number;\n\n /**\n * Custom grid appearance settings.\n * Only applies when showGrid is true.\n */\n gridSettings?: GridSettings;\n\n /**\n * Frame quality for sprite renders.\n * - **standard**: 72 frames (default) - good balance of quality and file size\n * - **high**: 144 frames - smoother animation, larger file size\n * \n * @default \"standard\"\n */\n frameQuality?: 'standard' | 'high';\n\n /**\n * Camera zoom level for server-side rendering.\n * Values > 1 move the camera further away (build appears smaller in the sprite).\n * Values < 1 move the camera closer (build appears larger in the sprite).\n * Range: 0.5 to 2.0\n * \n * @default 1\n */\n cameraZoom?: number;\n}\n\n/**\n * Response structure containing all available parts for each category.\n *\n * This type represents the response from the available parts API endpoint,\n * providing arrays of valid part IDs for each component category.\n *\n * @example Using available parts response\n * ```tsx\n * const availableParts: AvailablePartsResponse = {\n * CPU: [\n * { id: \"7xjqsomhr\", name: \"AMD Ryzen 7 9800X3D\", image: \"https://...\" },\n * { id: \"x2thvstj3\", name: \"AMD Ryzen 7 9700X\", image: \"https://...\" },\n * ],\n * GPU: [\n * { id: \"z7pyphm9k\", name: \"ASUS GeForce RTX 5080 ASTRAL\", image: \"https://...\" },\n * { id: \"4a0mjb360\", name: \"PNY GeForce RTX 5060 Ti 16GB\", image: \"https://...\" },\n * ],\n * // ... all other categories\n * };\n *\n * // Select one part per category for current build request\n * const buildRequest: RenderBuildRequest = {\n * parts: {\n * CPU: [availableParts.CPU[0].id], // Select first available CPU ID\n * GPU: [availableParts.GPU[1].id], // Select second available GPU ID\n * RAM: [availableParts.RAM[0].id], // Select first available RAM ID\n * }\n * };\n * ```\n *\n * @example Dynamic part selection\n * ```tsx\n * // Function to create build with user-selected parts\n * const createBuild = (selectedPartIds: Record<string, string>) => {\n * const buildRequest: RenderBuildRequest = {\n * parts: {\n * CPU: [selectedPartIds.cpu], // Single selected CPU ID\n * GPU: [selectedPartIds.gpu], // Single selected GPU ID\n * RAM: [selectedPartIds.ram], // Single selected RAM ID\n * // ... other single selections\n * }\n * };\n * return buildRequest;\n * };\n * ```\n */\n/**\n * Individual part information with details\n */\nexport interface PartDetails {\n /** Unique part identifier */\n id: string;\n /** Human-readable part name */\n name: string;\n /** URL to part image */\n image: string;\n}\n\n/**\n * Pagination metadata for available parts responses\n */\nexport interface AvailablePartsPagination {\n /** Total number of parts available for this category */\n total: number;\n /** Number of parts returned in this response */\n limit: number;\n /** Number of parts skipped */\n skip: number;\n /** Whether there are more parts available */\n hasNext: boolean;\n /** Whether there are previous parts available */\n hasPrev: boolean;\n}\n\n/**\n * Response envelope for the available parts endpoint.\n * Returns parts for the requested category under `data` keyed by category name.\n */\nexport interface AvailablePartsResponse {\n /**\n * Parts grouped by category. Only the requested category key is expected\n * to be present in the response.\n */\n data: Partial<Record<PartCategory, PartDetails[]>>;\n /** The requested category */\n category: PartCategory;\n /** Optional pagination information */\n pagination?: AvailablePartsPagination;\n}\n\n/**\n * Query options for fetching available parts\n */\nexport interface GetAvailablePartsOptions {\n /** Number of parts to return (default 20, min 1, max 100) */\n limit?: number;\n /** Number of parts to skip for pagination (default 0) */\n skip?: number;\n}\n\n// ============================================\n// Build and Parts API Types\n// ============================================\n\n/**\n * Extended part details including category information\n */\nexport interface PartDetailsWithCategory {\n /** Unique part identifier (BuildCores ID) */\n id: string;\n /** Human-readable part name */\n name: string;\n /** URL to part image (may be null) */\n image: string | null;\n /** Part category */\n category: PartCategory;\n}\n\n/**\n * Response from the get build by share code endpoint.\n * Contains build metadata and parts organized by category.\n *\n * @example\n * ```tsx\n * const build = await getBuildByShareCode('abc123xyz', config);\n * console.log(build.name); // \"My Gaming PC\"\n * console.log(build.parts.CPU); // [\"7xjqsomhr\"]\n * console.log(build.partDetails.CPU[0].name); // \"AMD Ryzen 7 9800X3D\"\n * ```\n */\nexport interface BuildResponse {\n /** The share code of the build */\n shareCode: string;\n /** Build name/title */\n name: string;\n /** Build description */\n description: string;\n /**\n * Part IDs mapped by category.\n * Use these IDs directly with RenderBuildRequest.\n */\n parts: {\n [K in PartCategory]?: string[];\n };\n /**\n * Detailed part information mapped by category.\n * Includes name, image URL, and category for each part.\n */\n partDetails: {\n [K in PartCategory]?: PartDetailsWithCategory[];\n };\n /**\n * Whether the case in this build has an interactive 3D model available.\n * If false, the build cannot be rendered in 3D.\n */\n hasInteractiveModel: boolean;\n}\n\n/**\n * Response from the get parts by IDs endpoint.\n *\n * @example\n * ```tsx\n * const response = await getPartsByIds(['7xjqsomhr', 'z7pyphm9k'], config);\n * response.parts.forEach(part => {\n * console.log(`${part.name} (${part.category})`);\n * });\n * ```\n */\nexport interface PartsResponse {\n /** Array of part details */\n parts: PartDetailsWithCategory[];\n}\n\n/**\n * Grid appearance settings for renders\n */\nexport interface GridSettings {\n /** Grid cell line thickness (default: 0.6) */\n cellThickness?: number;\n /** Grid section line thickness (default: 1.2) */\n sectionThickness?: number;\n /** Grid color as hex string (default: #6f6f6f) */\n color?: string;\n /** Distance at which grid starts to fade (default: 3) */\n fadeDistance?: number;\n /** Render order for depth sorting (default: 0, use -1 to render before other objects) */\n renderOrder?: number;\n}\n\n/**\n * Supported environment scene presets for render API endpoints.\n */\nexport type RenderScene =\n | \"sunset\"\n | \"dawn\"\n | \"night\"\n | \"warehouse\"\n | \"forest\"\n | \"apartment\"\n | \"studio\"\n | \"studio_v2\"\n | \"city\"\n | \"park\"\n | \"lobby\";\n\n/**\n * Options for rendering a build by share code\n */\nexport interface RenderByShareCodeOptions {\n /** Output format - video (MP4) or sprite (WebP sprite sheet) */\n format?: \"video\" | \"sprite\";\n /** Desired canvas pixel width (256-8192) */\n width?: number;\n /** Desired canvas pixel height (256-8192) */\n height?: number;\n /** Render quality profile */\n profile?: \"cinematic\" | \"flat\" | \"fast\";\n /** Environment scene preset */\n scene?: RenderScene;\n /** Whether to show the environment background */\n showBackground?: boolean;\n /** Show grid in render (default: true for cinematic profile) */\n showGrid?: boolean;\n /** Enable winter mode effects (mutually exclusive with springMode) */\n winterMode?: boolean;\n /** Enable spring mode effects (mutually exclusive with winterMode) */\n springMode?: boolean;\n /** Camera offset X for composition (positive = shift build right to leave room for text overlay) */\n cameraOffsetX?: number;\n /** Grid appearance settings (for thicker/more visible grid in renders) */\n gridSettings?: GridSettings;\n /** Frame quality - 'standard' (72 frames) or 'high' (144 frames for smoother animation) */\n frameQuality?: 'standard' | 'high';\n /** Camera zoom level for rendering. Values > 1 move camera further (build appears smaller). Range: 0.5 to 2.0 */\n cameraZoom?: number;\n /** Polling interval in milliseconds (default: 1500) */\n pollIntervalMs?: number;\n /** Timeout in milliseconds (default: 120000 = 2 minutes) */\n timeoutMs?: number;\n}\n\n/**\n * Response from the render by share code endpoint (job creation).\n */\nexport interface RenderByShareCodeJobResponse {\n /** Unique job identifier for polling status */\n job_id: string;\n /** Current job status */\n status: \"queued\" | \"processing\" | \"completed\" | \"error\";\n /** The share code of the build being rendered */\n share_code: string;\n}\n\n/**\n * Final response after render by share code completes.\n *\n * @example\n * ```tsx\n * const result = await renderByShareCode('abc123xyz', config);\n * // Use result.videoUrl to display the rendered video\n * ```\n */\nexport interface RenderByShareCodeResponse {\n /** URL to the rendered video or sprite sheet */\n videoUrl: string;\n}\n","import { useState, useEffect, useCallback, useRef } from \"react\";\nimport { RenderBuildRequest, PartCategory, ApiConfig } from \"../types\";\nimport { renderBuild, renderBuildExperimental } from \"../api\";\n\n/**\n * Compares two RenderBuildRequest objects for equality by checking if the same IDs\n * are present in each category array, regardless of order.\n */\nexport const arePartsEqual = (\n parts1: RenderBuildRequest,\n parts2: RenderBuildRequest\n): boolean => {\n const categories = Object.values(PartCategory);\n\n for (const category of categories) {\n const arr1 = parts1.parts[category] || [];\n const arr2 = parts2.parts[category] || [];\n\n // Check if arrays have the same length\n if (arr1.length !== arr2.length) {\n return false;\n }\n\n // Check if arrays contain the same elements (order doesn't matter)\n const set1 = new Set(arr1);\n const set2 = new Set(arr2);\n\n if (set1.size !== set2.size) {\n return false;\n }\n\n for (const id of set1) {\n if (!set2.has(id)) {\n return false;\n }\n }\n }\n\n return true;\n};\n\nexport interface UseBuildRenderReturn {\n videoSrc: string | null;\n isRenderingBuild: boolean;\n renderError: string | null;\n}\n\nexport interface UseBuildRenderOptions {\n /**\n * Choose which backend flow to use\n * - 'async' (default): uses /render-build and polls /render-build/{jobId}\n * - 'experimental': uses /render-build-experimental and returns Blob\n */\n mode?: \"async\" | \"experimental\";\n}\n\nexport const useBuildRender = (\n parts: RenderBuildRequest,\n apiConfig: ApiConfig,\n onLoadStart?: () => void,\n options?: UseBuildRenderOptions\n): UseBuildRenderReturn => {\n const [videoSrc, setVideoSrc] = useState<string | null>(null);\n const [isRenderingBuild, setIsRenderingBuild] = useState(false);\n const [renderError, setRenderError] = useState<string | null>(null);\n const previousPartsRef = useRef<RenderBuildRequest | null>(null);\n\n const fetchRenderBuild = useCallback(\n async (currentParts: RenderBuildRequest) => {\n try {\n setIsRenderingBuild(true);\n setRenderError(null);\n onLoadStart?.();\n\n const mode = options?.mode ?? \"async\";\n if (mode === \"experimental\") {\n const response = await renderBuildExperimental(currentParts, apiConfig);\n const objectUrl = URL.createObjectURL(response.video);\n setVideoSrc((prevSrc: string | null) => {\n if (prevSrc && prevSrc.startsWith(\"blob:\")) {\n URL.revokeObjectURL(prevSrc);\n }\n return objectUrl;\n });\n } else {\n const { videoUrl } = await renderBuild(currentParts, apiConfig);\n // Clean up previous object URL (if any) before setting new one\n setVideoSrc((prevSrc: string | null) => {\n if (prevSrc && prevSrc.startsWith(\"blob:\")) {\n URL.revokeObjectURL(prevSrc);\n }\n return videoUrl;\n });\n }\n } catch (error) {\n setRenderError(\n error instanceof Error ? error.message : \"Failed to render build\"\n );\n } finally {\n setIsRenderingBuild(false);\n }\n },\n [apiConfig, onLoadStart, options?.mode]\n );\n\n // Effect to call API when parts content changes (using custom equality check)\n useEffect(() => {\n const shouldFetch =\n previousPartsRef.current === null ||\n !arePartsEqual(previousPartsRef.current, parts);\n\n if (shouldFetch) {\n previousPartsRef.current = parts;\n fetchRenderBuild(parts);\n }\n }, [parts, fetchRenderBuild]);\n\n // Cleanup effect for component unmount\n useEffect(() => {\n return () => {\n if (videoSrc && videoSrc.startsWith(\"blob:\")) {\n URL.revokeObjectURL(videoSrc);\n }\n };\n }, [videoSrc]);\n\n return {\n videoSrc,\n isRenderingBuild,\n renderError,\n };\n};\n","import { useState, useEffect, useCallback, useRef } from \"react\";\nimport { RenderBuildRequest, ApiConfig } from \"../types\";\nimport { renderSpriteExperimental, renderBuild, renderByShareCode } from \"../api\";\nimport { arePartsEqual } from \"./useBuildRender\";\n\nexport interface UseSpriteRenderReturn {\n spriteSrc: string | null;\n isRenderingSprite: boolean;\n renderError: string | null;\n spriteMetadata: {\n cols: number;\n rows: number;\n totalFrames: number;\n } | null;\n}\n\nexport interface UseSpriteRenderOptions {\n /**\n * Choose which backend flow to use\n * - 'async' (default): uses /render-build and polls /render-build/{jobId} with format 'sprite'\n * - 'experimental': uses /render-build-experimental and returns Blob\n */\n mode?: \"async\" | \"experimental\";\n}\n\n/**\n * Grid settings for render composition\n */\nexport interface RenderGridSettings {\n cellThickness?: number;\n sectionThickness?: number;\n color?: string;\n fadeDistance?: number;\n renderOrder?: number;\n}\n\n/**\n * Input for sprite rendering - either parts (creates new build) or shareCode (uses existing build)\n */\nexport type SpriteRenderInput = \n | { \n type: 'parts'; \n parts: RenderBuildRequest;\n showGrid?: boolean;\n scene?: RenderBuildRequest[\"scene\"];\n showBackground?: boolean;\n winterMode?: boolean;\n springMode?: boolean;\n cameraOffsetX?: number;\n cameraZoom?: number;\n gridSettings?: RenderGridSettings;\n frameQuality?: 'standard' | 'high';\n }\n | { \n type: 'shareCode'; \n shareCode: string; \n profile?: 'cinematic' | 'flat' | 'fast';\n showGrid?: boolean;\n scene?: RenderBuildRequest[\"scene\"];\n showBackground?: boolean;\n winterMode?: boolean;\n springMode?: boolean;\n cameraOffsetX?: number;\n cameraZoom?: number;\n gridSettings?: RenderGridSettings;\n frameQuality?: 'standard' | 'high';\n };\n\nexport const useSpriteRender = (\n input: RenderBuildRequest | SpriteRenderInput,\n apiConfig: ApiConfig,\n onLoadStart?: () => void,\n options?: UseSpriteRenderOptions\n): UseSpriteRenderReturn => {\n const [spriteSrc, setSpriteSrc] = useState<string | null>(null);\n const [isRenderingSprite, setIsRenderingSprite] = useState(false);\n const [renderError, setRenderError] = useState<string | null>(null);\n const [spriteMetadata, setSpriteMetadata] = useState<{\n cols: number;\n rows: number;\n totalFrames: number;\n } | null>(null);\n const previousInputRef = useRef<RenderBuildRequest | SpriteRenderInput | null>(null);\n\n // Normalize input to SpriteRenderInput format\n const normalizedInput: SpriteRenderInput = \n 'type' in input\n ? input\n : {\n type: 'parts',\n parts: input,\n showGrid: input.showGrid,\n scene: input.scene,\n showBackground: input.showBackground,\n winterMode: input.winterMode,\n springMode: input.springMode,\n cameraOffsetX: input.cameraOffsetX,\n cameraZoom: input.cameraZoom,\n gridSettings: input.gridSettings,\n frameQuality: input.frameQuality\n };\n\n const fetchRenderSprite = useCallback(\n async (currentInput: SpriteRenderInput) => {\n try {\n setIsRenderingSprite(true);\n setRenderError(null);\n onLoadStart?.();\n\n // Handle share code rendering - uses existing build with proper interactive state\n if (currentInput.type === 'shareCode') {\n const { videoUrl: spriteUrl } = await renderByShareCode(\n currentInput.shareCode,\n apiConfig,\n { \n format: 'sprite', \n profile: currentInput.profile,\n showGrid: currentInput.showGrid,\n scene: currentInput.scene,\n showBackground: currentInput.showBackground,\n winterMode: currentInput.winterMode,\n springMode: currentInput.springMode,\n cameraOffsetX: currentInput.cameraOffsetX,\n cameraZoom: currentInput.cameraZoom,\n gridSettings: currentInput.gridSettings,\n frameQuality: currentInput.frameQuality\n }\n );\n\n // Set metadata BEFORE sprite URL to avoid race condition\n // (image load starts immediately when spriteSrc changes)\n const rows = currentInput.frameQuality === 'high' ? 12 : 6;\n setSpriteMetadata({ cols: 12, rows, totalFrames: 12 * rows });\n\n setSpriteSrc((prevSrc) => {\n if (prevSrc && prevSrc.startsWith(\"blob:\")) {\n URL.revokeObjectURL(prevSrc);\n }\n return spriteUrl;\n });\n return;\n }\n\n // Handle parts-based rendering (creates new build)\n const currentParts = currentInput.parts;\n const mode = options?.mode ?? \"async\";\n const frameQuality = currentInput.frameQuality;\n const rows = frameQuality === 'high' ? 12 : 6;\n \n if (mode === \"experimental\") {\n const response = await renderSpriteExperimental(\n {\n ...currentParts,\n showGrid: currentInput.showGrid,\n scene: currentInput.scene,\n showBackground: currentInput.showBackground,\n winterMode: currentInput.winterMode,\n springMode: currentInput.springMode,\n cameraOffsetX: currentInput.cameraOffsetX,\n cameraZoom: currentInput.cameraZoom,\n gridSettings: currentInput.gridSettings,\n frameQuality,\n },\n apiConfig\n );\n const objectUrl = URL.createObjectURL(response.sprite);\n\n // Set sprite metadata BEFORE sprite URL to avoid race condition\n setSpriteMetadata({\n cols: response.metadata?.cols || 12,\n rows: response.metadata?.rows || rows,\n totalFrames: response.metadata?.totalFrames || 12 * rows,\n });\n\n // Clean up previous sprite URL before setting new one\n setSpriteSrc((prevSrc) => {\n if (prevSrc && prevSrc.startsWith(\"blob:\")) {\n URL.revokeObjectURL(prevSrc);\n }\n return objectUrl;\n });\n } else {\n // Async job-based flow: request sprite format and use returned URL\n const { videoUrl: spriteUrl } = await renderBuild(\n { \n ...currentParts, \n format: \"sprite\",\n showGrid: currentInput.showGrid,\n scene: currentInput.scene,\n showBackground: currentInput.showBackground,\n winterMode: currentInput.winterMode,\n springMode: currentInput.springMode,\n cameraOffsetX: currentInput.cameraOffsetX,\n cameraZoom: currentInput.cameraZoom,\n gridSettings: currentInput.gridSettings,\n frameQuality,\n },\n apiConfig\n );\n\n // Set metadata BEFORE sprite URL to avoid race condition\n setSpriteMetadata({ cols: 12, rows, totalFrames: 12 * rows });\n\n setSpriteSrc((prevSrc) => {\n if (prevSrc && prevSrc.startsWith(\"blob:\")) {\n URL.revokeObjectURL(prevSrc);\n }\n return spriteUrl;\n });\n }\n } catch (error) {\n setRenderError(\n error instanceof Error ? error.message : \"Failed to render sprite\"\n );\n } finally {\n setIsRenderingSprite(false);\n }\n },\n [apiConfig, onLoadStart, options?.mode]\n );\n\n // Check if inputs are equal\n const areInputsEqual = (a: SpriteRenderInput | null, b: SpriteRenderInput): boolean => {\n if (!a) return false;\n if (a.type !== b.type) return false;\n if (a.type === 'shareCode' && b.type === 'shareCode') {\n // Compare grid settings (shallow comparison of properties)\n const gridSettingsEqual = \n JSON.stringify(a.gridSettings ?? {}) === JSON.stringify(b.gridSettings ?? {});\n return a.shareCode === b.shareCode && \n a.profile === b.profile &&\n a.showGrid === b.showGrid &&\n a.scene === b.scene &&\n a.showBackground === b.showBackground &&\n a.winterMode === b.winterMode &&\n a.springMode === b.springMode &&\n a.cameraOffsetX === b.cameraOffsetX &&\n a.cameraZoom === b.cameraZoom &&\n a.frameQuality === b.frameQuality &&\n gridSettingsEqual;\n }\n if (a.type === 'parts' && b.type === 'parts') {\n // Compare grid settings (shallow comparison of properties)\n const gridSettingsEqual = \n JSON.stringify(a.gridSettings ?? {}) === JSON.stringify(b.gridSettings ?? {});\n return arePartsEqual(a.parts, b.parts) &&\n a.showGrid === b.showGrid &&\n a.scene === b.scene &&\n a.showBackground === b.showBackground &&\n a.winterMode === b.winterMode &&\n a.springMode === b.springMode &&\n a.cameraOffsetX === b.cameraOffsetX &&\n a.cameraZoom === b.cameraZoom &&\n a.frameQuality === b.frameQuality &&\n gridSettingsEqual;\n }\n return false;\n };\n\n // Effect to call API when input changes\n useEffect(() => {\n const shouldFetch = !areInputsEqual(previousInputRef.current as SpriteRenderInput | null, normalizedInput);\n\n if (shouldFetch) {\n previousInputRef.current = normalizedInput;\n fetchRenderSprite(normalizedInput);\n }\n }, [normalizedInput, fetchRenderSprite]);\n\n // Cleanup effect for component unmount\n useEffect(() => {\n return () => {\n if (spriteSrc && spriteSrc.startsWith(\"blob:\")) {\n URL.revokeObjectURL(spriteSrc);\n }\n };\n }, [spriteSrc]);\n\n return {\n spriteSrc,\n isRenderingSprite,\n renderError,\n spriteMetadata,\n };\n};\n","import React from \"react\";\n\ninterface LoadingErrorOverlayProps {\n isVisible: boolean;\n renderError?: string;\n size: number;\n}\n\nexport const LoadingErrorOverlay: React.FC<LoadingErrorOverlayProps> = ({\n isVisible,\n renderError,\n size,\n}) => {\n if (!isVisible) return null;\n\n return (\n <div\n style={{\n position: \"absolute\",\n top: 0,\n left: 0,\n right: 0,\n bottom: 0,\n backgroundColor: \"rgba(0, 0, 0, 1)\",\n display: \"flex\",\n flexDirection: \"column\",\n alignItems: \"center\",\n justifyContent: \"center\",\n color: \"white\",\n zIndex: 10,\n }}\n >\n {renderError ? (\n <>\n <div\n style={{ marginBottom: \"20px\", fontSize: \"18px\", color: \"white\" }}\n >\n Render Failed\n </div>\n <div\n style={{\n fontSize: \"14px\",\n textAlign: \"center\",\n maxWidth: size * 0.8,\n color: \"white\",\n }}\n >\n {renderError}\n </div>\n </>\n ) : (\n <>\n <div\n style={{ marginBottom: \"20px\", fontSize: \"18px\", color: \"white\" }}\n >\n {\"Loading Build...\"}\n </div>\n </>\n )}\n </div>\n );\n};\n","import React from \"react\";\n\ninterface DragIconProps {\n width?: number;\n height?: number;\n className?: string;\n style?: React.CSSProperties;\n}\n\nexport const DragIcon: React.FC<DragIconProps> = ({\n width = 24,\n height = 24,\n className,\n style,\n ...props\n}) => {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n id=\"Layer_1\"\n width={width}\n height={height}\n data-name=\"Layer 1\"\n viewBox=\"0 0 24 24\"\n className={className}\n style={style}\n {...props}\n >\n <defs>\n <style>\n {\n \".cls-1{fill:none;stroke:currentColor;stroke-miterlimit:10;stroke-width:1.91px}\"\n }\n </style>\n </defs>\n <path\n d=\"m11.05 22.5-5.14-5.14a2 2 0 0 1-.59-1.43 2 2 0 0 1 2-2 2 2 0 0 1 1.43.59l1.32 1.32V6.38a2 2 0 0 1 1.74-2 1.89 1.89 0 0 1 1.52.56 1.87 1.87 0 0 1 .56 1.34V12l5 .72a1.91 1.91 0 0 1 1.64 1.89 17.18 17.18 0 0 1-1.82 7.71l-.09.18M19.64 7.23l2.86-2.87-2.86-2.86M15.82 4.36h6.68M4.36 7.23 1.5 4.36 4.36 1.5M8.18 4.36H1.5\"\n className=\"cls-1\"\n />\n </svg>\n );\n};\n","import React from \"react\";\nimport { DragIcon } from \"./DragIcon\";\n\ninterface InstructionTooltipProps {\n isVisible: boolean;\n progressValue: number;\n instructionIcon?: string;\n}\n\nexport const InstructionTooltip: React.FC<InstructionTooltipProps> = ({\n isVisible,\n progressValue,\n instructionIcon,\n}) => {\n if (!isVisible) {\n return null;\n }\n\n return (\n <div\n style={{\n position: \"absolute\",\n top: \"50%\",\n left: \"50%\",\n transform: `translate(-50%, -50%) translateX(${progressValue * 50}px)`,\n backgroundColor: \"rgba(0, 0, 0, 0.8)\",\n color: \"white\",\n padding: \"12px\",\n borderRadius: \"8px\",\n pointerEvents: \"none\",\n zIndex: 5,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n }}\n >\n {instructionIcon ? (\n <img\n src={instructionIcon}\n alt=\"drag to view 360\"\n style={{\n width: \"24px\",\n height: \"24px\",\n filter: \"invert(1)\", // Makes the icon white\n }}\n />\n ) : (\n <DragIcon\n width={24}\n height={24}\n style={{\n color: \"white\",\n }}\n />\n )}\n </div>\n );\n};\n","import {\n useCallback,\n useEffect,\n useRef,\n useState,\n type TouchEvent as ReactTouchEvent,\n type WheelEvent as ReactWheelEvent,\n} from \"react\";\n\ninterface UseZoomOptions {\n displayWidth?: number;\n displayHeight?: number;\n minScale?: number;\n maxScale?: number;\n initialScale?: number;\n}\n\ninterface UseZoomReturn {\n scale: number;\n isPinching: boolean;\n handleWheel: (event: ReactWheelEvent<Element>) => void;\n handleTouchStart: (event: ReactTouchEvent<HTMLCanvasElement>) => boolean;\n reset: () => void;\n}\n\nconst clamp = (value: number, min: number, max: number) =>\n Math.min(Math.max(value, min), max);\n\nconst getTouchDistance = (touches: TouchList | React.TouchList) => {\n const first = touches[0];\n const second = touches[1];\n if (!first || !second) return 0;\n return Math.hypot(\n second.clientX - first.clientX,\n second.clientY - first.clientY\n );\n};\n\nexport const useZoomPan = ({\n displayWidth,\n displayHeight,\n minScale = 0.5,\n maxScale = 2.5,\n initialScale = 1,\n}: UseZoomOptions = {}): UseZoomReturn => {\n const [scale, setScale] = useState(initialScale);\n const [isPinching, setIsPinching] = useState(false);\n\n const scaleRef = useRef(initialScale);\n const pinchDataRef = useRef({\n initialDistance: 0,\n initialScale: 1,\n });\n\n const setScaleSafe = useCallback(\n (next: number) => {\n const clamped = clamp(next, minScale, maxScale);\n if (clamped === scaleRef.current) return;\n\n scaleRef.current = clamped;\n setScale(clamped);\n },\n [minScale, maxScale]\n );\n\n const handleWheel = useCallback(\n (event: ReactWheelEvent<Element>) => {\n event.preventDefault();\n event.stopPropagation();\n\n const deltaY =\n event.deltaMode === 1\n ? event.deltaY * 16\n : event.deltaMode === 2\n ? event.deltaY * (displayHeight ?? 300)\n : event.deltaY;\n\n const zoomFactor = Math.exp(-deltaY * 0.0015);\n const nextScale = scaleRef.current * zoomFactor;\n setScaleSafe(nextScale);\n },\n [setScaleSafe, displayHeight]\n );\n\n const handleTouchStart = useCallback(\n (event: ReactTouchEvent<HTMLCanvasElement>) => {\n if (event.touches.length < 2) {\n return false;\n }\n\n const distance = getTouchDistance(event.touches);\n if (!distance) {\n return false;\n }\n\n pinchDataRef.current = {\n initialDistance: distance,\n initialScale: scaleRef.current,\n };\n setIsPinching(true);\n event.preventDefault();\n return true;\n },\n []\n );\n\n useEffect(() => {\n if (!isPinching) return;\n\n const handleMove = (event: TouchEvent) => {\n if (event.touches.length < 2) return;\n const distance = getTouchDistance(event.touches);\n if (!distance || pinchDataRef.current.initialDistance === 0) return;\n\n const scaleFactor =\n distance / pinchDataRef.current.initialDistance;\n const nextScale = pinchDataRef.current.initialScale * scaleFactor;\n setScaleSafe(nextScale);\n event.preventDefault();\n };\n\n const handleEnd = (event: TouchEvent) => {\n if (event.touches.length < 2) {\n setIsPinching(false);\n }\n };\n\n window.addEventListener(\"touchmove\", handleMove, { passive: false });\n window.addEventListener(\"touchend\", handleEnd);\n window.addEventListener(\"touchcancel\", handleEnd);\n\n return () => {\n window.removeEventListener(\"touchmove\", handleMove);\n window.removeEventListener(\"touchend\", handleEnd);\n window.removeEventListener(\"touchcancel\", handleEnd);\n };\n }, [isPinching, setScaleSafe]);\n\n const reset = useCallback(() => {\n scaleRef.current = initialScale;\n setScale(initialScale);\n }, [initialScale]);\n\n return {\n scale,\n isPinching,\n handleWheel,\n handleTouchStart,\n reset,\n };\n};\n\n","import { useRef, useState, useCallback, useEffect, useMemo } from \"react\";\nimport { useSpriteScrubbing } from \"./hooks/useSpriteScrubbing\";\nimport { useBouncePatternProgress } from \"./hooks/useProgressOneSecond\";\nimport { useContinuousSpin } from \"./hooks/useContinuousSpin\";\nimport { useSpriteRender, SpriteRenderInput } from \"./hooks/useSpriteRender\";\nimport { BuildRenderProps } from \"./types\";\nimport { LoadingErrorOverlay } from \"./components/LoadingErrorOverlay\";\nimport { InstructionTooltip } from \"./components/InstructionTooltip\";\nimport { useZoomPan } from \"./hooks/useZoomPan\";\nimport type { WheelEvent as ReactWheelEvent } from \"react\";\n\nexport const BuildRender: React.FC<BuildRenderProps> = ({\n parts,\n shareCode,\n width,\n height,\n size,\n apiConfig,\n useSpriteRenderOptions,\n mouseSensitivity = 0.2,\n touchSensitivity = 0.2,\n showGrid,\n scene,\n showBackground,\n winterMode,\n springMode,\n cameraOffsetX,\n cameraZoom,\n gridSettings,\n animationMode = 'bounce',\n spinDuration = 10000,\n interactive = true,\n frameQuality,\n zoom = 1,\n}) => {\n const canvasRef = useRef<HTMLCanvasElement | null>(null);\n const containerRef = useRef<HTMLDivElement | null>(null);\n const [img, setImg] = useState<HTMLImageElement | null>(null);\n const [isLoading, setIsLoading] = useState(true);\n const [bouncingAllowed, setBouncingAllowed] = useState(false);\n\n const displayW = width ?? size ?? 300;\n const displayH = height ?? size ?? 300;\n\n // Build the render input - prefer shareCode if provided (preserves interactive state like case fan slots)\n const renderInput: SpriteRenderInput = useMemo(() => {\n const resolvedShowGrid = showGrid ?? parts?.showGrid;\n const resolvedScene = scene ?? parts?.scene;\n const resolvedShowBackground = showBackground ?? parts?.showBackground;\n const resolvedWinterMode = winterMode ?? parts?.winterMode;\n const resolvedSpringMode = springMode ?? parts?.springMode;\n const resolvedCameraOffsetX = cameraOffsetX ?? parts?.cameraOffsetX;\n const resolvedCameraZoom = cameraZoom ?? parts?.cameraZoom;\n const resolvedGridSettings = gridSettings ?? parts?.gridSettings;\n const resolvedFrameQuality = frameQuality ?? parts?.frameQuality;\n\n if (shareCode) {\n return { \n type: 'shareCode', \n shareCode, \n profile: parts?.profile,\n showGrid: resolvedShowGrid,\n scene: resolvedScene,\n showBackground: resolvedShowBackground,\n winterMode: resolvedWinterMode,\n springMode: resolvedSpringMode,\n cameraOffsetX: resolvedCameraOffsetX,\n cameraZoom: resolvedCameraZoom,\n gridSettings: resolvedGridSettings,\n frameQuality: resolvedFrameQuality,\n };\n }\n return { \n type: 'parts', \n parts: parts!,\n showGrid: resolvedShowGrid,\n scene: resolvedScene,\n showBackground: resolvedShowBackground,\n winterMode: resolvedWinterMode,\n springMode: resolvedSpringMode,\n cameraOffsetX: resolvedCameraOffsetX,\n cameraZoom: resolvedCameraZoom,\n gridSettings: resolvedGridSettings,\n frameQuality: resolvedFrameQuality,\n };\n }, [shareCode, parts, showGrid, scene, showBackground, winterMode, springMode, cameraOffsetX, cameraZoom, gridSettings, frameQuality]);\n\n // Use custom hook for sprite rendering\n const { spriteSrc, isRenderingSprite, renderError, spriteMetadata } =\n useSpriteRender(renderInput, apiConfig, undefined, useSpriteRenderOptions);\n\n const total = spriteMetadata ? spriteMetadata.totalFrames : 72;\n\n // Animation hooks - only one will be active based on animationMode\n const { value: progressValue, isBouncing } =\n useBouncePatternProgress(bouncingAllowed && animationMode === 'bounce');\n \n const spinResult = useContinuousSpin(\n bouncingAllowed && animationMode === 'spin360',\n spinDuration,\n total\n );\n const cols = spriteMetadata ? spriteMetadata.cols : 12;\n const rows = spriteMetadata ? spriteMetadata.rows : 6;\n const frameRef = useRef(0);\n\n const {\n scale,\n handleWheel: handleZoomWheel,\n handleTouchStart: handleZoomTouchStart,\n reset: resetZoom,\n } = useZoomPan({\n displayWidth: displayW,\n displayHeight: displayH,\n initialScale: zoom,\n });\n\n // Image/frame sizes - only calculate if image dimensions match expected metadata\n // This prevents using stale image with new metadata during transitions\n const frameW = img ? img.width / cols : 0;\n const frameH = img ? img.height / rows : 0;\n \n // Track expected rows to detect stale images\n const expectedRowsRef = useRef(rows);\n expectedRowsRef.current = rows;\n\n // ---- Load sprite image ----\n useEffect(() => {\n if (!spriteSrc) {\n setImg(null);\n setIsLoading(true);\n return;\n }\n\n // Clear current image immediately when source changes to prevent \n // using old image with new metadata\n setImg(null);\n setIsLoading(true);\n setBouncingAllowed(false);\n \n const i = new Image();\n i.decoding = \"async\";\n i.loading = \"eager\";\n i.src = spriteSrc;\n i.onload = () => {\n // Only set the image if rows haven't changed since we started loading\n // This prevents race conditions where metadata updates mid-load\n setImg(i);\n setIsLoading(false);\n // Start bouncing animation after delay\n setTimeout(() => {\n setBouncingAllowed(true);\n }, 2000);\n };\n i.onerror = () => {\n setImg(null);\n setIsLoading(false);\n };\n \n // Cleanup: if this effect re-runs (due to spriteSrc or rows change), \n // the new effect will clear the image\n return () => {\n // Abort loading if component updates before load completes\n i.onload = null;\n i.onerror = null;\n };\n }, [spriteSrc, rows]);\n\n // ---- Drawing function with optional cross-fade interpolation ----\n const draw = useCallback(\n (frameIndex: number, nextFrameIndex?: number, blend?: number) => {\n const cnv = canvasRef.current;\n if (!cnv || !img || !frameW || !frameH) return;\n\n const ctx = cnv.getContext(\"2d\");\n if (!ctx) return;\n\n // Backing store sized for HiDPI; CSS size stays `size`\n const dpr = Math.max(1, window.devicePixelRatio || 1);\n const targetW = Math.round(displayW * dpr);\n const targetH = Math.round(displayH * dpr);\n if (cnv.width !== targetW || cnv.height !== targetH) {\n cnv.width = targetW;\n cnv.height = targetH;\n }\n\n // Calculate destination dimensions (letterboxing)\n const sw = Math.round(frameW);\n const sh = Math.round(frameH);\n const frameAspect = sw / sh;\n const canvasAspect = targetW / targetH;\n\n let drawW: number, drawH: number;\n if (frameAspect > canvasAspect) {\n drawW = targetW;\n drawH = targetW / frameAspect;\n } else {\n drawH = targetH;\n drawW = targetH * frameAspect;\n }\n\n // Apply zoom scale\n drawW *= scale;\n drawH *= scale;\n\n // Center in canvas\n const drawX = (targetW - drawW) / 2;\n const drawY = (targetH - drawH) / 2;\n\n ctx.clearRect(0, 0, targetW, targetH);\n ctx.imageSmoothingEnabled = true;\n ctx.imageSmoothingQuality = \"high\";\n\n // Helper to draw a specific frame\n const drawFrame = (frameIdx: number, opacity: number) => {\n let n = Math.round(frameIdx) % total;\n if (n < 0) n += total;\n \n const r = Math.floor(n / cols);\n const c = n % cols;\n const sx = Math.round(c * frameW);\n const sy = Math.round(r * frameH);\n\n ctx.globalAlpha = opacity;\n ctx.drawImage(img, sx, sy, sw, sh, drawX, drawY, drawW, drawH);\n };\n\n // Cross-fade interpolation for smooth animation\n if (nextFrameIndex !== undefined && blend !== undefined && blend > 0.01) {\n // Draw current frame at full opacity first\n drawFrame(frameIndex, 1);\n // Then overlay next frame with blend opacity for smooth transition\n drawFrame(nextFrameIndex, blend);\n ctx.globalAlpha = 1; // Reset\n } else {\n // Single frame draw (no interpolation)\n drawFrame(frameIndex, 1);\n }\n },\n [img, frameW, frameH, displayW, displayH, cols, rows, total, scale]\n );\n\n const { isDragging, handleMouseDown, handleTouchStart, hasDragged } =\n useSpriteScrubbing(canvasRef, total, {\n mouseSensitivity,\n touchSensitivity,\n onFrameChange: (newFrame: number) => {\n frameRef.current = newFrame;\n draw(newFrame);\n },\n });\n\n const handleLoadStartInternal = useCallback(() => {\n setIsLoading(true);\n setBouncingAllowed(false);\n }, []);\n\n // Auto-rotate when animation is allowed and user hasn't manually dragged\n useEffect(() => {\n if ((interactive && hasDragged.current) || !img) return;\n\n if (animationMode === 'spin360') {\n // Continuous 360 spin with cross-fade interpolation for smoothness\n frameRef.current = spinResult.frame;\n draw(spinResult.frame, spinResult.nextFrame, spinResult.blend);\n } else {\n // Bounce animation (no interpolation needed - it pauses between movements)\n const frame = ((progressValue / 5) * total) % total;\n frameRef.current = frame;\n draw(frame);\n }\n }, [progressValue, spinResult, hasDragged, img, total, draw, animationMode, interactive]);\n\n // Reset zoom when sprite changes or container size updates\n useEffect(() => {\n resetZoom();\n }, [spriteSrc, displayW, displayH, resetZoom]);\n\n // Add native wheel event listener to prevent scrolling AND handle zoom (only when interactive)\n useEffect(() => {\n const container = containerRef.current;\n if (!container || !interactive) return;\n\n const handleNativeWheel = (event: WheelEvent) => {\n event.preventDefault();\n event.stopPropagation();\n \n // Manually trigger zoom since we're preventing the React event\n const deltaY =\n event.deltaMode === 1\n ? event.deltaY * 16\n : event.deltaMode === 2\n ? event.deltaY * (displayH ?? 300)\n : event.deltaY;\n\n const zoomFactor = Math.exp(-deltaY * 0.0015);\n const nextScale = scale * zoomFactor;\n \n // We need to call the zoom handler directly\n // Create a synthetic React event-like object\n const syntheticEvent = {\n preventDefault: () => {},\n stopPropagation: () => {},\n deltaY: event.deltaY,\n deltaMode: event.deltaMode,\n currentTarget: container,\n } as any;\n \n handleZoomWheel(syntheticEvent);\n hasDragged.current = true;\n };\n\n // Add listener to container to catch all wheel events\n container.addEventListener('wheel', handleNativeWheel, { passive: false });\n\n return () => {\n container.removeEventListener('wheel', handleNativeWheel);\n };\n }, [handleZoomWheel, scale, displayH, interactive]);\n\n // Initial draw once image is ready or zoom changes\n useEffect(() => {\n if (img && !isLoading) {\n draw(frameRef.current);\n }\n }, [img, isLoading, draw]);\n\n const handleCanvasTouchStart = useCallback(\n (event: React.TouchEvent<HTMLCanvasElement>) => {\n if (handleZoomTouchStart(event)) {\n hasDragged.current = true;\n return;\n }\n\n handleTouchStart(event);\n },\n [handleZoomTouchStart, handleTouchStart, hasDragged]\n );\n\n const handleCanvasWheel = useCallback(\n (event: ReactWheelEvent<Element>) => {\n hasDragged.current = true;\n handleZoomWheel(event);\n },\n [handleZoomWheel, hasDragged]\n );\n\n return (\n <div\n ref={containerRef}\n style={{\n position: \"relative\",\n width: displayW,\n height: displayH,\n backgroundColor: \"black\",\n overflow: \"hidden\",\n }}\n >\n {img && (\n <canvas\n ref={canvasRef}\n onMouseDown={interactive ? handleMouseDown : undefined}\n onTouchStart={interactive ? handleCanvasTouchStart : undefined}\n style={{\n width: displayW,\n height: displayH,\n cursor: interactive ? (isDragging ? \"grabbing\" : \"grab\") : \"pointer\",\n touchAction: interactive ? \"none\" : \"auto\",\n display: \"block\",\n userSelect: \"none\",\n WebkitUserSelect: \"none\",\n WebkitTouchCallout: \"none\",\n pointerEvents: interactive ? \"auto\" : \"none\", // Allow click-through when not interactive\n }}\n role=\"img\"\n aria-label=\"360° viewer\"\n onContextMenu={interactive ? (e) => e.preventDefault() : undefined}\n />\n )}\n\n <LoadingErrorOverlay\n isVisible={isLoading || isRenderingSprite || !!renderError}\n renderError={renderError || undefined}\n size={Math.min(displayW, displayH)}\n />\n\n <InstructionTooltip\n isVisible={\n interactive &&\n animationMode === 'bounce' &&\n !isLoading &&\n !isRenderingSprite &&\n !renderError &&\n isBouncing &&\n !hasDragged.current\n }\n progressValue={progressValue}\n />\n </div>\n );\n};\n","import {\n useState,\n useRef,\n useEffect,\n useCallback,\n type RefObject,\n} from \"react\";\n\n// Helper to extract clientX from mouse or touch events\nconst getClientX = (e: MouseEvent | TouchEvent): number => {\n return \"touches\" in e ? e.touches[0].clientX : e.clientX;\n};\n\n// Helper to calculate new video time with circular wrapping\nexport const calculateCircularTime = (\n startTime: number,\n deltaX: number,\n sensitivity: number,\n duration: number\n): number => {\n const timeDelta = deltaX * sensitivity;\n let newTime = startTime + timeDelta;\n\n // Make it circular - wrap around when going past boundaries\n newTime = newTime % duration;\n if (newTime < 0) {\n newTime += duration;\n }\n\n return newTime;\n};\n\ninterface UseVideoScrubbingOptions {\n mouseSensitivity?: number;\n touchSensitivity?: number;\n progressSensitivity?: number;\n useProgressScrubbing?: boolean;\n}\n\nexport const useVideoScrubbing = (\n videoRef: RefObject<HTMLVideoElement | null>,\n options: UseVideoScrubbingOptions = {}\n) => {\n const { mouseSensitivity = 0.01, touchSensitivity = 0.01 } = options;\n\n const [isDragging, setIsDragging] = useState(false);\n const [dragStartX, setDragStartX] = useState(0);\n const [dragStartTime, setDragStartTime] = useState(0);\n const hasDragged = useRef(false);\n\n // Helper to start dragging (common logic for mouse and touch)\n const startDrag = useCallback(\n (clientX: number, event: Event) => {\n if (!videoRef.current) return;\n\n setIsDragging(true);\n setDragStartX(clientX);\n setDragStartTime(videoRef.current.currentTime);\n hasDragged.current = true;\n event.preventDefault();\n },\n [videoRef]\n );\n\n // Helper to handle drag movement (common logic for mouse and touch)\n const handleDragMove = useCallback(\n (clientX: number, sensitivity: number) => {\n if (!isDragging || !videoRef.current) return;\n\n const deltaX = clientX - dragStartX;\n const duration = videoRef.current.duration || 0;\n\n if (duration > 0) {\n const newTime = calculateCircularTime(\n dragStartTime,\n deltaX,\n sensitivity,\n duration\n );\n videoRef.current.currentTime = newTime;\n }\n },\n [isDragging, dragStartX, dragStartTime, videoRef]\n );\n\n // Helper to end dragging (common logic for mouse and touch)\n const endDrag = useCallback(() => {\n setIsDragging(false);\n }, []);\n\n const handleMouseDown = useCallback(\n (e: React.MouseEvent) => {\n startDrag(e.clientX, e.nativeEvent);\n },\n [startDrag]\n );\n\n const handleTouchStart = useCallback(\n (e: React.TouchEvent) => {\n startDrag(e.touches[0].clientX, e.nativeEvent);\n },\n [startDrag]\n );\n\n const handleDocumentMouseMove = useCallback(\n (e: MouseEvent) => {\n handleDragMove(getClientX(e), mouseSensitivity);\n },\n [handleDragMove, mouseSensitivity]\n );\n\n const handleDocumentTouchMove = useCallback(\n (e: TouchEvent) => {\n handleDragMove(getClientX(e), touchSensitivity);\n },\n [handleDragMove, touchSensitivity]\n );\n\n const handleDocumentMouseUp = useCallback(() => {\n endDrag();\n }, [endDrag]);\n\n const handleDocumentTouchEnd = useCallback(() => {\n endDrag();\n }, [endDrag]);\n\n // Add document-level event listeners when dragging starts\n useEffect(() => {\n if (isDragging) {\n document.addEventListener(\"mousemove\", handleDocumentMouseMove);\n document.addEventListener(\"mouseup\", handleDocumentMouseUp);\n document.addEventListener(\"touchmove\", handleDocumentTouchMove);\n document.addEventListener(\"touchend\", handleDocumentTouchEnd);\n\n return () => {\n document.removeEventListener(\"mousemove\", handleDocumentMouseMove);\n document.removeEventListener(\"mouseup\", handleDocumentMouseUp);\n document.removeEventListener(\"touchmove\", handleDocumentTouchMove);\n document.removeEventListener(\"touchend\", handleDocumentTouchEnd);\n };\n }\n }, [\n isDragging,\n handleDocumentMouseMove,\n handleDocumentMouseUp,\n handleDocumentTouchMove,\n handleDocumentTouchEnd,\n ]);\n\n return {\n isDragging,\n handleMouseDown,\n handleTouchStart,\n hasDragged,\n };\n};\n","import { useRef, useState, useCallback, useEffect } from \"react\";\nimport {\n calculateCircularTime,\n useVideoScrubbing,\n} from \"./hooks/useVideoScrubbing\";\nimport { useBouncePatternProgress } from \"./hooks/useProgressOneSecond\";\nimport { useBuildRender } from \"./hooks/useBuildRender\";\nimport { BuildRenderVideoProps } from \"./types\";\nimport { LoadingErrorOverlay } from \"./components/LoadingErrorOverlay\";\nimport { InstructionTooltip } from \"./components/InstructionTooltip\";\n\nexport const BuildRenderVideo: React.FC<BuildRenderVideoProps> = ({\n parts,\n width,\n height,\n size,\n apiConfig,\n useBuildRenderOptions,\n mouseSensitivity = 0.01,\n touchSensitivity = 0.01,\n}) => {\n const videoRef = useRef<HTMLVideoElement | null>(null);\n const [isLoading, setIsLoading] = useState(true);\n const [bouncingAllowed, setBouncingAllowed] = useState(false);\n\n const displayW = width ?? size ?? 300;\n const displayH = height ?? size ?? 300;\n\n // Use custom hook for build rendering\n const { videoSrc, isRenderingBuild, renderError } = useBuildRender(\n parts,\n apiConfig,\n undefined,\n useBuildRenderOptions\n );\n\n const { value: progressValue, isBouncing } =\n useBouncePatternProgress(bouncingAllowed);\n\n const { isDragging, handleMouseDown, handleTouchStart, hasDragged } =\n useVideoScrubbing(videoRef, {\n mouseSensitivity,\n touchSensitivity,\n });\n\n const handleLoadStartInternal = useCallback(() => {\n setIsLoading(true);\n setBouncingAllowed(false);\n }, []);\n\n const handleCanPlayInternal = useCallback(() => {\n setIsLoading(false);\n // Start bouncing animation after delay\n setTimeout(() => {\n setBouncingAllowed(true);\n }, 2000);\n }, []);\n\n useEffect(() => {\n if (hasDragged.current || !videoRef.current) return;\n\n const duration = videoRef.current.duration;\n if (!isFinite(duration)) return;\n\n const time = calculateCircularTime(0, progressValue, 0.5, duration);\n\n if (isFinite(time)) {\n videoRef.current.currentTime = time;\n }\n }, [progressValue, hasDragged]);\n\n return (\n <div style={{ position: \"relative\", width: displayW, height: displayH }}>\n {videoSrc && (\n <video\n key={videoSrc} // Force React to recreate video element when src changes\n ref={videoRef}\n src={videoSrc} // Set src directly on video element\n width={displayW}\n height={displayH}\n autoPlay={true}\n preload=\"metadata\"\n muted\n playsInline\n controls={false}\n disablePictureInPicture\n controlsList=\"nodownload nofullscreen noremoteplayback\"\n {...({ \"x-webkit-airplay\": \"deny\" } as any)}\n onMouseDown={handleMouseDown}\n onTouchStart={handleTouchStart}\n onLoadStart={handleLoadStartInternal}\n onCanPlay={handleCanPlayInternal}\n onLoadedData={() => {\n if (videoRef.current) {\n videoRef.current.pause();\n }\n }}\n style={\n {\n cursor: isDragging ? \"grabbing\" : \"grab\",\n touchAction: \"none\", // Prevents default touch behaviors like scrolling\n display: \"block\",\n // Completely hide video controls on all browsers including mobile\n WebkitMediaControls: \"none\",\n MozMediaControls: \"none\",\n OMediaControls: \"none\",\n msMediaControls: \"none\",\n mediaControls: \"none\",\n // Additional iOS-specific properties\n WebkitTouchCallout: \"none\",\n WebkitUserSelect: \"none\",\n userSelect: \"none\",\n } as React.CSSProperties\n }\n >\n Your browser does not support the video tag.\n </video>\n )}\n\n <LoadingErrorOverlay\n isVisible={isLoading || isRenderingBuild || !!renderError}\n renderError={renderError || undefined}\n size={Math.min(displayW, displayH)}\n />\n\n <InstructionTooltip\n isVisible={\n !isLoading &&\n !isRenderingBuild &&\n !renderError &&\n isBouncing &&\n !hasDragged.current\n }\n progressValue={progressValue}\n />\n </div>\n );\n};\n"],"names":["getClientX","useState","useRef","useCallback","useEffect","useAnimationFrame","PartCategory","_jsx","_jsxs","_Fragment","useMemo"],"mappings":"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"}
|