Package Exports
- @neodrag/svelte
- @neodrag/svelte/legacy
- @neodrag/svelte/package.json
Readme
@neodrag/svelte
One draggable to rule em all
A lightweight Svelte attachment to make your elements draggable.
Features
- 🤏 Small in size - ~5KB, plugin architecture enables tree-shaking
- 🧩 Plugin-based - Mix and match only what you need
- ⚡ Performance - Event delegation, pointer capture, optimized for modern browsers
- 🎯 Svelte 5 Native - Built for attachments with
{@attach}syntax - 🔄 Reactive - Change options on the fly with compartments
- 🗃️ Highly customizable - Tons of plugins available
Installing
npm install @neodrag/svelte@nextUsage
Svelte 5 (Recommended)
Basic usage
<script>
import { draggable } from '@neodrag/svelte';
</script>
<div {@attach draggable()}>Hello</div>With plugins
<script>
import { draggable, axis, grid } from '@neodrag/svelte';
</script>
<div {@attach draggable([axis('x'), grid([10, 10])])}>
Hello
</div>Defining plugins elsewhere with TypeScript
<script lang="ts">
import { draggable, axis, bounds, BoundsFrom, type Plugin } from '@neodrag/svelte';
let plugins: Plugin[] = [
axis('y'),
bounds(BoundsFrom.viewport()),
];
</script>
<div {@attach draggable(plugins)}>Hello</div>Reactive plugins with compartments
<script>
import { draggable, axis, createCompartment } from '@neodrag/svelte';
let currentAxis = $state('x');
const axisComp = createCompartment(() => axis(currentAxis));
</script>
<div {@attach draggable([axisComp])}>
Current axis: {currentAxis}
</div>
<button onclick={() => currentAxis = currentAxis === 'x' ? 'y' : 'x'}>
Switch Axis
</button>Svelte 4 (Legacy Support)
<script>
import { legacyDraggable, axis } from '@neodrag/svelte/legacy';
</script>
<div use:legacyDraggable={[axis('x')]}>Hello</div>Note: Legacy actions are deprecated and will be removed in v4. Migrate to Svelte 5 for better performance.
Credits
Inspired by react-draggable, but with a modern plugin architecture and optimized for performance.
License
MIT License © Puru Vijay