/**
 * useCanvasDnd — drag/drop primitives for the AVL canvas surface.
 *
 * Shares the sensor stack + collision waterfall with `useDataDnd` (both
 * import from `hooks/useAlmadarDndCollision`); diverges on drop semantics
 * because palette → canvas is a cursor-resolved tree insert, not a
 * sortable-list reorder.
 *
 * Pointer-sensor based so it works inside React Flow nodes (the native
 * HTML5 DnD path was swallowed by React Flow's pan/zoom handlers).
 *
 * Event contract (defaults — overridable via `CanvasDndProvider.onDrop`):
 *   - On drag start: emits `UI:DRAG_START` { kind, data }
 *   - On drag end:   emits `UI:DRAG_END`   { kind, data }
 *   - On 'pattern' drop:   emits `UI:PATTERN_DROP`  { patternType, containerNode, parentPath?, index? }
 *   - On 'behavior' drop:  emits `UI:BEHAVIOR_DROP` { behaviorName, containerNode }
 *
 * The `onDrop` callback lets consumers route OTHER payload kinds (e.g.
 * `'pattern-instance'` for in-canvas reorder of an existing pattern) to
 * their own bus events or schema mutations. Reorder semantics belong in
 * the consumer because they touch the SExpr tree directly — this primitive
 * only resolves payload + target + cursor and hands them off.
 */
import React from 'react';
import { useDraggable as dndKitUseDraggable } from '@dnd-kit/core';
import type { EventPayload } from '@almadar/core';
/**
 * Drag kinds the canvas understands. Open-ended `string` so consumers can
 * introduce new kinds (e.g. `'pattern-instance'` for in-canvas reorder of an
 * existing pattern) without touching this file — the provider's defaults
 * cover `'pattern'` and `'behavior'`; everything else routes through the
 * consumer's `onDrop`.
 */
export type CanvasDragKind = 'pattern' | 'behavior' | (string & {});
/**
 * Payload carried by a draggable. For `'pattern'` tiles `data` is
 * `{ type: string }`, for `'behavior'` tiles `{ name: string }`. For consumer
 * kinds (e.g. `'pattern-instance'`) the shape is whatever the consumer
 * agrees on with its own `onDrop`.
 */
export interface CanvasDragPayload {
    kind: CanvasDragKind;
    data: EventPayload;
}
/**
 * Orbital/trait/transition context a drop will mutate.
 *
 * Has an explicit `[key: string]: string | undefined` index signature so it
 * structurally matches `EventPayload` — required because we pass the whole
 * object as a field on the `UI:PATTERN_DROP` payload.
 */
export interface CanvasContainerNode {
    orbitalName?: string;
    traitName?: string;
    transitionEvent?: string;
    [key: string]: string | undefined;
}
/** Drop-target metadata stored on each droppable's `data` field. */
export interface CanvasDropTarget {
    /**
     * `l1` = outer orbital frame (overview level).
     * `l2` = render-ui slot inside an expanded orbital.
     * `wrapper` = page-level catch-all fired when nothing inner caught the drop.
     */
    level: 'l1' | 'l2' | 'wrapper' | (string & {});
    /** Full or partial container context this drop will mutate. */
    containerNode: CanvasContainerNode;
    /**
     * Optional resolver called at drop time to derive `parentPath` + `index`
     * from the pointer's final client position. L2 slots use this to walk the
     * DOM under their `contentRef` and find the nearest `data-accepts-children`
     * container plus the cursor-relative insertion index.
     */
    resolvePath?: (cursor: {
        x: number;
        y: number;
    }) => {
        parentPath: string;
        index: number;
    } | null;
}
export interface CanvasDropEvent {
    payload: CanvasDragPayload;
    target: CanvasDropTarget;
    /** Final pointer client position, when dnd-kit could compute it. */
    cursor: {
        x: number;
        y: number;
    } | null;
    /**
     * Resolved insertion path/index from `target.resolvePath(cursor)`. Null
     * when the target has no resolver or the cursor was unavailable.
     */
    resolved: {
        parentPath: string;
        index: number;
    } | null;
}
export interface UseCanvasDraggableArgs {
    /** Unique id (per-tile). dnd-kit uses this to track the active drag. */
    id: string;
    payload: CanvasDragPayload;
    disabled?: boolean;
}
export interface UseCanvasDraggableResult {
    setNodeRef: (node: HTMLElement | null) => void;
    attributes: ReturnType<typeof dndKitUseDraggable>['attributes'];
    listeners: ReturnType<typeof dndKitUseDraggable>['listeners'];
    isDragging: boolean;
    /** Spread on the tile — live transform + grab cursor + touch-action. */
    style: React.CSSProperties;
}
export declare function useCanvasDraggable({ id, payload, disabled, }: UseCanvasDraggableArgs): UseCanvasDraggableResult;
export interface UseCanvasDroppableArgs {
    id: string;
    target: CanvasDropTarget;
    /** Which drag kinds this zone accepts. Defaults to ['pattern','behavior']. */
    accepts?: readonly CanvasDragKind[];
    disabled?: boolean;
}
export interface UseCanvasDroppableResult {
    setNodeRef: (node: HTMLElement | null) => void;
    isOver: boolean;
}
export declare function useCanvasDroppable({ id, target, accepts, disabled, }: UseCanvasDroppableArgs): UseCanvasDroppableResult;
export interface CanvasDndProviderProps {
    children: React.ReactNode;
    /**
     * Override the default drop behavior. The default emits `UI:PATTERN_DROP`
     * / `UI:BEHAVIOR_DROP` based on payload kind. Pass an `onDrop` to route
     * additional kinds (e.g. `'pattern-instance'` reorder) elsewhere, or to
     * mutate schema directly without going through the bus.
     *
     * Return `true` from `onDrop` to suppress the default emit; return
     * `false`/`undefined` to fall through to defaults after running your code.
     */
    onDrop?: (drop: CanvasDropEvent) => boolean | void;
    /**
     * Renders the floating preview that follows the cursor during a drag.
     * @dnd-kit moves the source DOM node via CSS transform, which gets clipped
     * by any ancestor with `overflow: hidden|auto|scroll` (e.g. a scrollable
     * palette column). Returning a node here mounts a portal-attached overlay
     * outside the clip so the user always sees what they're dragging.
     *
     * Receives the active payload (or null between drags) and returns the
     * preview element — typically the same JSX the tile renders inline.
     */
    renderOverlay?: (payload: CanvasDragPayload | null) => React.ReactNode;
}
/**
 * Wraps a canvas subtree in one DndContext + sensors + collision waterfall.
 * Every `useCanvasDraggable` / `useCanvasDroppable` inside this provider
 * participates in the same drag session.
 */
export declare function CanvasDndProvider({ children, onDrop, renderOverlay, }: CanvasDndProviderProps): React.ReactElement;
