import { Position } from 'css-box-model';
import { ReactNode, TransitionEventHandler, DragEventHandler, FunctionComponent } from 'react';

declare type Id = string;
declare type DraggableId = Id;
declare type DroppableId = Id;
declare type TypeId = Id;
declare type ContextId = Id;
declare type ElementId = Id;
declare type DroppableMode = 'standard' | 'virtual';
interface DraggableOptions {
    canDragInteractiveElements: boolean;
    shouldRespectForcePress: boolean;
    isEnabled: boolean;
}
declare type Direction = 'horizontal' | 'vertical';
interface DraggableLocation {
    droppableId: DroppableId;
    index: number;
}
interface Combine {
    draggableId: DraggableId;
    droppableId: DroppableId;
}
declare type MovementMode = 'FLUID' | 'SNAP';
interface DraggableRubric {
    draggableId: DraggableId;
    type: TypeId;
    source: DraggableLocation;
}
interface BeforeCapture {
    draggableId: DraggableId;
    mode: MovementMode;
}
interface DragStart extends DraggableRubric {
    mode: MovementMode;
}
interface DragUpdate extends DragStart {
    destination: DraggableLocation | null;
    combine: Combine | null;
}
declare type DropReason = 'DROP' | 'CANCEL';
interface DropResult extends DragUpdate {
    reason: DropReason;
}
declare type Announce = (message: string) => void;
interface ResponderProvided {
    announce: Announce;
}
declare type OnBeforeCaptureResponder = (before: BeforeCapture) => void;
declare type OnBeforeDragStartResponder = (start: DragStart) => void;
declare type OnDragStartResponder = (start: DragStart, provided: ResponderProvided) => void;
declare type OnDragUpdateResponder = (update: DragUpdate, provided: ResponderProvided) => void;
declare type OnDragEndResponder = (result: DropResult, provided: ResponderProvided) => void;
interface Responders {
    onBeforeCapture?: OnBeforeCaptureResponder;
    onBeforeDragStart?: OnBeforeDragStartResponder;
    onDragStart?: OnDragStartResponder;
    onDragUpdate?: OnDragUpdateResponder;
    onDragEnd: OnDragEndResponder;
}
interface StopDragOptions {
    shouldBlockNextClick: boolean;
}
interface DragActions {
    drop: (args?: StopDragOptions) => void;
    cancel: (args?: StopDragOptions) => void;
    isActive: () => boolean;
    shouldRespectForcePress: () => boolean;
}
interface FluidDragActions extends DragActions {
    move: (clientSelection: Position) => void;
}
interface SnapDragActions extends DragActions {
    moveUp: () => void;
    moveDown: () => void;
    moveRight: () => void;
    moveLeft: () => void;
}
interface PreDragActions {
    isActive: () => boolean;
    shouldRespectForcePress: () => boolean;
    fluidLift: (clientSelection: Position) => FluidDragActions;
    snapLift: () => SnapDragActions;
    abort: () => void;
}
interface TryGetLockOptions {
    sourceEvent?: Event;
}
declare type TryGetLock = (draggableId: DraggableId, forceStop?: () => void, options?: TryGetLockOptions) => PreDragActions | null;
interface SensorAPI {
    tryGetLock: TryGetLock;
    canGetLock: (id: DraggableId) => boolean;
    isLockClaimed: () => boolean;
    tryReleaseLock: () => void;
    findClosestDraggableId: (event: Event) => DraggableId | null;
    findOptionsForDraggable: (id: DraggableId) => DraggableOptions | null;
}
declare type Sensor = (api: SensorAPI) => void;

declare type RecursivePartial<T> = {
    [P in keyof T]?: T[P] extends (infer U)[] ? RecursivePartial<U>[] : T[P] extends (...args: any) => any ? T[P] | undefined : T[P] extends object ? RecursivePartial<T[P]> : T[P];
};

/**
 * Customize autoScroller behavior
 */
interface AutoScrollerOptions {
    /**
     * Percentage distance from edge of container at which to start auto scrolling.
     * ex. 0.1 or 0.9
     */
    startFromPercentage: number;
    /**
     * Percentage distance from edge of container at which max scroll speed is achieved.
     * Should be less than startFromPercentage
     */
    maxScrollAtPercentage: number;
    /**
     * Maximum pixels to scroll per frame
     */
    maxPixelScroll: number;
    /**
     * A function used to ease a percentage value
     * A simple linear function would be: (percentage) => percentage;
     * percentage is between 0 and 1
     * result must be between 0 and 1
     */
    ease: (percentage: number) => number;
    durationDampening: {
        /**
         * How long to dampen the speed of an auto scroll from the start of a drag in milliseconds
         */
        stopDampeningAt: number;
        /**
         * When to start accelerating the reduction of duration dampening in milliseconds
         */
        accelerateAt: number;
    };
    /**
     * Whether or not autoscroll should be turned off entirely
     */
    disabled: boolean;
}
declare type PartialAutoScrollerOptions = RecursivePartial<AutoScrollerOptions>;

interface DragDropContextProps extends Responders {
    children: ReactNode | null;
    dragHandleUsageInstructions?: string;
    enableDefaultSensors?: boolean | null;
    nonce?: string;
    sensors?: Sensor[];
    /**
     * Customize auto scroller
     */
    autoScrollerOptions?: PartialAutoScrollerOptions;
}
declare function resetServerContext(): void;
declare function DragDropContext(props: DragDropContextProps): JSX.Element;

interface DraggingStyle {
    position: 'fixed';
    top: number;
    left: number;
    boxSizing: 'border-box';
    width: number;
    height: number;
    transition: string;
    transform?: string;
    zIndex: number;
    opacity?: number;
    pointerEvents: 'none';
}
interface NotDraggingStyle {
    transform?: string;
    transition?: 'none';
}
declare type DraggableStyle = DraggingStyle | NotDraggingStyle;
interface DraggableProvidedDraggableProps {
    style?: DraggableStyle;
    'data-rfd-draggable-context-id': ContextId;
    'data-rfd-draggable-id': DraggableId;
    onTransitionEnd?: TransitionEventHandler;
}
interface DraggableProvidedDragHandleProps {
    'data-rfd-drag-handle-draggable-id': DraggableId;
    'data-rfd-drag-handle-context-id': ContextId;
    role: string;
    'aria-describedby': ElementId;
    tabIndex: number;
    draggable: boolean;
    onDragStart: DragEventHandler;
}
interface DraggableProvided {
    draggableProps: DraggableProvidedDraggableProps;
    dragHandleProps: DraggableProvidedDragHandleProps | null;
    innerRef: (element?: HTMLElement | null) => void;
}
interface DropAnimation {
    duration: number;
    curve: string;
    moveTo: Position;
    opacity: number | null;
    scale: number | null;
}
interface DraggableStateSnapshot {
    isDragging: boolean;
    isDropAnimating: boolean;
    isClone: boolean;
    dropAnimation: DropAnimation | null;
    draggingOver: DroppableId | null;
    combineWith: DraggableId | null;
    combineTargetFor: DraggableId | null;
    mode: MovementMode | null;
}
declare type DraggableChildrenFn = (provided: DraggableProvided, snapshot: DraggableStateSnapshot, rubic: DraggableRubric) => ReactNode | null;
interface DraggableProps {
    draggableId: DraggableId;
    index: number;
    children: DraggableChildrenFn;
    isDragDisabled?: boolean;
    disableInteractiveElementBlocking?: boolean;
    shouldRespectForcePress?: boolean;
}

declare function PublicDraggable(props: DraggableProps): JSX.Element;

interface DroppableProvidedProps {
    'data-rfd-droppable-context-id': ContextId;
    'data-rfd-droppable-id': DroppableId;
}
interface DroppableProvided {
    innerRef: (a?: HTMLElement | null) => void;
    placeholder: ReactNode | null;
    droppableProps: DroppableProvidedProps;
}
interface DroppableStateSnapshot {
    isDraggingOver: boolean;
    draggingOverWith: DraggableId | null;
    draggingFromThisWith: DraggableId | null;
    isUsingPlaceholder: boolean;
}
interface DefaultProps {
    direction: Direction;
    getContainerForClone: () => HTMLElement;
    ignoreContainerClipping: boolean;
    isCombineEnabled: boolean;
    isDropDisabled: boolean;
    mode: DroppableMode;
    type: TypeId;
    renderClone: DraggableChildrenFn | null;
}
interface DroppableProps extends Partial<DefaultProps> {
    children: (provided: DroppableProvided, snapshot: DroppableStateSnapshot) => ReactNode;
    droppableId: DroppableId;
    renderClone?: DraggableChildrenFn | null;
}

declare const ConnectedDroppable: FunctionComponent<DroppableProps>;

declare function useMouseSensor(api: SensorAPI): void;

declare function useTouchSensor(api: SensorAPI): void;

declare function useKeyboardSensor(api: SensorAPI): void;

export { Announce, BeforeCapture, Direction, DragDropContext, DragDropContextProps, DragStart, DragUpdate, PublicDraggable as Draggable, DraggableChildrenFn, DraggableId, DraggableLocation, DraggableProps, DraggableProvided, DraggableProvidedDragHandleProps, DraggableProvidedDraggableProps, DraggableRubric, DraggableStateSnapshot, DraggableStyle, DraggingStyle, DropAnimation, DropResult, ConnectedDroppable as Droppable, DroppableId, DroppableProps, DroppableProvided, DroppableProvidedProps, DroppableStateSnapshot, Id, MovementMode, NotDraggingStyle, OnBeforeCaptureResponder, OnBeforeDragStartResponder, OnDragEndResponder, OnDragStartResponder, OnDragUpdateResponder, PreDragActions, ResponderProvided, Sensor, SensorAPI, SnapDragActions, TryGetLock, TryGetLockOptions, TypeId, resetServerContext, useKeyboardSensor, useMouseSensor, useTouchSensor };
