@react-hive/honey-layout 11.0.0 → 11.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.
@@ -1,7 +1,8 @@
1
+ import type { InertiaOptions } from '@react-hive/honey-utils';
1
2
  /**
2
3
  * Configuration options for {@link useHoneyDecay}.
3
4
  */
4
- export interface UseHoneyDecayOptions {
5
+ export interface UseHoneyDecayOptions extends Pick<InertiaOptions, 'friction' | 'minVelocityPxMs' | 'emaAlpha'> {
5
6
  /**
6
7
  * Initial numeric value from which inertial motion starts.
7
8
  *
@@ -22,24 +23,16 @@ export interface UseHoneyDecayOptions {
22
23
  */
23
24
  max: number;
24
25
  /**
25
- * Exponential friction coefficient applied per millisecond.
26
+ * Optional callback invoked exactly once when inertial motion terminates.
26
27
  *
27
- * Controls how quickly velocity decays over time.
28
+ * Triggered when inertia ends due to:
29
+ * - velocity decaying below `minVelocityPxMs`
30
+ * - movement being blocked by bounds
31
+ * - an explicit call to `stop()`
28
32
  *
29
- * Smaller values produce longer, floatier inertia;
30
- * larger values result in a quicker stop.
31
- *
32
- * @default 0.002
33
- */
34
- friction?: number;
35
- /**
36
- * Minimum absolute velocity below which inertia is considered complete.
37
- *
38
- * This prevents unnecessary micro-updates and jitter near rest.
39
- *
40
- * @default 0.01
33
+ * Not invoked if inertia was never started.
41
34
  */
42
- minVelocityPxMs?: number;
35
+ onStop?: () => void;
43
36
  }
44
37
  /**
45
38
  * Public control API returned by {@link useHoneyDecay}.
@@ -58,6 +51,38 @@ export interface UseHoneyDecayApi {
58
51
  * Indicates whether inertial motion is currently active.
59
52
  */
60
53
  isRunning: boolean;
54
+ /**
55
+ * Updates the hard bounds used by the decay simulation.
56
+ *
57
+ * This method is safe to call **at any time**, including while inertia is actively running.
58
+ *
59
+ * ### Behavior
60
+ * - If the current value lies **within** the new bounds:
61
+ * - bounds are updated
62
+ * - inertia (if running) continues uninterrupted
63
+ *
64
+ * - If the current value lies **outside** the new bounds:
65
+ * - the value is immediately clamped to the nearest boundary
66
+ * - internal velocity is reset to `0`
67
+ * - any active inertia is **terminated immediately**
68
+ * - `onStop` is invoked exactly once (if inertia was active)
69
+ *
70
+ * This deterministic behavior mirrors native scroll engines and ensures:
71
+ * - no overshoot
72
+ * - no extra inertia frames
73
+ * - consistent `onStop` semantics
74
+ *
75
+ * ### Intended usage
76
+ * - Responding to layout or content changes
77
+ * - Handling resize / orientation changes
78
+ * - Updating overscroll or overflow limits dynamically
79
+ *
80
+ * ⚠️ This method should **not** be called from inside the RAF frame handler.
81
+ *
82
+ * @param min - New lower bound (inclusive)
83
+ * @param max - New upper bound (inclusive)
84
+ */
85
+ setBounds: (min: number, max: number) => void;
61
86
  /**
62
87
  * Starts inertial motion from the current value using
63
88
  * the provided initial velocity.
@@ -70,18 +95,30 @@ export interface UseHoneyDecayApi {
70
95
  */
71
96
  start: (velocityPxMs: number) => void;
72
97
  /**
73
- * Immediately stops inertial motion.
98
+ * Immediately sets the value and starts inertial motion from that value in a single atomic operation.
99
+ *
100
+ * This is the preferred way to hand off from a gesture (e.g. drag end) to inertia, as it:
101
+ * - avoids transient intermediate states
102
+ * - guarantees correct value/velocity ordering
103
+ * - ensures `onStop` semantics remain consistent
104
+ *
105
+ * @param value - Starting value for the inertia simulation
106
+ * @param velocityPxMs - Initial velocity in pixels per millisecond (`px/ms`)
74
107
  */
75
- stop: () => void;
108
+ startFrom: (value: number, velocityPxMs: number) => void;
76
109
  /**
77
- * Immediately sets the value and cancels any active inertia.
110
+ * Immediately stops inertial motion.
78
111
  *
79
- * @param value - The value to apply immediately.
112
+ * If inertia is currently active, this will:
113
+ * - cancel the RAF loop
114
+ * - reset internal velocity
115
+ * - invoke `onStop` exactly once
80
116
  */
81
- snapTo: (value: number) => void;
117
+ stop: () => void;
82
118
  }
83
119
  /**
84
- * A bounded, velocity-based inertia (decay) hook built on top of {@link useHoneyRafLoop} and {@link applyInertiaStep}.
120
+ * A bounded, velocity-based inertia (decay) hook built on top
121
+ * of {@link useHoneyRafLoop} and {@link applyInertiaStep}.
85
122
  *
86
123
  * This hook models **momentum-driven motion** where:
87
124
  * - Motion starts with an initial velocity
@@ -139,4 +176,4 @@ export interface UseHoneyDecayApi {
139
176
  * );
140
177
  * ```
141
178
  */
142
- export declare const useHoneyDecay: ({ initialValue, min, max, friction, minVelocityPxMs, }: UseHoneyDecayOptions) => UseHoneyDecayApi;
179
+ export declare const useHoneyDecay: ({ initialValue, min, max, friction, minVelocityPxMs, emaAlpha, onStop, }: UseHoneyDecayOptions) => UseHoneyDecayApi;
@@ -0,0 +1,18 @@
1
+ import type { RefObject } from 'react';
2
+ type UseHoneyLatest = {
3
+ <T>(value: T): RefObject<T>;
4
+ <T>(value: T | undefined): RefObject<T | undefined>;
5
+ };
6
+ /**
7
+ * Stores the latest value in a stable ref.
8
+ *
9
+ * Guarantees that:
10
+ * - `ref.current` always points to the latest value
11
+ * - the ref object identity never changes
12
+ *
13
+ * Overload behavior:
14
+ * - If a non-optional value is provided, `.current` is non-optional
15
+ * - If an optional value is provided, `.current` is optional
16
+ */
17
+ export declare const useHoneyLatest: UseHoneyLatest;
18
+ export {};
@@ -1,4 +1,4 @@
1
- interface HoneyRafOnFrameContext {
1
+ interface HoneyRafFrameContext {
2
2
  /**
3
3
  * Immediately terminates the active `requestAnimationFrame` loop.
4
4
  *
@@ -29,9 +29,9 @@ interface HoneyRafOnFrameContext {
29
29
  * time steps caused by tab backgrounding, visibility changes,
30
30
  * or browser throttling.
31
31
  *
32
- * @param context - RAF lifecycle control context. See {@link HoneyRafOnFrameContext}.
32
+ * @param context - RAF lifecycle control context. See {@link HoneyRafFrameContext}.
33
33
  */
34
- export type HoneyRafOnFrameHandler = (deltaTimeMs: number, context: HoneyRafOnFrameContext) => void;
34
+ export type HoneyRafFrameHandler = (deltaTimeMs: number, context: HoneyRafFrameContext) => void;
35
35
  /**
36
36
  * Configuration options for {@link useHoneyRafLoop}.
37
37
  */
@@ -160,5 +160,5 @@ export interface HoneyRafLoopApi {
160
160
  * useHoneyRafLoop(onFrame);
161
161
  * ```
162
162
  */
163
- export declare const useHoneyRafLoop: (onFrame: HoneyRafOnFrameHandler, { autoStart, resumeOnVisibility, maxDeltaMs, onError, }?: UseHoneyRafLoopOptions) => HoneyRafLoopApi;
163
+ export declare const useHoneyRafLoop: (onFrame: HoneyRafFrameHandler, { autoStart, resumeOnVisibility, maxDeltaMs, onError, }?: UseHoneyRafLoopOptions) => HoneyRafLoopApi;
164
164
  export {};
@@ -5,7 +5,7 @@
5
5
  * - `countup` — increases time until it reaches `targetTimeMs` (if provided)
6
6
  */
7
7
  type UseHoneyTimerMode = 'countdown' | 'countup';
8
- type UseHoneyTimerOnEndHandler = () => void;
8
+ type UseHoneyTimerEndHandler = () => void;
9
9
  export interface UseHoneyTimerOptions {
10
10
  /**
11
11
  * Initial timer value in milliseconds.
@@ -40,7 +40,7 @@ export interface UseHoneyTimerOptions {
40
40
  /**
41
41
  * Optional callback invoked exactly once when the timer reaches the target time.
42
42
  */
43
- onEnd?: UseHoneyTimerOnEndHandler;
43
+ onEnd?: UseHoneyTimerEndHandler;
44
44
  }
45
45
  /**
46
46
  * Public control API returned by {@link useHoneyTimer}.