droppableContainers in @dnd-kit/core collision detection args is a custom
NodeMap class, not a plain Array. It implements [Symbol.iterator] (so
for...of works internally in closestCenter/pointerWithin) but does NOT
have Array.prototype methods like .filter().
Calling args.droppableContainers.filter(...) threw:
TypeError: args.droppableContainers.filter is not a function
dnd-kit silently catches errors in the collision detection callback and
treats them as no collision (over = null). Every module drag ended with
over = null, hitting the early return in handleDragEnd, causing the module
to snap back to its original slot every time.
Fix: Array.from(args.droppableContainers) converts the NodeMap iterable
to a plain array before filtering for dropType === 'slot' containers.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>