@react-hive/honey-layout 10.6.0 → 10.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -13730,6 +13730,7 @@ __webpack_require__.r(__webpack_exports__);
13730
13730
  /* harmony export */ useHoneySyntheticScroll: () => (/* reexport safe */ _use_honey_synthetic_scroll__WEBPACK_IMPORTED_MODULE_8__.useHoneySyntheticScroll),
13731
13731
  /* harmony export */ useHoneySyntheticScrollX: () => (/* reexport safe */ _use_honey_synthetic_scroll_x__WEBPACK_IMPORTED_MODULE_9__.useHoneySyntheticScrollX),
13732
13732
  /* harmony export */ useHoneySyntheticScrollY: () => (/* reexport safe */ _use_honey_synthetic_scroll_y__WEBPACK_IMPORTED_MODULE_10__.useHoneySyntheticScrollY),
13733
+ /* harmony export */ useHoneyTimer: () => (/* reexport safe */ _use_honey_timer__WEBPACK_IMPORTED_MODULE_12__.useHoneyTimer),
13733
13734
  /* harmony export */ useRegisterHoneyOverlay: () => (/* reexport safe */ _use_register_honey_overlay__WEBPACK_IMPORTED_MODULE_5__.useRegisterHoneyOverlay)
13734
13735
  /* harmony export */ });
13735
13736
  /* harmony import */ var _use_honey_on_change__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./use-honey-on-change */ "./src/hooks/use-honey-on-change.ts");
@@ -13744,6 +13745,8 @@ __webpack_require__.r(__webpack_exports__);
13744
13745
  /* harmony import */ var _use_honey_synthetic_scroll_x__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./use-honey-synthetic-scroll-x */ "./src/hooks/use-honey-synthetic-scroll-x.ts");
13745
13746
  /* harmony import */ var _use_honey_synthetic_scroll_y__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./use-honey-synthetic-scroll-y */ "./src/hooks/use-honey-synthetic-scroll-y.ts");
13746
13747
  /* harmony import */ var _use_honey_raf_loop__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./use-honey-raf-loop */ "./src/hooks/use-honey-raf-loop.ts");
13748
+ /* harmony import */ var _use_honey_timer__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ./use-honey-timer */ "./src/hooks/use-honey-timer.ts");
13749
+
13747
13750
 
13748
13751
 
13749
13752
 
@@ -14203,7 +14206,7 @@ __webpack_require__.r(__webpack_exports__);
14203
14206
  * This hook is designed for gesture handling, inertia, physics simulations,
14204
14207
  * and animation loops that must not trigger React re-renders on every frame.
14205
14208
  *
14206
- * @param callback - Function invoked on each animation frame.
14209
+ * @param onFrame - Function invoked on each animation frame.
14207
14210
  * @param options - Optional configuration for the RAF loop.
14208
14211
  *
14209
14212
  * @returns Control helpers and RAF loop state.
@@ -14215,7 +14218,7 @@ __webpack_require__.r(__webpack_exports__);
14215
14218
  *
14216
14219
  * const velocityRef = useRef({ x: 12, y: 4 });
14217
14220
  *
14218
- * const onFrame = useCallback<HoneyRafCallback>(
14221
+ * const onFrame = useCallback<HoneyRafOnFrameHandler>(
14219
14222
  * (dtMs, { stop }) => {
14220
14223
  * velocityRef.current.x *= 0.94;
14221
14224
  * velocityRef.current.y *= 0.94;
@@ -14238,27 +14241,27 @@ __webpack_require__.r(__webpack_exports__);
14238
14241
  * useHoneyRafLoop(onFrame);
14239
14242
  * ```
14240
14243
  */
14241
- const useHoneyRafLoop = (callback, { autoStart = false, resumeOnVisibility = false, maxDeltaMs = 32, // ~30fps clamp
14244
+ const useHoneyRafLoop = (onFrame, { autoStart = false, resumeOnVisibility = false, maxDeltaMs = 32, // ~30fps clamp
14242
14245
  onError, } = {}) => {
14243
14246
  const rafIdRef = (0,react__WEBPACK_IMPORTED_MODULE_0__.useRef)(null);
14244
- const lastTimeRef = (0,react__WEBPACK_IMPORTED_MODULE_0__.useRef)(null);
14245
- const callbackRef = (0,react__WEBPACK_IMPORTED_MODULE_0__.useRef)(callback);
14247
+ const lastTimeMsRef = (0,react__WEBPACK_IMPORTED_MODULE_0__.useRef)(null);
14248
+ const onFrameRef = (0,react__WEBPACK_IMPORTED_MODULE_0__.useRef)(onFrame);
14246
14249
  // Always keep the latest callback without restarting RAF
14247
- callbackRef.current = callback;
14250
+ onFrameRef.current = onFrame;
14248
14251
  const [isRafLoopRunning, setIsRafLoopRunning] = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(false);
14249
- const loop = (0,react__WEBPACK_IMPORTED_MODULE_0__.useCallback)(time => {
14250
- if (lastTimeRef.current === null) {
14251
- lastTimeRef.current = time;
14252
+ const loop = (0,react__WEBPACK_IMPORTED_MODULE_0__.useCallback)(timeMs => {
14253
+ if (lastTimeMsRef.current === null) {
14254
+ lastTimeMsRef.current = timeMs;
14252
14255
  }
14253
- let dt = time - lastTimeRef.current;
14254
- lastTimeRef.current = time;
14256
+ let deltaTimeMs = timeMs - lastTimeMsRef.current;
14257
+ lastTimeMsRef.current = timeMs;
14255
14258
  // Clamp delta (prevents jumps after background tab / lag)
14256
- if (dt > maxDeltaMs) {
14257
- dt = maxDeltaMs;
14259
+ if (deltaTimeMs > maxDeltaMs) {
14260
+ deltaTimeMs = maxDeltaMs;
14258
14261
  }
14259
14262
  try {
14260
- callbackRef.current(dt, {
14261
- stop: stopRafLoop,
14263
+ onFrameRef.current(deltaTimeMs, {
14264
+ stopRafLoop,
14262
14265
  });
14263
14266
  rafIdRef.current = requestAnimationFrame(loop);
14264
14267
  }
@@ -14271,7 +14274,7 @@ onError, } = {}) => {
14271
14274
  if (rafIdRef.current !== null) {
14272
14275
  return;
14273
14276
  }
14274
- lastTimeRef.current = null;
14277
+ lastTimeMsRef.current = null;
14275
14278
  setIsRafLoopRunning(true);
14276
14279
  rafIdRef.current = requestAnimationFrame(loop);
14277
14280
  }, [loop]);
@@ -14281,7 +14284,7 @@ onError, } = {}) => {
14281
14284
  }
14282
14285
  cancelAnimationFrame(rafIdRef.current);
14283
14286
  rafIdRef.current = null;
14284
- lastTimeRef.current = null;
14287
+ lastTimeMsRef.current = null;
14285
14288
  setIsRafLoopRunning(false);
14286
14289
  }, []);
14287
14290
  (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(() => {
@@ -14306,9 +14309,9 @@ onError, } = {}) => {
14306
14309
  };
14307
14310
  }, [autoStart, resumeOnVisibility, startRafLoop, stopRafLoop]);
14308
14311
  return {
14312
+ isRafLoopRunning,
14309
14313
  startRafLoop,
14310
14314
  stopRafLoop,
14311
- isRafLoopRunning,
14312
14315
  };
14313
14316
  };
14314
14317
 
@@ -14618,6 +14621,120 @@ const useHoneySyntheticScroll = ({ axis = 'both', overscrollPct = 0, onStartDrag
14618
14621
  };
14619
14622
 
14620
14623
 
14624
+ /***/ },
14625
+
14626
+ /***/ "./src/hooks/use-honey-timer.ts"
14627
+ /*!**************************************!*\
14628
+ !*** ./src/hooks/use-honey-timer.ts ***!
14629
+ \**************************************/
14630
+ (__unused_webpack_module, __webpack_exports__, __webpack_require__) {
14631
+
14632
+ "use strict";
14633
+ __webpack_require__.r(__webpack_exports__);
14634
+ /* harmony export */ __webpack_require__.d(__webpack_exports__, {
14635
+ /* harmony export */ useHoneyTimer: () => (/* binding */ useHoneyTimer)
14636
+ /* harmony export */ });
14637
+ /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ "react");
14638
+ /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);
14639
+ /* harmony import */ var _use_honey_raf_loop__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./use-honey-raf-loop */ "./src/hooks/use-honey-raf-loop.ts");
14640
+
14641
+
14642
+ /**
14643
+ * A high-precision timer hook built on top of {@link useHoneyRafLoop}.
14644
+ *
14645
+ * Features:
14646
+ * - Frame-accurate time progression using `requestAnimationFrame`
14647
+ * - Supports countdown and count-up modes
14648
+ * - Explicit lifecycle control (start / pause / resume / reset)
14649
+ * - Drift-free timing using delta-based updates
14650
+ * - Safe completion handling via `onEnd`
14651
+ *
14652
+ * Architectural notes:
14653
+ * - Time progression is handled imperatively via refs to avoid stale closures and unnecessary re-renders.
14654
+ * - React state is updated only with the derived timer value.
14655
+ * - RAF lifecycle is fully delegated to `useHoneyRafLoop`.
14656
+ *
14657
+ * @example
14658
+ * ```ts
14659
+ * const timer = useHoneyTimer({
14660
+ * initialTimeMs: 10_000,
14661
+ * targetTimeMs: 0,
14662
+ * onEnd: () => console.log('Done'),
14663
+ * });
14664
+ *
14665
+ * timer.startTimer();
14666
+ * ```
14667
+ */
14668
+ const useHoneyTimer = ({ initialTimeMs, targetTimeMs = 0, mode = 'countdown', autoStart = false, onEnd, }) => {
14669
+ const [timeMs, setTimeMs] = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(initialTimeMs);
14670
+ const timeRef = (0,react__WEBPACK_IMPORTED_MODULE_0__.useRef)(timeMs);
14671
+ timeRef.current = timeMs;
14672
+ const onEndRef = (0,react__WEBPACK_IMPORTED_MODULE_0__.useRef)(onEnd);
14673
+ onEndRef.current = onEnd;
14674
+ /**
14675
+ * RAF frame handler responsible for advancing the timer.
14676
+ *
14677
+ * - Computes the next timer value based on `deltaTimeMs`
14678
+ * - Detects completion and stops the RAF loop
14679
+ * - Updates React state with the derived value
14680
+ */
14681
+ const onFrameHandler = (0,react__WEBPACK_IMPORTED_MODULE_0__.useCallback)((deltaTimeMs, { stopRafLoop }) => {
14682
+ let nextTime = mode === 'countdown' ? timeRef.current - deltaTimeMs : timeRef.current + deltaTimeMs;
14683
+ let finished = false;
14684
+ if (mode === 'countdown') {
14685
+ if (nextTime <= targetTimeMs) {
14686
+ nextTime = targetTimeMs;
14687
+ finished = true;
14688
+ }
14689
+ }
14690
+ else if (targetTimeMs > 0 && nextTime >= targetTimeMs) {
14691
+ nextTime = targetTimeMs;
14692
+ finished = true;
14693
+ }
14694
+ timeRef.current = nextTime;
14695
+ setTimeMs(nextTime);
14696
+ if (finished) {
14697
+ stopRafLoop();
14698
+ onEndRef.current?.();
14699
+ }
14700
+ }, [mode, targetTimeMs]);
14701
+ const { startRafLoop, stopRafLoop, isRafLoopRunning } = (0,_use_honey_raf_loop__WEBPACK_IMPORTED_MODULE_1__.useHoneyRafLoop)(onFrameHandler, {
14702
+ autoStart,
14703
+ });
14704
+ const startTimer = (0,react__WEBPACK_IMPORTED_MODULE_0__.useCallback)(() => {
14705
+ timeRef.current = initialTimeMs;
14706
+ setTimeMs(initialTimeMs);
14707
+ startRafLoop();
14708
+ }, [initialTimeMs, startRafLoop]);
14709
+ const pauseTimer = (0,react__WEBPACK_IMPORTED_MODULE_0__.useCallback)(() => {
14710
+ stopRafLoop();
14711
+ }, [stopRafLoop]);
14712
+ const resumeTimer = (0,react__WEBPACK_IMPORTED_MODULE_0__.useCallback)(() => {
14713
+ if (!isRafLoopRunning) {
14714
+ startRafLoop();
14715
+ }
14716
+ }, [isRafLoopRunning, startRafLoop]);
14717
+ const resetTimer = (0,react__WEBPACK_IMPORTED_MODULE_0__.useCallback)((nextTimeMs = initialTimeMs) => {
14718
+ stopRafLoop();
14719
+ timeRef.current = nextTimeMs;
14720
+ setTimeMs(nextTimeMs);
14721
+ }, [initialTimeMs, stopRafLoop]);
14722
+ (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(() => {
14723
+ if (autoStart) {
14724
+ startTimer();
14725
+ }
14726
+ }, [autoStart, startTimer]);
14727
+ return {
14728
+ timerTimeMs: timeMs,
14729
+ isTimerRunning: isRafLoopRunning,
14730
+ startTimer,
14731
+ pauseTimer,
14732
+ resumeTimer,
14733
+ resetTimer,
14734
+ };
14735
+ };
14736
+
14737
+
14621
14738
  /***/ },
14622
14739
 
14623
14740
  /***/ "./src/hooks/use-register-honey-overlay.ts"
@@ -15412,6 +15529,7 @@ __webpack_require__.r(__webpack_exports__);
15412
15529
  /* harmony export */ useHoneySyntheticScroll: () => (/* reexport safe */ _hooks__WEBPACK_IMPORTED_MODULE_5__.useHoneySyntheticScroll),
15413
15530
  /* harmony export */ useHoneySyntheticScrollX: () => (/* reexport safe */ _hooks__WEBPACK_IMPORTED_MODULE_5__.useHoneySyntheticScrollX),
15414
15531
  /* harmony export */ useHoneySyntheticScrollY: () => (/* reexport safe */ _hooks__WEBPACK_IMPORTED_MODULE_5__.useHoneySyntheticScrollY),
15532
+ /* harmony export */ useHoneyTimer: () => (/* reexport safe */ _hooks__WEBPACK_IMPORTED_MODULE_5__.useHoneyTimer),
15415
15533
  /* harmony export */ useRegisterHoneyOverlay: () => (/* reexport safe */ _hooks__WEBPACK_IMPORTED_MODULE_5__.useRegisterHoneyOverlay),
15416
15534
  /* harmony export */ warnOnce: () => (/* reexport safe */ _utils__WEBPACK_IMPORTED_MODULE_6__.warnOnce)
15417
15535
  /* harmony export */ });