import { Signal } from "@preact/signals-core";
import { Graph } from "../../../graph";
import { GraphEventsDefinitions } from "../../../graphEvents";
import { Component } from "../../../lib";
import { TComponentContext, TComponentProps, TComponentState } from "../../../lib/Component";
import { HitBox, HitBoxData } from "../../../services/HitTest";
import { DragContext, DragDiff } from "../../../services/drag";
import { PortState, TPort, TPortId } from "../../../store/connection/port/Port";
import { TRect } from "../../../utils/types/shapes";
import { EventedComponent } from "../EventedComponent/EventedComponent";
import { CursorLayerCursorTypes } from "../layers/cursorLayer";
import { TGraphLayerContext } from "../layers/graphLayer/GraphLayer";
export type GraphComponentContext = TComponentContext & TGraphLayerContext & {
    graph: Graph;
    affectsUsableRect?: boolean;
};
export type TGraphComponentProps = TComponentProps & {
    interactive?: boolean;
    affectsUsableRect?: boolean;
};
export declare class GraphComponent<Props extends TGraphComponentProps = TGraphComponentProps, State extends TComponentState = TComponentState, Context extends GraphComponentContext = GraphComponentContext> extends EventedComponent<Props, State, Context> {
    hitBox: HitBox;
    private unsubscribe;
    protected ports: Map<TPortId, PortState>;
    getEntityId(): number | string;
    /**
     * Returns whether this component can be dragged.
     * Override in subclasses to enable drag behavior.
     * Components that return true will participate in drag operations managed by DragService.
     *
     * @returns true if the component is draggable, false otherwise
     */
    isDraggable(): boolean;
    /**
     * Called when a drag operation starts on this component.
     * Override in subclasses to handle drag start logic.
     *
     * @param _context - The drag context containing coordinates and participating components
     */
    handleDragStart(_context: DragContext): void;
    /**
     * Called on each frame during a drag operation.
     * Override in subclasses to update component position.
     *
     * @param _diff - The diff containing coordinate changes (deltaX/deltaY for incremental, diffX/diffY for absolute)
     * @param _context - The drag context containing coordinates and participating components
     */
    handleDrag(_diff: DragDiff, _context: DragContext): void;
    /**
     * Called when a drag operation ends.
     * Override in subclasses to finalize drag state.
     *
     * @param _context - The drag context containing final coordinates and participating components
     */
    handleDragEnd(_context: DragContext): void;
    get affectsUsableRect(): boolean;
    private mounted;
    protected hidden: boolean;
    constructor(props: Props, parent: Component);
    adoptColor(color: string, { alpha }?: {
        alpha?: number;
    }): string;
    createPort(id: TPortId): PortState<unknown>;
    getPort(id: TPortId): PortState;
    /**
     * Get all ports of this component
     * @returns Array of all port states
     */
    getPorts(): PortState[];
    /**
     * Update port position and metadata
     * @param id Port identifier
     * @param portChanges port changes {x?, y?, meta?}
     */
    updatePort<T = unknown>(id: TPortId, portChanges: Partial<TPort<T>>): void;
    protected setAffectsUsableRect(affectsUsableRect: boolean): void;
    protected propsChanged(_nextProps: Props): void;
    protected contextChanged(_nextContext: Context): void;
    onChange(cb: (v: this) => void): () => void;
    protected checkData(): boolean;
    protected onDrag({ onDragStart, onDragUpdate, onDrop, isDraggable, autopanning, dragCursor, }: {
        onDragStart?: (_event: MouseEvent) => void | boolean;
        onDragUpdate?: (diff: {
            startCoords: [number, number];
            prevCoords: [number, number];
            currentCoords: [number, number];
            diffX: number;
            diffY: number;
            deltaX: number;
            deltaY: number;
        }, _event: MouseEvent) => void;
        onDrop?: (_event: MouseEvent) => void;
        isDraggable?: (event: MouseEvent) => boolean;
        autopanning?: boolean;
        dragCursor?: CursorLayerCursorTypes;
    }): () => void;
    isMounted(): boolean;
    protected willMount(): void;
    /**
     * Subscribes to a graph event and automatically unsubscribes on component unmount.
     *
     * This is a convenience wrapper around this.context.graph.on that also registers the
     * returned unsubscribe function in the internal unsubscribe list, ensuring proper cleanup.
     *
     * @param eventName - Graph event name to subscribe to
     * @param handler - Event handler callback
     * @param options - Additional AddEventListener options
     * @returns Unsubscribe function
     */
    protected onGraphEvent<EventName extends keyof GraphEventsDefinitions, Cb extends GraphEventsDefinitions[EventName]>(eventName: EventName, handler: Cb, options?: AddEventListenerOptions | boolean): () => void;
    /**
     * Subscribes to a DOM event on the graph root element and automatically unsubscribes on unmount.
     *
     * @param eventName - DOM event name to subscribe to
     * @param handler - Event handler callback
     * @param options - Additional AddEventListener options
     * @returns Unsubscribe function
     */
    protected onRootEvent<K extends keyof HTMLElementEventMap>(eventName: K, handler: ((this: HTMLElement, ev: HTMLElementEventMap[K]) => void) | EventListenerObject, options?: AddEventListenerOptions | boolean): () => void;
    protected subscribeSignal<T>(signal: Signal<T>, cb: (v: T) => void): void;
    onUnmounted(cb: () => void): () => void;
    protected unmount(): void;
    setHitBox(minX: number, minY: number, maxX: number, maxY: number, force?: boolean): void;
    protected willIterate(): void;
    protected isVisible(): boolean;
    protected getHitBoxRect(): TRect;
    protected setVisibility(visible: boolean, { removeHitbox }: {
        removeHitbox: boolean;
    }): void;
    setRenderDelegated(delegated: boolean): void;
    getHitBox(): [number, number, number, number];
    removeHitBox(): void;
    destroyHitBox(): void;
    onHitBox(data: HitBoxData): boolean;
}
