import type { IntlShape } from 'react-intl';
import type { INPUT_METHOD } from '@atlaskit/editor-common/analytics';
import type { PortalProviderAPI } from '@atlaskit/editor-common/portal';
import type { DIRECTION, EditorCommand, NextEditorPlugin, OptionalPlugin, PublicPluginAPI } from '@atlaskit/editor-common/types';
import type { AccessibilityUtilsPlugin } from '@atlaskit/editor-plugin-accessibility-utils';
import type { AnalyticsPlugin } from '@atlaskit/editor-plugin-analytics';
import type { EditorDisabledPlugin } from '@atlaskit/editor-plugin-editor-disabled';
import type { EditorViewModePlugin } from '@atlaskit/editor-plugin-editor-viewmode';
import type { FeatureFlagsPlugin } from '@atlaskit/editor-plugin-feature-flags';
import type { InteractionPlugin } from '@atlaskit/editor-plugin-interaction';
import type { LimitedModePlugin } from '@atlaskit/editor-plugin-limited-mode';
import type { MetricsPlugin } from '@atlaskit/editor-plugin-metrics';
import type { QuickInsertPlugin } from '@atlaskit/editor-plugin-quick-insert';
import type { SelectionPlugin } from '@atlaskit/editor-plugin-selection';
import type { ToolbarPlugin } from '@atlaskit/editor-plugin-toolbar';
import type { TypeAheadPlugin } from '@atlaskit/editor-plugin-type-ahead';
import type { UserIntentPlugin } from '@atlaskit/editor-plugin-user-intent';
import type { WidthPlugin } from '@atlaskit/editor-plugin-width';
import type { EditorState, Selection } from '@atlaskit/editor-prosemirror/state';
import type { Mapping } from '@atlaskit/editor-prosemirror/transform';
import type { Decoration, DecorationSet } from '@atlaskit/editor-prosemirror/view';
export type ActiveNode = {
    anchorName: string;
    handleOptions?: HandleOptions;
    nodeType: string;
    pos: number;
    rootAnchorName?: string;
    rootNodeType?: string;
    rootPos?: number;
};
export type TriggerByNode = {
    nodeType: string;
    pos: number;
    rootPos?: number;
};
export type ActiveDropTargetNode = {
    nodeTypeName: string | null;
    pos: number;
};
export type MultiSelectDnD = {
    anchor: number;
    head: number;
    textAnchor: number;
    textHead: number;
    userAnchor: number;
    userHead: number;
};
export interface PluginState {
    activeDropTargetNode?: ActiveDropTargetNode;
    activeNode?: ActiveNode;
    blockMenuOptions?: {
        canMoveDown?: boolean;
        canMoveUp?: boolean;
        openedViaKeyboard?: boolean;
    };
    decorations: DecorationSet;
    editorHeight: number;
    editorWidthLeft: number;
    editorWidthRight: number;
    /**
     * @private
     * @deprecated Doc size limits no longer supported
     */
    isDocSizeLimitEnabled: boolean | null;
    isDragging: boolean;
    isMenuOpen?: boolean;
    /**
     * is dragging the node without using drag handle, i,e, native prosemirror DnD
     */
    isPMDragging: boolean;
    isResizerResizing: boolean;
    isSelectedViaDragHandle?: boolean;
    isShiftDown?: boolean;
    lastDragCancelled: boolean;
    menuTriggerBy?: string;
    menuTriggerByNode?: TriggerByNode;
    multiSelectDnD?: MultiSelectDnD;
    preservedSelection?: Selection;
}
export type ReleaseHiddenDecoration = () => boolean | undefined;
export type BlockControlsPluginConfig = {
    /** Enable the quick insert plus button icon on the left of the drag handle */
    quickInsertButtonEnabled?: boolean;
    /** Enable left/right hover split: show left controls when hovering left, right controls when hovering right */
    rightSideControlsEnabled?: boolean;
};
export type BlockControlsSharedState = {
    activeDropTargetNode?: ActiveDropTargetNode;
    activeNode?: ActiveNode;
    blockMenuOptions?: {
        canMoveDown?: boolean;
        canMoveUp?: boolean;
        openedViaKeyboard?: boolean;
    };
    hoverSide?: 'left' | 'right';
    isDragging: boolean;
    isEditing?: boolean;
    isMenuOpen: boolean;
    isMouseOut?: boolean;
    isPMDragging: boolean;
    isSelectedViaDragHandle?: boolean;
    isShiftDown?: boolean;
    lastDragCancelled: boolean;
    menuTriggerBy?: string;
    menuTriggerByNode?: TriggerByNode;
    multiSelectDnD?: MultiSelectDnD;
    preservedSelection?: Selection;
    /** Whether left/right hover split is enabled (from plugin config) */
    rightSideControlsEnabled?: boolean;
} | undefined;
export type HandleOptions = {
    isFocused: boolean;
} | undefined;
/**
 * Props passed to custom right-edge button components (e.g. config.rightEdgeButton).
 */
export type RightEdgeButtonProps = {
    api: PublicPluginAPI<[BlockControlsPlugin]>;
    getPos: () => number | undefined;
};
export type NodeDecorationFactoryParams = {
    anchorName: string;
    editorState: EditorState;
    nodeType: string;
    nodeViewPortalProviderAPI: PortalProviderAPI;
    rootAnchorName?: string;
    rootNodeType?: string;
    rootPos: number;
};
/**
 * When true, this factory's decorations are shown in view mode on block hover
 * (without drag handle or quick insert). Used for right-edge controls.
 */
export type NodeDecorationFactory = {
    create: (params: NodeDecorationFactoryParams) => Decoration;
    /**
     * Optional filter: when false, the decoration is not created.
     * Use for node-type-specific visibility (e.g. Remix button only on remixable blocks).
     */
    shouldCreate?: (params: NodeDecorationFactoryParams) => boolean;
    /** Show this decoration in view mode when hovering over a block */
    showInViewMode?: boolean;
    type: string;
};
export type MoveNode = (start: number, to: number, inputMethod?: MoveNodeMethod, formatMessage?: IntlShape['formatMessage']) => EditorCommand;
export type BlockControlsPluginDependencies = [
    OptionalPlugin<LimitedModePlugin>,
    OptionalPlugin<EditorDisabledPlugin>,
    OptionalPlugin<EditorViewModePlugin>,
    OptionalPlugin<WidthPlugin>,
    OptionalPlugin<FeatureFlagsPlugin>,
    OptionalPlugin<AnalyticsPlugin>,
    OptionalPlugin<AccessibilityUtilsPlugin>,
    OptionalPlugin<QuickInsertPlugin>,
    OptionalPlugin<TypeAheadPlugin>,
    OptionalPlugin<SelectionPlugin>,
    OptionalPlugin<MetricsPlugin>,
    OptionalPlugin<InteractionPlugin>,
    OptionalPlugin<UserIntentPlugin>,
    OptionalPlugin<ToolbarPlugin>
];
export type BlockControlsPlugin = NextEditorPlugin<'blockControls', {
    actions: {
        registerNodeDecoration: (factory: NodeDecorationFactory) => void;
        unregisterNodeDecoration: (type: string) => void;
    };
    commands: {
        /**
         * Updates the transaction's selection based on the clicked drag handle position.
         *
         * - If the clicked handle is within an existing multi-block selection range, the selection
         *   is expanded to cover both the existing range and the clicked node's range.
         * - For tables, a table cell selection is used.
         * - Otherwise, selects the single node at the clicked handle position.
         */
        expandAndUpdateSelection: (options: {
            isShiftPressed: boolean;
            nodeType: string;
            selection: Selection;
            startPos: number;
        }) => EditorCommand;
        handleKeyDownWithPreservedSelection: (event: KeyboardEvent) => EditorCommand;
        mapPreservedSelection: (mapping: Mapping) => EditorCommand;
        moveNode: MoveNode;
        moveNodeWithBlockMenu: (direction: DIRECTION.UP | DIRECTION.DOWN) => EditorCommand;
        /**
         * Move a node before (unless `moveToEnd` is set) another node to expand a layout or create a new layout
         * @param from position of the node to be moved
         * @param to position of the layout/layout column/node to move the node to
         * @param options moveToEnd: move the node to after the layout/layout column/another node
         * @param options selectMovedNode: select the moved node after moving it
         */
        moveToLayout: (start: number, to: number, options?: {
            moveNodeAtCursorPos?: boolean;
            moveToEnd?: boolean;
            selectMovedNode?: boolean;
        }) => EditorCommand;
        setMultiSelectPositions: (anchor?: number, head?: number) => EditorCommand;
        setNodeDragged: (getPos: () => number | undefined, anchorName: string, nodeType: string) => EditorCommand;
        setSelectedViaDragHandle: (isSelectedViaDragHandle?: boolean) => EditorCommand;
        showDragHandleAt: (pos: number, anchorName: string, nodeType: string, handleOptions?: HandleOptions, rootPos?: number, rootAnchorName?: string, rootNodeType?: string) => EditorCommand;
        /**
         * Starts preserving the current selection across transactions.
         * Used when opening block menus, dragging, or other interactions
         * where multi-node selections should remain stable.
         */
        startPreservingSelection: () => EditorCommand;
        /**
         * Stops preserving the selection, allowing it to change freely.
         * Called when block menus close or drag operations end.
         */
        stopPreservingSelection: () => EditorCommand;
        toggleBlockMenu: (options?: {
            anchorName?: string;
            closeMenu?: boolean;
            openedViaKeyboard?: boolean;
            triggerByNode?: TriggerByNode;
        }) => EditorCommand;
    };
    dependencies: BlockControlsPluginDependencies;
    pluginConfiguration?: BlockControlsPluginConfig;
    sharedState: BlockControlsSharedState;
}>;
export type BlockControlsMeta = {
    activeNode: ActiveNode;
    dom: HTMLElement;
    editorBlurred: boolean;
    editorHeight: number;
    nodeMoved: boolean;
    preservedSelectionMapping: Mapping;
    type: string;
};
export type MoveNodeMethod = INPUT_METHOD.DRAG_AND_DROP | INPUT_METHOD.SHORTCUT | INPUT_METHOD.BLOCK_MENU;
