import { PointerEvent as ReactPointerEvent, RefObject } from 'react'; /** * Drag-to-reorder driven by pointer events. * * Native HTML5 drag-and-drop is deliberately not used: its events are unreliable * inside a shadow root (which is how the editor ships), it can't be driven by * touch, and it depends on a drag image the browser composes for us. Pointer * events are plain coordinates, so both surfaces that reorder items — the * sidebar list and the form canvas — behave the same. * * Press anywhere on an item to arm; the drag begins only once the pointer has * travelled past a small threshold, so an ordinary click still lands. */ /** * Pixels of travel before a press turns into a drag. Exported so the other * pointer gesture that starts on a press — dragging a new element out of the * sidebar picker — arms at exactly the same distance. */ export declare const THRESHOLD = 4; /** * Where the dragged item would land relative to the one under the pointer. * * `before`/`after` put it on its own line above or below. `start`/`end` put it * *beside* the target, sharing its row — which is how a form gets first name * next to last name. Which one you get is read off the pointer: near either * side edge of the target means beside it, anywhere in the middle means its own * line. Side drops are opt-in per surface (see `sideDrops`), because a plain * vertical list has no rows to join. */ export type DropEdge = 'before' | 'after' | 'start' | 'end'; /** Whether the surface reads right to left, so side drops pair as it reads. */ export declare function isRtl(container: HTMLElement | null): boolean; /** * Where a drop on `target` would land, given where the pointer sits over it. * * Pure and exported so the zones can be tested directly: this is the whole of * what separates "put it beside this field" from "put it on its own line", and * getting it wrong is invisible until someone tries to build a two-column row. */ export declare function dropEdgeAt(target: DOMRect, x: number, y: number, { sideDrops, rtl, movingDown, sameRow, }: { sideDrops: boolean; rtl: boolean; movingDown: boolean; /** * The dragged item is standing on this target's line. Then `movingDown` has * no answer to give: the item is leaving the line, so above the line and * below it are two different places and neither is the one it is in. Order * would only ever offer whichever of the two follows it, which left the * other reachable only by moving both items in turn. */ sameRow?: boolean; }): DropEdge; export interface DragSort { /** The item being dragged, once the press has passed the threshold. */ draggingId: string | null; /** The item the pointer is currently over. */ overId: string | null; /** The side of `overId` the drop would land on — where to draw the line. */ overEdge: DropEdge | null; /** Call from an item's `onPointerDown` to arm a drag on it. */ press: (id: string, e: ReactPointerEvent) => void; } /** * The item the pointer is aiming at: the one under it, or — when it sits in a * gap between two, or has strayed past the edge of the list — the nearest one. * Dropping "between" items is the most common way a reorder gets lost, so there * is deliberately no way to point at nothing. * * Exported for the insert drag (see builder/insertDrag), which aims at the same * items with no item of its own to move: one rule for what a pointer is over. */ export declare function itemAt(container: HTMLElement | null, selector: string, x: number, y: number): HTMLElement | null; export declare function useDragSort(containerRef: RefObject, /** How to find the sortable items inside the container, e.g. `[data-pm-item]`. */ itemSelector: string, /** The attribute on an item holding its id. */ idAttribute: string, onReorder: (draggedId: string, targetId: string, edge: DropEdge) => void, /** * Offer the side drops that put two items on one row. The form canvas wants * them; the sidebar, a single column of full-width rows, has no row to join * and so leaves them off. */ sideDrops?: boolean): DragSort;