Документация/API
Сенсоры
Что превращает ввод в драги — встроенные сенсоры указателя и клавиатуры и API для собственных.
Страница переведена ИИ и может содержать неточности. Читать английский оригинал
import { defineSensor, useSensor, pointerSensor, keyboardSensor } from '@vue-dnd-kit/core';
SensorМышь, касание и перо через Pointer Events. По умолчанию есть в sensors.
SensorSpace/Enter, стрелки и Escape (переназначаются опцией keyboard провайдера). По умолчанию есть в sensors; он также отменяет по Escape драги указателем и собственные драги, даже при keyboard: false.
(sensor: Sensor) => SensorОпределяет сенсор (см. Sensor): только помогает с типами и возвращает свой аргумент.
(sensor: Sensor) => voidЗапускает сенсор в провайдере выше, пока живёт вызвавший компонент (или effect scope), рядом с sensors провайдера. Его драг отменяется при размонтировании.
Сенсор лишь говорит «тащи этот элемент отсюда», затем — куда он сдвинулся и что его бросили или отменили; остальное проверяет провайдер (что можно перетаскивать, активацию, один драг за раз). См. сенсоры и программное перетаскивание.
Ниже небольшой собственный сенсор (запущенный через useSensor) перетаскивает фигуры доски с
миникарты, рядом с собственными сенсорами провайдера.
Загружаем демо…
<script setup lang="ts">
import { DnDProvider } from '@vue-dnd-kit/core';
import SensorDesk from './SensorDesk.vue';
</script>
<template>
<DnDProvider>
<SensorDesk />
</DnDProvider>
</template>Sensor
Ввод, который начинает драги: указатель, клавиатура или ваш собственный (геймпад, экранный джойстик, голос, драги из скрипта). setup выполняется один раз на провайдер, только в браузере, внутри effect scope, который заканчивается вместе с провайдером (или когда сенсор уходит из sensors, или когда размонтируется компонент, вызвавший useSensor). Регистрируйте слушатели через useEventListener или верните функцию очистки; драг, который в этот момент ещё идёт, отменяется.
Чтобы обернуть сенсор, вызовите его setup со своим контекстом. Object.create(context, { activate: { value: … } }) сохраняет живые геттеры (status, drag, props), а spread заморозил бы их.
Что сенсор получает от провайдера, в котором работает.
Readonly<DnDProviderProps>Пропсы провайдера (например, activation, keyboard). Читайте их, когда они нужны: они могут меняться.
DnDStatusСтатус драга провайдера, какой бы сенсор им ни управлял.
SensorDrag | nullДраг провайдера — ожидающий или идущий, какой бы сенсор его ни начал; null, если драга нет. Сенсоры могут управлять драгами друг друга: сенсор клавиатуры двигает и бросает любой драг с клавиатуры, например начатый кнопкой «Move» (@vue-dnd-kit/actions).
(activation: SensorActivation) => SensorDrag | nullЗапрашивает драг элемента. Провайдер проверяет, что он свободен (один драг за раз и ни одного, пока приземляется бросок), что цель — его собственный перетаскиваемый элемент и он не отключён, куда пришёлся ввод (см. target) и canDrag перетаскиваемого элемента. Затем ждёт ограничение активации и начинает драг. Возвращает драг (ожидающий или уже идущий, если ждать нечего) или null, если драг начать нельзя.
() => voidОтменяет драг провайдера или ожидающую активацию, какой бы сенсор ими ни управлял (Escape, скрытая вкладка).
Активация
Что сенсор запрашивает, когда его ввод хочет начать драг (SensorContext.activate()).
Element | KeyКуда пришёлся ввод: элемент внутри перетаскиваемого элемента или id перетаскиваемого элемента. Элемент должен принадлежать этому провайдеру. Для драгов 'pointer' он должен быть на ручке, если она есть, и не на интерактивном потомке (кнопке, поле ввода); для драгов 'keyboard' он должен быть целью фокуса перетаскиваемого элемента (ручкой, а без неё — самим элементом) и не редактируемым полем. С id эти проверки пропускаются: драг начинается с элемента, где бы ни был ввод.
SensorTypeКак движется драг. 'pointer' (по умолчанию): он следует за точками, переданными в move(), цели ищутся в этих точках, контейнеры автоматически прокручиваются у краёв, а страница показывает курсор захвата. 'keyboard': он перемещается по элементам через step() и place(), как стрелки; цели прокручиваются в видимую область вместо автоскролла, а по окончании фокус возвращается на элемент. Какой из двух — показывает Active.sensor.
CoordinatesГде начинается драг, в координатах вьюпорта. По умолчанию — центр перетаскиваемого элемента.
PointerEvent | KeyboardEventСобытие ввода. Оно передаётся в canDrag перетаскиваемого элемента; без события (геймпад, программный драг) canDrag не вызывается. pointerType, равный 'touch', делает драг драгом касанием (haptics).
PointerKind | ActivationConstraintЧего драг ждёт перед стартом (до этого useDnD().status равен 'activating', с прогрессом). Для типа указателя берётся опция activation перетаскиваемого элемента, затем провайдера, затем значения по умолчанию (мышь — 4px, на ручке — сразу; перо — 4px; касание — долгое нажатие 200 мс с допуском 5px). Ограничение используется как есть. По умолчанию — ничего, драг начинается сразу.
(drag: SensorDrag) => voidДраг начался после активации: например, захватите указатель.
(drag: SensorDrag) => voidДраг закончен: его активация прервана, или он завершился броском, или его отменили (кто угодно).
(drag: SensorDrag) => voidБросок, который запросил сенсор, не состоялся, и драг продолжается (onBeforeDrop ответил 'continue'): move, drop и cancel снова работают. Сенсор указателя даёт элементу следовать за указателем до следующего отпускания.
Для каждого типа указателя. По умолчанию: мышь — { distance: 4 } (на ручке — сразу), перо — { distance: 4 }, касание — { delay: 200, tolerance: 5 }.
type ActivationOptions = Partial< Record<PointerKind, ActivationConstraint> >Что должно произойти с нажатием, прежде чем оно станет драгом: указатель проходит distance или удерживается delay — что наступит раньше. Ничего не задано: драг начинается сразу.
Драг
Один драг сенсора — от activate() до конца. Любой вызов, который уже неуместен, игнорируется: перемещения до старта или после конца, повторный drop().
KeyId перетаскиваемого элемента.
SensorTypeКак движется драг — как запросил activate() (SensorActivation.type).
SensorDragStateНа каком этапе драг: ждёт активации, идёт или закончился.
booleanДраг начался, даже если с тех пор уже закончился (сенсор указателя поглощает клик, который следует за ним).
(point: Coordinates) => voidВвод сдвинулся. Пока драг ожидает активации, проверяется ограничение активации (выход за допуск прерывает её); во время драга драг перемещается туда. Драги указателем берут одну позицию за кадр; драги с клавиатуры перемещаются сразу, после предшествующих шагов.
(direction: SensorDirection, options?: SensorStepOptions) => Promise<void>Драги с клавиатуры: один шаг стрелкой, как у стрелок сенсора клавиатуры (следующий элемент списка, следующая принимающая цель в режиме 'droppables' или keyboard.step пикселей). Шаги встают в очередь: каждый выполняется, когда отрендерился предыдущий, а повтор клавиши (event.repeat) пропускается, пока предыдущий шаг ещё выполняется. Драги указателем это игнорируют.
(position: SortablePosition) => Promise<boolean>Ставит элемент на позицию в сортируемом списке, как это делают перемещения с клавиатуры (другие списки берут его, только если принимают), и переносит драг на новое место. Разрешается в false, если ни один список его туда не берёт. В драгах с клавиатуры встаёт в очередь, как step().
() => Promise<boolean>Бросает; ожидающая активация вместо этого прерывается. Разрешается, когда драг закончился и приземлился: true, если бросок прошёл, false, если его отклонили (цель, onBeforeDrop) или бросать было нечего.
() => voidОтменяет драг (элемент улетает обратно) или прерывает ожидающую активацию.
'pending': ожидание ограничения активации;'dragging': от старта до решения о броске или отмены драга;'ended': активация прервана, или драг завершился броском, или отменён — сенсором или чем-то другим (Escape, скрытая вкладка,useDnD().cancel(), размонтирование провайдера).
type SensorDragState = 'pending' | 'dragging' | 'ended'Опции SensorDrag.step().
Стрелка шага с клавиатуры.
type SensorDirection = 'up' | 'down' | 'left' | 'right'Позиция в сортируемом списке для SensorDrag.place() (и moveItem из @vue-dnd-kit/actions). Только для списков: деревья размещают элементы по своим ключам.