events
Listen to drag start, drag, and drag end events
The events
plugin provides callbacks that fire during different phases of dragging. Get notified when dragging starts, during movement, and when it ends - perfect for updating UI state, logging, or triggering animations.
events({
onDragStart: (data) => console.log('Started dragging'),
onDrag: (data) => console.log('Moving:', data.offset),
onDragEnd: (data) => console.log('Finished dragging'),
});
Basic Usage
<script>
import { events } from '@neodrag/svelte';
let dragStatus = $state('idle');
let position = $state({ x: 0, y: 0 });
const eventHandlers = events({
onDragStart: () => {
dragStatus = 'dragging';
},
onDrag: (data) => {
position = { x: data.offset.x, y: data.offset.y };
},
onDragEnd: () => {
dragStatus = 'idle';
},
});
</script>
<div {@attach draggable([eventHandlers])}>
Status: {dragStatus}
<br />
Position: {position.x}, {position.y}
</div>
Event Data
All event callbacks receive a DragEventData
object with:
offset
- Current position{ x: number, y: number }
rootNode
- Element with draggable appliedcurrentNode
- Element being dragged (can change mid-drag)event
- The pointer event that triggered this callback
<script>
import { events } from '@neodrag/svelte';
function logEventData(data) {
console.log('Position:', data.offset);
console.log('Root element:', data.rootNode);
console.log('Current element:', data.currentNode);
console.log('Pointer event:', data.event);
}
const eventHandlers = events({
onDragStart: logEventData,
onDrag: logEventData,
onDragEnd: logEventData,
});
</script>
<div {@attach draggable([eventHandlers])}>
Check console for event data
</div>
Real-World Examples
Position Tracking with Velocity
<script>
import { events } from '@neodrag/svelte';
let position = $state({ x: 0, y: 0 });
let velocity = $state({ x: 0, y: 0 });
let lastTime = 0;
let lastPosition = { x: 0, y: 0 };
const trackingHandler = events({
onDrag: (data) => {
const now = Date.now();
const deltaTime = now - lastTime;
if (deltaTime > 0) {
velocity = {
x: Math.round(
((data.offset.x - lastPosition.x) / deltaTime) * 1000,
),
y: Math.round(
((data.offset.y - lastPosition.y) / deltaTime) * 1000,
),
};
}
position = { ...data.offset };
lastPosition = { ...data.offset };
lastTime = now;
},
});
</script>
<div {@attach draggable([trackingHandler])}>
Position: ({position.x}, {position.y})
<br />
Velocity: ({velocity.x}px/s, {velocity.y}px/s)
</div>
Save Position to Storage
<script>
import { events } from '@neodrag/svelte';
const saveHandler = events({
onDragEnd: (data) => {
localStorage.setItem(
'elementPosition',
JSON.stringify({
x: data.offset.x,
y: data.offset.y,
timestamp: Date.now(),
}),
);
console.log('Position saved!');
},
});
</script>
<div {@attach draggable([saveHandler])}>
Position saves when you stop dragging
</div>
Analytics Tracking
// Track user interactions for analytics
events({
onDragStart: (data) => {
analytics.track('drag_started', {
element: data.rootNode.id,
timestamp: Date.now(),
});
},
onDragEnd: (data) => {
analytics.track('drag_completed', {
element: data.rootNode.id,
finalPosition: data.offset,
timestamp: Date.now(),
});
},
});
Progress Indicator
// Show progress based on how far element has moved
const maxDistance = 300;
events({
onDragStart: () => {
progressBar.style.display = 'block';
},
onDrag: (data) => {
const distance = Math.sqrt(
data.offset.x ** 2 + data.offset.y ** 2,
);
const progress = Math.min((distance / maxDistance) * 100, 100);
progressBar.style.width = `${progress}%`;
},
onDragEnd: () => {
progressBar.style.display = 'none';
},
});
How It Works
The events plugin:
- Stores event data in its state during each hook
- Schedules callbacks using
ctx.effect.immediate()
for fast execution - Provides consistent data across all three event types
- Non-cancelable - Always runs regardless of other plugin cancellations
The callbacks fire in this order:
onDragStart
→onDrag
(repeatedly) →onDragEnd
API Reference
function events(options?: {
onDragStart?: (data: DragEventData) => void;
onDrag?: (data: DragEventData) => void;
onDragEnd?: (data: DragEventData) => void;
}): Plugin;
Options:
onDragStart
- Called when dragging beginsonDrag
- Called repeatedly during draggingonDragEnd
- Called when dragging ends
DragEventData:
offset
- Current position{ x: number, y: number }
rootNode
- Element with draggable appliedcurrentNode
- Element being draggedevent
- The pointer event that triggered this callback
Returns: A plugin object for use with draggable.