@buildcores/render-client 1.0.5 → 1.0.7
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/api.d.ts +14 -7
- package/dist/hooks/useBuildRender.d.ts +2 -2
- package/dist/hooks/useSpriteRender.d.ts +2 -2
- package/dist/index.d.ts +196 -11
- package/dist/index.esm.js +95 -28
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +96 -27
- package/dist/index.js.map +1 -1
- package/dist/types.d.ts +65 -0
- package/package.json +1 -1
package/dist/api.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { RenderBuildRequest, AvailablePartsResponse } from "./types";
|
|
2
|
-
declare const API_BASE_URL = "https://
|
|
2
|
+
declare const API_BASE_URL = "https://www.renderapi.buildcores.com";
|
|
3
3
|
export declare const API_ENDPOINTS: {
|
|
4
4
|
readonly RENDER_BUILD_EXPERIMENTAL: "/render-build-experimental";
|
|
5
5
|
readonly AVAILABLE_PARTS: "/available-parts";
|
|
@@ -38,17 +38,24 @@ export interface RenderAPIService {
|
|
|
38
38
|
/**
|
|
39
39
|
* Submit a render build request
|
|
40
40
|
* @param parts - The parts configuration for the build
|
|
41
|
+
* @param config - API configuration (environment, auth token) - required
|
|
41
42
|
* @returns Promise with the rendered MP4 video
|
|
42
43
|
*/
|
|
43
|
-
renderBuildExperimental(parts: RenderBuildRequest): Promise<RenderBuildResponse>;
|
|
44
|
+
renderBuildExperimental(parts: RenderBuildRequest, config: ApiConfig): Promise<RenderBuildResponse>;
|
|
44
45
|
/**
|
|
45
46
|
* Get available parts for building
|
|
47
|
+
* @param config - API configuration (environment, auth token) - required
|
|
46
48
|
* @returns Promise with available parts by category
|
|
47
49
|
*/
|
|
48
|
-
getAvailableParts(): Promise<AvailablePartsResponse>;
|
|
50
|
+
getAvailableParts(config: ApiConfig): Promise<AvailablePartsResponse>;
|
|
49
51
|
}
|
|
50
|
-
export
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
52
|
+
export interface ApiConfig {
|
|
53
|
+
environment?: "staging" | "prod";
|
|
54
|
+
authToken?: string;
|
|
55
|
+
}
|
|
56
|
+
export declare const buildApiUrl: (endpoint: string, config: ApiConfig) => string;
|
|
57
|
+
export declare const buildHeaders: (config: ApiConfig) => Record<string, string>;
|
|
58
|
+
export declare const renderBuildExperimental: (request: RenderBuildRequest, config: ApiConfig) => Promise<RenderBuildResponse>;
|
|
59
|
+
export declare const renderSpriteExperimental: (request: RenderBuildRequest, config: ApiConfig) => Promise<RenderSpriteResponse>;
|
|
60
|
+
export declare const getAvailableParts: (config: ApiConfig) => Promise<AvailablePartsResponse>;
|
|
54
61
|
export { API_BASE_URL };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { RenderBuildRequest } from "../types";
|
|
1
|
+
import { RenderBuildRequest, ApiConfig } from "../types";
|
|
2
2
|
/**
|
|
3
3
|
* Compares two RenderBuildRequest objects for equality by checking if the same IDs
|
|
4
4
|
* are present in each category array, regardless of order.
|
|
@@ -9,4 +9,4 @@ export interface UseBuildRenderReturn {
|
|
|
9
9
|
isRenderingBuild: boolean;
|
|
10
10
|
renderError: string | null;
|
|
11
11
|
}
|
|
12
|
-
export declare const useBuildRender: (parts: RenderBuildRequest, onLoadStart?: () => void) => UseBuildRenderReturn;
|
|
12
|
+
export declare const useBuildRender: (parts: RenderBuildRequest, apiConfig: ApiConfig, onLoadStart?: () => void) => UseBuildRenderReturn;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { RenderBuildRequest } from "../types";
|
|
1
|
+
import { RenderBuildRequest, ApiConfig } from "../types";
|
|
2
2
|
export interface UseSpriteRenderReturn {
|
|
3
3
|
spriteSrc: string | null;
|
|
4
4
|
isRenderingSprite: boolean;
|
|
@@ -9,4 +9,4 @@ export interface UseSpriteRenderReturn {
|
|
|
9
9
|
totalFrames: number;
|
|
10
10
|
} | null;
|
|
11
11
|
}
|
|
12
|
-
export declare const useSpriteRender: (parts: RenderBuildRequest, onLoadStart?: () => void) => UseSpriteRenderReturn;
|
|
12
|
+
export declare const useSpriteRender: (parts: RenderBuildRequest, apiConfig: ApiConfig, onLoadStart?: () => void) => UseSpriteRenderReturn;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,134 @@
|
|
|
1
1
|
import * as React$1 from 'react';
|
|
2
2
|
import React__default, { RefObject } from 'react';
|
|
3
3
|
|
|
4
|
+
interface BuildRenderVideoProps {
|
|
5
|
+
/**
|
|
6
|
+
* Parts configuration for the build render.
|
|
7
|
+
*
|
|
8
|
+
* This object defines which PC components should be included in the 3D render.
|
|
9
|
+
* Each part category contains an array with a single part ID that will be rendered.
|
|
10
|
+
*
|
|
11
|
+
* **Current Limitation**: Only 1 part per category is supported. Arrays must contain
|
|
12
|
+
* exactly one part ID per category. Future versions will support multiple parts per category.
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```tsx
|
|
16
|
+
* const parts = {
|
|
17
|
+
* parts: {
|
|
18
|
+
* CPU: ["7xjqsomhr"], // AMD Ryzen 7 9800X3D
|
|
19
|
+
* GPU: ["z7pyphm9k"], // ASUS GeForce RTX 5080 ASTRAL
|
|
20
|
+
* RAM: ["dpl1iyvb5"], // PNY DDR5
|
|
21
|
+
* Motherboard: ["iwin2u9vx"], // Asus ROG STRIX X870E-E GAMING WIFI
|
|
22
|
+
* PSU: ["m4kilv190"], // LIAN LI 1300W
|
|
23
|
+
* Storage: ["0bkvs17po"], // SAMSUNG 990 EVO
|
|
24
|
+
* PCCase: ["qq9jamk7c"], // MONTECH KING 95 PRO
|
|
25
|
+
* CPUCooler: ["62d8zelr5"], // ARCTIC LIQUID FREEZER 360
|
|
26
|
+
* }
|
|
27
|
+
* };
|
|
28
|
+
*
|
|
29
|
+
* <BuildRender parts={parts} size={300} />
|
|
30
|
+
* ```
|
|
31
|
+
*
|
|
32
|
+
* @example Minimal build (only required components)
|
|
33
|
+
* ```tsx
|
|
34
|
+
* const parts = {
|
|
35
|
+
* parts: {
|
|
36
|
+
* CPU: ["7xjqsomhr"], // Single CPU required
|
|
37
|
+
* Motherboard: ["iwin2u9vx"], // Single motherboard required
|
|
38
|
+
* PCCase: ["qq9jamk7c"], // Single case required
|
|
39
|
+
* }
|
|
40
|
+
* };
|
|
41
|
+
* ```
|
|
42
|
+
*
|
|
43
|
+
* Note: Part IDs must correspond to valid components in the BuildCores database.
|
|
44
|
+
* Use the available parts API to get valid part IDs for each category.
|
|
45
|
+
*/
|
|
46
|
+
parts: RenderBuildRequest;
|
|
47
|
+
/**
|
|
48
|
+
* Video size in pixels (width and height will be the same).
|
|
49
|
+
*
|
|
50
|
+
* This determines the resolution of the rendered 3D video. Higher values
|
|
51
|
+
* provide better quality but may impact performance.
|
|
52
|
+
*
|
|
53
|
+
* @example
|
|
54
|
+
* ```tsx
|
|
55
|
+
* <BuildRender parts={parts} size={300} /> // 300x300px
|
|
56
|
+
* <BuildRender parts={parts} size={500} /> // 500x500px
|
|
57
|
+
* <BuildRender parts={parts} size={800} /> // 800x800px - high quality
|
|
58
|
+
* ```
|
|
59
|
+
*
|
|
60
|
+
* Recommended sizes:
|
|
61
|
+
* - 300px: Good for thumbnails or small previews
|
|
62
|
+
* - 500px: Standard size for most use cases
|
|
63
|
+
* - 800px+: High quality for detailed viewing
|
|
64
|
+
*/
|
|
65
|
+
size: number;
|
|
66
|
+
/**
|
|
67
|
+
* API configuration for environment and authentication.
|
|
68
|
+
* This is required to make API calls to the BuildCores rendering service.
|
|
69
|
+
*
|
|
70
|
+
* @example
|
|
71
|
+
* ```tsx
|
|
72
|
+
* <BuildRender
|
|
73
|
+
* parts={parts}
|
|
74
|
+
* size={300}
|
|
75
|
+
* apiConfig={{
|
|
76
|
+
* environment: 'staging',
|
|
77
|
+
* authToken: 'your-auth-token'
|
|
78
|
+
* }}
|
|
79
|
+
* />
|
|
80
|
+
* ```
|
|
81
|
+
*/
|
|
82
|
+
apiConfig: ApiConfig$1;
|
|
83
|
+
/**
|
|
84
|
+
* Optional mouse sensitivity for dragging (default: 0.005).
|
|
85
|
+
*
|
|
86
|
+
* Controls how responsive the 3D model rotation is to mouse movements.
|
|
87
|
+
* Lower values make rotation slower and more precise, higher values make it faster.
|
|
88
|
+
*
|
|
89
|
+
* @example
|
|
90
|
+
* ```tsx
|
|
91
|
+
* <BuildRender
|
|
92
|
+
* parts={parts}
|
|
93
|
+
* size={300}
|
|
94
|
+
* mouseSensitivity={0.003} // Slower, more precise
|
|
95
|
+
* />
|
|
96
|
+
*
|
|
97
|
+
* <BuildRender
|
|
98
|
+
* parts={parts}
|
|
99
|
+
* size={300}
|
|
100
|
+
* mouseSensitivity={0.01} // Faster rotation
|
|
101
|
+
* />
|
|
102
|
+
* ```
|
|
103
|
+
*
|
|
104
|
+
* @default 0.005
|
|
105
|
+
*/
|
|
106
|
+
mouseSensitivity?: number;
|
|
107
|
+
/**
|
|
108
|
+
* Optional touch sensitivity for dragging (default: 0.01).
|
|
109
|
+
*
|
|
110
|
+
* Controls how responsive the 3D model rotation is to touch gestures on mobile devices.
|
|
111
|
+
* Generally set higher than mouseSensitivity for better touch experience.
|
|
112
|
+
*
|
|
113
|
+
* @example
|
|
114
|
+
* ```tsx
|
|
115
|
+
* <BuildRender
|
|
116
|
+
* parts={parts}
|
|
117
|
+
* size={300}
|
|
118
|
+
* touchSensitivity={0.008} // Slower touch rotation
|
|
119
|
+
* />
|
|
120
|
+
*
|
|
121
|
+
* <BuildRender
|
|
122
|
+
* parts={parts}
|
|
123
|
+
* size={300}
|
|
124
|
+
* touchSensitivity={0.015} // Faster touch rotation
|
|
125
|
+
* />
|
|
126
|
+
* ```
|
|
127
|
+
*
|
|
128
|
+
* @default 0.01
|
|
129
|
+
*/
|
|
130
|
+
touchSensitivity?: number;
|
|
131
|
+
}
|
|
4
132
|
interface BuildRenderProps {
|
|
5
133
|
/**
|
|
6
134
|
* Parts configuration for the sprite render.
|
|
@@ -44,6 +172,23 @@ interface BuildRenderProps {
|
|
|
44
172
|
* ```
|
|
45
173
|
*/
|
|
46
174
|
size: number;
|
|
175
|
+
/**
|
|
176
|
+
* API configuration for environment and authentication.
|
|
177
|
+
* This is required to make API calls to the BuildCores rendering service.
|
|
178
|
+
*
|
|
179
|
+
* @example
|
|
180
|
+
* ```tsx
|
|
181
|
+
* <SpriteRender
|
|
182
|
+
* parts={parts}
|
|
183
|
+
* size={300}
|
|
184
|
+
* apiConfig={{
|
|
185
|
+
* environment: 'staging',
|
|
186
|
+
* authToken: 'your-auth-token'
|
|
187
|
+
* }}
|
|
188
|
+
* />
|
|
189
|
+
* ```
|
|
190
|
+
*/
|
|
191
|
+
apiConfig: ApiConfig$1;
|
|
47
192
|
/**
|
|
48
193
|
* Optional mouse sensitivity for dragging (default: 0.05).
|
|
49
194
|
*
|
|
@@ -63,6 +208,37 @@ interface BuildRenderProps {
|
|
|
63
208
|
*/
|
|
64
209
|
touchSensitivity?: number;
|
|
65
210
|
}
|
|
211
|
+
/**
|
|
212
|
+
* API configuration for environment and authentication
|
|
213
|
+
*/
|
|
214
|
+
interface ApiConfig$1 {
|
|
215
|
+
/**
|
|
216
|
+
* Environment to use for API requests
|
|
217
|
+
* - 'staging': Development/testing environment
|
|
218
|
+
* - 'prod': Production environment
|
|
219
|
+
*
|
|
220
|
+
* @example
|
|
221
|
+
* ```tsx
|
|
222
|
+
* const config: ApiConfig = {
|
|
223
|
+
* environment: 'staging',
|
|
224
|
+
* authToken: 'your-bearer-token'
|
|
225
|
+
* };
|
|
226
|
+
* ```
|
|
227
|
+
*/
|
|
228
|
+
environment?: "staging" | "prod";
|
|
229
|
+
/**
|
|
230
|
+
* Bearer token for API authentication
|
|
231
|
+
*
|
|
232
|
+
* @example
|
|
233
|
+
* ```tsx
|
|
234
|
+
* const config: ApiConfig = {
|
|
235
|
+
* environment: 'prod',
|
|
236
|
+
* authToken: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...'
|
|
237
|
+
* };
|
|
238
|
+
* ```
|
|
239
|
+
*/
|
|
240
|
+
authToken?: string;
|
|
241
|
+
}
|
|
66
242
|
/**
|
|
67
243
|
* Enum defining all available PC part categories that can be rendered.
|
|
68
244
|
*
|
|
@@ -233,6 +409,8 @@ type AvailablePartsResponse = {
|
|
|
233
409
|
|
|
234
410
|
declare const BuildRender: React.FC<BuildRenderProps>;
|
|
235
411
|
|
|
412
|
+
declare const BuildRenderVideo: React.FC<BuildRenderVideoProps>;
|
|
413
|
+
|
|
236
414
|
declare const calculateCircularTime: (startTime: number, deltaX: number, sensitivity: number, duration: number) => number;
|
|
237
415
|
interface UseVideoScrubbingOptions {
|
|
238
416
|
mouseSensitivity?: number;
|
|
@@ -277,7 +455,7 @@ interface UseBuildRenderReturn {
|
|
|
277
455
|
isRenderingBuild: boolean;
|
|
278
456
|
renderError: string | null;
|
|
279
457
|
}
|
|
280
|
-
declare const useBuildRender: (parts: RenderBuildRequest, onLoadStart?: () => void) => UseBuildRenderReturn;
|
|
458
|
+
declare const useBuildRender: (parts: RenderBuildRequest, apiConfig: ApiConfig$1, onLoadStart?: () => void) => UseBuildRenderReturn;
|
|
281
459
|
|
|
282
460
|
interface UseSpriteRenderReturn {
|
|
283
461
|
spriteSrc: string | null;
|
|
@@ -289,7 +467,7 @@ interface UseSpriteRenderReturn {
|
|
|
289
467
|
totalFrames: number;
|
|
290
468
|
} | null;
|
|
291
469
|
}
|
|
292
|
-
declare const useSpriteRender: (parts: RenderBuildRequest, onLoadStart?: () => void) => UseSpriteRenderReturn;
|
|
470
|
+
declare const useSpriteRender: (parts: RenderBuildRequest, apiConfig: ApiConfig$1, onLoadStart?: () => void) => UseSpriteRenderReturn;
|
|
293
471
|
|
|
294
472
|
interface DragIconProps {
|
|
295
473
|
width?: number;
|
|
@@ -313,7 +491,7 @@ interface InstructionTooltipProps {
|
|
|
313
491
|
}
|
|
314
492
|
declare const InstructionTooltip: React__default.FC<InstructionTooltipProps>;
|
|
315
493
|
|
|
316
|
-
declare const API_BASE_URL = "https://
|
|
494
|
+
declare const API_BASE_URL = "https://www.renderapi.buildcores.com";
|
|
317
495
|
declare const API_ENDPOINTS: {
|
|
318
496
|
readonly RENDER_BUILD_EXPERIMENTAL: "/render-build-experimental";
|
|
319
497
|
readonly AVAILABLE_PARTS: "/available-parts";
|
|
@@ -352,19 +530,26 @@ interface RenderAPIService {
|
|
|
352
530
|
/**
|
|
353
531
|
* Submit a render build request
|
|
354
532
|
* @param parts - The parts configuration for the build
|
|
533
|
+
* @param config - API configuration (environment, auth token) - required
|
|
355
534
|
* @returns Promise with the rendered MP4 video
|
|
356
535
|
*/
|
|
357
|
-
renderBuildExperimental(parts: RenderBuildRequest): Promise<RenderBuildResponse>;
|
|
536
|
+
renderBuildExperimental(parts: RenderBuildRequest, config: ApiConfig): Promise<RenderBuildResponse>;
|
|
358
537
|
/**
|
|
359
538
|
* Get available parts for building
|
|
539
|
+
* @param config - API configuration (environment, auth token) - required
|
|
360
540
|
* @returns Promise with available parts by category
|
|
361
541
|
*/
|
|
362
|
-
getAvailableParts(): Promise<AvailablePartsResponse>;
|
|
542
|
+
getAvailableParts(config: ApiConfig): Promise<AvailablePartsResponse>;
|
|
543
|
+
}
|
|
544
|
+
interface ApiConfig {
|
|
545
|
+
environment?: "staging" | "prod";
|
|
546
|
+
authToken?: string;
|
|
363
547
|
}
|
|
364
|
-
declare const buildApiUrl: (endpoint: string) => string;
|
|
365
|
-
declare const
|
|
366
|
-
declare const
|
|
367
|
-
declare const
|
|
548
|
+
declare const buildApiUrl: (endpoint: string, config: ApiConfig) => string;
|
|
549
|
+
declare const buildHeaders: (config: ApiConfig) => Record<string, string>;
|
|
550
|
+
declare const renderBuildExperimental: (request: RenderBuildRequest, config: ApiConfig) => Promise<RenderBuildResponse>;
|
|
551
|
+
declare const renderSpriteExperimental: (request: RenderBuildRequest, config: ApiConfig) => Promise<RenderSpriteResponse>;
|
|
552
|
+
declare const getAvailableParts: (config: ApiConfig) => Promise<AvailablePartsResponse>;
|
|
368
553
|
|
|
369
|
-
export { API_BASE_URL, API_ENDPOINTS, BuildRender, DragIcon, InstructionTooltip, LoadingErrorOverlay, PartCategory, arePartsEqual, buildApiUrl, calculateCircularFrame, calculateCircularTime, getAvailableParts, renderBuildExperimental, renderSpriteExperimental, useBouncePatternProgress, useBuildRender, useSpriteRender, useSpriteScrubbing, useVideoScrubbing };
|
|
370
|
-
export type { AvailablePartsResponse, BuildRenderProps, PartDetails, RenderAPIService, RenderBuildRequest, RenderBuildResponse, RenderSpriteResponse, UseBuildRenderReturn, UseSpriteRenderReturn };
|
|
554
|
+
export { API_BASE_URL, API_ENDPOINTS, BuildRender, BuildRenderVideo, DragIcon, InstructionTooltip, LoadingErrorOverlay, PartCategory, arePartsEqual, buildApiUrl, buildHeaders, calculateCircularFrame, calculateCircularTime, getAvailableParts, renderBuildExperimental, renderSpriteExperimental, useBouncePatternProgress, useBuildRender, useSpriteRender, useSpriteScrubbing, useVideoScrubbing };
|
|
555
|
+
export type { ApiConfig$1 as ApiConfig, AvailablePartsResponse, BuildRenderProps, BuildRenderVideoProps, PartDetails, RenderAPIService, RenderBuildRequest, RenderBuildResponse, RenderSpriteResponse, UseBuildRenderReturn, UseSpriteRenderReturn };
|
package/dist/index.esm.js
CHANGED
|
@@ -320,27 +320,41 @@ function useBouncePatternProgress(enabled = true) {
|
|
|
320
320
|
}
|
|
321
321
|
|
|
322
322
|
// API Configuration
|
|
323
|
-
const API_BASE_URL = "https://
|
|
323
|
+
const API_BASE_URL = "https://www.renderapi.buildcores.com";
|
|
324
324
|
// API Endpoints
|
|
325
325
|
const API_ENDPOINTS = {
|
|
326
326
|
RENDER_BUILD_EXPERIMENTAL: "/render-build-experimental",
|
|
327
327
|
AVAILABLE_PARTS: "/available-parts",
|
|
328
328
|
};
|
|
329
329
|
// API URL helpers
|
|
330
|
-
const buildApiUrl = (endpoint) => {
|
|
331
|
-
|
|
330
|
+
const buildApiUrl = (endpoint, config) => {
|
|
331
|
+
const baseUrl = `${API_BASE_URL}${endpoint}`;
|
|
332
|
+
if (config.environment) {
|
|
333
|
+
const separator = endpoint.includes("?") ? "&" : "?";
|
|
334
|
+
return `${baseUrl}${separator}environment=${config.environment}`;
|
|
335
|
+
}
|
|
336
|
+
return baseUrl;
|
|
337
|
+
};
|
|
338
|
+
// Helper to build request headers with auth token
|
|
339
|
+
const buildHeaders = (config) => {
|
|
340
|
+
const headers = {
|
|
341
|
+
"Content-Type": "application/json",
|
|
342
|
+
accept: "application/json",
|
|
343
|
+
};
|
|
344
|
+
if (config.authToken) {
|
|
345
|
+
headers["Authorization"] = `Bearer ${config.authToken}`;
|
|
346
|
+
}
|
|
347
|
+
return headers;
|
|
332
348
|
};
|
|
333
349
|
// API Implementation
|
|
334
|
-
const renderBuildExperimental = async (request) => {
|
|
350
|
+
const renderBuildExperimental = async (request, config) => {
|
|
335
351
|
const requestWithFormat = {
|
|
336
352
|
...request,
|
|
337
353
|
format: request.format || "video", // Default to video format
|
|
338
354
|
};
|
|
339
|
-
const response = await fetch(buildApiUrl(API_ENDPOINTS.RENDER_BUILD_EXPERIMENTAL), {
|
|
355
|
+
const response = await fetch(buildApiUrl(API_ENDPOINTS.RENDER_BUILD_EXPERIMENTAL, config), {
|
|
340
356
|
method: "POST",
|
|
341
|
-
headers:
|
|
342
|
-
"Content-Type": "application/json",
|
|
343
|
-
},
|
|
357
|
+
headers: buildHeaders(config),
|
|
344
358
|
body: JSON.stringify(requestWithFormat),
|
|
345
359
|
});
|
|
346
360
|
if (!response.ok) {
|
|
@@ -355,16 +369,14 @@ const renderBuildExperimental = async (request) => {
|
|
|
355
369
|
},
|
|
356
370
|
};
|
|
357
371
|
};
|
|
358
|
-
const renderSpriteExperimental = async (request) => {
|
|
372
|
+
const renderSpriteExperimental = async (request, config) => {
|
|
359
373
|
const requestWithFormat = {
|
|
360
374
|
...request,
|
|
361
375
|
format: "sprite",
|
|
362
376
|
};
|
|
363
|
-
const response = await fetch(buildApiUrl(API_ENDPOINTS.RENDER_BUILD_EXPERIMENTAL), {
|
|
377
|
+
const response = await fetch(buildApiUrl(API_ENDPOINTS.RENDER_BUILD_EXPERIMENTAL, config), {
|
|
364
378
|
method: "POST",
|
|
365
|
-
headers:
|
|
366
|
-
"Content-Type": "application/json",
|
|
367
|
-
},
|
|
379
|
+
headers: buildHeaders(config),
|
|
368
380
|
body: JSON.stringify(requestWithFormat),
|
|
369
381
|
});
|
|
370
382
|
if (!response.ok) {
|
|
@@ -382,12 +394,10 @@ const renderSpriteExperimental = async (request) => {
|
|
|
382
394
|
},
|
|
383
395
|
};
|
|
384
396
|
};
|
|
385
|
-
const getAvailableParts = async () => {
|
|
386
|
-
const response = await fetch(buildApiUrl(API_ENDPOINTS.AVAILABLE_PARTS), {
|
|
397
|
+
const getAvailableParts = async (config) => {
|
|
398
|
+
const response = await fetch(buildApiUrl(API_ENDPOINTS.AVAILABLE_PARTS, config), {
|
|
387
399
|
method: "GET",
|
|
388
|
-
headers:
|
|
389
|
-
"Content-Type": "application/json",
|
|
390
|
-
},
|
|
400
|
+
headers: buildHeaders(config),
|
|
391
401
|
});
|
|
392
402
|
if (!response.ok) {
|
|
393
403
|
throw new Error(`Get available parts failed: ${response.status} ${response.statusText}`);
|
|
@@ -395,7 +405,6 @@ const getAvailableParts = async () => {
|
|
|
395
405
|
return response.json();
|
|
396
406
|
};
|
|
397
407
|
|
|
398
|
-
// API Types
|
|
399
408
|
/**
|
|
400
409
|
* Enum defining all available PC part categories that can be rendered.
|
|
401
410
|
*
|
|
@@ -464,7 +473,7 @@ const arePartsEqual = (parts1, parts2) => {
|
|
|
464
473
|
}
|
|
465
474
|
return true;
|
|
466
475
|
};
|
|
467
|
-
const useBuildRender = (parts, onLoadStart) => {
|
|
476
|
+
const useBuildRender = (parts, apiConfig, onLoadStart) => {
|
|
468
477
|
const [videoSrc, setVideoSrc] = useState(null);
|
|
469
478
|
const [isRenderingBuild, setIsRenderingBuild] = useState(false);
|
|
470
479
|
const [renderError, setRenderError] = useState(null);
|
|
@@ -474,7 +483,7 @@ const useBuildRender = (parts, onLoadStart) => {
|
|
|
474
483
|
setIsRenderingBuild(true);
|
|
475
484
|
setRenderError(null);
|
|
476
485
|
onLoadStart?.();
|
|
477
|
-
const response = await renderBuildExperimental(currentParts);
|
|
486
|
+
const response = await renderBuildExperimental(currentParts, apiConfig);
|
|
478
487
|
const objectUrl = URL.createObjectURL(response.video);
|
|
479
488
|
// Clean up previous video URL before setting new one
|
|
480
489
|
setVideoSrc((prevSrc) => {
|
|
@@ -490,7 +499,7 @@ const useBuildRender = (parts, onLoadStart) => {
|
|
|
490
499
|
finally {
|
|
491
500
|
setIsRenderingBuild(false);
|
|
492
501
|
}
|
|
493
|
-
}, [onLoadStart]);
|
|
502
|
+
}, [apiConfig, onLoadStart]);
|
|
494
503
|
// Effect to call API when parts content changes (using custom equality check)
|
|
495
504
|
useEffect(() => {
|
|
496
505
|
const shouldFetch = previousPartsRef.current === null ||
|
|
@@ -515,7 +524,7 @@ const useBuildRender = (parts, onLoadStart) => {
|
|
|
515
524
|
};
|
|
516
525
|
};
|
|
517
526
|
|
|
518
|
-
const useSpriteRender = (parts, onLoadStart) => {
|
|
527
|
+
const useSpriteRender = (parts, apiConfig, onLoadStart) => {
|
|
519
528
|
const [spriteSrc, setSpriteSrc] = useState(null);
|
|
520
529
|
const [isRenderingSprite, setIsRenderingSprite] = useState(false);
|
|
521
530
|
const [renderError, setRenderError] = useState(null);
|
|
@@ -526,7 +535,7 @@ const useSpriteRender = (parts, onLoadStart) => {
|
|
|
526
535
|
setIsRenderingSprite(true);
|
|
527
536
|
setRenderError(null);
|
|
528
537
|
onLoadStart?.();
|
|
529
|
-
const response = await renderSpriteExperimental(currentParts);
|
|
538
|
+
const response = await renderSpriteExperimental(currentParts, apiConfig);
|
|
530
539
|
const objectUrl = URL.createObjectURL(response.sprite);
|
|
531
540
|
// Clean up previous sprite URL before setting new one
|
|
532
541
|
setSpriteSrc((prevSrc) => {
|
|
@@ -548,7 +557,7 @@ const useSpriteRender = (parts, onLoadStart) => {
|
|
|
548
557
|
finally {
|
|
549
558
|
setIsRenderingSprite(false);
|
|
550
559
|
}
|
|
551
|
-
}, [onLoadStart]);
|
|
560
|
+
}, [apiConfig, onLoadStart]);
|
|
552
561
|
// Effect to call API when parts content changes (using custom equality check)
|
|
553
562
|
useEffect(() => {
|
|
554
563
|
const shouldFetch = previousPartsRef.current === null ||
|
|
@@ -629,13 +638,13 @@ const InstructionTooltip = ({ isVisible, progressValue, instructionIcon, }) => {
|
|
|
629
638
|
} })) }));
|
|
630
639
|
};
|
|
631
640
|
|
|
632
|
-
const BuildRender = ({ parts, size, mouseSensitivity = 0.2, touchSensitivity = 0.2, }) => {
|
|
641
|
+
const BuildRender = ({ parts, size, apiConfig, mouseSensitivity = 0.2, touchSensitivity = 0.2, }) => {
|
|
633
642
|
const canvasRef = useRef(null);
|
|
634
643
|
const [img, setImg] = useState(null);
|
|
635
644
|
const [isLoading, setIsLoading] = useState(true);
|
|
636
645
|
const [bouncingAllowed, setBouncingAllowed] = useState(false);
|
|
637
646
|
// Use custom hook for sprite rendering
|
|
638
|
-
const { spriteSrc, isRenderingSprite, renderError, spriteMetadata } = useSpriteRender(parts);
|
|
647
|
+
const { spriteSrc, isRenderingSprite, renderError, spriteMetadata } = useSpriteRender(parts, apiConfig);
|
|
639
648
|
const { value: progressValue, isBouncing } = useBouncePatternProgress(bouncingAllowed);
|
|
640
649
|
const total = spriteMetadata ? spriteMetadata.totalFrames : 72;
|
|
641
650
|
const cols = spriteMetadata ? spriteMetadata.cols : 12;
|
|
@@ -842,5 +851,63 @@ const useVideoScrubbing = (videoRef, options = {}) => {
|
|
|
842
851
|
};
|
|
843
852
|
};
|
|
844
853
|
|
|
845
|
-
|
|
854
|
+
const BuildRenderVideo = ({ parts, size, apiConfig, mouseSensitivity = 0.01, touchSensitivity = 0.01, }) => {
|
|
855
|
+
const videoRef = useRef(null);
|
|
856
|
+
const [isLoading, setIsLoading] = useState(true);
|
|
857
|
+
const [bouncingAllowed, setBouncingAllowed] = useState(false);
|
|
858
|
+
// Use custom hook for build rendering
|
|
859
|
+
const { videoSrc, isRenderingBuild, renderError } = useBuildRender(parts, apiConfig);
|
|
860
|
+
const { value: progressValue, isBouncing } = useBouncePatternProgress(bouncingAllowed);
|
|
861
|
+
const { isDragging, handleMouseDown, handleTouchStart, hasDragged } = useVideoScrubbing(videoRef, {
|
|
862
|
+
mouseSensitivity,
|
|
863
|
+
touchSensitivity,
|
|
864
|
+
});
|
|
865
|
+
const handleLoadStartInternal = useCallback(() => {
|
|
866
|
+
setIsLoading(true);
|
|
867
|
+
setBouncingAllowed(false);
|
|
868
|
+
}, []);
|
|
869
|
+
const handleCanPlayInternal = useCallback(() => {
|
|
870
|
+
setIsLoading(false);
|
|
871
|
+
// Start bouncing animation after delay
|
|
872
|
+
setTimeout(() => {
|
|
873
|
+
setBouncingAllowed(true);
|
|
874
|
+
}, 2000);
|
|
875
|
+
}, []);
|
|
876
|
+
useEffect(() => {
|
|
877
|
+
if (hasDragged.current || !videoRef.current)
|
|
878
|
+
return;
|
|
879
|
+
const duration = videoRef.current.duration;
|
|
880
|
+
if (!isFinite(duration))
|
|
881
|
+
return;
|
|
882
|
+
const time = calculateCircularTime(0, progressValue, 0.5, duration);
|
|
883
|
+
if (isFinite(time)) {
|
|
884
|
+
videoRef.current.currentTime = time;
|
|
885
|
+
}
|
|
886
|
+
}, [progressValue, hasDragged]);
|
|
887
|
+
return (jsxs("div", { style: { position: "relative", width: size, height: size }, children: [videoSrc && (jsx("video", { ref: videoRef, src: videoSrc, width: size, height: size, autoPlay: true, preload: "metadata", muted: true, playsInline: true, controls: false, disablePictureInPicture: true, controlsList: "nodownload nofullscreen noremoteplayback", ...{ "x-webkit-airplay": "deny" }, onMouseDown: handleMouseDown, onTouchStart: handleTouchStart, onLoadStart: handleLoadStartInternal, onCanPlay: handleCanPlayInternal, onLoadedData: () => {
|
|
888
|
+
if (videoRef.current) {
|
|
889
|
+
videoRef.current.pause();
|
|
890
|
+
}
|
|
891
|
+
}, style: {
|
|
892
|
+
cursor: isDragging ? "grabbing" : "grab",
|
|
893
|
+
touchAction: "none", // Prevents default touch behaviors like scrolling
|
|
894
|
+
display: "block",
|
|
895
|
+
// Completely hide video controls on all browsers including mobile
|
|
896
|
+
WebkitMediaControls: "none",
|
|
897
|
+
MozMediaControls: "none",
|
|
898
|
+
OMediaControls: "none",
|
|
899
|
+
msMediaControls: "none",
|
|
900
|
+
mediaControls: "none",
|
|
901
|
+
// Additional iOS-specific properties
|
|
902
|
+
WebkitTouchCallout: "none",
|
|
903
|
+
WebkitUserSelect: "none",
|
|
904
|
+
userSelect: "none",
|
|
905
|
+
}, children: "Your browser does not support the video tag." }, videoSrc)), jsx(LoadingErrorOverlay, { isVisible: isLoading || isRenderingBuild || !!renderError, renderError: renderError || undefined, size: size }), jsx(InstructionTooltip, { isVisible: !isLoading &&
|
|
906
|
+
!isRenderingBuild &&
|
|
907
|
+
!renderError &&
|
|
908
|
+
isBouncing &&
|
|
909
|
+
!hasDragged.current, progressValue: progressValue })] }));
|
|
910
|
+
};
|
|
911
|
+
|
|
912
|
+
export { API_BASE_URL, API_ENDPOINTS, BuildRender, BuildRenderVideo, DragIcon, InstructionTooltip, LoadingErrorOverlay, PartCategory, arePartsEqual, buildApiUrl, buildHeaders, calculateCircularFrame, calculateCircularTime, getAvailableParts, renderBuildExperimental, renderSpriteExperimental, useBouncePatternProgress, useBuildRender, useSpriteRender, useSpriteScrubbing, useVideoScrubbing };
|
|
846
913
|
//# sourceMappingURL=index.esm.js.map
|