@react-hive/honey-layout 11.1.0 → 12.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.
@@ -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}.
@@ -61,9 +54,30 @@ export interface UseHoneyDecayApi {
61
54
  /**
62
55
  * Updates the hard bounds used by the decay simulation.
63
56
  *
64
- * The current value is clamped implicitly on the next frame if it lies outside the new bounds.
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
65
74
  *
66
- * This is intended for dynamic layouts where overflow can change (e.g. resize, content updates).
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.
67
81
  *
68
82
  * @param min - New lower bound (inclusive)
69
83
  * @param max - New upper bound (inclusive)
@@ -81,18 +95,30 @@ export interface UseHoneyDecayApi {
81
95
  */
82
96
  start: (velocityPxMs: number) => void;
83
97
  /**
84
- * 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`)
85
107
  */
86
- stop: () => void;
108
+ startFrom: (value: number, velocityPxMs: number) => void;
87
109
  /**
88
- * Immediately sets the value and cancels any active inertia.
110
+ * Immediately stops inertial motion.
89
111
  *
90
- * @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
91
116
  */
92
- snapTo: (value: number) => void;
117
+ stop: () => void;
93
118
  }
94
119
  /**
95
- * 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}.
96
122
  *
97
123
  * This hook models **momentum-driven motion** where:
98
124
  * - Motion starts with an initial velocity
@@ -150,4 +176,4 @@ export interface UseHoneyDecayApi {
150
176
  * );
151
177
  * ```
152
178
  */
153
- 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;
@@ -1,6 +1,6 @@
1
- import type { HoneyKeyboardEventCode } from '../types';
2
- export type HoneyDocumentKeyUpHandler = (keyCode: HoneyKeyboardEventCode, e: KeyboardEvent) => void;
3
- interface UseHoneyDocumentKeyUpHandlerOptions {
1
+ import type { HoneyKeyboardEventCode } from '~/types';
2
+ export type UseHoneyDocumentOnKeyUpHandler = (keyCode: HoneyKeyboardEventCode, e: KeyboardEvent) => void;
3
+ interface UseHoneyDocumentKeyUpOptions {
4
4
  /**
5
5
  * Whether the event listener should be active.
6
6
  *
@@ -22,13 +22,13 @@ interface UseHoneyDocumentKeyUpHandlerOptions {
22
22
  * This hook adds a `keyup` event listener at the document level and triggers the provided `keyUpHandler`
23
23
  * when one of the specified `listenKeys` is released.
24
24
  *
25
- * @param keyUpHandler - The callback function invoked when a matching key is released.
25
+ * @param onKeyUp - The callback function invoked when a matching key is released.
26
26
  * @param listenKeys - An array of key codes (`KeyboardEvent.code`) to listen for.
27
27
  * @param options - Optional configuration to control event behavior and listener activation.
28
28
  *
29
29
  * @example
30
30
  * ```tsx
31
- * useHoneyDocumentKeyUpHandler(
31
+ * useHoneyDocumentKeyUp(
32
32
  * (keyCode, event) => {
33
33
  * console.log('Key released:', keyCode);
34
34
  * },
@@ -36,5 +36,5 @@ interface UseHoneyDocumentKeyUpHandlerOptions {
36
36
  * );
37
37
  * ```
38
38
  */
39
- export declare const useHoneyDocumentKeyUpHandler: (keyUpHandler: HoneyDocumentKeyUpHandler, listenKeys: HoneyKeyboardEventCode[], { enabled, preventDefault }?: UseHoneyDocumentKeyUpHandlerOptions) => void;
39
+ export declare const useHoneyDocumentKeyUp: (onKeyUp: UseHoneyDocumentOnKeyUpHandler, listenKeys: HoneyKeyboardEventCode[], { enabled, preventDefault }?: UseHoneyDocumentKeyUpOptions) => void;
40
40
  export {};
@@ -1,5 +1,5 @@
1
1
  import type { RefObject } from 'react';
2
- import type { Nullable } from '../types';
2
+ import type { Nullable } from '~/types';
3
3
  /**
4
4
  * Invoked when a drag gesture is about to start.
5
5
  *
@@ -20,14 +20,14 @@ import type { Nullable } from '../types';
20
20
  * - `true` to allow the drag to begin
21
21
  * - `false` to cancel the drag
22
22
  */
23
- export type HoneyDragOnStartHandler<Element extends HTMLElement> = (draggableElement: Element, e: MouseEvent | TouchEvent) => Promise<boolean>;
23
+ export type UseHoneyDragOnStartHandler<Element extends HTMLElement> = (draggableElement: Element, e: MouseEvent | TouchEvent) => Promise<boolean>;
24
24
  /**
25
25
  * Context describing pointer movement during an active drag gesture.
26
26
  *
27
27
  * All values are expressed in **pixels** and are relative
28
28
  * to the drag start or previous frame as noted.
29
29
  */
30
- export interface HoneyDragMoveContext {
30
+ export interface UseHoneyDragOnMoveContext {
31
31
  /**
32
32
  * Horizontal delta since the previous move event.
33
33
  *
@@ -64,18 +64,18 @@ export interface HoneyDragMoveContext {
64
64
  * @param draggableElement - The element being dragged.
65
65
  *
66
66
  * @returns A function invoked on every pointer move, receiving
67
- * {@link HoneyDragMoveContext}, and resolving to:
67
+ * {@link UseHoneyDragOnMoveContext}, and resolving to:
68
68
  * - `true` to continue dragging
69
69
  * - `false` to stop dragging immediately
70
70
  */
71
- export type HoneyDragOnMoveHandler<Element extends HTMLElement> = (draggableElement: Element) => (context: HoneyDragMoveContext) => Promise<boolean>;
71
+ export type UseHoneyDragOnMoveHandler<Element extends HTMLElement> = (draggableElement: Element) => (context: UseHoneyDragOnMoveContext) => Promise<boolean>;
72
72
  /**
73
73
  * Context describing the final state of a completed drag gesture.
74
74
  *
75
75
  * This context exposes **release velocity**, which is suitable for
76
76
  * inertia, momentum, or decay-based motion systems.
77
77
  */
78
- interface HoneyDragEndContext {
78
+ interface UseHoneyDragOnEndContext {
79
79
  /**
80
80
  * Total horizontal displacement from drag start to release.
81
81
  */
@@ -117,7 +117,7 @@ interface HoneyDragEndContext {
117
117
  *
118
118
  * @returns A promise that resolves when cleanup or follow-up logic completes.
119
119
  */
120
- export type HoneyDragOnEndHandler<Element extends HTMLElement> = (context: HoneyDragEndContext, draggableElement: Element, e: MouseEvent | TouchEvent) => Promise<void>;
120
+ export type UseHoneyDragOnEndHandler<Element extends HTMLElement> = (context: UseHoneyDragOnEndContext, draggableElement: Element, e: MouseEvent | TouchEvent) => Promise<void>;
121
121
  /**
122
122
  * Collection of handlers controlling the lifecycle of a drag gesture.
123
123
  *
@@ -126,7 +126,7 @@ export type HoneyDragOnEndHandler<Element extends HTMLElement> = (context: Honey
126
126
  * - How movement is handled
127
127
  * - What happens when dragging ends
128
128
  */
129
- export interface HoneyDragHandlers<Element extends HTMLElement> {
129
+ export interface UseHoneyDragHandlers<Element extends HTMLElement> {
130
130
  /**
131
131
  * Optional handler triggered when the drag operation starts.
132
132
  * This is useful for capturing the initial state or performing any setup actions before the drag starts.
@@ -135,7 +135,7 @@ export interface HoneyDragHandlers<Element extends HTMLElement> {
135
135
  *
136
136
  * @returns A boolean or Promise resolving to a boolean indicating if the drag should proceed.
137
137
  */
138
- onStartDrag?: HoneyDragOnStartHandler<Element>;
138
+ onStartDrag?: UseHoneyDragOnStartHandler<Element>;
139
139
  /**
140
140
  * Required handler triggered continuously during the drag operation.
141
141
  * This handler is responsible for updating the drag state and typically tracks the element's movement.
@@ -144,7 +144,7 @@ export interface HoneyDragHandlers<Element extends HTMLElement> {
144
144
  *
145
145
  * @returns A boolean or Promise resolving to a boolean indicating whether the drag should continue.
146
146
  */
147
- onMoveDrag: HoneyDragOnMoveHandler<Element>;
147
+ onMoveDrag: UseHoneyDragOnMoveHandler<Element>;
148
148
  /**
149
149
  * Optional handler triggered when the drag operation ends.
150
150
  * This is commonly used for cleanup or finalizing the drag process.
@@ -154,7 +154,7 @@ export interface HoneyDragHandlers<Element extends HTMLElement> {
154
154
  *
155
155
  * @returns A Promise.
156
156
  */
157
- onEndDrag?: HoneyDragOnEndHandler<Element>;
157
+ onEndDrag?: UseHoneyDragOnEndHandler<Element>;
158
158
  }
159
159
  /**
160
160
  * Configuration options controlling drag behavior.
@@ -162,7 +162,7 @@ export interface HoneyDragHandlers<Element extends HTMLElement> {
162
162
  * These options affect lifecycle handling and enable/disable logic,
163
163
  * but do not influence movement physics directly.
164
164
  */
165
- export interface HoneyDragOptions<Element extends HTMLElement> extends HoneyDragHandlers<Element> {
165
+ export interface UseHoneyDragOptions<Element extends HTMLElement> extends UseHoneyDragHandlers<Element> {
166
166
  /**
167
167
  * Controls whether the `onEndDrag` handler is skipped when the drag operation is forcibly stopped.
168
168
  * This can be useful when dragging is interrupted or terminated early due to movement restrictions.
@@ -196,5 +196,5 @@ export interface HoneyDragOptions<Element extends HTMLElement> extends HoneyDrag
196
196
  * @param draggableElementRef - Ref pointing to the draggable element.
197
197
  * @param options - Drag lifecycle handlers and configuration flags.
198
198
  */
199
- export declare const useHoneyDrag: <Element extends HTMLElement>(draggableElementRef: RefObject<Nullable<Element>>, { skipOnEndDragWhenStopped, enabled, onMoveDrag, onStartDrag, onEndDrag, }: HoneyDragOptions<Element>) => void;
199
+ export declare const useHoneyDrag: <Element extends HTMLElement>(draggableElementRef: RefObject<Nullable<Element>>, { skipOnEndDragWhenStopped, enabled, onMoveDrag, onStartDrag, onEndDrag, }: UseHoneyDragOptions<Element>) => void;
200
200
  export {};
@@ -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 {};
@@ -5,4 +5,4 @@
5
5
  *
6
6
  * @returns The context value providing theming utilities and screen state.
7
7
  */
8
- export declare const useHoneyLayout: () => import("../contexts").HoneyLayoutContextValue;
8
+ export declare const useHoneyLayout: () => import("~/contexts").HoneyLayoutContextValue;
@@ -1,5 +1,5 @@
1
1
  import type { HoneyTheme } from '@react-hive/honey-style';
2
- import type { HoneyScreenState } from '../types';
2
+ import type { HoneyScreenState } from '~/types';
3
3
  export interface UseHoneyMediaQueryOptions {
4
4
  /**
5
5
  * Throttle interval (in milliseconds) for the resize event handler.
@@ -1,4 +1,4 @@
1
- import type { HoneyOverlayId, HoneyOverlayEventListenerHandler } from '../types';
1
+ import type { HoneyOverlayId, HoneyOverlayEventListenerHandler } from '~/types';
2
2
  interface UseHoneyOverlayOptions {
3
3
  onKeyUp?: HoneyOverlayEventListenerHandler;
4
4
  }
@@ -26,5 +26,5 @@ interface UseHoneyOverlayOptions {
26
26
  * });
27
27
  * ```
28
28
  */
29
- export declare const useHoneyOverlay: (targetOverlayId: HoneyOverlayId, { onKeyUp }?: UseHoneyOverlayOptions) => import("../types").HoneyActiveOverlay | undefined;
29
+ export declare const useHoneyOverlay: (targetOverlayId: HoneyOverlayId, { onKeyUp }?: UseHoneyOverlayOptions) => import("~/types").HoneyActiveOverlay | undefined;
30
30
  export {};
@@ -1,4 +1,4 @@
1
- interface HoneyRafFrameContext {
1
+ interface UseHoneyRafFrameContext {
2
2
  /**
3
3
  * Immediately terminates the active `requestAnimationFrame` loop.
4
4
  *
@@ -29,9 +29,9 @@ interface HoneyRafFrameContext {
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 HoneyRafFrameContext}.
32
+ * @param context - RAF lifecycle control context. See {@link UseHoneyRafFrameContext}.
33
33
  */
34
- export type HoneyRafFrameHandler = (deltaTimeMs: number, context: HoneyRafFrameContext) => void;
34
+ export type UseHoneyRafOnFrameHandler = (deltaTimeMs: number, context: UseHoneyRafFrameContext) => 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: HoneyRafFrameHandler, { autoStart, resumeOnVisibility, maxDeltaMs, onError, }?: UseHoneyRafLoopOptions) => HoneyRafLoopApi;
163
+ export declare const useHoneyRafLoop: (onFrame: UseHoneyRafOnFrameHandler, { autoStart, resumeOnVisibility, maxDeltaMs, onError, }?: UseHoneyRafLoopOptions) => HoneyRafLoopApi;
164
164
  export {};
@@ -1,7 +1,7 @@
1
1
  import type { RefObject } from 'react';
2
2
  import { Axis } from '@react-hive/honey-utils';
3
3
  import type { Nullable } from '~/types';
4
- import type { HoneyDragHandlers } from './use-honey-drag';
4
+ import type { UseHoneyDragHandlers } from './use-honey-drag';
5
5
  interface ResolveAxisTranslateOptions {
6
6
  /**
7
7
  * Drag delta for the axis (deltaX or deltaY).
@@ -25,7 +25,7 @@ interface ResolveAxisTranslateOptions {
25
25
  overscrollPct: number;
26
26
  }
27
27
  export declare const resolveAxisTranslate: ({ delta, translate, containerSize, overflowSize, overscrollPct, }: ResolveAxisTranslateOptions) => Nullable<number>;
28
- export interface UseHoneySyntheticScrollOptions<Element extends HTMLElement> extends Pick<HoneyDragHandlers<Element>, 'onStartDrag' | 'onEndDrag'> {
28
+ export interface UseHoneySyntheticScrollOptions<Element extends HTMLElement> extends Pick<UseHoneyDragHandlers<Element>, 'onStartDrag' | 'onEndDrag'> {
29
29
  /**
30
30
  * Axis along which synthetic scrolling is enabled.
31
31
  *
@@ -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 UseHoneyTimerEndHandler = () => void;
8
+ type UseHoneyTimerOnEndHandler = () => 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?: UseHoneyTimerEndHandler;
43
+ onEnd?: UseHoneyTimerOnEndHandler;
44
44
  }
45
45
  /**
46
46
  * Public control API returned by {@link useHoneyTimer}.
@@ -1,4 +1,4 @@
1
- import type { HoneyActiveOverlay, HoneyOverlayConfig, Nullable } from '../types';
1
+ import type { HoneyActiveOverlay, HoneyOverlayConfig, Nullable } from '~/types';
2
2
  /**
3
3
  * A hook for registering and managing an overlay in the layout system.
4
4
  *