import { BlockDOMEventHandlers, BlockHandler } from "./BlockHandler";
import { SlotDOMEventHandlers, SlotHandler } from "./SlotHandler";
import { BlockContext } from "./BlockContext";
import { FirstParameter } from "./utils";
import { EventEmitter } from "./EventEmitter";
import { IBMoveBetweenSlotsAction, IBMoveInSlotAction, IBSlotBeforeDropAction } from "./action";
import { IBBlockDragStartAction } from "./action";
export interface DraggingContextEvents {
    /** fires when one of `hoveringSlot`, `hoveringBlock` or `isHovering` changes */
    hoverChanged(ctx: BlockContext): void;
    /** fires when start dragging a block */
    blockDragStart(action: IBBlockDragStartAction): void;
    slotBeforeDrop(action: IBSlotBeforeDropAction): void;
}
export interface ComputeIndexToDropRequest {
    clientX: number;
    clientY: number;
    offsetX: number;
    offsetY: number;
    currentTarget: HTMLElement;
    ctx: BlockContext;
    slot: SlotHandler;
    isDraggingFromCurrentCtx: boolean;
    /** if drag source is from current BlockContext, this will be the array of current dragging blocks */
    draggingBlocks?: readonly BlockHandler[];
    /** the original dataTransfer object from DragEvent */
    dataTransfer: DataTransfer | null;
    dropEffect: "none" | "copy" | "link" | "move";
}
declare module "./SlotHandler" {
    interface SlotInfo {
        /**
         * for drag-n-drop
         */
        onMoveInSlot?(action: IBMoveInSlotAction): void;
        /**
         * for drag-n-drop
         */
        onMoveToThisSlot?(action: IBMoveBetweenSlotsAction): void;
        /**
         * for drag-n-drop
         *
         * fires when `isDragHovering` or `indexToDrop` change
         */
        onDragHoverStatusChange?(ctx: BlockContext): void;
        /**
         * for drag-n-drop
         *
         * check if this slot is droppable and compute the insert position.
         *
         * returns:
         *
         * - `false` to prevent dropping,
         * - `undefined` to use auto-computed position (which might not accurate),
         * - index number
         */
        computeIndexToDrop?(req: ComputeIndexToDropRequest): number | false | void;
    }
    interface SlotHandler {
        isDragHovering?: boolean;
        /** the position to drop. only available when `isDragHovering` */
        indexToDrop?: number | undefined;
    }
}
declare module "./BlockHandler" {
    interface BlockInfo {
        onDragStart?(action: IBBlockDragStartAction): void;
    }
}
export declare class DraggingContext extends EventEmitter<DraggingContextEvents> {
    ctx: BlockContext;
    draggingBlocks: Array<BlockHandler> | undefined;
    slotOfDraggingBlocks: SlotHandler | undefined;
    isHovering: boolean;
    hoveringSlot: SlotHandler | undefined;
    hoveringBlock: BlockHandler | undefined;
    /** available when isHovering */
    dropEffect?: "none" | "copy" | "link" | "move";
    constructor(ctx: BlockContext);
    dispose(): void;
    private setHoveringSlot;
    private _originalSetHoveringSlot;
    getBlockDOMEventHandlers(block: BlockHandler): Partial<BlockDOMEventHandlers>;
    handleBlockDragStart(block: BlockHandler, ev: FirstParameter<BlockDOMEventHandlers["dragStart"]>): void;
    handleBlockDragEnd(): void;
    handleBlockDragOver(block: BlockHandler): void;
    handleBlockDragLeave(block: BlockHandler): void;
    getSlotDOMEventHandlers(slot: SlotHandler): Partial<SlotDOMEventHandlers>;
    handleSlotDragOver(slot: SlotHandler, ev: FirstParameter<SlotDOMEventHandlers["dragOver"]>): boolean;
    handleSlotDrop(slot: SlotHandler, ev: FirstParameter<SlotDOMEventHandlers["dragOver"]>): void;
    handleSlotDragLeave(slot: SlotHandler): void;
    /**
     * side effect: update this.dropEffect
     *
     * @return false means not droppable. otherwise a number is returned.
     */
    computeIndexToDrop(slot: SlotHandler, ev: DragEvent): false | number;
}
