SnapSort

Versatile and Extensible

A wide variety of core components are available out of the box to provide building blocks for any type of drag and drop UI.

Get started

npm install @snap-engine/snapsort @snap-engine/asset-base
<script lang="ts">
  import { Engine } from "@snap-engine/asset-base/svelte";
  import { Container, Ghost, Item } from "@snap-engine/snapsort/svelte";
  import {
    createRenderEntries,
    createRenderTree,
    reduceRenderTree,
    type ContainerCallbacks,
    type GhostLifecycleEvent,
    type ItemMoveEvent,
  } from "@snap-engine/snapsort";

  let tasks = $state.raw(
    createRenderTree(createRenderEntries([
      { id: "design", label: "Design" },
      { id: "build", label: "Build" },
      { id: "ship", label: "Ship" },
    ], (task) => task.id)),
  );

  function onItemMove(event: ItemMoveEvent) {
    tasks = reduceRenderTree(tasks, event);
  }
  function onGhostMove(event: GhostLifecycleEvent) {
    tasks = reduceRenderTree(tasks, event);
  }
  const callbacks = {
    onItemMove,
    onGhostInsert: onGhostMove,
    onGhostMove,
    onGhostRemove: onGhostMove,
  } satisfies ContainerCallbacks;
</script>

<Engine id="quick-start">
  <Container
    itemId="quick-start-root"
    config={{ callbacks }}
  >
    {#each tasks.entries as entry (entry.itemId)}
      {#if entry.isGhost}
        <Ghost ghost={entry.ghost} />
      {:else}
        <Item itemId={entry.itemId}>{entry.value.label}</Item>
      {/if}
    {/each}
  </Container>
</Engine>