Drag to reorder
Item 1
Item 2
Item 3
Item 4
HTML
<div class="list"> <div class="item" data-vel-plugin="DragToReorderPlugin" data-vel-view="item"> Item 1 </div> <div class="item" data-vel-plugin="DragToReorderPlugin" data-vel-view="item"> Item 2 </div> <div class="item" data-vel-plugin="DragToReorderPlugin" data-vel-view="item"> Item 3 </div> <div class="item" data-vel-plugin="DragToReorderPlugin" data-vel-view="item"> Item 4 </div></div>
CSS
.list { display: flex; flex-direction: column; gap: 10px 0; width: 100%; max-width: 200px;}
.item { font-size: 18px; background: whitesmoke; padding: 8px 10px; border-radius: 5px; color: #222; font-weight: 500; user-select: none; -webkit-user-select: none; touch-action: none; -webkit-touch-action: none; will-change: transform; box-shadow: 1px 2px 10px rgba(0, 0, 0, 0.2);}
JavaScript
API Style:
Functions
Classes
import { createApp, DragEventPlugin, DragEvent } from 'veloxi'
const DragToReorderPlugin = (context) => { const dragEventPlugin = context.useEventPlugin(DragEventPlugin) dragEventPlugin.on(DragEvent, onDrag)
let items
let draggingItem = null
const itemIdSlotMap = new Map()
const slotPositionMap = new Map()
context.setup(() => { items = context.getViews('item')
items.forEach((item, index) => { assignItemToSlot(item, index) dragEventPlugin.addView(item) item.position.animator.set('dynamic') slotPositionMap.set(index, item.position.y) }) })
function onDrag(event) { if (event.isDragging) { draggingItem = event.view draggingItem.position.set({ x: event.x, y: event.y }) draggingItem.styles.zIndex = '2'
updateItemPositions() } else { if (!draggingItem) return draggingItem.styles.zIndex = '' draggingItem.position.set({ x: draggingItem.position.initialX, y: getSlotPositionForItem(draggingItem) }) draggingItem = null } }
function updateItemPositions() { items .filter((item) => item.id !== draggingItem?.id) .forEach((item) => { if (!draggingItem) return
const draggingItemSlot = itemIdSlotMap.get(draggingItem.id) const itemSlot = itemIdSlotMap.get(item.id)
if (draggingItemSlot === undefined || itemSlot === undefined) return
const draggingItemPosition = draggingItem.position.y const itemPosition = getSlotPositionForItem(item)
if ( draggingItemSlot < itemSlot && draggingItemPosition + draggingItem.size.height > itemPosition + item.size.height / 2 ) { assignItemToSlot(item, draggingItemSlot) assignItemToSlot(draggingItem, itemSlot) item.position.set({ y: slotPositionMap.get(draggingItemSlot) }) } else if ( draggingItemSlot > itemSlot && draggingItemPosition < itemPosition + item.size.height / 2 ) { assignItemToSlot(item, draggingItemSlot) assignItemToSlot(draggingItem, itemSlot) item.position.set({ y: slotPositionMap.get(draggingItemSlot) }) } }) }
function assignItemToSlot(item, slot) { itemIdSlotMap.set(item.id, slot) }
function getSlotPositionForItem(item) { const slot = itemIdSlotMap.get(item.id) return slotPositionMap.get(slot) }}
DragToReorderPlugin.pluginName = 'DragToReorderPlugin'
const app = createApp()
app.addPlugin(DragToReorderPlugin)
app.run()