diff --git a/docs/.vitepress/sidebar.ts b/docs/.vitepress/sidebar.ts
index 89b4d2bb..201995e9 100644
--- a/docs/.vitepress/sidebar.ts
+++ b/docs/.vitepress/sidebar.ts
@@ -17,7 +17,9 @@ export const sidebar = {
{ text: 'Mixin Animation', link: '/en/demo/transitions/' },
{ text: 'Table Row', link: '/en/demo/table/' },
{ text: 'Table Column', link: '/en/demo/table-column/' },
- { text: 'Nesting', link: '/en/demo/nested/' }
+ { text: 'Nesting', link: '/en/demo/nested/' },
+ { text: 'Swap', link: '/en/demo/swap/' },
+ { text: 'Multi Drag', link: '/en/demo/multi-drag/' }
]
},
{
@@ -47,7 +49,9 @@ export const sidebar = {
{ text: '内置动画合并', link: '/demo/transitions/' },
{ text: '表格行拖拽', link: '/demo/table/' },
{ text: '表格列拖拽', link: '/demo/table-column/' },
- { text: '嵌套', link: '/demo/nested/' }
+ { text: '嵌套', link: '/demo/nested/' },
+ { text: '交换', link: '/demo/swap/' },
+ { text: '多选拖拽', link: '/demo/multi-drag/' }
]
},
{
diff --git a/src/__docs__/multi-drag/demo.vue b/src/__docs__/multi-drag/demo.vue
new file mode 100644
index 00000000..bd9c003a
--- /dev/null
+++ b/src/__docs__/multi-drag/demo.vue
@@ -0,0 +1,83 @@
+
+
+
+
+
+
+ {{ item.name }}
+
+
+
+
+
+
+
+
+
diff --git a/src/__docs__/multi-drag/directive.vue b/src/__docs__/multi-drag/directive.vue
new file mode 100644
index 00000000..24c656f9
--- /dev/null
+++ b/src/__docs__/multi-drag/directive.vue
@@ -0,0 +1,66 @@
+
+
+
+
+
+
+
diff --git a/src/__docs__/multi-drag/function.vue b/src/__docs__/multi-drag/function.vue
new file mode 100644
index 00000000..15043e07
--- /dev/null
+++ b/src/__docs__/multi-drag/function.vue
@@ -0,0 +1,64 @@
+
+
+
+
+
+
+
+
+
diff --git a/src/__docs__/multi-drag/index.en-US.md b/src/__docs__/multi-drag/index.en-US.md
new file mode 100644
index 00000000..f57b2f79
--- /dev/null
+++ b/src/__docs__/multi-drag/index.en-US.md
@@ -0,0 +1,30 @@
+---
+map:
+ path: /demo/multi-drag
+---
+
+# Basic Usage
+
+Allow selecting multiple items within a sortable at once, and drag them as one item. Once placed, the items will unfold into their original order, but all beside each other at the new position.
+
+## Component Usage
+
+
+
+
+
+## Function Usage
+
+
+
+
+## Directive Usage
+
+
+
diff --git a/src/__docs__/multi-drag/index.zh-CN.md b/src/__docs__/multi-drag/index.zh-CN.md
new file mode 100644
index 00000000..43073b39
--- /dev/null
+++ b/src/__docs__/multi-drag/index.zh-CN.md
@@ -0,0 +1,30 @@
+---
+map:
+ path: /demo/multi-drag
+---
+
+# 基础使用
+
+允许一次选择可排序项中的多个选项,并将它们作为一个选项拖动。一旦放置,这些选项将按原始顺序展开,但在新的位置上会并排放置。
+
+## 组件使用
+
+
+
+
+
+## 函数使用
+
+
+
+
+## 指令使用
+
+
+
diff --git a/src/__docs__/swap/demo.vue b/src/__docs__/swap/demo.vue
new file mode 100644
index 00000000..4d272a5b
--- /dev/null
+++ b/src/__docs__/swap/demo.vue
@@ -0,0 +1,83 @@
+
+
+
+
+
+
+ {{ item.name }}
+
+
+
+
+
+
+
+
+
diff --git a/src/__docs__/swap/directive.vue b/src/__docs__/swap/directive.vue
new file mode 100644
index 00000000..93842a35
--- /dev/null
+++ b/src/__docs__/swap/directive.vue
@@ -0,0 +1,65 @@
+
+
+
+
+
+
+
diff --git a/src/__docs__/swap/function.vue b/src/__docs__/swap/function.vue
new file mode 100644
index 00000000..39f9fbdd
--- /dev/null
+++ b/src/__docs__/swap/function.vue
@@ -0,0 +1,63 @@
+
+
+
+
+
+
+
+
+
diff --git a/src/__docs__/swap/index.en-US.md b/src/__docs__/swap/index.en-US.md
new file mode 100644
index 00000000..66f25804
--- /dev/null
+++ b/src/__docs__/swap/index.en-US.md
@@ -0,0 +1,30 @@
+---
+map:
+ path: /demo/swap
+---
+
+# Basic Usage
+
+Change the behaviour of Sortable to allow for items to be swapped with eachother rather than sorted.
+
+## Component Usage
+
+
+
+
+
+## Function Usage
+
+
+
+
+## Directive Usage
+
+
+
diff --git a/src/__docs__/swap/index.zh-CN.md b/src/__docs__/swap/index.zh-CN.md
new file mode 100644
index 00000000..15dbba59
--- /dev/null
+++ b/src/__docs__/swap/index.zh-CN.md
@@ -0,0 +1,30 @@
+---
+map:
+ path: /demo/swap
+---
+
+# 基础使用
+
+更改 Sortable 的行为以允许相互交换而不是排序。
+
+## 组件使用
+
+
+
+
+
+## 函数使用
+
+
+
+
+## 指令使用
+
+
+
diff --git a/src/shims.d.ts b/src/shims.d.ts
new file mode 100644
index 00000000..84541def
--- /dev/null
+++ b/src/shims.d.ts
@@ -0,0 +1,4 @@
+declare module 'sortablejs/Sortable' {
+ import Sortable from 'sortablejs'
+ export default Sortable
+}
diff --git a/src/useDraggable.ts b/src/useDraggable.ts
index 012a7c94..dc242662 100644
--- a/src/useDraggable.ts
+++ b/src/useDraggable.ts
@@ -1,4 +1,5 @@
-import Sortable, { type Options, type SortableEvent } from 'sortablejs'
+import { type Options, type SortableEvent } from 'sortablejs'
+import Sortable from 'sortablejs/Sortable'
import {
getCurrentInstance,
isRef,
@@ -26,7 +27,8 @@ import {
mergeOptionsEvents,
moveArrayElement,
removeElement,
- removeNode
+ removeNode,
+ swapArrayElement
} from './utils'
function defaultClone(element: T): T {
@@ -145,7 +147,9 @@ export function useDraggable(...args: any[]): UseDraggableReturn {
const {
immediate = true,
clone = defaultClone,
- customUpdate
+ customUpdate,
+ swap,
+ multiDrag
} = unref(options) ?? {}
/**
@@ -205,7 +209,37 @@ export function useDraggable(...args: any[]): UseDraggableReturn {
customUpdate(evt)
return
}
- const { from, item, oldIndex, newIndex } = evt
+
+ const { from, item, oldIndex, newIndex, oldIndicies, newIndicies } = evt
+
+ if (multiDrag) {
+ const oldIndexList = oldIndicies.map(i => i.index)
+ const newIndexList = newIndicies.map(i => i.index)
+
+ const newList = [...unref(list)]
+
+ const selectedItems = oldIndexList.map(index => newList[index])
+
+ oldIndexList
+ .sort((a, b) => b - a)
+ .forEach(oIndex => {
+ newList.splice(oIndex, 1)
+ })
+
+ newIndexList.forEach((nIndex, i) => {
+ newList.splice(nIndex, 0, selectedItems[i])
+ })
+
+ list.value = newList
+ return
+ }
+
+ if (swap) {
+ const newList = [...unref(list)]
+ list.value = swapArrayElement(newList, oldIndex!, newIndex!)
+ return
+ }
+
removeNode(item)
insertNodeAt(from, item, oldIndex!)
if (isRef(list)) {
diff --git a/src/utils/index.ts b/src/utils/index.ts
index cf9af01a..1a560f89 100644
--- a/src/utils/index.ts
+++ b/src/utils/index.ts
@@ -14,6 +14,22 @@ export function moveArrayElement(array: T[], from: number, to: number): T[] {
return array
}
+/**
+ * Swaps two elements in an array.
+ * @param {T[]} array
+ * @param {number} index1
+ * @param {number} index2
+ * @returns {T[]}
+ */
+export function swapArrayElement(
+ array: T[],
+ index1: number,
+ index2: number
+): T[] {
+ ;[array[index1], array[index2]] = [array[index2], array[index1]]
+ return array
+}
+
/**
* Convert a hyphen-delimited string to camelCase.
* @param {string} str