diff --git a/package-lock.json b/package-lock.json index 956d97f1..dc2848d5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8097,6 +8097,12 @@ "semver-compare": "^1.0.0" } }, + "pointer-tracker": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pointer-tracker/-/pointer-tracker-2.0.3.tgz", + "integrity": "sha512-PURBF4oc45JPECuguX6oPL3pJU5AlF0Nb/4sZdmqzPNAkV4LGL9MJMqb0smWDtmQ0F0KpbxEJn4/Lf5ugN1keQ==", + "dev": true + }, "portfinder": { "version": "1.0.17", "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.17.tgz", diff --git a/package.json b/package.json index c37e8702..09af2400 100644 --- a/package.json +++ b/package.json @@ -30,18 +30,25 @@ "babel-plugin-transform-react-remove-prop-types": "^0.4.19", "babel-preset-env": "^1.7.0", "babel-register": "^6.26.0", + "classnames": "^2.2.6", "clean-webpack-plugin": "^0.1.19", + "comlink": "^3.0.3", "copy-webpack-plugin": "^4.5.3", "css-loader": "^0.28.11", "exports-loader": "^0.7.0", + "file-drop-element": "0.0.7", "file-loader": "^1.1.11", "html-webpack-plugin": "^3.2.0", "husky": "^1.1.2", "if-env": "^1.0.4", + "linkstate": "^1.1.1", "loader-utils": "^1.1.0", "mini-css-extract-plugin": "^0.3.0", "node-sass": "^4.9.4", "optimize-css-assets-webpack-plugin": "^4.0.3", + "pointer-tracker": "^2.0.3", + "preact": "^8.3.1", + "pretty-bytes": "^5.1.0", "progress-bar-webpack-plugin": "^1.11.0", "raw-loader": "^0.5.1", "sass-loader": "^7.1.0", @@ -60,12 +67,6 @@ "webpack-cli": "^2.1.5", "webpack-dev-server": "^3.1.5", "webpack-plugin-replace": "^1.1.1", - "classnames": "^2.2.6", - "comlink": "^3.0.3", - "linkstate": "^1.1.1", - "preact": "^8.3.1", - "pretty-bytes": "^5.1.0", - "worker-plugin": "^1.1.1", - "file-drop-element": "0.0.7" + "worker-plugin": "^1.1.1" } } diff --git a/src/components/Output/custom-els/PinchZoom/index.ts b/src/components/Output/custom-els/PinchZoom/index.ts index 101407b0..1e50fe13 100644 --- a/src/components/Output/custom-els/PinchZoom/index.ts +++ b/src/components/Output/custom-els/PinchZoom/index.ts @@ -1,5 +1,5 @@ +import PointerTracker, { Pointer } from 'pointer-tracker'; import './styles.css'; -import { PointerTracker, Pointer } from '../../../../lib/PointerTracker'; interface Point { clientX: number; diff --git a/src/components/Output/custom-els/TwoUp/index.ts b/src/components/Output/custom-els/TwoUp/index.ts index d3cd7d3e..0d771eaa 100644 --- a/src/components/Output/custom-els/TwoUp/index.ts +++ b/src/components/Output/custom-els/TwoUp/index.ts @@ -1,5 +1,5 @@ +import PointerTracker, { Pointer } from 'pointer-tracker'; import * as styles from './styles.css'; -import { PointerTracker, Pointer } from '../../../../lib/PointerTracker'; const legacyClipCompatAttr = 'legacy-clip-compat'; const orientationAttr = 'orientation'; diff --git a/src/custom-els/RangeInput/index.ts b/src/custom-els/RangeInput/index.ts index 0fb985f7..838a24c5 100644 --- a/src/custom-els/RangeInput/index.ts +++ b/src/custom-els/RangeInput/index.ts @@ -1,6 +1,6 @@ +import PointerTracker from 'pointer-tracker'; import { bind } from '../../lib/initial-util'; import * as style from './styles.css'; -import { PointerTracker } from '../../lib/PointerTracker'; const RETARGETED_EVENTS = ['focus', 'blur']; const UPDATE_EVENTS = ['input', 'change']; diff --git a/src/lib/PointerTracker/index.ts b/src/lib/PointerTracker/index.ts deleted file mode 100644 index 10974669..00000000 --- a/src/lib/PointerTracker/index.ts +++ /dev/null @@ -1,255 +0,0 @@ -import { bind } from '../../lib/initial-util'; -const enum Button { Left } - -export class Pointer { - /** x offset from the top of the document */ - pageX: number; - /** y offset from the top of the document */ - pageY: number; - /** x offset from the top of the viewport */ - clientX: number; - /** y offset from the top of the viewport */ - clientY: number; - /** ID for this pointer */ - id: number = -1; - /** The platform object used to create this Pointer */ - nativePointer: Touch | PointerEvent | MouseEvent; - - constructor (nativePointer: Touch | PointerEvent | MouseEvent) { - this.nativePointer = nativePointer; - this.pageX = nativePointer.pageX; - this.pageY = nativePointer.pageY; - this.clientX = nativePointer.clientX; - this.clientY = nativePointer.clientY; - - if (self.Touch && nativePointer instanceof Touch) { - this.id = nativePointer.identifier; - } else if (isPointerEvent(nativePointer)) { // is PointerEvent - this.id = nativePointer.pointerId; - } - } - - /** - * Returns an expanded set of Pointers for high-resolution inputs. - */ - getCoalesced(): Pointer[] { - if ('getCoalescedEvents' in this.nativePointer) { - return this.nativePointer.getCoalescedEvents().map(p => new Pointer(p)); - } - return [this]; - } -} - -const isPointerEvent = (event: any): event is PointerEvent => - self.PointerEvent && event instanceof PointerEvent; - -const noop = () => {}; - -export type InputEvent = TouchEvent | PointerEvent | MouseEvent; -type StartCallback = (pointer: Pointer, event: InputEvent) => boolean; -type MoveCallback = ( - previousPointers: Pointer[], - changedPointers: Pointer[], - event: InputEvent, -) => void; -type EndCallback = (pointer: Pointer, event: InputEvent) => void; - -interface PointerTrackerCallbacks { - /** - * Called when a pointer is pressed/touched within the element. - * - * @param pointer The new pointer. - * This pointer isn't included in this.currentPointers or this.startPointers yet. - * @param event The event related to this pointer. - * - * @returns Whether you want to track this pointer as it moves. - */ - start?: StartCallback; - /** - * Called when pointers have moved. - * - * @param previousPointers The state of the pointers before this event. - * This contains the same number of pointers, in the same order, as - * this.currentPointers and this.startPointers. - * @param changedPointers The pointers that have changed since the last move callback. - * @param event The event related to the pointer changes. - */ - move?: MoveCallback; - /** - * Called when a pointer is released. - * - * @param pointer The final state of the pointer that ended. This - * pointer is now absent from this.currentPointers and - * this.startPointers. - * @param event The event related to this pointer. - */ - end?: EndCallback; -} - -/** - * Track pointers across a particular element - */ -export class PointerTracker { - /** - * State of the tracked pointers when they were pressed/touched. - */ - readonly startPointers: Pointer[] = []; - /** - * Latest state of the tracked pointers. Contains the same number - * of pointers, and in the same order as this.startPointers. - */ - readonly currentPointers: Pointer[] = []; - - private _startCallback: StartCallback; - private _moveCallback: MoveCallback; - private _endCallback: EndCallback; - - /** - * Track pointers across a particular element - * - * @param element Element to monitor. - * @param callbacks - */ - constructor (private _element: HTMLElement, callbacks: PointerTrackerCallbacks) { - const { - start = () => true, - move = noop, - end = noop, - } = callbacks; - - this._startCallback = start; - this._moveCallback = move; - this._endCallback = end; - - // Add listeners - if (self.PointerEvent) { - this._element.addEventListener('pointerdown', this._pointerStart); - } else { - this._element.addEventListener('mousedown', this._pointerStart); - this._element.addEventListener('touchstart', this._touchStart); - this._element.addEventListener('touchmove', this._move); - this._element.addEventListener('touchend', this._touchEnd); - } - } - - /** - * Call the start callback for this pointer, and track it if the user wants. - * - * @param pointer Pointer - * @param event Related event - * @returns Whether the pointer is being tracked. - */ - private _triggerPointerStart (pointer: Pointer, event: InputEvent): boolean { - if (!this._startCallback(pointer, event)) return false; - this.currentPointers.push(pointer); - this.startPointers.push(pointer); - return true; - } - - /** - * Listener for mouse/pointer starts. Bound to the class in the constructor. - * - * @param event This will only be a MouseEvent if the browser doesn't support - * pointer events. - */ - @bind - private _pointerStart (event: PointerEvent | MouseEvent) { - if (event.button !== Button.Left) return; - if (!this._triggerPointerStart(new Pointer(event), event)) return; - - // Add listeners for additional events. - // The listeners may already exist, but no harm in adding them again. - if (isPointerEvent(event)) { - this._element.setPointerCapture(event.pointerId); - this._element.addEventListener('pointermove', this._move); - this._element.addEventListener('pointerup', this._pointerEnd); - } else { // MouseEvent - window.addEventListener('mousemove', this._move); - window.addEventListener('mouseup', this._pointerEnd); - } - } - - /** - * Listener for touchstart. Bound to the class in the constructor. - * Only used if the browser doesn't support pointer events. - */ - @bind - private _touchStart (event: TouchEvent) { - for (const touch of Array.from(event.changedTouches)) { - this._triggerPointerStart(new Pointer(touch), event); - } - } - - /** - * Listener for pointer/mouse/touch move events. - * Bound to the class in the constructor. - */ - @bind - private _move (event: PointerEvent | MouseEvent | TouchEvent) { - const previousPointers = this.currentPointers.slice(); - const changedPointers = ('changedTouches' in event) ? // Shortcut for 'is touch event'. - Array.from(event.changedTouches).map(t => new Pointer(t)) : - [new Pointer(event)]; - const trackedChangedPointers = []; - - for (const pointer of changedPointers) { - const index = this.currentPointers.findIndex(p => p.id === pointer.id); - if (index === -1) continue; // Not a pointer we're tracking - trackedChangedPointers.push(pointer); - this.currentPointers[index] = pointer; - } - - if (trackedChangedPointers.length === 0) return; - - this._moveCallback(previousPointers, trackedChangedPointers, event); - } - - /** - * Call the end callback for this pointer. - * - * @param pointer Pointer - * @param event Related event - */ - @bind - private _triggerPointerEnd (pointer: Pointer, event: InputEvent): boolean { - const index = this.currentPointers.findIndex(p => p.id === pointer.id); - // Not a pointer we're interested in? - if (index === -1) return false; - - this.currentPointers.splice(index, 1); - this.startPointers.splice(index, 1); - - this._endCallback(pointer, event); - return true; - } - - /** - * Listener for mouse/pointer ends. Bound to the class in the constructor. - * @param event This will only be a MouseEvent if the browser doesn't support - * pointer events. - */ - @bind - private _pointerEnd (event: PointerEvent | MouseEvent) { - if (!this._triggerPointerEnd(new Pointer(event), event)) return; - - if (isPointerEvent(event)) { - if (this.currentPointers.length) return; - this._element.removeEventListener('pointermove', this._move); - this._element.removeEventListener('pointerup', this._pointerEnd); - } else { // MouseEvent - window.removeEventListener('mousemove', this._move); - window.removeEventListener('mouseup', this._pointerEnd); - } - } - - /** - * Listener for touchend. Bound to the class in the constructor. - * Only used if the browser doesn't support pointer events. - */ - @bind - private _touchEnd (event: TouchEvent) { - for (const touch of Array.from(event.changedTouches)) { - this._triggerPointerEnd(new Pointer(touch), event); - } - } -} diff --git a/src/lib/PointerTracker/missing-types.d.ts b/src/lib/PointerTracker/missing-types.d.ts deleted file mode 100644 index f724d114..00000000 --- a/src/lib/PointerTracker/missing-types.d.ts +++ /dev/null @@ -1,10 +0,0 @@ -// TypeScript, you make me sad. -// https://github.com/Microsoft/TypeScript/issues/18756 -interface Window { - PointerEvent: typeof PointerEvent; - Touch: typeof Touch; -} - -interface PointerEvent { - getCoalescedEvents(): PointerEvent[]; -}