@react-hive/honey-layout 10.8.0 → 11.0.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.
@@ -11,3 +11,4 @@ export * from './use-honey-synthetic-scroll-x';
11
11
  export * from './use-honey-synthetic-scroll-y';
12
12
  export * from './use-honey-raf-loop';
13
13
  export * from './use-honey-timer';
14
+ export * from './use-honey-decay';
@@ -0,0 +1,142 @@
1
+ /**
2
+ * Configuration options for {@link useHoneyDecay}.
3
+ */
4
+ export interface UseHoneyDecayOptions {
5
+ /**
6
+ * Initial numeric value from which inertial motion starts.
7
+ *
8
+ * This typically represents a translated position (e.g. scroll offset or `translateX` value),
9
+ * but may be any bounded numeric domain.
10
+ */
11
+ initialValue: number;
12
+ /**
13
+ * Lower bound for the value (inclusive).
14
+ *
15
+ * Movement beyond this boundary is not permitted.
16
+ */
17
+ min: number;
18
+ /**
19
+ * Upper bound for the value (inclusive).
20
+ *
21
+ * Movement beyond this boundary is not permitted.
22
+ */
23
+ max: number;
24
+ /**
25
+ * Exponential friction coefficient applied per millisecond.
26
+ *
27
+ * Controls how quickly velocity decays over time.
28
+ *
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
41
+ */
42
+ minVelocityPxMs?: number;
43
+ }
44
+ /**
45
+ * Public control API returned by {@link useHoneyDecay}.
46
+ *
47
+ * Exposes imperative controls for managing velocity-based inertial motion.
48
+ */
49
+ export interface UseHoneyDecayApi {
50
+ /**
51
+ * Current value produced by the decay simulation.
52
+ *
53
+ * This value updates over time while inertia is active
54
+ * and always remains within the configured bounds.
55
+ */
56
+ value: number;
57
+ /**
58
+ * Indicates whether inertial motion is currently active.
59
+ */
60
+ isRunning: boolean;
61
+ /**
62
+ * Starts inertial motion from the current value using
63
+ * the provided initial velocity.
64
+ *
65
+ * The sign of the velocity determines a direction:
66
+ * - Positive → movement toward the upper bound
67
+ * - Negative → movement toward the lower bound
68
+ *
69
+ * @param velocityPxMs - Initial velocity expressed in pixels per millisecond (`px/ms`).
70
+ */
71
+ start: (velocityPxMs: number) => void;
72
+ /**
73
+ * Immediately stops inertial motion.
74
+ */
75
+ stop: () => void;
76
+ /**
77
+ * Immediately sets the value and cancels any active inertia.
78
+ *
79
+ * @param value - The value to apply immediately.
80
+ */
81
+ snapTo: (value: number) => void;
82
+ }
83
+ /**
84
+ * A bounded, velocity-based inertia (decay) hook built on top of {@link useHoneyRafLoop} and {@link applyInertiaStep}.
85
+ *
86
+ * This hook models **momentum-driven motion** where:
87
+ * - Motion starts with an initial velocity
88
+ * - Velocity decays exponentially over time
89
+ * - Movement is constrained by hard numeric bounds
90
+ * - Inertia stops naturally when velocity becomes negligible
91
+ *
92
+ * Unlike spring-based motion, this hook has **no target value**.
93
+ * Motion continues purely based on momentum until it decays
94
+ * or is blocked by a boundary.
95
+ *
96
+ * ---
97
+ *
98
+ * ### Key characteristics
99
+ * - Frame-rate independent (delta-time based)
100
+ * - Deterministic and interruptible
101
+ * - Direction-aware and bound-safe (no overshoot or jitter)
102
+ * - Closely matches native scroll and drag inertia behavior
103
+ *
104
+ * ---
105
+ *
106
+ * ### Visibility behavior
107
+ * This hook is a **simulation-based system**:
108
+ * - Inertia automatically pauses when the document becomes hidden
109
+ * - No time elapses while hidden
110
+ * - Motion resumes only when explicitly restarted
111
+ *
112
+ * This behavior is inherited from {@link useHoneyRafLoop} and is intentional.
113
+ *
114
+ * ---
115
+ *
116
+ * ### Common use cases
117
+ * - Scroll containers with momentum
118
+ * - Drag-to-scroll interactions
119
+ * - Carousels and sliders
120
+ * - Timelines and scrubbers
121
+ * - Kinetic panning and flinging
122
+ *
123
+ * ---
124
+ *
125
+ * @example
126
+ * ```ts
127
+ * const decay = useHoneyDecay({
128
+ * initialValue: 0,
129
+ * min: -maxOverflow,
130
+ * max: 0,
131
+ * });
132
+ *
133
+ * const onRelease = (velocityPxMs: number) => {
134
+ * decay.start(velocityPxMs);
135
+ * };
136
+ *
137
+ * return (
138
+ * <div style={{ transform: `translateX(${decay.value}px)` }} />
139
+ * );
140
+ * ```
141
+ */
142
+ export declare const useHoneyDecay: ({ initialValue, min, max, friction, minVelocityPxMs, }: UseHoneyDecayOptions) => UseHoneyDecayApi;
@@ -1,97 +1,130 @@
1
1
  import type { RefObject } from 'react';
2
2
  import type { Nullable } from '../types';
3
3
  /**
4
- * Handler triggered when a drag operation starts.
4
+ * Invoked when a drag gesture is about to start.
5
5
  *
6
- * @template Element - The type of the draggable element (must extend HTMLElement).
6
+ * This handler is called on the initial pointer-down interaction
7
+ * (mouse or touch) **before** drag tracking begins.
7
8
  *
8
- * @param draggableElement - The element being dragged.
9
- * @param e - The event that initiated the drag. Can be either a `MouseEvent` or a `TouchEvent`.
9
+ * It can be used to:
10
+ * - Conditionally allow or block dragging
11
+ * - Capture initial external state
12
+ * - Cancel dragging based on application logic
13
+ *
14
+ * @template Element - The draggable element type.
10
15
  *
11
- * @returns A Promise that resolves to a boolean:
12
- * - `false` to cancel the drag.
13
- * - `true` to proceed with the drag.
16
+ * @param draggableElement - The element that will be dragged.
17
+ * @param e - The initiating pointer event.
18
+ *
19
+ * @returns A promise resolving to:
20
+ * - `true` to allow the drag to begin
21
+ * - `false` to cancel the drag
14
22
  */
15
23
  export type HoneyDragOnStartHandler<Element extends HTMLElement> = (draggableElement: Element, e: MouseEvent | TouchEvent) => Promise<boolean>;
16
24
  /**
17
- * Context provided to the move handler, containing information about the drag's movement.
25
+ * Context describing pointer movement during an active drag gesture.
26
+ *
27
+ * All values are expressed in **pixels** and are relative
28
+ * to the drag start or previous frame as noted.
18
29
  */
19
30
  export interface HoneyDragMoveContext {
20
31
  /**
21
- * The horizontal distance has moved since the last frame.
32
+ * Horizontal delta since the previous move event.
33
+ *
34
+ * Positive values indicate movement to the right.
22
35
  */
23
36
  deltaX: number;
24
37
  /**
25
- * The vertical distance has moved since the last frame.
38
+ * Vertical delta since the previous move event.
39
+ *
40
+ * Positive values indicate movement downward.
26
41
  */
27
42
  deltaY: number;
28
43
  /**
29
- * The total horizontal distance from the starting position to the current position.
44
+ * Total horizontal displacement from the drag start position.
30
45
  */
31
46
  distanceX: number;
32
47
  /**
33
- * The total vertical distance from the starting position to the current position.
48
+ * Total vertical displacement from the drag start position.
34
49
  */
35
50
  distanceY: number;
36
- /**
37
- * The straight-line distance from the starting position to the current position.
38
- */
39
- euclideanDistance: number;
40
51
  }
41
52
  /**
42
- * Handler triggered during a drag operation.
53
+ * Handler invoked continuously while a drag gesture is active.
43
54
  *
44
- * @template Element - The type of the draggable element (must extend HTMLElement).
55
+ * This handler:
56
+ * - Is created once per drag start
57
+ * - Receives incremental movement data on each pointer move
58
+ * - Can synchronously or asynchronously decide whether dragging continues
45
59
  *
46
- * Behavior:
47
- * - The handler receives the draggable element and returns a function that is called on every move event.
48
- * - If the returned function resolves to `false`, the drag operation stops immediately.
60
+ * Returning `false` from the move callback immediately terminates the drag.
49
61
  *
50
- * This allows for real-time handling of drag events and asynchronous conditions during dragging.
62
+ * @template Element - The draggable element type.
51
63
  *
52
64
  * @param draggableElement - The element being dragged.
53
65
  *
54
- * @returns A function that handles move events and returns a Promise that resolves to `true`
55
- * to continue dragging, or `false` to stop it.
66
+ * @returns A function invoked on every pointer move, receiving
67
+ * {@link HoneyDragMoveContext}, and resolving to:
68
+ * - `true` to continue dragging
69
+ * - `false` to stop dragging immediately
56
70
  */
57
71
  export type HoneyDragOnMoveHandler<Element extends HTMLElement> = (draggableElement: Element) => (context: HoneyDragMoveContext) => Promise<boolean>;
58
72
  /**
59
- * Context provided to the end handler, containing information about the drag's end state.
73
+ * Context describing the final state of a completed drag gesture.
74
+ *
75
+ * This context exposes **release velocity**, which is suitable for
76
+ * inertia, momentum, or decay-based motion systems.
60
77
  */
61
78
  interface HoneyDragEndContext {
62
79
  /**
63
- * The total horizontal movement from the starting position to the ending position.
80
+ * Total horizontal displacement from drag start to release.
64
81
  */
65
82
  deltaX: number;
66
83
  /**
67
- * The total vertical movement from the starting position to the ending position.
84
+ * Total vertical displacement from drag start to release.
68
85
  */
69
86
  deltaY: number;
70
87
  /**
71
- * The speed of movement in the horizontal direction (X axis).
88
+ * Horizontal release velocity in pixels per millisecond (`px/ms`).
89
+ *
90
+ * This value represents the **instantaneous velocity at release**
91
+ * and is suitable for inertia or momentum-based motion.
72
92
  */
73
- movingSpeedX: number;
93
+ velocityXPxMs: number;
74
94
  /**
75
- * The speed of movement in the vertical direction (Y axis).
95
+ * Vertical release velocity in pixels per millisecond (`px/ms`).
96
+ *
97
+ * This value represents the **instantaneous velocity at release**
98
+ * and is suitable for inertia or momentum-based motion.
76
99
  */
77
- movingSpeedY: number;
100
+ velocityYPxMs: number;
78
101
  }
79
102
  /**
80
- * Handler triggered when a drag operation ends.
103
+ * Invoked when a drag gesture ends.
104
+ *
105
+ * This handler is called when:
106
+ * - The pointer is released
107
+ * - The drag is programmatically terminated (unless explicitly skipped)
81
108
  *
82
- * @template Element - The type of the draggable element (must extend HTMLElement).
109
+ * It provides final displacement and **release velocity**, making it
110
+ * ideal for triggering inertia or decay animations.
83
111
  *
84
- * @param context - The context containing details about the drag operation at its end.
85
- * Provides information such as the final position and drag result.
86
- * @param draggableElement - The element that was being dragged.
87
- * @param e - The event that ended the drag. Can be either a `MouseEvent` or a `TouchEvent`.
112
+ * @template Element - The draggable element type.
88
113
  *
89
- * @returns A Promise that resolves when the end handler completes its operations.
114
+ * @param context - Final drag metrics, including release velocity.
115
+ * @param draggableElement - The element that was dragged.
116
+ * @param e - The pointer event that finished the drag.
117
+ *
118
+ * @returns A promise that resolves when cleanup or follow-up logic completes.
90
119
  */
91
120
  export type HoneyDragOnEndHandler<Element extends HTMLElement> = (context: HoneyDragEndContext, draggableElement: Element, e: MouseEvent | TouchEvent) => Promise<void>;
92
121
  /**
93
- * A set of handlers that define the behavior of the drag operation at different stages.
94
- * These handlers are customizable for managing drag initialization, movement, and completion.
122
+ * Collection of handlers controlling the lifecycle of a drag gesture.
123
+ *
124
+ * Together, these handlers define:
125
+ * - Whether dragging is allowed
126
+ * - How movement is handled
127
+ * - What happens when dragging ends
95
128
  */
96
129
  export interface HoneyDragHandlers<Element extends HTMLElement> {
97
130
  /**
@@ -124,8 +157,10 @@ export interface HoneyDragHandlers<Element extends HTMLElement> {
124
157
  onEndDrag?: HoneyDragOnEndHandler<Element>;
125
158
  }
126
159
  /**
127
- * Configuration options for the drag functionality.
128
- * These options control the behavior of the drag hook and modify how the drag events are handled.
160
+ * Configuration options controlling drag behavior.
161
+ *
162
+ * These options affect lifecycle handling and enable/disable logic,
163
+ * but do not influence movement physics directly.
129
164
  */
130
165
  export interface HoneyDragOptions<Element extends HTMLElement> extends HoneyDragHandlers<Element> {
131
166
  /**
@@ -143,17 +178,23 @@ export interface HoneyDragOptions<Element extends HTMLElement> extends HoneyDrag
143
178
  enabled?: boolean;
144
179
  }
145
180
  /**
146
- * A hook that provides touch and mouse-based dragging functionality for an element.
147
- * It enables the ability to drag an element on both mouse and touch interfaces,
148
- * with customizable handlers for different stages of the drag.
181
+ * Enables high-precision mouse and touch dragging for an element.
182
+ *
183
+ * This hook:
184
+ * - Tracks pointer movement using `performance.now()`
185
+ * - Computes **instantaneous release velocity** (px/ms)
186
+ * - Emits deterministic drag lifecycle events
187
+ * - Supports both mouse and touch input
149
188
  *
150
- * @template Element - The type of the HTML element that is being dragged.
189
+ * Architectural notes:
190
+ * - Velocity is computed **during movement**, not at drag end
191
+ * - Release velocity is suitable for inertia / decay systems
192
+ * - No layout reads or writes are performed internally
151
193
  *
152
- * @param draggableElementRef - A reference to the element that can be dragged.
153
- * @param options - Handlers for different stages of the drag operation and configuration options
154
- * for controlling drag behavior.
194
+ * @template Element - The draggable HTML element type.
155
195
  *
156
- * @returns A cleanup function to remove event listeners when the component is unmounted.
196
+ * @param draggableElementRef - Ref pointing to the draggable element.
197
+ * @param options - Drag lifecycle handlers and configuration flags.
157
198
  */
158
199
  export declare const useHoneyDrag: <Element extends HTMLElement>(draggableElementRef: RefObject<Nullable<Element>>, { skipOnEndDragWhenStopped, enabled, onMoveDrag, onStartDrag, onEndDrag, }: HoneyDragOptions<Element>) => void;
159
200
  export {};