Skip to content

Instantly share code, notes, and snippets.

@andyjessop
Created October 25, 2022 15:10
Show Gist options
  • Save andyjessop/facdb6de647b35adce31e9ffd8156fdc to your computer and use it in GitHub Desktop.
Save andyjessop/facdb6de647b35adce31e9ffd8156fdc to your computer and use it in GitHub Desktop.
Draggable directive
import { Directive, directive } from 'lit/directive.js';
import type { ElementPart, PartInfo } from 'lit/directive.js';
import { noChange } from 'lit';
export class Draggable extends Directive {
registered = false;
render({
id,
onDrag,
onDragMove,
onDrop,
}: {
id: string;
onDrag: (id: string, event: Event) => void;
onDragMove: (event: Event) => void;
onDrop: (id: string, event: Event) => void;
}) {
return noChange;
}
update(part: ElementPart, [{ id, onDrag, onDragMove, onDrop }]: Parameters<Draggable['render']>) {
if (this.registered) {
return;
}
this.registered = true;
const { element } = part;
element.addEventListener('pointerdown', (event) => {
const target = element;
const x = (event as PointerEvent).pageX;
const y = (event as PointerEvent).pageY;
const rect = target.getBoundingClientRect();
let shiftX = x - rect.left;
let shiftY = y - rect.top;
const clone = target.cloneNode(true) as HTMLElement;
clone.style.width = `${rect.width}px`;
clone.style.height = `${rect.height}px`;
clone.style.position = 'absolute';
clone.style.zIndex = '1000';
clone.style.transition = 'none';
clone.ondragstart = function () {
return false;
};
document.body.append(clone);
snapTo(x, y);
document.addEventListener('pointermove', onMouseMove);
document.addEventListener('pointerup', () => {
document.removeEventListener('pointermove', onMouseMove);
clone.remove();
onDrop(id, event);
});
onDrag(id, event);
function snapTo(pageX: number, pageY: number) {
clone.style.left = pageX - shiftX + 'px';
clone.style.top = pageY - shiftY + 'px';
}
function onMouseMove(event: Event) {
const currentX = (event as PointerEvent).pageX;
const currentY = (event as PointerEvent).pageY;
snapTo(currentX, currentY);
onDragMove(event);
}
});
return noChange;
}
}
export const draggable = directive(Draggable);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment