Auto Scroll
Adds horizontal and vertical auto-scrolling for the closest scrollable container element.
Demo
ts
export interface AutoScrollMiddlewareOptions {
/**
* Interval (in milliseconds)
*
* Defaults to: 8
*/
interval: number
/**
* Steps (in pixels)
*
* Defaults to: 4
*/
steps: number
/**
* Distance to the outer bounds of the scrollable container that triggers
* auto-scrolling.
*
* Defaults to: 100
*/
threshold: number
}vue
<script lang="ts" setup>
import createDragDropObservable, {
addClasses,
autoScroll,
dragImage,
indicator,
reorderItems,
} from 'dndrxjs'
import { onMounted, onUnmounted, ref } from 'vue'
import COLORS from './data/MOCK_DATA_COLORS.json'
const items = ref(COLORS.map(hex => ({ id: hex })))
const container = ref(null)
onMounted(() => {
const subscription = createDragDropObservable({
container: container.value!,
vertical: false,
dropPositionFn: ({ dragElement, dropElement }) => 'around',
})
.pipe(
addClasses(),
indicator({ offset: 6 }),
dragImage({ minElements: 1 }),
autoScroll({ threshold: 120 }),
)
.subscribe(({ type, dragElements, dropElement, position }) => {
if (!!dropElement && type === 'DragEnd') {
const index = Number.parseInt(dropElement?.getAttribute('data-index') || '0')
const selectedItems = dragElements.map(
e =>
items.value.find(item => item.id === e.getAttribute('data-id'))!,
)
if (position === 'after') {
items.value = reorderItems(items.value, selectedItems, index + 1)
}
else if (position === 'before') {
items.value = reorderItems(items.value, selectedItems, index)
}
}
})
onUnmounted(() => subscription.unsubscribe())
})
</script>
<template>
<div
ref="container"
class="demo"
style="
overflow: scroll;
max-height: 420px;
padding: 12px;
position: relative;
"
>
<div
style="
display: flex;
flex-wrap: wrap;
gap: 12px;
width: calc((180px + 12px) * 10 - 12px);
"
>
<div
v-for="(item, index) in items"
:key="item.id"
draggable="false"
:data-index="index"
:data-id="item.id"
>
<div
style="
width: 180px;
height: 180px;
padding: 5px;
font-size: 13px;
border-radius: 4px;
display: flex;
text-align: center;
align-items: center;
justify-content: center;
font-weight: bold;
color: #fff;
"
:style="{ background: item.id }"
>
<span>{{ item.id }}</span>
</div>
</div>
</div>
</div>
</template>