import type { GridRowDragMode, GridRowDropInfo, GridRowId } from '../types' import type { Collection, SortFn } from './types' export function getIndexAfterDrop( collection: Collection, draggedRowIds: Set, parentId: null | GridRowId, beforeId: null | GridRowId, sortFn: SortFn ) { if (beforeId === null) { return 0 } let ids = collection.ids if (parentId) { ids = collection.meta.get(parentId)?.children ?? [] } const filteredIds = ids.filter((id) => !draggedRowIds.has(id)) const sortedIds = sortFn ? sortFn(filteredIds, collection.entities, collection.meta) : filteredIds const prevIndex = sortedIds.indexOf(beforeId) return prevIndex === -1 ? null : prevIndex + 1 } const allParentsMatch = ( ids: GridRowId[], parentLookup: Map, targetParentId: GridRowId | null ) => ids.every((id) => { const parentId = parentLookup.get(id) return targetParentId === null ? parentId == null : parentId === targetParentId }) export const doesDropProduceChange = ( dropInfo: Pick< GridRowDropInfo, 'draggedRowIds' | 'resultIds' | 'targetParentId' >, mode: GridRowDragMode, parentLookup: Map, existingListIds: GridRowId[] | null ) => { const { draggedRowIds, resultIds, targetParentId } = dropInfo const parentsMatch = allParentsMatch( draggedRowIds, parentLookup, targetParentId ) // If any parents have changed, we can immediately process the drop if (!parentsMatch) { return true } if (mode === 'parent' || resultIds === null) { return false } else { if ( existingListIds === null || existingListIds.length !== resultIds.length ) { return true } return !resultIds.every((id, index) => existingListIds[index] === id) } }