qtsd-fork
Version:
Do not use this please
174 lines (145 loc) • 4.57 kB
JavaScript
import invariant from 'invariant'
import isArray from 'lodash/isArray'
import isObject from 'lodash/isObject'
import matchesType from '../utils/matchesType'
export const BEGIN_DRAG = 'dnd-core/BEGIN_DRAG'
export const PUBLISH_DRAG_SOURCE = 'dnd-core/PUBLISH_DRAG_SOURCE'
export const HOVER = 'dnd-core/HOVER'
export const DROP = 'dnd-core/DROP'
export const END_DRAG = 'dnd-core/END_DRAG'
export function beginDrag(
sourceIds,
options = { publishSource: true, clientOffset: null },
) {
const { publishSource, clientOffset, getSourceClientOffset } = options
invariant(isArray(sourceIds), 'Expected sourceIds to be an array.')
const monitor = this.getMonitor()
const registry = this.getRegistry()
invariant(!monitor.isDragging(), 'Cannot call beginDrag while dragging.')
for (let i = 0; i < sourceIds.length; i++) {
invariant(
registry.getSource(sourceIds[i]),
'Expected sourceIds to be registered.',
)
}
let sourceId = null
for (let i = sourceIds.length - 1; i >= 0; i--) {
if (monitor.canDragSource(sourceIds[i])) {
sourceId = sourceIds[i]
break
}
}
if (sourceId === null) {
return
}
let sourceClientOffset = null
if (clientOffset) {
invariant(
typeof getSourceClientOffset === 'function',
'When clientOffset is provided, getSourceClientOffset must be a function.',
)
sourceClientOffset = getSourceClientOffset(sourceId)
}
const source = registry.getSource(sourceId)
const item = source.beginDrag(monitor, sourceId)
invariant(isObject(item), 'Item must be an object.')
registry.pinSource(sourceId)
const itemType = registry.getSourceType(sourceId)
return {
type: BEGIN_DRAG,
itemType,
item,
sourceId,
clientOffset,
sourceClientOffset,
isSourcePublic: publishSource,
}
}
export function publishDragSource() {
const monitor = this.getMonitor()
if (!monitor.isDragging()) {
return
}
return { type: PUBLISH_DRAG_SOURCE }
}
export function hover(targetIdsArg, { clientOffset = null } = {}) {
invariant(isArray(targetIdsArg), 'Expected targetIds to be an array.')
const targetIds = targetIdsArg.slice(0)
const monitor = this.getMonitor()
const registry = this.getRegistry()
invariant(monitor.isDragging(), 'Cannot call hover while not dragging.')
invariant(!monitor.didDrop(), 'Cannot call hover after drop.')
// First check invariants.
for (let i = 0; i < targetIds.length; i++) {
const targetId = targetIds[i]
invariant(
targetIds.lastIndexOf(targetId) === i,
'Expected targetIds to be unique in the passed array.',
)
const target = registry.getTarget(targetId)
invariant(target, 'Expected targetIds to be registered.')
}
const draggedItemType = monitor.getItemType()
// Remove those targetIds that don't match the targetType. This
// fixes shallow isOver which would only be non-shallow because of
// non-matching targets.
for (let i = targetIds.length - 1; i >= 0; i--) {
const targetId = targetIds[i]
const targetType = registry.getTargetType(targetId)
if (!matchesType(targetType, draggedItemType)) {
targetIds.splice(i, 1)
}
}
// Finally call hover on all matching targets.
for (let i = 0; i < targetIds.length; i++) {
const targetId = targetIds[i]
const target = registry.getTarget(targetId)
target.hover(monitor, targetId)
}
return {
type: HOVER,
targetIds,
clientOffset,
}
}
export function drop(options = {}) {
const monitor = this.getMonitor()
const registry = this.getRegistry()
invariant(monitor.isDragging(), 'Cannot call drop while not dragging.')
invariant(
!monitor.didDrop(),
'Cannot call drop twice during one drag operation.',
)
const targetIds = monitor
.getTargetIds()
.filter(monitor.canDropOnTarget, monitor)
targetIds.reverse()
targetIds.forEach((targetId, index) => {
const target = registry.getTarget(targetId)
let dropResult = target.drop(monitor, targetId)
invariant(
typeof dropResult === 'undefined' || isObject(dropResult),
'Drop result must either be an object or undefined.',
)
if (typeof dropResult === 'undefined') {
dropResult = index === 0 ? {} : monitor.getDropResult()
}
this.store.dispatch({
type: DROP,
dropResult: {
...options,
...dropResult,
},
})
})
}
export function endDrag() {
const monitor = this.getMonitor()
const registry = this.getRegistry()
invariant(monitor.isDragging(), 'Cannot call endDrag while not dragging.')
const sourceId = monitor.getSourceId()
const source = registry.getSource(sourceId, true)
source.endDrag(monitor, sourceId)
registry.unpinSource()
return { type: END_DRAG }
}