import { useState } from 'react';
import type { MoveEventHandler } from '../../src';
import { useMove } from '../../src';
import { toContentPoint } from '../utils';
import { DragContainer, DragItem } from './DragElements';
const getStateStyle = ({
colorInvert,
dragging,
}: {
colorInvert?: boolean;
dragging?: boolean;
}): React.CSSProperties => ({
...(dragging ? { borderColor: 'red' } : {}),
...(colorInvert ? { backgroundColor: 'black', color: 'white' } : {}),
});
function SimpleDrag(): React.ReactElement {
const [coord, setCoord] = useState({ x: 0, y: 0 });
const [dragging, setDragging] = useState(false);
const [colorInvert, setColorInvert] = useState(false);
const { moveProps } = useMove({
clickTolerance: 10,
onMove(_evt, { movementX, movementY }) {
setCoord(({ x, y }) => ({ x: x + movementX, y: y + movementY }));
},
onMoveEnd(_evt, { movementX, movementY }) {
setCoord(({ x, y }) => ({ x: x + movementX, y: y + movementY }));
setDragging(false);
},
onMoveStart() {
setDragging(true);
},
onPureClick() {
setColorInvert((invert) => !invert);
},
});
const [dragCoord, setDragCoord] = useState({ x: 100, y: 0 });
const [dragDragging, setDragDragging] = useState(false);
const { moveProps: dragMoveProps } = useMove({
onMove(_evt, { movementX, movementY }) {
setDragCoord(({ x, y }) => ({ x: x + movementX, y: y + movementY }));
},
onMoveEnd(_evt, { movementX, movementY }) {
setDragCoord(({ x, y }) => ({ x: x + movementX, y: y + movementY }));
setDragDragging(false);
},
onMoveStart() {
setDragDragging(true);
},
});
const [clickColorInvert, setClickColorInvert] = useState(false);
const { moveProps: clickMoveProps } = useMove({
clickTolerance: 10,
onPureClick() {
setClickColorInvert((invert) => !invert);
},
});
return (
drag click
drag only
click only
);
}
function NestingDrag(): React.ReactElement {
const [parentCoord, setParentCoord] = useState({ x: 50, y: 50 });
const [parentColorInvert, setParentColorInvert] = useState(false);
const { moveProps: parentMoveProps } = useMove({
clickTolerance: 10,
onMove(_evt, { movementX, movementY }) {
setParentCoord(({ x, y }) => ({ x: x + movementX, y: y + movementY }));
},
onMoveEnd(_evt, { movementX, movementY }) {
setParentCoord(({ x, y }) => ({ x: x + movementX, y: y + movementY }));
},
onMoveStart(evt) {
evt.stopPropagation();
},
onPureClick(evt) {
evt.stopPropagation();
setParentColorInvert((invert) => !invert);
},
});
const [coord, setCoord] = useState({ x: 0, y: 0 });
const [dragging, setDragging] = useState(false);
const [colorInvert, setColorInvert] = useState(false);
const { moveProps } = useMove({
clickTolerance: 10,
moveStop(evt) {
return evt.ctrlKey || evt.metaKey;
},
onMove(_evt, { movementX, movementY }) {
setCoord(({ x, y }) => ({ x: x + movementX, y: y + movementY }));
},
onMoveEnd(_evt, { movementX, movementY }) {
setCoord(({ x, y }) => ({ x: x + movementX, y: y + movementY }));
setDragging(false);
},
onMoveStart(evt) {
evt.stopPropagation();
setDragging(true);
},
onPureClick(evt) {
evt.stopPropagation();
setColorInvert((invert) => !invert);
},
});
const [dragCoord, setDragCoord] = useState({ x: 100, y: 0 });
const [dragDragging, setDragDragging] = useState(false);
const { moveProps: dragMoveProps } = useMove({
onMove(_evt, { movementX, movementY }) {
setDragCoord(({ x, y }) => ({ x: x + movementX, y: y + movementY }));
},
onMoveEnd(_evt, { movementX, movementY }) {
setDragCoord(({ x, y }) => ({ x: x + movementX, y: y + movementY }));
setDragDragging(false);
},
onMoveStart(evt) {
evt.stopPropagation();
setDragDragging(true);
},
});
const [otherCoord, setOtherCoord] = useState({ x: 0, y: 100 });
const [otherDraggingCoord, setOtherDraggingCoord] = useState(otherCoord);
const [otherDragging, setOtherDragging] = useState(false);
const { moveProps: otherDraggingMoveProps } = useMove({
onMove(_evt, { movementX, movementY }) {
setOtherDraggingCoord(({ x, y }) => ({ x: x + movementX, y: y + movementY }));
},
onMoveEnd(_evt, { movementX, movementY }) {
setOtherDraggingCoord(({ x, y }) => {
const nextCoord = { x: x + movementX, y: y + movementY };
setOtherCoord(nextCoord);
return nextCoord;
});
setOtherDragging(false);
},
onMoveStart(evt) {
evt.stopPropagation();
setOtherDragging(true);
},
});
const [clickColorInvert, setClickColorInvert] = useState(false);
const { moveProps: clickMoveProps } = useMove({
clickTolerance: 10,
onPureClick(evt) {
evt.stopPropagation();
setClickColorInvert((invert) => !invert);
},
});
const { moveProps: voidMoveProps } = useMove({});
return (
<>
drag click
drag only
other drag
click only
void
>
);
}
function SVGDrag(): React.ReactElement {
const [coord, setCoord] = useState({ x: 0, y: 0 });
const [dragging, setDragging] = useState(false);
const onMove: MoveEventHandler = (evt, moveData) => {
const elem = evt.currentTarget as SVGGraphicsElement;
const contentPoint = toContentPoint({ x: moveData.clientX, y: moveData.clientY }, elem);
const lastContentPoint = toContentPoint(
{ x: moveData.lastClientX, y: moveData.lastClientY },
elem,
);
const movementX = contentPoint.x - lastContentPoint.x;
const movementY = contentPoint.y - lastContentPoint.y;
setCoord(({ x, y }) => ({ x: x + movementX, y: y + movementY }));
if (evt.type !== 'pointermove') setDragging(false);
};
const { moveProps } = useMove({
onMove,
onMoveEnd: onMove,
onMoveStart(evt) {
evt.stopPropagation();
setDragging(true);
},
});
return (
);
}
export function UseMoveExamples(): React.ReactElement {
return (
Simple drag
Nesting drag
SVG drag
);
}