The “Declarative” API

Items are added and removed to containers in a declarative fashion. That is, to add or remove an item, you simply add or remove the component from the frontend framework. SnapSort will detect these events and run the necessary code to properly register or unregister the item from the container.

This is not only convenient, but an important design to make it more explicit that the application, not SnapSort, is responsible for managing the items. Ghosts are an exception in that SnapSort itself has to create it upon drag start, hence the necessity for callbacks like onGhostInsert to ask the frontend to add it in to the DOM on its behalf.

The “Imperative API”

There are, however, situations where you want to do more than just add or remove items. Situations where you want to trigger events like onItemMove that usually are reserved for humans manually moving the items with a mouse or a touch gesture.

moveItem

container.moveItem is a function exactly for this purpose. It can be thought of as a two step process:

  1. Application code invokes moveItem to request SnapSort to run the code necessary move an item to a new location.
  2. SnapSort does so, and replies back with a request to modify the DOM accordingly.

You might ask how this is different than just removing and adding the item yourself in the application code. As a matter of fact, we just said that SnapSort can handle such operations gracefully!

The main benefit is that it makes it easier for both you the developer and SnapSort to keep track of which items are moving where. If a manual drag and drop triggered onItemMove while programmatic move invoked frontend code to add and remove and item, we now have two code paths to do the same thing.

For SnapSort, using these imperative APIs allows items to be animated smoothly.

removeItem

container.removeItem(id) provides the same distinction for removal. When the source Container configures animation.move, SnapSort accepts the command, captures the current root layout, invokes onItemRemove in the next coordinated frame, and animates surviving Items as they close the gap. The removed Item itself is unmounted by the framework and does not receive an exit animation.

Without animation.move, removal keeps its synchronous behavior. Deleting an entry directly from Svelte or React state also remains synchronous and does not enter SnapSort’s animation pipeline. While an animated programmatic move or removal is waiting to commit, further move/remove commands for that Item return false and dragging that Item is temporarily disabled.