@buildcores/render-client 1.0.5 → 1.0.6

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/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../src/hooks/useSpriteScrubbing.ts","../node_modules/framer-motion/dist/es/context/MotionConfigContext.mjs","../node_modules/motion-utils/dist/es/noop.mjs","../node_modules/motion-utils/dist/es/errors.mjs","../node_modules/framer-motion/dist/es/frameloop/render-step.mjs","../node_modules/framer-motion/dist/es/frameloop/batcher.mjs","../node_modules/framer-motion/dist/es/frameloop/frame.mjs","../node_modules/framer-motion/dist/es/utils/use-animation-frame.mjs","../src/hooks/useProgressOneSecond.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/BuildRender.tsx","../src/hooks/useVideoScrubbing.ts"],"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","\"use client\";\nimport { createContext } from 'react';\n\n/**\n * @public\n */\nconst MotionConfigContext = createContext({\n transformPagePoint: (p) => p,\n isStatic: false,\n reducedMotion: \"never\",\n});\n\nexport { MotionConfigContext };\n","/*#__NO_SIDE_EFFECTS__*/\nconst noop = (any) => any;\n\nexport { noop };\n","import { noop } from './noop.mjs';\n\nlet warning = noop;\nlet invariant = noop;\nif (process.env.NODE_ENV !== \"production\") {\n warning = (check, message) => {\n if (!check && typeof console !== \"undefined\") {\n console.warn(message);\n }\n };\n invariant = (check, message) => {\n if (!check) {\n throw new Error(message);\n }\n };\n}\n\nexport { invariant, warning };\n","function createRenderStep(runNextFrame) {\n /**\n * We create and reuse two queues, one to queue jobs for the current frame\n * and one for the next. We reuse to avoid triggering GC after x frames.\n */\n let thisFrame = new Set();\n let nextFrame = new Set();\n /**\n * Track whether we're currently processing jobs in this step. This way\n * we can decide whether to schedule new jobs for this frame or next.\n */\n let isProcessing = false;\n let flushNextFrame = false;\n /**\n * A set of processes which were marked keepAlive when scheduled.\n */\n const toKeepAlive = new WeakSet();\n let latestFrameData = {\n delta: 0.0,\n timestamp: 0.0,\n isProcessing: false,\n };\n function triggerCallback(callback) {\n if (toKeepAlive.has(callback)) {\n step.schedule(callback);\n runNextFrame();\n }\n callback(latestFrameData);\n }\n const step = {\n /**\n * Schedule a process to run on the next frame.\n */\n schedule: (callback, keepAlive = false, immediate = false) => {\n const addToCurrentFrame = immediate && isProcessing;\n const queue = addToCurrentFrame ? thisFrame : nextFrame;\n if (keepAlive)\n toKeepAlive.add(callback);\n if (!queue.has(callback))\n queue.add(callback);\n return callback;\n },\n /**\n * Cancel the provided callback from running on the next frame.\n */\n cancel: (callback) => {\n nextFrame.delete(callback);\n toKeepAlive.delete(callback);\n },\n /**\n * Execute all schedule callbacks.\n */\n process: (frameData) => {\n latestFrameData = frameData;\n /**\n * If we're already processing we've probably been triggered by a flushSync\n * inside an existing process. Instead of executing, mark flushNextFrame\n * as true and ensure we flush the following frame at the end of this one.\n */\n if (isProcessing) {\n flushNextFrame = true;\n return;\n }\n isProcessing = true;\n [thisFrame, nextFrame] = [nextFrame, thisFrame];\n // Execute this frame\n thisFrame.forEach(triggerCallback);\n // Clear the frame so no callbacks remain. This is to avoid\n // memory leaks should this render step not run for a while.\n thisFrame.clear();\n isProcessing = false;\n if (flushNextFrame) {\n flushNextFrame = false;\n step.process(frameData);\n }\n },\n };\n return step;\n}\n\nexport { createRenderStep };\n","import { MotionGlobalConfig } from '../utils/GlobalConfig.mjs';\nimport { createRenderStep } from './render-step.mjs';\n\nconst stepsOrder = [\n \"read\", // Read\n \"resolveKeyframes\", // Write/Read/Write/Read\n \"update\", // Compute\n \"preRender\", // Compute\n \"render\", // Write\n \"postRender\", // Compute\n];\nconst maxElapsed = 40;\nfunction createRenderBatcher(scheduleNextBatch, allowKeepAlive) {\n let runNextFrame = false;\n let useDefaultElapsed = true;\n const state = {\n delta: 0.0,\n timestamp: 0.0,\n isProcessing: false,\n };\n const flagRunNextFrame = () => (runNextFrame = true);\n const steps = stepsOrder.reduce((acc, key) => {\n acc[key] = createRenderStep(flagRunNextFrame);\n return acc;\n }, {});\n const { read, resolveKeyframes, update, preRender, render, postRender } = steps;\n const processBatch = () => {\n const timestamp = MotionGlobalConfig.useManualTiming\n ? state.timestamp\n : performance.now();\n runNextFrame = false;\n state.delta = useDefaultElapsed\n ? 1000 / 60\n : Math.max(Math.min(timestamp - state.timestamp, maxElapsed), 1);\n state.timestamp = timestamp;\n state.isProcessing = true;\n // Unrolled render loop for better per-frame performance\n read.process(state);\n resolveKeyframes.process(state);\n update.process(state);\n preRender.process(state);\n render.process(state);\n postRender.process(state);\n state.isProcessing = false;\n if (runNextFrame && allowKeepAlive) {\n useDefaultElapsed = false;\n scheduleNextBatch(processBatch);\n }\n };\n const wake = () => {\n runNextFrame = true;\n useDefaultElapsed = true;\n if (!state.isProcessing) {\n scheduleNextBatch(processBatch);\n }\n };\n const schedule = stepsOrder.reduce((acc, key) => {\n const step = steps[key];\n acc[key] = (process, keepAlive = false, immediate = false) => {\n if (!runNextFrame)\n wake();\n return step.schedule(process, keepAlive, immediate);\n };\n return acc;\n }, {});\n const cancel = (process) => {\n for (let i = 0; i < stepsOrder.length; i++) {\n steps[stepsOrder[i]].cancel(process);\n }\n };\n return { schedule, cancel, state, steps };\n}\n\nexport { createRenderBatcher, stepsOrder };\n","import { noop } from 'motion-utils';\nimport { createRenderBatcher } from './batcher.mjs';\n\nconst { schedule: frame, cancel: cancelFrame, state: frameData, steps: frameSteps, } = createRenderBatcher(typeof requestAnimationFrame !== \"undefined\" ? requestAnimationFrame : noop, true);\n\nexport { cancelFrame, frame, frameData, frameSteps };\n","import { useRef, useContext, useEffect } from 'react';\nimport { MotionConfigContext } from '../context/MotionConfigContext.mjs';\nimport { frame, cancelFrame } from '../frameloop/frame.mjs';\n\nfunction useAnimationFrame(callback) {\n const initialTimestamp = useRef(0);\n const { isStatic } = useContext(MotionConfigContext);\n useEffect(() => {\n if (isStatic)\n return;\n const provideTimeSinceStart = ({ timestamp, delta }) => {\n if (!initialTimestamp.current)\n initialTimestamp.current = timestamp;\n callback(timestamp - initialTimestamp.current, delta);\n };\n frame.update(provideTimeSinceStart, true);\n return () => cancelFrame(provideTimeSinceStart);\n }, [callback]);\n}\n\nexport { useAnimationFrame };\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 { RenderBuildRequest, AvailablePartsResponse } from \"./types\";\n\n// API Configuration\nconst API_BASE_URL = \"https://squid-app-7aeyk.ondigitalocean.app\";\n\n// API Endpoints\nexport const API_ENDPOINTS = {\n RENDER_BUILD_EXPERIMENTAL: \"/render-build-experimental\",\n AVAILABLE_PARTS: \"/available-parts\",\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\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 * @returns Promise with the rendered MP4 video\n */\n renderBuildExperimental(\n parts: RenderBuildRequest\n ): Promise<RenderBuildResponse>;\n\n /**\n * Get available parts for building\n * @returns Promise with available parts by category\n */\n getAvailableParts(): Promise<AvailablePartsResponse>;\n}\n\n// API URL helpers\nexport const buildApiUrl = (endpoint: string): string => {\n return `${API_BASE_URL}${endpoint}`;\n};\n\n// API Implementation\nexport const renderBuildExperimental = async (\n request: RenderBuildRequest\n): Promise<RenderBuildResponse> => {\n const requestWithFormat = {\n ...request,\n format: request.format || \"video\", // Default to video format\n };\n\n const response = await fetch(\n buildApiUrl(API_ENDPOINTS.RENDER_BUILD_EXPERIMENTAL),\n {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n },\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\nexport const renderSpriteExperimental = async (\n request: RenderBuildRequest\n): Promise<RenderSpriteResponse> => {\n const requestWithFormat = {\n ...request,\n format: \"sprite\",\n };\n\n const response = await fetch(\n buildApiUrl(API_ENDPOINTS.RENDER_BUILD_EXPERIMENTAL),\n {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n },\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 (): Promise<AvailablePartsResponse> => {\n const response = await fetch(buildApiUrl(API_ENDPOINTS.AVAILABLE_PARTS), {\n method: \"GET\",\n headers: {\n \"Content-Type\": \"application/json\",\n },\n });\n\n if (!response.ok) {\n throw new Error(\n `Get available parts failed: ${response.status} ${response.statusText}`\n );\n }\n\n return response.json();\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 * Video size in pixels (width and height will be the same).\n *\n * This determines the resolution of the rendered 3D video. Higher values\n * provide better quality but may impact performance.\n *\n * @example\n * ```tsx\n * <BuildRender parts={parts} size={300} /> // 300x300px\n * <BuildRender parts={parts} size={500} /> // 500x500px\n * <BuildRender parts={parts} size={800} /> // 800x800px - high quality\n * ```\n *\n * Recommended sizes:\n * - 300px: Good for thumbnails or small previews\n * - 500px: Standard size for most use cases\n * - 800px+: High quality for detailed viewing\n */\n size: number;\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 * **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 * Sprite size in pixels (width and height will be the same).\n *\n * This determines the display size of the rendered 3D sprite. The sprite sheet\n * itself is rendered at a fixed resolution, but this controls the display size.\n *\n * @example\n * ```tsx\n * <SpriteRender parts={parts} size={300} /> // 300x300px\n * <SpriteRender parts={parts} size={500} /> // 500x500px\n * <SpriteRender parts={parts} size={800} /> // 800x800px - larger display\n * ```\n */\n size: number;\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// API Types\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}\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/**\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\nexport type AvailablePartsResponse = {\n [K in PartCategory]: PartDetails[];\n};\n","import { useState, useEffect, useCallback, useRef } from \"react\";\nimport { RenderBuildRequest, PartCategory } from \"../types\";\nimport { 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 const useBuildRender = (\n parts: RenderBuildRequest,\n onLoadStart?: () => void\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 response = await renderBuildExperimental(currentParts);\n const objectUrl = URL.createObjectURL(response.video);\n\n // Clean up previous video URL before setting new one\n setVideoSrc((prevSrc) => {\n if (prevSrc) {\n URL.revokeObjectURL(prevSrc);\n }\n return objectUrl;\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 [onLoadStart]\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) {\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 } from \"../types\";\nimport { renderSpriteExperimental } 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 const useSpriteRender = (\n parts: RenderBuildRequest,\n onLoadStart?: () => void\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 previousPartsRef = useRef<RenderBuildRequest | null>(null);\n\n const fetchRenderSprite = useCallback(\n async (currentParts: RenderBuildRequest) => {\n try {\n setIsRenderingSprite(true);\n setRenderError(null);\n onLoadStart?.();\n\n const response = await renderSpriteExperimental(currentParts);\n const objectUrl = URL.createObjectURL(response.sprite);\n\n // Clean up previous sprite URL before setting new one\n setSpriteSrc((prevSrc) => {\n if (prevSrc) {\n URL.revokeObjectURL(prevSrc);\n }\n return objectUrl;\n });\n\n // Set sprite metadata\n setSpriteMetadata({\n cols: response.metadata?.cols || 12,\n rows: response.metadata?.rows || 6,\n totalFrames: response.metadata?.totalFrames || 72,\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 [onLoadStart]\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 fetchRenderSprite(parts);\n }\n }, [parts, fetchRenderSprite]);\n\n // Cleanup effect for component unmount\n useEffect(() => {\n return () => {\n if (spriteSrc) {\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 { useRef, useState, useCallback, useEffect } from \"react\";\nimport { useSpriteScrubbing } from \"./hooks/useSpriteScrubbing\";\nimport { useBouncePatternProgress } from \"./hooks/useProgressOneSecond\";\nimport { useSpriteRender } from \"./hooks/useSpriteRender\";\nimport { BuildRenderProps } from \"./types\";\nimport { LoadingErrorOverlay } from \"./components/LoadingErrorOverlay\";\nimport { InstructionTooltip } from \"./components/InstructionTooltip\";\n\nexport const BuildRender: React.FC<BuildRenderProps> = ({\n parts,\n size,\n mouseSensitivity = 0.2,\n touchSensitivity = 0.2,\n}) => {\n const canvasRef = useRef<HTMLCanvasElement | null>(null);\n const [img, setImg] = useState<HTMLImageElement | null>(null);\n const [isLoading, setIsLoading] = useState(true);\n const [bouncingAllowed, setBouncingAllowed] = useState(false);\n\n // Use custom hook for sprite rendering\n const { spriteSrc, isRenderingSprite, renderError, spriteMetadata } =\n useSpriteRender(parts);\n\n const { value: progressValue, isBouncing } =\n useBouncePatternProgress(bouncingAllowed);\n\n const total = spriteMetadata ? spriteMetadata.totalFrames : 72;\n const cols = spriteMetadata ? spriteMetadata.cols : 12;\n const rows = spriteMetadata ? spriteMetadata.rows : 6;\n const frameRef = useRef(0);\n\n // Image/frame sizes\n const frameW = img ? img.width / cols : 0;\n const frameH = img ? img.height / rows : 0;\n\n // ---- Load sprite image ----\n useEffect(() => {\n if (!spriteSrc) {\n setImg(null);\n setIsLoading(true);\n return;\n }\n\n setIsLoading(true);\n const i = new Image();\n i.decoding = \"async\";\n i.loading = \"eager\";\n i.src = spriteSrc;\n i.onload = () => {\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 }, [spriteSrc]);\n\n // ---- Drawing function ----\n const draw = useCallback(\n (frameIndex: 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(size * dpr);\n const targetH = Math.round(size * dpr);\n if (cnv.width !== targetW || cnv.height !== targetH) {\n cnv.width = targetW;\n cnv.height = targetH;\n }\n\n // Snap to integer frame (never between tiles)\n let n = Math.round(frameIndex) % total;\n if (n < 0) n += total;\n\n const r = Math.floor(n / cols);\n const c = n % cols;\n\n // Use integer source rects to avoid sampling bleed across tiles\n const sx = Math.round(c * frameW);\n const sy = Math.round(r * frameH);\n const sw = Math.round(frameW);\n const sh = Math.round(frameH);\n\n ctx.clearRect(0, 0, targetW, targetH);\n ctx.imageSmoothingEnabled = true;\n ctx.imageSmoothingQuality = \"high\";\n ctx.drawImage(img, sx, sy, sw, sh, 0, 0, targetW, targetH);\n },\n [img, frameW, frameH, size, cols, total]\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 bouncing is allowed and not dragged\n useEffect(() => {\n if (hasDragged.current || !img) return;\n\n // Calculate frame based on progress value (similar to video time calculation)\n const frame = ((progressValue / 5) * total) % total;\n frameRef.current = frame;\n draw(frame);\n }, [progressValue, hasDragged, img, total, draw]);\n\n // Initial draw once image is ready\n useEffect(() => {\n if (img && !isLoading) {\n draw(frameRef.current);\n }\n }, [img, isLoading, draw]);\n\n return (\n <div\n style={{\n position: \"relative\",\n width: size,\n height: size,\n backgroundColor: \"black\",\n }}\n >\n {img && (\n <canvas\n ref={canvasRef}\n onMouseDown={handleMouseDown}\n onTouchStart={handleTouchStart}\n style={{\n width: size,\n height: size,\n cursor: isDragging ? \"grabbing\" : \"grab\",\n touchAction: \"none\", // Prevents default touch behaviors like scrolling\n display: \"block\",\n userSelect: \"none\",\n WebkitUserSelect: \"none\",\n WebkitTouchCallout: \"none\",\n }}\n role=\"img\"\n aria-label=\"360° viewer\"\n onContextMenu={(e) => e.preventDefault()}\n />\n )}\n\n <LoadingErrorOverlay\n isVisible={isLoading || isRenderingSprite || !!renderError}\n renderError={renderError || undefined}\n size={size}\n />\n\n <InstructionTooltip\n isVisible={\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"],"names":["getClientX","useState","useRef","useCallback","useEffect","createContext","useContext","PartCategory","_jsx","_jsxs","_Fragment"],"mappings":"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","x_google_ignoreList":[1,2,3,4,5,6,7]}
1
+ {"version":3,"file":"index.js","sources":["../src/hooks/useSpriteScrubbing.ts","../node_modules/framer-motion/dist/es/context/MotionConfigContext.mjs","../node_modules/motion-utils/dist/es/noop.mjs","../node_modules/motion-utils/dist/es/errors.mjs","../node_modules/framer-motion/dist/es/frameloop/render-step.mjs","../node_modules/framer-motion/dist/es/frameloop/batcher.mjs","../node_modules/framer-motion/dist/es/frameloop/frame.mjs","../node_modules/framer-motion/dist/es/utils/use-animation-frame.mjs","../src/hooks/useProgressOneSecond.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/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","\"use client\";\nimport { createContext } from 'react';\n\n/**\n * @public\n */\nconst MotionConfigContext = createContext({\n transformPagePoint: (p) => p,\n isStatic: false,\n reducedMotion: \"never\",\n});\n\nexport { MotionConfigContext };\n","/*#__NO_SIDE_EFFECTS__*/\nconst noop = (any) => any;\n\nexport { noop };\n","import { noop } from './noop.mjs';\n\nlet warning = noop;\nlet invariant = noop;\nif (process.env.NODE_ENV !== \"production\") {\n warning = (check, message) => {\n if (!check && typeof console !== \"undefined\") {\n console.warn(message);\n }\n };\n invariant = (check, message) => {\n if (!check) {\n throw new Error(message);\n }\n };\n}\n\nexport { invariant, warning };\n","function createRenderStep(runNextFrame) {\n /**\n * We create and reuse two queues, one to queue jobs for the current frame\n * and one for the next. We reuse to avoid triggering GC after x frames.\n */\n let thisFrame = new Set();\n let nextFrame = new Set();\n /**\n * Track whether we're currently processing jobs in this step. This way\n * we can decide whether to schedule new jobs for this frame or next.\n */\n let isProcessing = false;\n let flushNextFrame = false;\n /**\n * A set of processes which were marked keepAlive when scheduled.\n */\n const toKeepAlive = new WeakSet();\n let latestFrameData = {\n delta: 0.0,\n timestamp: 0.0,\n isProcessing: false,\n };\n function triggerCallback(callback) {\n if (toKeepAlive.has(callback)) {\n step.schedule(callback);\n runNextFrame();\n }\n callback(latestFrameData);\n }\n const step = {\n /**\n * Schedule a process to run on the next frame.\n */\n schedule: (callback, keepAlive = false, immediate = false) => {\n const addToCurrentFrame = immediate && isProcessing;\n const queue = addToCurrentFrame ? thisFrame : nextFrame;\n if (keepAlive)\n toKeepAlive.add(callback);\n if (!queue.has(callback))\n queue.add(callback);\n return callback;\n },\n /**\n * Cancel the provided callback from running on the next frame.\n */\n cancel: (callback) => {\n nextFrame.delete(callback);\n toKeepAlive.delete(callback);\n },\n /**\n * Execute all schedule callbacks.\n */\n process: (frameData) => {\n latestFrameData = frameData;\n /**\n * If we're already processing we've probably been triggered by a flushSync\n * inside an existing process. Instead of executing, mark flushNextFrame\n * as true and ensure we flush the following frame at the end of this one.\n */\n if (isProcessing) {\n flushNextFrame = true;\n return;\n }\n isProcessing = true;\n [thisFrame, nextFrame] = [nextFrame, thisFrame];\n // Execute this frame\n thisFrame.forEach(triggerCallback);\n // Clear the frame so no callbacks remain. This is to avoid\n // memory leaks should this render step not run for a while.\n thisFrame.clear();\n isProcessing = false;\n if (flushNextFrame) {\n flushNextFrame = false;\n step.process(frameData);\n }\n },\n };\n return step;\n}\n\nexport { createRenderStep };\n","import { MotionGlobalConfig } from '../utils/GlobalConfig.mjs';\nimport { createRenderStep } from './render-step.mjs';\n\nconst stepsOrder = [\n \"read\", // Read\n \"resolveKeyframes\", // Write/Read/Write/Read\n \"update\", // Compute\n \"preRender\", // Compute\n \"render\", // Write\n \"postRender\", // Compute\n];\nconst maxElapsed = 40;\nfunction createRenderBatcher(scheduleNextBatch, allowKeepAlive) {\n let runNextFrame = false;\n let useDefaultElapsed = true;\n const state = {\n delta: 0.0,\n timestamp: 0.0,\n isProcessing: false,\n };\n const flagRunNextFrame = () => (runNextFrame = true);\n const steps = stepsOrder.reduce((acc, key) => {\n acc[key] = createRenderStep(flagRunNextFrame);\n return acc;\n }, {});\n const { read, resolveKeyframes, update, preRender, render, postRender } = steps;\n const processBatch = () => {\n const timestamp = MotionGlobalConfig.useManualTiming\n ? state.timestamp\n : performance.now();\n runNextFrame = false;\n state.delta = useDefaultElapsed\n ? 1000 / 60\n : Math.max(Math.min(timestamp - state.timestamp, maxElapsed), 1);\n state.timestamp = timestamp;\n state.isProcessing = true;\n // Unrolled render loop for better per-frame performance\n read.process(state);\n resolveKeyframes.process(state);\n update.process(state);\n preRender.process(state);\n render.process(state);\n postRender.process(state);\n state.isProcessing = false;\n if (runNextFrame && allowKeepAlive) {\n useDefaultElapsed = false;\n scheduleNextBatch(processBatch);\n }\n };\n const wake = () => {\n runNextFrame = true;\n useDefaultElapsed = true;\n if (!state.isProcessing) {\n scheduleNextBatch(processBatch);\n }\n };\n const schedule = stepsOrder.reduce((acc, key) => {\n const step = steps[key];\n acc[key] = (process, keepAlive = false, immediate = false) => {\n if (!runNextFrame)\n wake();\n return step.schedule(process, keepAlive, immediate);\n };\n return acc;\n }, {});\n const cancel = (process) => {\n for (let i = 0; i < stepsOrder.length; i++) {\n steps[stepsOrder[i]].cancel(process);\n }\n };\n return { schedule, cancel, state, steps };\n}\n\nexport { createRenderBatcher, stepsOrder };\n","import { noop } from 'motion-utils';\nimport { createRenderBatcher } from './batcher.mjs';\n\nconst { schedule: frame, cancel: cancelFrame, state: frameData, steps: frameSteps, } = createRenderBatcher(typeof requestAnimationFrame !== \"undefined\" ? requestAnimationFrame : noop, true);\n\nexport { cancelFrame, frame, frameData, frameSteps };\n","import { useRef, useContext, useEffect } from 'react';\nimport { MotionConfigContext } from '../context/MotionConfigContext.mjs';\nimport { frame, cancelFrame } from '../frameloop/frame.mjs';\n\nfunction useAnimationFrame(callback) {\n const initialTimestamp = useRef(0);\n const { isStatic } = useContext(MotionConfigContext);\n useEffect(() => {\n if (isStatic)\n return;\n const provideTimeSinceStart = ({ timestamp, delta }) => {\n if (!initialTimestamp.current)\n initialTimestamp.current = timestamp;\n callback(timestamp - initialTimestamp.current, delta);\n };\n frame.update(provideTimeSinceStart, true);\n return () => cancelFrame(provideTimeSinceStart);\n }, [callback]);\n}\n\nexport { useAnimationFrame };\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 { RenderBuildRequest, AvailablePartsResponse } 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 AVAILABLE_PARTS: \"/available-parts\",\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\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 - Optional API configuration (environment, auth token)\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 - Optional API configuration (environment, auth token)\n * @returns Promise with available parts by category\n */\n getAvailableParts(config?: ApiConfig): Promise<AvailablePartsResponse>;\n}\n\n// API Configuration Types\nexport interface ApiConfig {\n environment?: \"staging\" | \"prod\";\n authToken?: string;\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\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 };\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\nexport const renderSpriteExperimental = async (\n request: RenderBuildRequest,\n config?: ApiConfig\n): Promise<RenderSpriteResponse> => {\n const requestWithFormat = {\n ...request,\n format: \"sprite\",\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 config?: ApiConfig\n): Promise<AvailablePartsResponse> => {\n const response = await fetch(\n buildApiUrl(API_ENDPOINTS.AVAILABLE_PARTS, config),\n {\n method: \"GET\",\n headers: buildHeaders(config),\n }\n );\n\n if (!response.ok) {\n throw new Error(\n `Get available parts failed: ${response.status} ${response.statusText}`\n );\n }\n\n return response.json();\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 * Video size in pixels (width and height will be the same).\n *\n * This determines the resolution of the rendered 3D video. Higher values\n * provide better quality but may impact performance.\n *\n * @example\n * ```tsx\n * <BuildRender parts={parts} size={300} /> // 300x300px\n * <BuildRender parts={parts} size={500} /> // 500x500px\n * <BuildRender parts={parts} size={800} /> // 800x800px - high quality\n * ```\n *\n * Recommended sizes:\n * - 300px: Good for thumbnails or small previews\n * - 500px: Standard size for most use cases\n * - 800px+: High quality for detailed viewing\n */\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 * 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 * **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 * Sprite size in pixels (width and height will be the same).\n *\n * This determines the display size of the rendered 3D sprite. The sprite sheet\n * itself is rendered at a fixed resolution, but this controls the display size.\n *\n * @example\n * ```tsx\n * <SpriteRender parts={parts} size={300} /> // 300x300px\n * <SpriteRender parts={parts} size={500} /> // 500x500px\n * <SpriteRender parts={parts} size={800} /> // 800x800px - larger display\n * ```\n */\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 * 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// 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}\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/**\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\nexport type AvailablePartsResponse = {\n [K in PartCategory]: PartDetails[];\n};\n","import { useState, useEffect, useCallback, useRef } from \"react\";\nimport { RenderBuildRequest, PartCategory, ApiConfig } from \"../types\";\nimport { 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 const useBuildRender = (\n parts: RenderBuildRequest,\n apiConfig: ApiConfig,\n onLoadStart?: () => void\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 response = await renderBuildExperimental(currentParts, apiConfig);\n const objectUrl = URL.createObjectURL(response.video);\n\n // Clean up previous video URL before setting new one\n setVideoSrc((prevSrc) => {\n if (prevSrc) {\n URL.revokeObjectURL(prevSrc);\n }\n return objectUrl;\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]\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) {\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 } 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 const useSpriteRender = (\n parts: RenderBuildRequest,\n apiConfig: ApiConfig,\n onLoadStart?: () => void\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 previousPartsRef = useRef<RenderBuildRequest | null>(null);\n\n const fetchRenderSprite = useCallback(\n async (currentParts: RenderBuildRequest) => {\n try {\n setIsRenderingSprite(true);\n setRenderError(null);\n onLoadStart?.();\n\n const response = await renderSpriteExperimental(\n currentParts,\n apiConfig\n );\n const objectUrl = URL.createObjectURL(response.sprite);\n\n // Clean up previous sprite URL before setting new one\n setSpriteSrc((prevSrc) => {\n if (prevSrc) {\n URL.revokeObjectURL(prevSrc);\n }\n return objectUrl;\n });\n\n // Set sprite metadata\n setSpriteMetadata({\n cols: response.metadata?.cols || 12,\n rows: response.metadata?.rows || 6,\n totalFrames: response.metadata?.totalFrames || 72,\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]\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 fetchRenderSprite(parts);\n }\n }, [parts, fetchRenderSprite]);\n\n // Cleanup effect for component unmount\n useEffect(() => {\n return () => {\n if (spriteSrc) {\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 { useRef, useState, useCallback, useEffect } from \"react\";\nimport { useSpriteScrubbing } from \"./hooks/useSpriteScrubbing\";\nimport { useBouncePatternProgress } from \"./hooks/useProgressOneSecond\";\nimport { useSpriteRender } from \"./hooks/useSpriteRender\";\nimport { BuildRenderProps } from \"./types\";\nimport { LoadingErrorOverlay } from \"./components/LoadingErrorOverlay\";\nimport { InstructionTooltip } from \"./components/InstructionTooltip\";\n\nexport const BuildRender: React.FC<BuildRenderProps> = ({\n parts,\n size,\n apiConfig,\n mouseSensitivity = 0.2,\n touchSensitivity = 0.2,\n}) => {\n const canvasRef = useRef<HTMLCanvasElement | null>(null);\n const [img, setImg] = useState<HTMLImageElement | null>(null);\n const [isLoading, setIsLoading] = useState(true);\n const [bouncingAllowed, setBouncingAllowed] = useState(false);\n\n // Use custom hook for sprite rendering\n const { spriteSrc, isRenderingSprite, renderError, spriteMetadata } =\n useSpriteRender(parts, apiConfig);\n\n const { value: progressValue, isBouncing } =\n useBouncePatternProgress(bouncingAllowed);\n\n const total = spriteMetadata ? spriteMetadata.totalFrames : 72;\n const cols = spriteMetadata ? spriteMetadata.cols : 12;\n const rows = spriteMetadata ? spriteMetadata.rows : 6;\n const frameRef = useRef(0);\n\n // Image/frame sizes\n const frameW = img ? img.width / cols : 0;\n const frameH = img ? img.height / rows : 0;\n\n // ---- Load sprite image ----\n useEffect(() => {\n if (!spriteSrc) {\n setImg(null);\n setIsLoading(true);\n return;\n }\n\n setIsLoading(true);\n const i = new Image();\n i.decoding = \"async\";\n i.loading = \"eager\";\n i.src = spriteSrc;\n i.onload = () => {\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 }, [spriteSrc]);\n\n // ---- Drawing function ----\n const draw = useCallback(\n (frameIndex: 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(size * dpr);\n const targetH = Math.round(size * dpr);\n if (cnv.width !== targetW || cnv.height !== targetH) {\n cnv.width = targetW;\n cnv.height = targetH;\n }\n\n // Snap to integer frame (never between tiles)\n let n = Math.round(frameIndex) % total;\n if (n < 0) n += total;\n\n const r = Math.floor(n / cols);\n const c = n % cols;\n\n // Use integer source rects to avoid sampling bleed across tiles\n const sx = Math.round(c * frameW);\n const sy = Math.round(r * frameH);\n const sw = Math.round(frameW);\n const sh = Math.round(frameH);\n\n ctx.clearRect(0, 0, targetW, targetH);\n ctx.imageSmoothingEnabled = true;\n ctx.imageSmoothingQuality = \"high\";\n ctx.drawImage(img, sx, sy, sw, sh, 0, 0, targetW, targetH);\n },\n [img, frameW, frameH, size, cols, total]\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 bouncing is allowed and not dragged\n useEffect(() => {\n if (hasDragged.current || !img) return;\n\n // Calculate frame based on progress value (similar to video time calculation)\n const frame = ((progressValue / 5) * total) % total;\n frameRef.current = frame;\n draw(frame);\n }, [progressValue, hasDragged, img, total, draw]);\n\n // Initial draw once image is ready\n useEffect(() => {\n if (img && !isLoading) {\n draw(frameRef.current);\n }\n }, [img, isLoading, draw]);\n\n return (\n <div\n style={{\n position: \"relative\",\n width: size,\n height: size,\n backgroundColor: \"black\",\n }}\n >\n {img && (\n <canvas\n ref={canvasRef}\n onMouseDown={handleMouseDown}\n onTouchStart={handleTouchStart}\n style={{\n width: size,\n height: size,\n cursor: isDragging ? \"grabbing\" : \"grab\",\n touchAction: \"none\", // Prevents default touch behaviors like scrolling\n display: \"block\",\n userSelect: \"none\",\n WebkitUserSelect: \"none\",\n WebkitTouchCallout: \"none\",\n }}\n role=\"img\"\n aria-label=\"360° viewer\"\n onContextMenu={(e) => e.preventDefault()}\n />\n )}\n\n <LoadingErrorOverlay\n isVisible={isLoading || isRenderingSprite || !!renderError}\n renderError={renderError || undefined}\n size={size}\n />\n\n <InstructionTooltip\n isVisible={\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 size,\n apiConfig,\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 // Use custom hook for build rendering\n const { videoSrc, isRenderingBuild, renderError } = useBuildRender(\n parts,\n apiConfig\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: size, height: size }}>\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={size}\n height={size}\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={size}\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","createContext","useContext","PartCategory","_jsx","_jsxs","_Fragment"],"mappings":"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","x_google_ignoreList":[1,2,3,4,5,6,7]}
package/dist/types.d.ts CHANGED
@@ -60,6 +60,23 @@ export interface BuildRenderVideoProps {
60
60
  * - 800px+: High quality for detailed viewing
61
61
  */
62
62
  size: number;
63
+ /**
64
+ * API configuration for environment and authentication.
65
+ * This is required to make API calls to the BuildCores rendering service.
66
+ *
67
+ * @example
68
+ * ```tsx
69
+ * <BuildRender
70
+ * parts={parts}
71
+ * size={300}
72
+ * apiConfig={{
73
+ * environment: 'staging',
74
+ * authToken: 'your-auth-token'
75
+ * }}
76
+ * />
77
+ * ```
78
+ */
79
+ apiConfig: ApiConfig;
63
80
  /**
64
81
  * Optional mouse sensitivity for dragging (default: 0.005).
65
82
  *
@@ -152,6 +169,23 @@ export interface BuildRenderProps {
152
169
  * ```
153
170
  */
154
171
  size: number;
172
+ /**
173
+ * API configuration for environment and authentication.
174
+ * This is required to make API calls to the BuildCores rendering service.
175
+ *
176
+ * @example
177
+ * ```tsx
178
+ * <SpriteRender
179
+ * parts={parts}
180
+ * size={300}
181
+ * apiConfig={{
182
+ * environment: 'staging',
183
+ * authToken: 'your-auth-token'
184
+ * }}
185
+ * />
186
+ * ```
187
+ */
188
+ apiConfig: ApiConfig;
155
189
  /**
156
190
  * Optional mouse sensitivity for dragging (default: 0.05).
157
191
  *
@@ -171,6 +205,37 @@ export interface BuildRenderProps {
171
205
  */
172
206
  touchSensitivity?: number;
173
207
  }
208
+ /**
209
+ * API configuration for environment and authentication
210
+ */
211
+ export interface ApiConfig {
212
+ /**
213
+ * Environment to use for API requests
214
+ * - 'staging': Development/testing environment
215
+ * - 'prod': Production environment
216
+ *
217
+ * @example
218
+ * ```tsx
219
+ * const config: ApiConfig = {
220
+ * environment: 'staging',
221
+ * authToken: 'your-bearer-token'
222
+ * };
223
+ * ```
224
+ */
225
+ environment?: "staging" | "prod";
226
+ /**
227
+ * Bearer token for API authentication
228
+ *
229
+ * @example
230
+ * ```tsx
231
+ * const config: ApiConfig = {
232
+ * environment: 'prod',
233
+ * authToken: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...'
234
+ * };
235
+ * ```
236
+ */
237
+ authToken?: string;
238
+ }
174
239
  /**
175
240
  * Enum defining all available PC part categories that can be rendered.
176
241
  *
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@buildcores/render-client",
3
- "version": "1.0.5",
3
+ "version": "1.0.6",
4
4
  "type": "module",
5
5
  "description": "React component for interactive 360-degree video rendering",
6
6
  "repository": {