import type { GridStore } from '../core/grid-store'; import type { EventBus } from '../event-bus/event-bus'; import type { IconRenderer } from '../icons/icon-renderer'; export declare class RowDragRenderer { private store; private eventBus; private iconRenderer; /** Positions the drag chip with a compositor-only transform. */ private readonly ghost; /** * Owns the stylesheet carrying the previewed row `top` overrides and skips the * assignment when the generated CSS is unchanged. * * The previous implementation looked the element up with a document-wide * `document.querySelector` on every read *and* every clear, then rewrote it * unconditionally. */ private readonly topStyles; private draggingNodeId; private dragLabel; private isDragging; private gridEl; private bodyWrapEl; private targetNodeId; private targetPosition; /** `true` when Tree Data is active — switches drop-zone classification from a 2-way (before/after) to a 3-way (before/inside/after) split, and routes the commit through `treeReparentHandler` instead of the flat splice. Set via `setTreeMode`, called from `GridCore` only when a mutable hierarchy source (`parentId`/`childrenField`) is configured. */ private treeModeActive; private treeReparentHandler; private scrollFn; private autoScrollRAF; private autoScrollLastTs; private cursorX; private cursorY; /** * Body-viewport bounds, captured at drag start and refreshed only when the * layout can have moved (a re-render, an auto-scroll step). * * Both the drop-target hit test and the auto-scroll tick used to call * `getBoundingClientRect()` — the hit test on every pointer event, immediately * after the chip's position had been written, which forces a synchronous * layout flush each time. */ private bodyRect; /** * Coalesces `pointermove` into one frame of work. * * Hit-testing the render window, regenerating the row-`top` sheet, and * renumbering the serial column now happen once per painted frame against the * newest sample instead of once per pointer event. */ private readonly frames; /** * Serial-number ``s by node id, plus the pool of values to redistribute. * * Built once at drag start and after each `ROWS_RENDERED`, rather than * re-queried, re-parsed, and re-sorted on every drop-target change. */ private serialSpans; private serialValues; /** `false` when {@link serialSpans} must be rebuilt before the next renumber. */ private serialCacheValid; /** * `false` when the grid must not rewrite row order itself — the application * commits the move instead. See {@link setManagedReorder}. */ private managedReorder; /** The dragged row node, captured at drag start so its index can be resolved in O(1). */ private draggedRow; /** The row the pointer is currently over, kept alongside {@link targetNodeId}. */ private targetRow; /** Tears down the `ROWS_RENDERED` subscription that re-applies drag visuals after virtualization re-renders. `null` until `mount`. */ private unsubscribeRowsRendered; private boundMouseDown; private boundMouseMove; private boundMouseUp; constructor(store: GridStore, eventBus: EventBus, iconRenderer: IconRenderer); mount(gridEl: HTMLElement, bodyWrapEl: HTMLElement, scrollFn: (dy: number) => void): void; /** * Enables Tree Data drag-to-reparent. `reparentHandler` is called on drop * with the resolved `'before'|'after'|'inside'` position and should mutate * the raw hierarchy + trigger a pipeline refresh (see * `TreeDataService.moveNode`) — this renderer never touches tree structure * itself, only mouse tracking and drop-zone classification. */ setTreeMode(active: boolean, reparentHandler: (draggedId: string, targetId: string, position: 'before' | 'after' | 'inside') => boolean): void; /** * Declares whether the grid applies the reorder itself on drop. * * When `false` the drag and its live preview run exactly as normal, but the * row array is never touched and `ROW_DROP` is emitted with `managed: false` * — a request for the application to persist the move and refresh. That is the * only coherent mode under a server-backed row model, where the datasource * owns row order. See `RowDragOptions`. */ setManagedReorder(managed: boolean): void; destroy(): void; /** * The `nodeId` of the row currently being dragged, or `null` when no drag is * in progress. * * `GridRenderer` reads this each render to pin the dragged row inside the * virtual render window: the drag preview repositions it via a `top` override * near the drop target, but vertical virtualization slices on each row's * *real* `top`, so once auto-scroll moves that real position off-screen the * row would otherwise be evicted — leaving the placeholder gap blank. */ getDraggingNodeId(): string | null; private onMouseDown; private startDrag; /** * Records the pointer sample. All work is deferred to {@link applyDragFrame}, * which the scheduler runs at most once per painted frame. */ private onMouseMove; /** The row drag's per-frame workload: move the chip, then re-resolve the drop slot. */ private applyDragFrame; private updateDropTarget; /** * Re-stamps the drag's imperative DOM state onto the current row elements * after a body re-render. Bound to `ROWS_RENDERED`. * * The absolute-`top` overrides survive a re-render on their own — they live * in a global stylesheet keyed by `data-node-id` (see `updateRowTops`) — but * the dragged-row opacity marker, the tree-mode drop highlight, and the * previewed serial numbering are applied directly to elements that * virtualization recycles and `BodyRenderer.updatePanelRow` overwrites. Those * must be re-applied on the fresh DOM or the placeholder vanishes the moment * the viewport scrolls mid-drag. No-op unless a drag is in progress. */ private reapplyDragVisuals; /** Tree mode's drop feedback: highlights the target row and flags whether the drop would nest the dragged row inside it. */ private updateTreeDropHighlight; /** 2-way (before/after) split normally; 3-way (before/inside/after, thirds) when Tree Data drag-to-reparent is active. */ private classifyDropPosition; private onMouseUp; /** * Resolves the drop into concrete indices, or `null` when it would not move * the row (dropped back into its own slot, or onto a row whose position can't * be resolved). */ private resolveMove; private startAutoScrollLoop; /** * One auto-scroll frame. * * Two changes from the previous implementation: * * - The body rect comes from {@link ensureBodyRect} instead of a fresh * `getBoundingClientRect()` per frame. Scrolling changes the body's content * offset, not its position on screen, so the cached rect stays valid for the * whole drag unless a re-render invalidates it. * - Speed is px/**second** scaled by real elapsed time rather than px/frame, so * an identical gesture scrolls at the same rate on a 60 Hz and a 120 Hz * display. The previous fixed-per-frame model ran twice as fast on the latter. * * Bound as an arrow field so it can be handed straight to `requestAnimationFrame`. */ private readonly autoScrollTick; /** * The body viewport's bounds, read at most once per invalidation. * * Invalidated at drag start and on every `ROWS_RENDERED` — the only events * during a drag that can move the viewport on screen. */ private ensureBodyRect; private updateRowTops; /** * Index of `row` in the published array. * * `RowNode.rowIndex` is the row's absolute position in `visibleRows`, * assigned by `RowModel.layoutNodes` — the same invariant `BodyRenderer` * already relies on for serials and stripe parity. So it serves as an O(1) * hint, verified against the array before it is trusted, with a scan of the * render window as the fallback. */ private indexOf; /** The published rows plus the half-open index range currently painted. */ private renderWindow; /** The painted row carrying `nodeId`, or `null`. */ private findInWindow; private clearDragTops; /** * Re-numbers the serial-number column so the on-screen serials read in * ascending order top-to-bottom for the given row order. * * The set of serial VALUES currently rendered is invariant during a drag * (only their row assignment changes), so those exact values are * redistributed to the rows in `order`. This is intentionally agnostic to how * serials are computed (absolute vs. window-relative) — it neither knows nor * needs the numbering scheme, which avoids any value "jump" at drag start. * * Only rows currently in the DOM carry serial cells, and `order` is scoped to * the render window for exactly that reason — a row that is not painted has * no serial to renumber. No-op when the serial column is disabled (no serial * cells present). * * ### Performance * The span lookup table is built once per render (see {@link ensureSerialCache}) * rather than re-queried, re-parsed, and re-sorted here — this used to run a * `querySelectorAll` plus a `closest` and a `parseInt` per serial cell on every * drop-target change *and* every `ROWS_RENDERED`. Each span is written only * when its value actually changes, so a frame that shifts nothing is free. * * @param order - Painted row nodes in the desired visual order (previewed * order while dragging; real order to restore). */ private renumberSerialCells; /** * Rebuilds the serial-cell lookup table if it is stale. * * Invalidated at drag start and on every `ROWS_RENDERED`, which are the only * points at which the rendered serial cells — or the pool of values they carry * — can change. */ private ensureSerialCache; private reorderRows; private getScrollTop; /** * The offset RowPositionSheet currently subtracts from every row's `top`. * Published by `ScrollController.setRowOrigin`; see the paint-coordinate * rebasing note in `GridRenderer.performRender`. */ private getRowOriginY; private setDraggingClass; private cleanupInteraction; private cleanupVisuals; private cleanup; } //# sourceMappingURL=row-drag-renderer.d.ts.map