@buildcores/render-client 1.0.12 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,7 +1,8 @@
1
1
  'use strict';
2
2
 
3
3
  var jsxRuntime = require('react/jsx-runtime');
4
- var React = require('react');
4
+ var react = require('react');
5
+ var framerMotion = require('framer-motion');
5
6
 
6
7
  // Helper to extract clientX from mouse or touch events
7
8
  const getClientX$1 = (e) => {
@@ -20,13 +21,13 @@ const calculateCircularFrame = (startFrame, deltaX, sensitivity, totalFrames) =>
20
21
  };
21
22
  const useSpriteScrubbing = (canvasRef, totalFrames, options = {}) => {
22
23
  const { mouseSensitivity = 0.1, touchSensitivity = 0.1, onFrameChange, } = options;
23
- const [isDragging, setIsDragging] = React.useState(false);
24
- const [dragStartX, setDragStartX] = React.useState(0);
25
- const [dragStartFrame, setDragStartFrame] = React.useState(0);
26
- const hasDragged = React.useRef(false);
27
- const currentFrame = React.useRef(0);
24
+ const [isDragging, setIsDragging] = react.useState(false);
25
+ const [dragStartX, setDragStartX] = react.useState(0);
26
+ const [dragStartFrame, setDragStartFrame] = react.useState(0);
27
+ const hasDragged = react.useRef(false);
28
+ const currentFrame = react.useRef(0);
28
29
  // Helper to start dragging (common logic for mouse and touch)
29
- const startDrag = React.useCallback((clientX, event) => {
30
+ const startDrag = react.useCallback((clientX, event) => {
30
31
  if (!canvasRef.current)
31
32
  return;
32
33
  setIsDragging(true);
@@ -36,7 +37,7 @@ const useSpriteScrubbing = (canvasRef, totalFrames, options = {}) => {
36
37
  event.preventDefault();
37
38
  }, [canvasRef]);
38
39
  // Helper to handle drag movement (common logic for mouse and touch)
39
- const handleDragMove = React.useCallback((clientX, sensitivity) => {
40
+ const handleDragMove = react.useCallback((clientX, sensitivity) => {
40
41
  if (!isDragging || !canvasRef.current)
41
42
  return;
42
43
  const deltaX = clientX - dragStartX;
@@ -50,29 +51,29 @@ const useSpriteScrubbing = (canvasRef, totalFrames, options = {}) => {
50
51
  return newFrame;
51
52
  }, [isDragging, dragStartX, dragStartFrame, totalFrames, onFrameChange]);
52
53
  // Helper to end dragging (common logic for mouse and touch)
53
- const endDrag = React.useCallback(() => {
54
+ const endDrag = react.useCallback(() => {
54
55
  setIsDragging(false);
55
56
  }, []);
56
- const handleMouseDown = React.useCallback((e) => {
57
+ const handleMouseDown = react.useCallback((e) => {
57
58
  startDrag(e.clientX, e.nativeEvent);
58
59
  }, [startDrag]);
59
- const handleTouchStart = React.useCallback((e) => {
60
+ const handleTouchStart = react.useCallback((e) => {
60
61
  startDrag(e.touches[0].clientX, e.nativeEvent);
61
62
  }, [startDrag]);
62
- const handleDocumentMouseMove = React.useCallback((e) => {
63
+ const handleDocumentMouseMove = react.useCallback((e) => {
63
64
  return handleDragMove(getClientX$1(e), mouseSensitivity);
64
65
  }, [handleDragMove, mouseSensitivity]);
65
- const handleDocumentTouchMove = React.useCallback((e) => {
66
+ const handleDocumentTouchMove = react.useCallback((e) => {
66
67
  return handleDragMove(getClientX$1(e), touchSensitivity);
67
68
  }, [handleDragMove, touchSensitivity]);
68
- const handleDocumentMouseUp = React.useCallback(() => {
69
+ const handleDocumentMouseUp = react.useCallback(() => {
69
70
  endDrag();
70
71
  }, [endDrag]);
71
- const handleDocumentTouchEnd = React.useCallback(() => {
72
+ const handleDocumentTouchEnd = react.useCallback(() => {
72
73
  endDrag();
73
74
  }, [endDrag]);
74
75
  // Add document-level event listeners when dragging starts
75
- React.useEffect(() => {
76
+ react.useEffect(() => {
76
77
  if (isDragging) {
77
78
  document.addEventListener("mousemove", handleDocumentMouseMove);
78
79
  document.addEventListener("mouseup", handleDocumentMouseUp);
@@ -104,191 +105,11 @@ const useSpriteScrubbing = (canvasRef, totalFrames, options = {}) => {
104
105
  };
105
106
  };
106
107
 
107
- /**
108
- * @public
109
- */
110
- const MotionConfigContext = React.createContext({
111
- transformPagePoint: (p) => p,
112
- isStatic: false,
113
- reducedMotion: "never",
114
- });
115
-
116
- /*#__NO_SIDE_EFFECTS__*/
117
- const noop = (any) => any;
118
-
119
- if (process.env.NODE_ENV !== "production") ;
120
-
121
- function createRenderStep(runNextFrame) {
122
- /**
123
- * We create and reuse two queues, one to queue jobs for the current frame
124
- * and one for the next. We reuse to avoid triggering GC after x frames.
125
- */
126
- let thisFrame = new Set();
127
- let nextFrame = new Set();
128
- /**
129
- * Track whether we're currently processing jobs in this step. This way
130
- * we can decide whether to schedule new jobs for this frame or next.
131
- */
132
- let isProcessing = false;
133
- let flushNextFrame = false;
134
- /**
135
- * A set of processes which were marked keepAlive when scheduled.
136
- */
137
- const toKeepAlive = new WeakSet();
138
- let latestFrameData = {
139
- delta: 0.0,
140
- timestamp: 0.0,
141
- isProcessing: false,
142
- };
143
- function triggerCallback(callback) {
144
- if (toKeepAlive.has(callback)) {
145
- step.schedule(callback);
146
- runNextFrame();
147
- }
148
- callback(latestFrameData);
149
- }
150
- const step = {
151
- /**
152
- * Schedule a process to run on the next frame.
153
- */
154
- schedule: (callback, keepAlive = false, immediate = false) => {
155
- const addToCurrentFrame = immediate && isProcessing;
156
- const queue = addToCurrentFrame ? thisFrame : nextFrame;
157
- if (keepAlive)
158
- toKeepAlive.add(callback);
159
- if (!queue.has(callback))
160
- queue.add(callback);
161
- return callback;
162
- },
163
- /**
164
- * Cancel the provided callback from running on the next frame.
165
- */
166
- cancel: (callback) => {
167
- nextFrame.delete(callback);
168
- toKeepAlive.delete(callback);
169
- },
170
- /**
171
- * Execute all schedule callbacks.
172
- */
173
- process: (frameData) => {
174
- latestFrameData = frameData;
175
- /**
176
- * If we're already processing we've probably been triggered by a flushSync
177
- * inside an existing process. Instead of executing, mark flushNextFrame
178
- * as true and ensure we flush the following frame at the end of this one.
179
- */
180
- if (isProcessing) {
181
- flushNextFrame = true;
182
- return;
183
- }
184
- isProcessing = true;
185
- [thisFrame, nextFrame] = [nextFrame, thisFrame];
186
- // Execute this frame
187
- thisFrame.forEach(triggerCallback);
188
- // Clear the frame so no callbacks remain. This is to avoid
189
- // memory leaks should this render step not run for a while.
190
- thisFrame.clear();
191
- isProcessing = false;
192
- if (flushNextFrame) {
193
- flushNextFrame = false;
194
- step.process(frameData);
195
- }
196
- },
197
- };
198
- return step;
199
- }
200
-
201
- const stepsOrder = [
202
- "read", // Read
203
- "resolveKeyframes", // Write/Read/Write/Read
204
- "update", // Compute
205
- "preRender", // Compute
206
- "render", // Write
207
- "postRender", // Compute
208
- ];
209
- const maxElapsed = 40;
210
- function createRenderBatcher(scheduleNextBatch, allowKeepAlive) {
211
- let runNextFrame = false;
212
- let useDefaultElapsed = true;
213
- const state = {
214
- delta: 0.0,
215
- timestamp: 0.0,
216
- isProcessing: false,
217
- };
218
- const flagRunNextFrame = () => (runNextFrame = true);
219
- const steps = stepsOrder.reduce((acc, key) => {
220
- acc[key] = createRenderStep(flagRunNextFrame);
221
- return acc;
222
- }, {});
223
- const { read, resolveKeyframes, update, preRender, render, postRender } = steps;
224
- const processBatch = () => {
225
- const timestamp = performance.now();
226
- runNextFrame = false;
227
- state.delta = useDefaultElapsed
228
- ? 1000 / 60
229
- : Math.max(Math.min(timestamp - state.timestamp, maxElapsed), 1);
230
- state.timestamp = timestamp;
231
- state.isProcessing = true;
232
- // Unrolled render loop for better per-frame performance
233
- read.process(state);
234
- resolveKeyframes.process(state);
235
- update.process(state);
236
- preRender.process(state);
237
- render.process(state);
238
- postRender.process(state);
239
- state.isProcessing = false;
240
- if (runNextFrame && allowKeepAlive) {
241
- useDefaultElapsed = false;
242
- scheduleNextBatch(processBatch);
243
- }
244
- };
245
- const wake = () => {
246
- runNextFrame = true;
247
- useDefaultElapsed = true;
248
- if (!state.isProcessing) {
249
- scheduleNextBatch(processBatch);
250
- }
251
- };
252
- const schedule = stepsOrder.reduce((acc, key) => {
253
- const step = steps[key];
254
- acc[key] = (process, keepAlive = false, immediate = false) => {
255
- if (!runNextFrame)
256
- wake();
257
- return step.schedule(process, keepAlive, immediate);
258
- };
259
- return acc;
260
- }, {});
261
- const cancel = (process) => {
262
- for (let i = 0; i < stepsOrder.length; i++) {
263
- steps[stepsOrder[i]].cancel(process);
264
- }
265
- };
266
- return { schedule, cancel, state, steps };
267
- }
268
-
269
- const { schedule: frame, cancel: cancelFrame} = createRenderBatcher(typeof requestAnimationFrame !== "undefined" ? requestAnimationFrame : noop, true);
270
-
271
- function useAnimationFrame(callback) {
272
- const initialTimestamp = React.useRef(0);
273
- const { isStatic } = React.useContext(MotionConfigContext);
274
- React.useEffect(() => {
275
- if (isStatic)
276
- return;
277
- const provideTimeSinceStart = ({ timestamp, delta }) => {
278
- if (!initialTimestamp.current)
279
- initialTimestamp.current = timestamp;
280
- callback(timestamp - initialTimestamp.current, delta);
281
- };
282
- frame.update(provideTimeSinceStart, true);
283
- return () => cancelFrame(provideTimeSinceStart);
284
- }, [callback]);
285
- }
286
-
287
108
  function useBouncePatternProgress(enabled = true) {
288
- const [value, setValue] = React.useState(0);
289
- const [isBouncing, setIsBouncing] = React.useState(false);
290
- const start = React.useRef(null);
291
- useAnimationFrame((t) => {
109
+ const [value, setValue] = react.useState(0);
110
+ const [isBouncing, setIsBouncing] = react.useState(false);
111
+ const start = react.useRef(null);
112
+ framerMotion.useAnimationFrame((t) => {
292
113
  if (!enabled) {
293
114
  // Reset animation when disabled
294
115
  if (start.current !== null) {
@@ -355,6 +176,9 @@ const renderBuildExperimental = async (request, config) => {
355
176
  const requestWithFormat = {
356
177
  ...request,
357
178
  format: request.format || "video", // Default to video format
179
+ // Include width and height if provided
180
+ ...(request.width !== undefined ? { width: request.width } : {}),
181
+ ...(request.height !== undefined ? { height: request.height } : {}),
358
182
  };
359
183
  const response = await fetch(buildApiUrl(API_ENDPOINTS.RENDER_BUILD_EXPERIMENTAL, config), {
360
184
  method: "POST",
@@ -379,6 +203,9 @@ const createRenderBuildJob = async (request, config) => {
379
203
  parts: request.parts,
380
204
  // If provided, forward format; default handled server-side but we keep explicit default
381
205
  ...(request.format ? { format: request.format } : {}),
206
+ // Include width and height if provided
207
+ ...(request.width !== undefined ? { width: request.width } : {}),
208
+ ...(request.height !== undefined ? { height: request.height } : {}),
382
209
  };
383
210
  const response = await fetch(buildApiUrl(API_ENDPOINTS.RENDER_BUILD, config), {
384
211
  method: "POST",
@@ -439,6 +266,9 @@ const renderSpriteExperimental = async (request, config) => {
439
266
  const requestWithFormat = {
440
267
  ...request,
441
268
  format: "sprite",
269
+ // Include width and height if provided
270
+ ...(request.width !== undefined ? { width: request.width } : {}),
271
+ ...(request.height !== undefined ? { height: request.height } : {}),
442
272
  };
443
273
  const response = await fetch(buildApiUrl(API_ENDPOINTS.RENDER_BUILD_EXPERIMENTAL, config), {
444
274
  method: "POST",
@@ -460,15 +290,24 @@ const renderSpriteExperimental = async (request, config) => {
460
290
  },
461
291
  };
462
292
  };
463
- const getAvailableParts = async (config) => {
464
- const response = await fetch(buildApiUrl(API_ENDPOINTS.AVAILABLE_PARTS, config), {
293
+ const getAvailableParts = async (category, config, options) => {
294
+ const base = buildApiUrl(API_ENDPOINTS.AVAILABLE_PARTS, config);
295
+ const params = new URLSearchParams();
296
+ params.set("category", category);
297
+ if (typeof options?.limit === "number")
298
+ params.set("limit", String(options.limit));
299
+ if (typeof options?.skip === "number")
300
+ params.set("skip", String(options.skip));
301
+ const separator = base.includes("?") ? "&" : "?";
302
+ const url = `${base}${separator}${params.toString()}`;
303
+ const response = await fetch(url, {
465
304
  method: "GET",
466
305
  headers: buildHeaders(config),
467
306
  });
468
307
  if (!response.ok) {
469
308
  throw new Error(`Get available parts failed: ${response.status} ${response.statusText}`);
470
309
  }
471
- return response.json();
310
+ return (await response.json());
472
311
  };
473
312
 
474
313
  /**
@@ -540,11 +379,11 @@ const arePartsEqual = (parts1, parts2) => {
540
379
  return true;
541
380
  };
542
381
  const useBuildRender = (parts, apiConfig, onLoadStart, options) => {
543
- const [videoSrc, setVideoSrc] = React.useState(null);
544
- const [isRenderingBuild, setIsRenderingBuild] = React.useState(false);
545
- const [renderError, setRenderError] = React.useState(null);
546
- const previousPartsRef = React.useRef(null);
547
- const fetchRenderBuild = React.useCallback(async (currentParts) => {
382
+ const [videoSrc, setVideoSrc] = react.useState(null);
383
+ const [isRenderingBuild, setIsRenderingBuild] = react.useState(false);
384
+ const [renderError, setRenderError] = react.useState(null);
385
+ const previousPartsRef = react.useRef(null);
386
+ const fetchRenderBuild = react.useCallback(async (currentParts) => {
548
387
  try {
549
388
  setIsRenderingBuild(true);
550
389
  setRenderError(null);
@@ -579,7 +418,7 @@ const useBuildRender = (parts, apiConfig, onLoadStart, options) => {
579
418
  }
580
419
  }, [apiConfig, onLoadStart, options?.mode]);
581
420
  // Effect to call API when parts content changes (using custom equality check)
582
- React.useEffect(() => {
421
+ react.useEffect(() => {
583
422
  const shouldFetch = previousPartsRef.current === null ||
584
423
  !arePartsEqual(previousPartsRef.current, parts);
585
424
  if (shouldFetch) {
@@ -588,7 +427,7 @@ const useBuildRender = (parts, apiConfig, onLoadStart, options) => {
588
427
  }
589
428
  }, [parts, fetchRenderBuild]);
590
429
  // Cleanup effect for component unmount
591
- React.useEffect(() => {
430
+ react.useEffect(() => {
592
431
  return () => {
593
432
  if (videoSrc && videoSrc.startsWith("blob:")) {
594
433
  URL.revokeObjectURL(videoSrc);
@@ -603,12 +442,12 @@ const useBuildRender = (parts, apiConfig, onLoadStart, options) => {
603
442
  };
604
443
 
605
444
  const useSpriteRender = (parts, apiConfig, onLoadStart, options) => {
606
- const [spriteSrc, setSpriteSrc] = React.useState(null);
607
- const [isRenderingSprite, setIsRenderingSprite] = React.useState(false);
608
- const [renderError, setRenderError] = React.useState(null);
609
- const [spriteMetadata, setSpriteMetadata] = React.useState(null);
610
- const previousPartsRef = React.useRef(null);
611
- const fetchRenderSprite = React.useCallback(async (currentParts) => {
445
+ const [spriteSrc, setSpriteSrc] = react.useState(null);
446
+ const [isRenderingSprite, setIsRenderingSprite] = react.useState(false);
447
+ const [renderError, setRenderError] = react.useState(null);
448
+ const [spriteMetadata, setSpriteMetadata] = react.useState(null);
449
+ const previousPartsRef = react.useRef(null);
450
+ const fetchRenderSprite = react.useCallback(async (currentParts) => {
612
451
  try {
613
452
  setIsRenderingSprite(true);
614
453
  setRenderError(null);
@@ -652,7 +491,7 @@ const useSpriteRender = (parts, apiConfig, onLoadStart, options) => {
652
491
  }
653
492
  }, [apiConfig, onLoadStart, options?.mode]);
654
493
  // Effect to call API when parts content changes (using custom equality check)
655
- React.useEffect(() => {
494
+ react.useEffect(() => {
656
495
  const shouldFetch = previousPartsRef.current === null ||
657
496
  !arePartsEqual(previousPartsRef.current, parts);
658
497
  if (shouldFetch) {
@@ -661,7 +500,7 @@ const useSpriteRender = (parts, apiConfig, onLoadStart, options) => {
661
500
  }
662
501
  }, [parts, fetchRenderSprite]);
663
502
  // Cleanup effect for component unmount
664
- React.useEffect(() => {
503
+ react.useEffect(() => {
665
504
  return () => {
666
505
  if (spriteSrc && spriteSrc.startsWith("blob:")) {
667
506
  URL.revokeObjectURL(spriteSrc);
@@ -732,10 +571,10 @@ const InstructionTooltip = ({ isVisible, progressValue, instructionIcon, }) => {
732
571
  };
733
572
 
734
573
  const BuildRender = ({ parts, width, height, size, apiConfig, useSpriteRenderOptions, mouseSensitivity = 0.2, touchSensitivity = 0.2, }) => {
735
- const canvasRef = React.useRef(null);
736
- const [img, setImg] = React.useState(null);
737
- const [isLoading, setIsLoading] = React.useState(true);
738
- const [bouncingAllowed, setBouncingAllowed] = React.useState(false);
574
+ const canvasRef = react.useRef(null);
575
+ const [img, setImg] = react.useState(null);
576
+ const [isLoading, setIsLoading] = react.useState(true);
577
+ const [bouncingAllowed, setBouncingAllowed] = react.useState(false);
739
578
  const displayW = width ?? size ?? 300;
740
579
  const displayH = height ?? size ?? 300;
741
580
  // Use custom hook for sprite rendering
@@ -744,12 +583,12 @@ const BuildRender = ({ parts, width, height, size, apiConfig, useSpriteRenderOpt
744
583
  const total = spriteMetadata ? spriteMetadata.totalFrames : 72;
745
584
  const cols = spriteMetadata ? spriteMetadata.cols : 12;
746
585
  const rows = spriteMetadata ? spriteMetadata.rows : 6;
747
- const frameRef = React.useRef(0);
586
+ const frameRef = react.useRef(0);
748
587
  // Image/frame sizes
749
588
  const frameW = img ? img.width / cols : 0;
750
589
  const frameH = img ? img.height / rows : 0;
751
590
  // ---- Load sprite image ----
752
- React.useEffect(() => {
591
+ react.useEffect(() => {
753
592
  if (!spriteSrc) {
754
593
  setImg(null);
755
594
  setIsLoading(true);
@@ -774,7 +613,7 @@ const BuildRender = ({ parts, width, height, size, apiConfig, useSpriteRenderOpt
774
613
  };
775
614
  }, [spriteSrc]);
776
615
  // ---- Drawing function ----
777
- const draw = React.useCallback((frameIndex) => {
616
+ const draw = react.useCallback((frameIndex) => {
778
617
  const cnv = canvasRef.current;
779
618
  if (!cnv || !img || !frameW || !frameH)
780
619
  return;
@@ -813,12 +652,12 @@ const BuildRender = ({ parts, width, height, size, apiConfig, useSpriteRenderOpt
813
652
  draw(newFrame);
814
653
  },
815
654
  });
816
- React.useCallback(() => {
655
+ react.useCallback(() => {
817
656
  setIsLoading(true);
818
657
  setBouncingAllowed(false);
819
658
  }, []);
820
659
  // Auto-rotate when bouncing is allowed and not dragged
821
- React.useEffect(() => {
660
+ react.useEffect(() => {
822
661
  if (hasDragged.current || !img)
823
662
  return;
824
663
  // Calculate frame based on progress value (similar to video time calculation)
@@ -827,7 +666,7 @@ const BuildRender = ({ parts, width, height, size, apiConfig, useSpriteRenderOpt
827
666
  draw(frame);
828
667
  }, [progressValue, hasDragged, img, total, draw]);
829
668
  // Initial draw once image is ready
830
- React.useEffect(() => {
669
+ react.useEffect(() => {
831
670
  if (img && !isLoading) {
832
671
  draw(frameRef.current);
833
672
  }
@@ -870,12 +709,12 @@ const calculateCircularTime = (startTime, deltaX, sensitivity, duration) => {
870
709
  };
871
710
  const useVideoScrubbing = (videoRef, options = {}) => {
872
711
  const { mouseSensitivity = 0.01, touchSensitivity = 0.01 } = options;
873
- const [isDragging, setIsDragging] = React.useState(false);
874
- const [dragStartX, setDragStartX] = React.useState(0);
875
- const [dragStartTime, setDragStartTime] = React.useState(0);
876
- const hasDragged = React.useRef(false);
712
+ const [isDragging, setIsDragging] = react.useState(false);
713
+ const [dragStartX, setDragStartX] = react.useState(0);
714
+ const [dragStartTime, setDragStartTime] = react.useState(0);
715
+ const hasDragged = react.useRef(false);
877
716
  // Helper to start dragging (common logic for mouse and touch)
878
- const startDrag = React.useCallback((clientX, event) => {
717
+ const startDrag = react.useCallback((clientX, event) => {
879
718
  if (!videoRef.current)
880
719
  return;
881
720
  setIsDragging(true);
@@ -885,7 +724,7 @@ const useVideoScrubbing = (videoRef, options = {}) => {
885
724
  event.preventDefault();
886
725
  }, [videoRef]);
887
726
  // Helper to handle drag movement (common logic for mouse and touch)
888
- const handleDragMove = React.useCallback((clientX, sensitivity) => {
727
+ const handleDragMove = react.useCallback((clientX, sensitivity) => {
889
728
  if (!isDragging || !videoRef.current)
890
729
  return;
891
730
  const deltaX = clientX - dragStartX;
@@ -896,29 +735,29 @@ const useVideoScrubbing = (videoRef, options = {}) => {
896
735
  }
897
736
  }, [isDragging, dragStartX, dragStartTime, videoRef]);
898
737
  // Helper to end dragging (common logic for mouse and touch)
899
- const endDrag = React.useCallback(() => {
738
+ const endDrag = react.useCallback(() => {
900
739
  setIsDragging(false);
901
740
  }, []);
902
- const handleMouseDown = React.useCallback((e) => {
741
+ const handleMouseDown = react.useCallback((e) => {
903
742
  startDrag(e.clientX, e.nativeEvent);
904
743
  }, [startDrag]);
905
- const handleTouchStart = React.useCallback((e) => {
744
+ const handleTouchStart = react.useCallback((e) => {
906
745
  startDrag(e.touches[0].clientX, e.nativeEvent);
907
746
  }, [startDrag]);
908
- const handleDocumentMouseMove = React.useCallback((e) => {
747
+ const handleDocumentMouseMove = react.useCallback((e) => {
909
748
  handleDragMove(getClientX(e), mouseSensitivity);
910
749
  }, [handleDragMove, mouseSensitivity]);
911
- const handleDocumentTouchMove = React.useCallback((e) => {
750
+ const handleDocumentTouchMove = react.useCallback((e) => {
912
751
  handleDragMove(getClientX(e), touchSensitivity);
913
752
  }, [handleDragMove, touchSensitivity]);
914
- const handleDocumentMouseUp = React.useCallback(() => {
753
+ const handleDocumentMouseUp = react.useCallback(() => {
915
754
  endDrag();
916
755
  }, [endDrag]);
917
- const handleDocumentTouchEnd = React.useCallback(() => {
756
+ const handleDocumentTouchEnd = react.useCallback(() => {
918
757
  endDrag();
919
758
  }, [endDrag]);
920
759
  // Add document-level event listeners when dragging starts
921
- React.useEffect(() => {
760
+ react.useEffect(() => {
922
761
  if (isDragging) {
923
762
  document.addEventListener("mousemove", handleDocumentMouseMove);
924
763
  document.addEventListener("mouseup", handleDocumentMouseUp);
@@ -947,9 +786,9 @@ const useVideoScrubbing = (videoRef, options = {}) => {
947
786
  };
948
787
 
949
788
  const BuildRenderVideo = ({ parts, width, height, size, apiConfig, useBuildRenderOptions, mouseSensitivity = 0.01, touchSensitivity = 0.01, }) => {
950
- const videoRef = React.useRef(null);
951
- const [isLoading, setIsLoading] = React.useState(true);
952
- const [bouncingAllowed, setBouncingAllowed] = React.useState(false);
789
+ const videoRef = react.useRef(null);
790
+ const [isLoading, setIsLoading] = react.useState(true);
791
+ const [bouncingAllowed, setBouncingAllowed] = react.useState(false);
953
792
  const displayW = width ?? size ?? 300;
954
793
  const displayH = height ?? size ?? 300;
955
794
  // Use custom hook for build rendering
@@ -959,18 +798,18 @@ const BuildRenderVideo = ({ parts, width, height, size, apiConfig, useBuildRende
959
798
  mouseSensitivity,
960
799
  touchSensitivity,
961
800
  });
962
- const handleLoadStartInternal = React.useCallback(() => {
801
+ const handleLoadStartInternal = react.useCallback(() => {
963
802
  setIsLoading(true);
964
803
  setBouncingAllowed(false);
965
804
  }, []);
966
- const handleCanPlayInternal = React.useCallback(() => {
805
+ const handleCanPlayInternal = react.useCallback(() => {
967
806
  setIsLoading(false);
968
807
  // Start bouncing animation after delay
969
808
  setTimeout(() => {
970
809
  setBouncingAllowed(true);
971
810
  }, 2000);
972
811
  }, []);
973
- React.useEffect(() => {
812
+ react.useEffect(() => {
974
813
  if (hasDragged.current || !videoRef.current)
975
814
  return;
976
815
  const duration = videoRef.current.duration;