import { DependencyList } from 'react';
/**
 * Manages a socket subscription lifecycle inside a React component.
 *
 * ## What it solves
 *
 * Three problems appear in every socket hook:
 *
 * 1. **Handler staleness** — the handler passed to socket.on() captures stale
 *    state/props from the first render.  The fix is a stable wrapper that always
 *    delegates to the *latest* version, without changing the function reference.
 *
 * 2. **Missing cleanup** — subscribe() in a useEffect must always have a
 *    matching unsubscribe() in the cleanup function, otherwise listeners leak
 *    on unmount and when deps change (new id, enabled toggling, etc.).
 *
 * 3. **Re-subscription on dep change** — when the key changes (e.g. planId),
 *    the old subscription must be torn down before opening a new one.  This
 *    happens automatically when you list the key in `deps`.
 *
 * ## Why not useEffectEvent?
 *
 * useEffectEvent (React 18 experimental / React 19 stable) solves the staleness
 * problem natively and is conceptually the right primitive here.  Two reasons we
 * use the useRef pattern instead:
 *
 * - It is still marked experimental in React 18 and must be imported as
 *   `React.experimental_useEffectEvent`.
 * - React's contract says the resulting functions must only be called
 *   synchronously from within effects, not stored by external systems (like a
 *   socket library that retains the handler reference for later invocation).
 *   The useRef approach has no such restriction.
 *
 * When React 19 is adopted and the restriction is clarified, each handler can be
 * wrapped in useEffectEvent instead of the manual ref trick.
 *
 * ## Usage
 *
 * ```ts
 * useSocketSubscription({
 *     handlers: { onUpdated: handlePlanUpdated },
 *     enabled: isActive,
 *     deps: [planId],
 *     onSubscribe:   (h) => listener.subscribe({ planId, handlers: h }),
 *     onUnsubscribe: ()  => listener.unsubscribe({ planId }),
 * });
 * ```
 *
 * `handlers` can contain any number of callbacks — all are wrapped in stable
 * references automatically.  The original callbacks are never in the deps array,
 * so changing them (e.g. a fresh useCallback) never triggers a re-subscription.
 */
export declare function useSocketSubscription<THandlers extends Record<string, ((...args: any[]) => void) | undefined>>({ handlers, enabled, deps, onSubscribe, onUnsubscribe, }: {
    /** Event handlers to pass to the listener.  May be unstable references. */
    handlers: THandlers;
    /** When false the subscription is not opened (and existing one is closed). */
    enabled?: boolean;
    /** Re-subscribe whenever any of these values change (e.g. [planId]). */
    deps?: DependencyList;
    /**
     * Called with stable handler wrappers when the subscription opens.
     * Receives the same object shape as `handlers` but with stable references
     * safe to pass to socket.on() / socket.off().
     */
    onSubscribe: (stableHandlers: THandlers) => void;
    /** Called when the subscription should close (unmount or dep change). */
    onUnsubscribe: () => void;
}): void;
