gristlabs_grist-core/app/client/ui/mouseDrag.ts
Dmitry S 2f26f140c8 (core) Add our very own implementation of tokenfield (aka pillbox, tag list)
Summary:
- Supports auto-completion
- Supports various keyboard interactions to delete/select/copy-paste tokens
- Supports various mouse interactions to select and move tokens.
- Supports undo/redo while editing tokens.

Test Plan: stand-alone fixture and browser test verify the supported behaviors

Reviewers: paulfitz

Reviewed By: paulfitz

Differential Revision: https://phab.getgrist.com/D2789
2021-05-03 17:16:24 -04:00

48 lines
1.6 KiB
TypeScript

/**
* Small utility to help with processing mouse-drag events. Usage is:
* dom('div', mouseDrag((startEvent, elem) => ({
* onMove(moveEvent) { ... },
* onStop(stopEvent) { ... },
* })));
*
* The passed-in callback is called on 'mousedown' events. It may return null to ignore the event.
* Otherwise, it should return a handler for mousemove/mouseup: we will then subscribe to these
* events, and clean up on mouseup.
*/
import {dom, DomElementMethod, IDisposable} from "grainjs";
export interface MouseDragHandler {
onMove(moveEv: MouseEvent): void;
onStop(endEv: MouseEvent): void;
}
export type MouseDragStart = (startEv: MouseEvent, elem: HTMLElement) => MouseDragHandler|null;
export function mouseDragElem(elem: HTMLElement, onStart: MouseDragStart): IDisposable {
// This prevents the default text-drag behavior when elem is part of a text selection.
elem.style.userSelect = 'none';
return dom.onElem(elem, 'mousedown', (ev, el) => _startDragging(ev, el, onStart));
}
export function mouseDrag(onStart: MouseDragStart): DomElementMethod {
return (elem) => { mouseDragElem(elem, onStart); };
}
function _startDragging(startEv: MouseEvent, elem: HTMLElement, onStart: MouseDragStart) {
const dragHandler = onStart(startEv, elem);
if (dragHandler) {
const {onMove, onStop} = dragHandler;
const upLis = dom.onElem(document, 'mouseup', stop, {useCapture: true});
const moveLis = dom.onElem(document, 'mousemove', onMove, {useCapture: true});
function stop(stopEv: MouseEvent) {
moveLis.dispose();
upLis.dispose();
onStop(stopEv);
}
}
}