import { UmbControllerBase } from '../../../libs/class-api/index.js';
import type { UmbControllerHostElement } from '../../../libs/controller-api/index.js';
export type UmbSorterResolvePlacementReturn = boolean | null | {
    placeAfter: boolean;
    verticalDirection?: boolean;
};
export type UmbSorterResolvePlacementArgs<T, ElementType extends HTMLElement = HTMLElement> = {
    containerElement: Element;
    containerRect: DOMRect;
    item: T;
    itemIndex: number | null;
    element: ElementType | undefined;
    elementRect: DOMRect;
    relatedElement: ElementType;
    relatedModel: T;
    relatedRect: DOMRect;
    relatedIndex: number | null;
    placeholderIsInThisRow: boolean;
    horizontalPlaceAfter: boolean;
    pointerX: number;
    pointerY: number;
};
type UniqueType = string | symbol | number;
/**
 * Internal type, which is adjusted to become the public one.
  @internal */
type INTERNAL_UmbSorterConfig<T, ElementType extends HTMLElement> = {
    /**
     * Define how to retrive the unique identifier of an element. If this method returns undefined, the move will be cancelled.
     */
    getUniqueOfElement: (element: ElementType) => UniqueType | null | undefined;
    getUniqueOfModel: (modeEntry: T) => UniqueType | null | undefined;
    /**
     * Optionally define a unique identifier for each sorter experience, all Sorters that uses the same identifier to connect with other sorters.
     */
    identifier: UniqueType;
    /**
     * A query selector for the item element.
     */
    itemSelector: string;
    disabledItemSelector?: string;
    /**
     * A selector for the container element, if not defined the host element will be used as container.
     */
    containerSelector: string;
    /**
     * A selector for elements to ignore, elements that should not be draggable when within an draggable item, This defaults to links, images & iframes.
     */
    ignorerSelector: string;
    /**
     * An class to set on the placeholder element.
     */
    placeholderClass?: string;
    /**
     * An attribute to set on the placeholder element.
     */
    placeholderAttr?: string;
    /**
     * The selector to find the draggable element within the item.
     */
    draggableSelector?: string;
    /**
     * The selector to define the interactive element within the item, this element will then become the only interactive part, the item can only be dragged by mouse when interacting with this element.
     */
    handleSelector?: string;
    dataTransferResolver?: (dataTransfer: DataTransfer | null, currentItem: T) => void;
    onStart?: (argument: {
        item: T;
        element: ElementType;
    }) => void;
    /**
     * This callback is executed every time where is a change to this model, this could be a move, insert or remove.
     * But notice its not called if a more specific callback is provided, such would be the performItemMove, performItemInsert or performItemRemove or performItemRemove.
     */
    onChange?: (argument: {
        item: T;
        model: Array<T>;
    }) => void;
    /**
     * This callback is executed when an item is moved from another container to this container.
     */
    onContainerChange?: (argument: {
        item: T;
        model: Array<T>;
        from: UmbSorterController<T, ElementType> | undefined;
    }) => void | Promise<void>;
    onEnd?: (argument: {
        item: T;
        element: ElementType;
    }) => void;
    itemHasNestedContainersResolver?: (element: HTMLElement) => boolean;
    /**
     * Callback when a item move is disallowed.
     * This should make a visual indication for the user to understand that the move is not allowed.
     */
    onDisallowed?: (argument: {
        item: T;
        element: ElementType;
    }) => void;
    /**
     * Callback when a item move is allowed.
     * This should remove any visual indication of the disallowing, reverting the work of the onDisallowed callback.
     */
    onAllowed?: (argument: {
        item: T;
        element: ElementType;
    }) => void;
    /**
     * Callback when user tries to move an item from another Sorter to this Sorter, return true or false to allow or disallow the move.
     */
    onRequestMove?: (argument: {
        item: T;
    }) => boolean;
    /**
     * Callback when user tries to drop an item from another window/tab/source.
     */
    onRequestDrop?: (argument: {
        unique: string;
    }) => Promise<T | undefined>;
    /**
     * Callback when user tries to remove an item from another Sorter to this Sorter, return true or false to allow or disallow the move.
     */
    requestExternalRemove?: (argument: {
        item: T;
    }) => Promise<boolean>;
    /**
     * Callback when user tries to remove an item from another Sorter to this Sorter, return true or false to allow or disallow the move.
     */
    requestExternalInsert?: (argument: {
        item: T;
    }) => Promise<boolean>;
    /**
     * This callback is executed when an item is hovered within this container.
     * The callback should return true if the item should be placed after the hovered item, or false if it should be placed before the hovered item.
     * In this way the callback can control the placement of the item.
     * If it returns null the placement will be prevented.
     * @example
     * This is equivalent to the default behavior:
     * ```ts
     * resolvePlacement: (argument) => {
     * 	if(argument.pointerY > argument.relatedRect.top + argument.relatedRect.height * 0.5) {
     * 		return true; // Place after
     * 	} else {
     * 		return false; // Place before
     * 	}
     * }
     */
    resolvePlacement?: (argument: UmbSorterResolvePlacementArgs<T, ElementType>) => UmbSorterResolvePlacementReturn;
    /**
     * This callback is executed when an item is moved within this container.
     */
    performItemMove?: (argument: {
        item: T;
        newIndex: number;
        oldIndex: number;
    }) => Promise<boolean> | boolean;
    /**
     * This callback is executed when an item should be inserted into this container.
     */
    performItemInsert?: (argument: {
        item: T;
        newIndex: number;
    }) => Promise<boolean> | boolean;
    /**
     * This callback is executed when an item should be removed from this container.
     */
    performItemRemove?: (argument: {
        item: T;
    }) => Promise<boolean> | boolean;
};
export type UmbSorterConfig<T, ElementType extends HTMLElement = HTMLElement> = Omit<INTERNAL_UmbSorterConfig<T, ElementType>, 'ignorerSelector' | 'containerSelector' | 'identifier'> & Partial<Pick<INTERNAL_UmbSorterConfig<T, ElementType>, 'ignorerSelector' | 'containerSelector' | 'identifier'>>;
/**
 * @class UmbSorterController
 * @implements {UmbControllerInterface}
 * @description This controller can make user able to sort items.
 * @example
 *
 * This example shows how to setup a sorter controller with no special needs.
 * Assuming your declaring this on a Umbraco Element(UmbControllerHostElement):
 *
 * ```ts
 * const sorter = new UmbSorterController(this, {
 * 	itemSelector: '.item',
 * 	containerSelector: '.container',
 * 	getUniqueOfElement: (element) => element.dataset.id,
 * 	getUniqueOfModel: (model) => model.id
 * });
 * ```
 */
export declare class UmbSorterController<T, ElementType extends HTMLElement = HTMLElement> extends UmbControllerBase {
    #private;
    static lastIndicationSorter?: UmbSorterController<unknown>;
    static originalSorter?: UmbSorterController<unknown>;
    static originalIndex?: number;
    static dropSorter?: UmbSorterController<unknown>;
    static activeSorter?: UmbSorterController<unknown>;
    static activeIndex?: number;
    static activeItem?: any;
    static activeElement?: HTMLElement;
    static activeDragElement?: HTMLElement;
    static rqaId?: number;
    get identifier(): UniqueType;
    set identifier(identifier: UniqueType);
    constructor(host: UmbControllerHostElement, config: UmbSorterConfig<T, ElementType>);
    /**
     * Enables the sorter, this will allow sorting to happen.
     * @returns {*}  {void}
     * @memberof UmbSorterController
     */
    enable(): void;
    /**
     * Disables the sorter, this will prevent any sorting to happen.
     * @returns {*}  {void}
     * @memberof UmbSorterController
     */
    disable(): void;
    setModel(model: Array<T> | undefined): void;
    /**
     * Returns the model of the sorter.
     * @returns {Array<T>} The model of this sorter.
     * @memberof UmbSorterController
     */
    getModel(): Array<T>;
    hasItem(unique: UniqueType): boolean;
    getItem(unique: UniqueType): T | undefined;
    hostConnected(): void;
    hostDisconnected(): void;
    setupItem(element: ElementType): void;
    destroyItem(element: HTMLElement): void;
    /** Management methods: */
    getItemOfElement(element: ElementType): T | undefined;
    getElementOfItem(item: T): ElementType | undefined;
    removeItem(item: T): Promise<boolean>;
    hasOtherItemsThan(item: T): boolean;
    moveItemInModel(newIndex: number, fromCtrl: UmbSorterController<T, ElementType> | undefined): Promise<boolean>;
    updateAllowIndication(item: T): boolean;
    removeAllowIndication(): void;
    private _autoScrollX;
    private _autoScrollY;
    notifyDisallowed(): void;
    notifyAllowed(): void;
    notifyRequestMove(data: any): boolean;
}
export {};
