I had to tackle this problem for my index card app, Card Buddy. [1] It was definitely a fun challenge and I still found a better way to do it later.
What I ended up doing is when you pick up a card, I compute the layout as if the card was deleted from the board, and then it becomes easy. Wherever you hover the mouse, I just displace whatever is there.
There were still tons of edge cases I had to work out, though, especially when you start editing a new card that hasn’t been “committed” to the data model yet. I had to add the option to shift existing cards out of the way to make room for a phantom card.
It helps to recognize that there are just lots of edge cases you have to manually handle. If you try to tackle it as though there’s a more generic/homogeneous solution, you end up going around in circles a bit with the design. I should probably create a blog post on all the different edge cases.
As I said, though, I found an even better way to do my layout, which saves on unnecessary computations and makes the layout engine more flexible and user-friendly. (It’s amazing what a difference your choice of data model representation makes on your solution.) It’s been a fun puzzle to solve!
[1] https://www.ussherpress.com/cardbuddy/