Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
export default function useMouseSensor(api: SensorAPI) {
const phaseRef = useRef(idle);
const unbindEventsRef = useRef<() => void>(noop);
const getPhase = useCallback(function getPhase(): Phase {
return phaseRef.current;
}, []);
const setPhase = useCallback(function setPhase(phase: Phase) {
phaseRef.current = phase;
}, []);
const startCaptureBinding: EventBinding = useMemo(
() => ({
eventName: 'touchstart',
fn: function onTouchStart(event: TouchEvent) {
// Event already used by something else
if (event.defaultPrevented) {
return;
}
// We need to NOT call event.preventDefault() so as to maintain as much standard
// browser interactions as possible.
// This includes navigation on anchors which we want to preserve
export default function useDragHandle(args: Args): ?DragHandleProps {
// Capturing
const capturingRef = useRef(null);
const onCaptureStart = useCallback((abort: () => void) => {
invariant(
!capturingRef.current,
'Cannot start capturing while something else is',
);
capturingRef.current = {
abort,
};
}, []);
const onCaptureEnd = useCallback(() => {
invariant(
capturingRef.current,
'Cannot stop capturing while nothing is capturing',
);
capturingRef.current = null;
}, []);
const abortCapture = useCallback(() => {
invariant(capturingRef.current, 'Cannot abort capture when there is none');
capturingRef.current.abort();
}, []);
const { canLift, style: styleContext }: AppContextValue = useRequiredContext(
AppContext,
);
const {
isDragging,
if (event.currentTarget !== getWindow()) {
return;
}
callbacks.onWindowScroll();
},
},
// Cancel on page visibility change
{
eventName: supportedPageVisibilityEventName,
fn: cancel,
},
];
}, [callbacks, cancel, getIsDragging, getWindow]);
const bindWindowEvents = useCallback(() => {
const win: HTMLElement = getWindow();
const options = { capture: true };
// setting up our unbind before we bind
unbindWindowEventsRef.current = () =>
unbindEvents(win, windowBindings, options);
bindEvents(win, windowBindings, options);
}, [getWindow, windowBindings]);
const startDragging = useCallback(() => {
invariant(!isDraggingRef.current, 'Cannot start a drag while dragging');
const ref: ?HTMLElement = getDraggableRef();
invariant(ref, 'Cannot start a keyboard drag without a draggable ref');
isDraggingRef.current = true;
tryAbandonLock(previous, current);
previous = current;
});
// unsubscribe from store when unmounting
return unsubscribe;
},
[lockAPI, store, tryAbandonLock],
);
// abort any lock on unmount
useLayoutEffect(() => {
return lockAPI.tryAbandon;
}, [lockAPI.tryAbandon]);
const canGetLock = useCallback(
(draggableId: DraggableId): boolean => {
return canStart({
lockAPI,
registry,
store,
draggableId,
});
},
[lockAPI, registry, store],
);
const tryGetLock: TryGetLock = useCallback(
(
draggableId: DraggableId,
forceStop?: () => void,
options?: TryGetLockOptions,
export default function useMouseSensor(api: SensorAPI) {
const phaseRef = useRef(idle);
const unbindEventsRef = useRef<() => void>(noop);
const getPhase = useCallback(function getPhase(): Phase {
return phaseRef.current;
}, []);
const setPhase = useCallback(function setPhase(phase: Phase) {
phaseRef.current = phase;
}, []);
const startCaptureBinding: EventBinding = useMemo(
() => ({
eventName: 'touchstart',
fn: function onTouchStart(event: TouchEvent) {
// Event already used by something else
if (event.defaultPrevented) {
return;
}
draggableId,
callbacks,
getDraggableRef,
getShouldRespectForcePress,
canDragInteractiveElements,
} = args;
const lastArgsRef = usePreviousRef(args);
useValidation({ isEnabled, getDraggableRef });
const getWindow = useCallback(
(): HTMLElement => getWindowFromEl(getDraggableRef()),
[getDraggableRef],
);
const canStartCapturing = useCallback(
(event: Event) => {
// Cannot lift when disabled
if (!isEnabled) {
return false;
}
// Something on this element might be capturing.
// A drag might not have started yet
// We want to prevent anything else from capturing
if (capturingRef.current) {
return false;
}
// Do not drag if anything else in the system is dragging
if (!canLift(draggableId)) {
return false;
}
return state.isDragging || state.phase === 'DROP_ANIMATING';
}, []);
const appCallbacks: AppCallbacks = useMemo(
() => ({
isDragging,
tryAbort: tryResetStore,
}),
[isDragging, tryResetStore],
);
// doing this in render rather than a side effect so any errors on the
// initial mount are caught
setCallbacks(appCallbacks);
const getCanLift = useCallback(
(id: DraggableId) => canStartDrag(getStore(lazyStoreRef).getState(), id),
[],
);
const getIsMovementAllowed = useCallback(
() => isMovementAllowed(getStore(lazyStoreRef).getState()),
[],
);
const appContext: AppContextValue = useMemo(
() => ({
marshal: dimensionMarshal,
focus: focusMarshal,
contextId,
canLift: getCanLift,
isMovementAllowed: getIsMovementAllowed,
}
// Do not drag if anything else in the system is dragging
if (!canLift(draggableId)) {
return false;
}
// Check if we are dragging an interactive element
return shouldAllowDraggingFromTarget(event, canDragInteractiveElements);
},
[canDragInteractiveElements, canLift, draggableId, isEnabled],
);
const { onBlur, onFocus } = useFocusRetainer(args);
const mouseArgs: MouseSensorArgs = useMemoOne(
() => ({
callbacks,
getDraggableRef,
getWindow,
canStartCapturing,
onCaptureStart,
onCaptureEnd,
getShouldRespectForcePress,
}),
[
callbacks,
getDraggableRef,
getWindow,
canStartCapturing,
onCaptureStart,
onCaptureEnd,
);
callbacks.onCancel();
}
}
// Handle aborting
// No longer dragging but still capturing: need to abort
// Using a layout effect to ensure that there is a flip from isDragging => !isDragging
// When there is a pending drag !isDragging will always be true
useIsomorphicLayoutEffect(() => {
if (!isDragging && capturingRef.current) {
abortCapture();
}
}, [abortCapture, isDragging]);
const props: ?DragHandleProps = useMemoOne(() => {
if (!isEnabled) {
return null;
}
return {
onMouseDown,
onKeyDown,
onTouchStart,
onFocus,
onBlur,
tabIndex: 0,
'data-react-beautiful-dnd-drag-handle': styleContext,
// English default. Consumers are welcome to add their own start instruction
'aria-roledescription': 'Draggable item. Press space bar to lift',
// Opting out of html5 drag and drops
draggable: false,
onDragStart: preventHtml5Dnd,
schedule.cancel();
unbindWindowEventsRef.current();
isDraggingRef.current = false;
onCaptureEnd();
}, [getIsDragging, onCaptureEnd, schedule]);
const cancel = useCallback(() => {
const wasDragging: boolean = isDraggingRef.current;
stop();
if (wasDragging) {
callbacks.onCancel();
}
}, [callbacks, stop]);
const windowBindings: EventBinding[] = useMemo(() => {
invariant(
!getIsDragging(),
'Should not recreate window bindings when dragging',
);
return [
// any mouse actions kills a drag
{
eventName: 'mousedown',
fn: cancel,
},
{
eventName: 'mouseup',
fn: cancel,
},
{
eventName: 'click',