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 @@ + + + + + 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 @@ + + + + + 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