import { pan } from './pan' import { findTargetAndParseOptions } from './utils' export interface PanOnDragOptions { readonly button: 'left' | 'right' readonly modifier?: 'Alt' | 'Control' | 'Meta' | 'Shift' } export const panOnDrag = (container: HTMLElement | null, attributeName: string, defaultOptions: PanOnDragOptions) => { if (container === null) { container = document.documentElement; } container.addEventListener('mousedown', event => { if (event.button !== 0 && event.button !== 2) { return } const [target, options] = findTargetAndParseOptions(event.target as Element, attributeName) if (!target || !options || !isPanButtonPressed(event, options, defaultOptions)) { return } event.preventDefault() let previousClientX = event.clientX let previousClientY = event.clientY const onMouseMove = (event: MouseEvent) => { pan( target, previousClientX - event.clientX, previousClientY - event.clientY, ) previousClientX = event.clientX previousClientY = event.clientY event.preventDefault() } const preventDefault = (event: Event) => event.preventDefault() const onMouseUp = () => { container?.removeEventListener('mouseup', onMouseUp) container?.removeEventListener('mousemove', onMouseMove) setTimeout(() => container?.removeEventListener('contextmenu', preventDefault)) } container?.addEventListener('mouseup', onMouseUp) container?.addEventListener('mousemove', onMouseMove) container?.addEventListener('contextmenu', preventDefault) }) } const isPanButtonPressed = (event: MouseEvent, options: Partial, defaultOptions: PanOnDragOptions) => (!options.modifier || event.getModifierState(options.modifier)) && event.button === ((options.button || defaultOptions.button) === 'right' ? 2 : 0)