import { ReactiveController, ReactiveElement } from 'lit'; /** * Snapshot of the fields read from a native `DragEvent` before it's recycled * by the browser, safe to read after the debounce in {@link DragAndDropControllerOptions.onDragLeave}. */ export interface DragLeaveSnapshot { clientX: number; clientY: number; relatedTarget: EventTarget | null; } /** Configuration options for {@link DragAndDropController}. */ export interface DragAndDropControllerOptions { /** * The host's own current "is a drag over me" flag. The controller never * keeps a copy of this state; it re-reads it on every native event so a * host that also exposes this flag as a public, externally-settable * property (as `swc-dropzone` does) can never drift out of sync with it. */ isDragged: () => boolean; /** * Return `false` to reject the current drag payload; sets the OS cursor to * "not-allowed". Called on every native `dragover` tick. Defaults to * always-accept. */ shouldAccept?: (event: DragEvent) => boolean; /** Called once when an accepted drag enters — not on every `dragover` tick. Set `isDragged`'s backing flag to `true` here. */ onDragEnter?: (event: DragEvent) => void; /** Called once the accepted drag leaves or becomes rejected. Set `isDragged`'s backing flag to `false` here. */ onDragLeave?: (snapshot: DragLeaveSnapshot) => void; /** Called on drop, only when `isDragged()` is currently `true`. */ onDrop?: (event: DragEvent) => void; /** OS cursor feedback while an accepted drag hovers. Defaults to `'copy'`. */ dropEffect?: () => DataTransfer['dropEffect']; } /** * A Lit {@link ReactiveController} that manages native drag-and-drop event * wiring (`dragover` / `dragleave` / `drop`) for a host element: debounces * `dragleave` so passing over a child element doesn't flicker the state, * de-duplicates entry so `onDragEnter` fires once per hover session rather * than on every `dragover` tick, and lets the host veto payloads it doesn't * want via `shouldAccept`. * * The host owns its own "dragged" state (via `isDragged`/`onDragEnter`/ * `onDragLeave`); this controller only drives the timing. * * @example * ```ts * const dragAndDrop = new DragAndDropController(this, { * isDragged: () => this._dragged, * onDragEnter: () => { this._dragged = true; }, * onDragLeave: () => { this._dragged = false; }, * onDrop: (event) => this._handleFilesDropped(event.dataTransfer?.files), * }); * ``` */ export declare class DragAndDropController implements ReactiveController { private readonly _host; private readonly _options; private _dragLeaveTimer; private _abortController; constructor(host: ReactiveElement, options: DragAndDropControllerOptions); hostConnected(): void; hostDisconnected(): void; private readonly _onDragOver; private readonly _onDragLeave; private readonly _onDrop; private _clearDragLeaveTimer; }