SafetyScreen-ui/node_modules/@interactjs/core/Interaction.js

521 lines
14 KiB
JavaScript

import * as arr from "../utils/arr.js";
import extend from "../utils/extend.js";
import hypot from "../utils/hypot.js";
import { warnOnce, copyAction } from "../utils/misc.js";
import * as pointerUtils from "../utils/pointerUtils.js";
import * as rectUtils from "../utils/rect.js";
import { InteractEvent } from "./InteractEvent.js";
import { PointerInfo } from "./PointerInfo.js";
export let _ProxyValues;
(function (_ProxyValues) {
_ProxyValues["interactable"] = "";
_ProxyValues["element"] = "";
_ProxyValues["prepared"] = "";
_ProxyValues["pointerIsDown"] = "";
_ProxyValues["pointerWasMoved"] = "";
_ProxyValues["_proxy"] = "";
})(_ProxyValues || (_ProxyValues = {}));
export let _ProxyMethods;
(function (_ProxyMethods) {
_ProxyMethods["start"] = "";
_ProxyMethods["move"] = "";
_ProxyMethods["end"] = "";
_ProxyMethods["stop"] = "";
_ProxyMethods["interacting"] = "";
})(_ProxyMethods || (_ProxyMethods = {}));
let idCounter = 0;
export class Interaction {
// current interactable being interacted with
// the target element of the interactable
// action that's ready to be fired on next move event
// keep track of added pointers
// pointerdown/mousedown/touchstart event
// previous action event
/** @internal */
get pointerMoveTolerance() {
return 1;
}
/**
* @alias Interaction.prototype.move
*/
/** */
constructor({
pointerType,
scopeFire
}) {
this.interactable = null;
this.element = null;
this.rect = void 0;
this._rects = void 0;
this.edges = void 0;
this._scopeFire = void 0;
this.prepared = {
name: null,
axis: null,
edges: null
};
this.pointerType = void 0;
this.pointers = [];
this.downEvent = null;
this.downPointer = {};
this._latestPointer = {
pointer: null,
event: null,
eventTarget: null
};
this.prevEvent = null;
this.pointerIsDown = false;
this.pointerWasMoved = false;
this._interacting = false;
this._ending = false;
this._stopped = true;
this._proxy = null;
this.simulation = null;
this.doMove = warnOnce(function (signalArg) {
this.move(signalArg);
}, 'The interaction.doMove() method has been renamed to interaction.move()');
this.coords = {
// Starting InteractEvent pointer coordinates
start: pointerUtils.newCoords(),
// Previous native pointer move event coordinates
prev: pointerUtils.newCoords(),
// current native pointer move event coordinates
cur: pointerUtils.newCoords(),
// Change in coordinates and time of the pointer
delta: pointerUtils.newCoords(),
// pointer velocity
velocity: pointerUtils.newCoords()
};
this._id = idCounter++;
this._scopeFire = scopeFire;
this.pointerType = pointerType;
const that = this;
this._proxy = {};
for (const key in _ProxyValues) {
Object.defineProperty(this._proxy, key, {
get() {
return that[key];
}
});
}
for (const key in _ProxyMethods) {
Object.defineProperty(this._proxy, key, {
value: (...args) => that[key](...args)
});
}
this._scopeFire('interactions:new', {
interaction: this
});
}
pointerDown(pointer, event, eventTarget) {
const pointerIndex = this.updatePointer(pointer, event, eventTarget, true);
const pointerInfo = this.pointers[pointerIndex];
this._scopeFire('interactions:down', {
pointer,
event,
eventTarget,
pointerIndex,
pointerInfo,
type: 'down',
interaction: this
});
}
/**
* ```js
* interact(target)
* .draggable({
* // disable the default drag start by down->move
* manualStart: true
* })
* // start dragging after the user holds the pointer down
* .on('hold', function (event) {
* var interaction = event.interaction
*
* if (!interaction.interacting()) {
* interaction.start({ name: 'drag' },
* event.interactable,
* event.currentTarget)
* }
* })
* ```
*
* Start an action with the given Interactable and Element as tartgets. The
* action must be enabled for the target Interactable and an appropriate
* number of pointers must be held down - 1 for drag/resize, 2 for gesture.
*
* Use it with `interactable.<action>able({ manualStart: false })` to always
* [start actions manually](https://github.com/taye/interact.js/issues/114)
*
* @param {object} action The action to be performed - drag, resize, etc.
* @param {Interactable} target The Interactable to target
* @param {Element} element The DOM Element to target
* @return {Boolean} Whether the interaction was successfully started
*/
start(action, interactable, element) {
if (this.interacting() || !this.pointerIsDown || this.pointers.length < (action.name === 'gesture' ? 2 : 1) || !interactable.options[action.name].enabled) {
return false;
}
copyAction(this.prepared, action);
this.interactable = interactable;
this.element = element;
this.rect = interactable.getRect(element);
this.edges = this.prepared.edges ? extend({}, this.prepared.edges) : {
left: true,
right: true,
top: true,
bottom: true
};
this._stopped = false;
this._interacting = this._doPhase({
interaction: this,
event: this.downEvent,
phase: 'start'
}) && !this._stopped;
return this._interacting;
}
pointerMove(pointer, event, eventTarget) {
if (!this.simulation && !(this.modification && this.modification.endResult)) {
this.updatePointer(pointer, event, eventTarget, false);
}
const duplicateMove = this.coords.cur.page.x === this.coords.prev.page.x && this.coords.cur.page.y === this.coords.prev.page.y && this.coords.cur.client.x === this.coords.prev.client.x && this.coords.cur.client.y === this.coords.prev.client.y;
let dx;
let dy; // register movement greater than pointerMoveTolerance
if (this.pointerIsDown && !this.pointerWasMoved) {
dx = this.coords.cur.client.x - this.coords.start.client.x;
dy = this.coords.cur.client.y - this.coords.start.client.y;
this.pointerWasMoved = hypot(dx, dy) > this.pointerMoveTolerance;
}
const pointerIndex = this.getPointerIndex(pointer);
const signalArg = {
pointer,
pointerIndex,
pointerInfo: this.pointers[pointerIndex],
event,
type: 'move',
eventTarget,
dx,
dy,
duplicate: duplicateMove,
interaction: this
};
if (!duplicateMove) {
// set pointer coordinate, time changes and velocity
pointerUtils.setCoordVelocity(this.coords.velocity, this.coords.delta);
}
this._scopeFire('interactions:move', signalArg);
if (!duplicateMove && !this.simulation) {
// if interacting, fire an 'action-move' signal etc
if (this.interacting()) {
signalArg.type = null;
this.move(signalArg);
}
if (this.pointerWasMoved) {
pointerUtils.copyCoords(this.coords.prev, this.coords.cur);
}
}
}
/**
* ```js
* interact(target)
* .draggable(true)
* .on('dragmove', function (event) {
* if (someCondition) {
* // change the snap settings
* event.interactable.draggable({ snap: { targets: [] }})
* // fire another move event with re-calculated snap
* event.interaction.move()
* }
* })
* ```
*
* Force a move of the current action at the same coordinates. Useful if
* snap/restrict has been changed and you want a movement with the new
* settings.
*/
move(signalArg) {
if (!signalArg || !signalArg.event) {
pointerUtils.setZeroCoords(this.coords.delta);
}
signalArg = extend({
pointer: this._latestPointer.pointer,
event: this._latestPointer.event,
eventTarget: this._latestPointer.eventTarget,
interaction: this
}, signalArg || {});
signalArg.phase = 'move';
this._doPhase(signalArg);
} // End interact move events and stop auto-scroll unless simulation is running
pointerUp(pointer, event, eventTarget, curEventTarget) {
let pointerIndex = this.getPointerIndex(pointer);
if (pointerIndex === -1) {
pointerIndex = this.updatePointer(pointer, event, eventTarget, false);
}
const type = /cancel$/i.test(event.type) ? 'cancel' : 'up';
this._scopeFire(`interactions:${type}`, {
pointer,
pointerIndex,
pointerInfo: this.pointers[pointerIndex],
event,
eventTarget,
type: type,
curEventTarget,
interaction: this
});
if (!this.simulation) {
this.end(event);
}
this.removePointer(pointer, event);
}
documentBlur(event) {
this.end(event);
this._scopeFire('interactions:blur', {
event,
type: 'blur',
interaction: this
});
}
/**
* ```js
* interact(target)
* .draggable(true)
* .on('move', function (event) {
* if (event.pageX > 1000) {
* // end the current action
* event.interaction.end()
* // stop all further listeners from being called
* event.stopImmediatePropagation()
* }
* })
* ```
*
* @param {PointerEvent} [event]
*/
end(event) {
this._ending = true;
event = event || this._latestPointer.event;
let endPhaseResult;
if (this.interacting()) {
endPhaseResult = this._doPhase({
event,
interaction: this,
phase: 'end'
});
}
this._ending = false;
if (endPhaseResult === true) {
this.stop();
}
}
currentAction() {
return this._interacting ? this.prepared.name : null;
}
interacting() {
return this._interacting;
}
/** */
stop() {
this._scopeFire('interactions:stop', {
interaction: this
});
this.interactable = this.element = null;
this._interacting = false;
this._stopped = true;
this.prepared.name = this.prevEvent = null;
}
getPointerIndex(pointer) {
const pointerId = pointerUtils.getPointerId(pointer); // mouse and pen interactions may have only one pointer
return this.pointerType === 'mouse' || this.pointerType === 'pen' ? this.pointers.length - 1 : arr.findIndex(this.pointers, curPointer => curPointer.id === pointerId);
}
getPointerInfo(pointer) {
return this.pointers[this.getPointerIndex(pointer)];
}
updatePointer(pointer, event, eventTarget, down) {
const id = pointerUtils.getPointerId(pointer);
let pointerIndex = this.getPointerIndex(pointer);
let pointerInfo = this.pointers[pointerIndex];
down = down === false ? false : down || /(down|start)$/i.test(event.type);
if (!pointerInfo) {
pointerInfo = new PointerInfo(id, pointer, event, null, null);
pointerIndex = this.pointers.length;
this.pointers.push(pointerInfo);
} else {
pointerInfo.pointer = pointer;
}
pointerUtils.setCoords(this.coords.cur, this.pointers.map(p => p.pointer), this._now());
pointerUtils.setCoordDeltas(this.coords.delta, this.coords.prev, this.coords.cur);
if (down) {
this.pointerIsDown = true;
pointerInfo.downTime = this.coords.cur.timeStamp;
pointerInfo.downTarget = eventTarget;
pointerUtils.pointerExtend(this.downPointer, pointer);
if (!this.interacting()) {
pointerUtils.copyCoords(this.coords.start, this.coords.cur);
pointerUtils.copyCoords(this.coords.prev, this.coords.cur);
this.downEvent = event;
this.pointerWasMoved = false;
}
}
this._updateLatestPointer(pointer, event, eventTarget);
this._scopeFire('interactions:update-pointer', {
pointer,
event,
eventTarget,
down,
pointerInfo,
pointerIndex,
interaction: this
});
return pointerIndex;
}
removePointer(pointer, event) {
const pointerIndex = this.getPointerIndex(pointer);
if (pointerIndex === -1) {
return;
}
const pointerInfo = this.pointers[pointerIndex];
this._scopeFire('interactions:remove-pointer', {
pointer,
event,
eventTarget: null,
pointerIndex,
pointerInfo,
interaction: this
});
this.pointers.splice(pointerIndex, 1);
this.pointerIsDown = false;
}
_updateLatestPointer(pointer, event, eventTarget) {
this._latestPointer.pointer = pointer;
this._latestPointer.event = event;
this._latestPointer.eventTarget = eventTarget;
}
destroy() {
this._latestPointer.pointer = null;
this._latestPointer.event = null;
this._latestPointer.eventTarget = null;
}
_createPreparedEvent(event, phase, preEnd, type) {
return new InteractEvent(this, event, this.prepared.name, phase, this.element, preEnd, type);
}
_fireEvent(iEvent) {
this.interactable.fire(iEvent);
if (!this.prevEvent || iEvent.timeStamp >= this.prevEvent.timeStamp) {
this.prevEvent = iEvent;
}
}
_doPhase(signalArg) {
const {
event,
phase,
preEnd,
type
} = signalArg;
const {
rect
} = this;
if (rect && phase === 'move') {
// update the rect changes due to pointer move
rectUtils.addEdges(this.edges, rect, this.coords.delta[this.interactable.options.deltaSource]);
rect.width = rect.right - rect.left;
rect.height = rect.bottom - rect.top;
}
const beforeResult = this._scopeFire(`interactions:before-action-${phase}`, signalArg);
if (beforeResult === false) {
return false;
}
const iEvent = signalArg.iEvent = this._createPreparedEvent(event, phase, preEnd, type);
this._scopeFire(`interactions:action-${phase}`, signalArg);
if (phase === 'start') {
this.prevEvent = iEvent;
}
this._fireEvent(iEvent);
this._scopeFire(`interactions:after-action-${phase}`, signalArg);
return true;
}
_now() {
return Date.now();
}
}
export default Interaction;
export { PointerInfo };
//# sourceMappingURL=Interaction.js.map