import type { DisplayGroupNode } from './display-group.types'; /** * Fired by {@link DisplayGroupDragHandler} when the user drops a group at a * new position. * * @param logicalGroupId - The logical group being moved. * @param sourcePanel - The panel the drag originated from. * @param targetPanel - The panel the group is dropped into. * @param insertBeforeColId - First leaf column to the right of the drop target. * `null` means append at the end of the target panel section. */ export type GroupMovedCallback = (logicalGroupId: string, sourcePanel: 'left' | null | 'right', targetPanel: 'left' | null | 'right', insertBeforeColId: string | null) => void; /** * Callbacks used for real-time (AG Grid-style) group tree preview during drag. * * When provided the drag handler uses a live-rebuild path instead of CSS * transforms: on every slot change the column order is updated in the store so * the header re-renders with the group in its new position before the user drops. */ export interface GroupPreviewCallbacks { /** Called once when the drag crosses the activation threshold. */ onPreviewStart: () => void; /** * Called on every slot change during the drag. * The engine applies the move from the original snapshot so the header * rebuilds with the group at the new position. */ onPreviewMove: GroupMovedCallback; /** * Called on mouseup to commit the final preview position. * The store already reflects the correct order — this just clears the snapshot. */ onPreviewConfirm: () => void; } /** * Handles atomic column-group drag and drop. * * ### Rules * - Only **group header cells** (`.pg-th--group`) can be dragged. * - Group children cannot escape their group during drag. * - Drop targets are root-level positions only (before/after other groups or * flat columns). Dropping inside another group is not supported. * - Moving across panels changes the `pinned` property of all group leaves. * * ### Visual feedback — two modes * **Live preview** (when `previewCallbacks` is provided): * The column order is updated in the store on every slot change so the header * re-renders in real time — identical to AG Grid behaviour. CSS transforms are * not used; the rebuilt DOM IS the visual feedback. * * **CSS-transform** (legacy fallback): * `translateX` rules are injected via a `