@react-hive/honey-layout 10.4.1 → 10.5.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.
@@ -9,3 +9,4 @@ export * from './use-honey-resize';
9
9
  export * from './use-honey-synthetic-scroll';
10
10
  export * from './use-honey-synthetic-scroll-x';
11
11
  export * from './use-honey-synthetic-scroll-y';
12
+ export * from './use-honey-raf-loop';
@@ -0,0 +1,144 @@
1
+ interface HoneyRafCallbackContext {
2
+ /**
3
+ * Stops the currently running RAF loop.
4
+ *
5
+ * Calling this function immediately:
6
+ * - Cancels the next animation frame
7
+ * - Resets internal timing state
8
+ * - Sets `isRafLoopRunning` to `false`
9
+ *
10
+ * This function is safe to call from within the RAF callback
11
+ * and is the preferred way to terminate the loop based on
12
+ * frame-driven conditions (e.g. inertia decay, animation completion).
13
+ */
14
+ stop: () => void;
15
+ }
16
+ /**
17
+ * RAF callback invoked on every animation frame.
18
+ *
19
+ * The callback is invoked with the elapsed time since the previous
20
+ * frame and a control context for managing the RAF loop lifecycle.
21
+ *
22
+ * ⚠️ Callback stability
23
+ * The callback should be wrapped in `useCallback` to ensure
24
+ * referential stability and to make dependencies explicit.
25
+ *
26
+ * @param dtMs - Delta time in milliseconds since the previous frame.
27
+ * The value is clamped to `maxDeltaMs` to avoid large jumps
28
+ * when the tab is inactive, backgrounded, or the browser
29
+ * throttles animation frames.
30
+ *
31
+ * @param context - RAF loop control helpers.
32
+ */
33
+ export type HoneyRafCallback = (dtMs: number, context: HoneyRafCallbackContext) => void;
34
+ /**
35
+ * Configuration options for {@link useHoneyRafLoop}.
36
+ */
37
+ interface UseHoneyRafLoopOptions {
38
+ /**
39
+ * Automatically start the RAF loop on mount.
40
+ *
41
+ * This is useful for continuous loops (e.g. visualizers),
42
+ * but should generally be disabled for gesture- or intent-driven animations.
43
+ *
44
+ * @default false
45
+ */
46
+ autoStart?: boolean;
47
+ /**
48
+ * Whether the RAF loop should automatically resume when the
49
+ * document becomes visible again after being hidden.
50
+ *
51
+ * ⚠️ Important:
52
+ * - Visibility changes will ALWAYS stop the RAF loop
53
+ * - Resuming is **opt-in** and never happens implicitly
54
+ *
55
+ * This option should only be enabled for truly continuous
56
+ * systems (e.g. game loops, live visualizations).
57
+ *
58
+ * It is intentionally disabled by default to avoid restarting
59
+ * gesture-driven or state-sensitive animations with stale data.
60
+ *
61
+ * Requires `autoStart` to be enabled.
62
+ *
63
+ * @default false
64
+ */
65
+ resumeOnVisibility?: boolean;
66
+ /**
67
+ * Maximum allowed delta time between frames.
68
+ *
69
+ * This prevents physics, inertia, or animation logic from receiving large
70
+ * time steps after backgrounding, tab switches, or frame drops.
71
+ *
72
+ * @default 32
73
+ */
74
+ maxDeltaMs?: number;
75
+ /**
76
+ * Optional error handler invoked when the RAF callback throws.
77
+ *
78
+ * When an error occurs:
79
+ * - The RAF loop is immediately stopped
80
+ * - `isRafLoopRunning` is set to `false`
81
+ * - The error is passed to this handler
82
+ *
83
+ * @default undefined
84
+ */
85
+ onError?: (error: unknown) => void;
86
+ }
87
+ /**
88
+ * A hook for running a controlled `requestAnimationFrame` loop.
89
+ *
90
+ * Features:
91
+ * - Explicit RAF lifecycle control (`start` / `stop`)
92
+ * - Delta time (`dt`) calculation with frame clamping
93
+ * - Automatic cleanup on unmounting
94
+ * - Conservative handling of tab visibility changes (mobile-safe)
95
+ * - Safe error handling (stops loop on exception)
96
+ *
97
+ * Visibility behavior:
98
+ * - The RAF loop is always stopped when the document becomes hidden
99
+ * - Automatic resume is disabled by default and must be explicitly enabled
100
+ *
101
+ * This hook is designed for gesture handling, inertia, physics simulations,
102
+ * and animation loops that must not trigger React re-renders on every frame.
103
+ *
104
+ * @param callback - Function invoked on each animation frame.
105
+ * @param options - Optional configuration for the RAF loop.
106
+ *
107
+ * @returns Control helpers and RAF loop state.
108
+ *
109
+ * @example
110
+ * ```ts
111
+ * // Gesture-driven inertia (recommended usage)
112
+ * // The RAF loop stops itself when motion decays.
113
+ *
114
+ * const velocityRef = useRef({ x: 12, y: 4 });
115
+ *
116
+ * const onFrame = useCallback<HoneyRafCallback>(
117
+ * (dtMs, { stop }) => {
118
+ * velocityRef.current.x *= 0.94;
119
+ * velocityRef.current.y *= 0.94;
120
+ *
121
+ * setPosition(p => ({
122
+ * x: p.x + velocityRef.current.x,
123
+ * y: p.y + velocityRef.current.y,
124
+ * }));
125
+ *
126
+ * if (
127
+ * Math.abs(velocityRef.current.x) < 0.1 &&
128
+ * Math.abs(velocityRef.current.y) < 0.1
129
+ * ) {
130
+ * stop(); // terminate RAF loop
131
+ * }
132
+ * },
133
+ * [],
134
+ * );
135
+ *
136
+ * useHoneyRafLoop(onFrame);
137
+ * ```
138
+ */
139
+ export declare const useHoneyRafLoop: (callback: HoneyRafCallback, { autoStart, resumeOnVisibility, maxDeltaMs, onError, }?: UseHoneyRafLoopOptions) => {
140
+ startRafLoop: () => void;
141
+ stopRafLoop: () => void;
142
+ isRafLoopRunning: boolean;
143
+ };
144
+ export {};