nuxtjs-sortable
v0.0.9
Published
Nuxt module for Sortable.js
Maintainers
Readme
@typed-draggable/nuxt
Nuxt module for typed-vuedraggable - Vue.js draggable component with full TypeScript support powered by Sortable.js.
Features
- 🚀 Full TypeScript support - Complete type definitions for all props and events
- 🎨 Auto-import - Components are automatically available in your templates
- 📦 Small bundle - Only includes what you need
- 🔄 Two-way binding - Works with
v-modelfor seamless data synchronization - 🎯 Slot-based API - Flexible item rendering with header and footer slots
- 🔀 Multi-list support - Drag and drop between multiple lists
- 🎬 Transition support - Works with Vue transitions out of the box
Quick Setup
Install the module to your Nuxt application with one command:
npx nuxi module add @typed-draggable/nuxtOr install manually:
# npm
npm install @typed-draggable/nuxt
# pnpm
pnpm add @typed-draggable/nuxt
# yarn
yarn add @typed-draggable/nuxtThen add the module to your nuxt.config.ts:
export default defineNuxtConfig({
modules: ['@typed-draggable/nuxt'],
draggable: {
// module options
prefix: '', // optional prefix for component name
},
})That's it! You can now use the Draggable component in your Nuxt app ✨
Usage
Basic Example
<template>
<Draggable v-model="items" item-key="id" ghost-class="ghost">
<template #item="{ element }">
<div class="item">{{ element.name }}</div>
</template>
</Draggable>
</template>
<script setup lang="ts">
interface Item {
id: number
name: string
}
const items = ref<Item[]>([
{ id: 1, name: 'Item 1' },
{ id: 2, name: 'Item 2' },
{ id: 3, name: 'Item 3' },
])
</script>Two Lists with Shared Group
<template>
<div class="lists">
<Draggable v-model="listA" item-key="id" group="shared">
<template #item="{ element }">
<div class="item">{{ element.name }}</div>
</template>
</Draggable>
<Draggable v-model="listB" item-key="id" group="shared">
<template #item="{ element }">
<div class="item">{{ element.name }}</div>
</template>
</Draggable>
</div>
</template>With Header and Footer Slots
<template>
<Draggable v-model="items" item-key="id">
<template #header>
<div class="header">Header - Not draggable</div>
</template>
<template #item="{ element, index }">
<div class="item">{{ index + 1 }}. {{ element.name }}</div>
</template>
<template #footer>
<div class="footer">Footer - Not draggable</div>
</template>
</Draggable>
</template>With Custom Tag
<template>
<Draggable v-model="items" item-key="id" tag="ul">
<template #item="{ element }">
<li>{{ element.name }}</li>
</template>
</Draggable>
</template>With Transitions
<template>
<Draggable v-model="items" item-key="id" tag="TransitionGroup" :component-data="{ name: 'list' }">
<template #item="{ element }">
<div class="item">{{ element.name }}</div>
</template>
</Draggable>
</template>
<style>
.list-move {
transition: transform 0.3s;
}
</style>Props
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| v-model / modelValue | T[] | null | The list of items (two-way bound) |
| list | T[] | null | Alternative to v-model (one-way) |
| itemKey | string \| ((item: T) => string \| number) | required | Unique key for each item |
| tag | string | 'div' | HTML tag or component name for the container |
| clone | (item: T) => T | (x) => x | Function to clone items |
| move | (evt, originalEvent) => boolean \| void | null | Function to determine if move is allowed |
| componentData | object | null | Props to pass to the container component |
All Sortable.js options are also supported as props (e.g., group, sort, delay, animation, handle, ghostClass, etc.).
Events
| Event | Payload | Description |
|-------|---------|-------------|
| update:modelValue | T[] | Emitted when the list changes |
| change | ChangeEvent<T> | Emitted on add, remove, or move with details |
| start | SortableEvent | Drag started |
| end | SortableEvent | Drag ended |
| add | SortableEvent | Item added to list |
| remove | SortableEvent | Item removed from list |
| update | SortableEvent | Item moved within list |
| choose | SortableEvent | Item chosen |
| unchoose | SortableEvent | Item unchosen |
| sort | SortableEvent | Sorting changed |
| filter | SortableEvent | Tried to drag filtered item |
| clone | SortableEvent | Clone created |
TypeScript
The module provides full TypeScript support. Import types as needed:
import type {
ChangeEvent,
AddedEvent,
RemovedEvent,
MovedEvent,
MoveEventContext
} from '@typed-draggable/nuxt/runtime/types'
function handleChange(event: ChangeEvent<MyItem>) {
if ('added' in event) {
console.log('Added:', event.added.element)
}
}Important Notes
- The component only works on the client side (uses
SortableJSwhich requires DOM) - Wrap in
<ClientOnly>if needed for SSR applications itemKeyprop is required and must return unique values for each item
Development
# Install dependencies
pnpm install
# Generate type stubs
pnpm run dev:prepare
# Develop with the playground
pnpm run dev
# Build the module
pnpm run prepack
# Run tests
pnpm run test