UNPKG

@tldraw/editor

Version:

tldraw infinite canvas SDK (editor).

545 lines (544 loc) • 16 kB
var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __decorateClass = (decorators, target, key, kind) => { var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target; for (var i = decorators.length - 1, decorator; i >= 0; i--) if (decorator = decorators[i]) result = (kind ? decorator(target, key, result) : decorator(result)) || result; if (kind && result) __defProp(target, key, result); return result; }; import { atom, computed, unsafe__withoutCapture } from "@tldraw/state"; import { AtomSet } from "@tldraw/store"; import { TLINSTANCE_ID, TLPOINTER_ID } from "@tldraw/tlschema"; import { INTERNAL_POINTER_IDS } from "../../../constants.mjs"; import { Vec } from "../../../primitives/Vec.mjs"; import { isAccelKey } from "../../../utils/keyboard.mjs"; class InputsManager { constructor(editor) { this.editor = editor; } editor; _originPagePoint = atom("originPagePoint", new Vec()); /** * The most recent pointer down's position in the current page space. */ getOriginPagePoint() { return this._originPagePoint.get(); } /** * @deprecated Use `getOriginPagePoint()` instead. */ // eslint-disable-next-line tldraw/no-setter-getter get originPagePoint() { return this.getOriginPagePoint(); } _originScreenPoint = atom("originScreenPoint", new Vec()); /** * The most recent pointer down's position in screen space. */ getOriginScreenPoint() { return this._originScreenPoint.get(); } /** * @deprecated Use `getOriginScreenPoint()` instead. */ // eslint-disable-next-line tldraw/no-setter-getter get originScreenPoint() { return this.getOriginScreenPoint(); } _previousPagePoint = atom("previousPagePoint", new Vec()); /** * The previous pointer position in the current page space. */ getPreviousPagePoint() { return this._previousPagePoint.get(); } /** * @deprecated Use `getPreviousPagePoint()` instead. */ // eslint-disable-next-line tldraw/no-setter-getter get previousPagePoint() { return this.getPreviousPagePoint(); } _previousScreenPoint = atom("previousScreenPoint", new Vec()); /** * The previous pointer position in screen space. */ getPreviousScreenPoint() { return this._previousScreenPoint.get(); } /** * @deprecated Use `getPreviousScreenPoint()` instead. */ // eslint-disable-next-line tldraw/no-setter-getter get previousScreenPoint() { return this.getPreviousScreenPoint(); } _currentPagePoint = atom("currentPagePoint", new Vec()); /** * The most recent pointer position in the current page space. */ getCurrentPagePoint() { return this._currentPagePoint.get(); } /** * @deprecated Use `getCurrentPagePoint()` instead. */ // eslint-disable-next-line tldraw/no-setter-getter get currentPagePoint() { return this.getCurrentPagePoint(); } _currentScreenPoint = atom("currentScreenPoint", new Vec()); /** * The most recent pointer position in screen space. */ getCurrentScreenPoint() { return this._currentScreenPoint.get(); } /** * @deprecated Use `getCurrentScreenPoint()` instead. */ // eslint-disable-next-line tldraw/no-setter-getter get currentScreenPoint() { return this.getCurrentScreenPoint(); } _pointerVelocity = atom("pointerVelocity", new Vec()); /** * Velocity of mouse pointer, in pixels per millisecond. */ getPointerVelocity() { return this._pointerVelocity.get(); } /** * @deprecated Use `getPointerVelocity()` instead. */ // eslint-disable-next-line tldraw/no-setter-getter get pointerVelocity() { return this.getPointerVelocity(); } /** * Normally you shouldn't need to set the pointer velocity directly, this is set by the tick manager. * However, this is currently used in tests to fake pointer velocity. * @param pointerVelocity - The pointer velocity. * @internal */ setPointerVelocity(pointerVelocity) { this._pointerVelocity.set(pointerVelocity); } /** * A set containing the currently pressed keys. */ keys = new AtomSet("keys"); /** * A set containing the currently pressed buttons. */ buttons = new AtomSet("buttons"); _isPen = atom("isPen", false); /** * Whether the input is from a pen. */ getIsPen() { return this._isPen.get(); } /** * @deprecated Use `getIsPen()` instead. */ // eslint-disable-next-line tldraw/no-setter-getter get isPen() { return this.getIsPen(); } // eslint-disable-next-line tldraw/no-setter-getter set isPen(isPen) { this.setIsPen(isPen); } /** * @param isPen - Whether the input is from a pen. */ setIsPen(isPen) { this._isPen.set(isPen); } _shiftKey = atom("shiftKey", false); /** * Whether the shift key is currently pressed. */ getShiftKey() { return this._shiftKey.get(); } /** * @deprecated Use `getShiftKey()` instead. */ // eslint-disable-next-line tldraw/no-setter-getter get shiftKey() { return this.getShiftKey(); } // eslint-disable-next-line tldraw/no-setter-getter set shiftKey(shiftKey) { this.setShiftKey(shiftKey); } /** * @param shiftKey - Whether the shift key is pressed. * @internal */ setShiftKey(shiftKey) { this._shiftKey.set(shiftKey); } _metaKey = atom("metaKey", false); /** * Whether the meta key is currently pressed. */ getMetaKey() { return this._metaKey.get(); } /** * @deprecated Use `getMetaKey()` instead. */ // eslint-disable-next-line tldraw/no-setter-getter get metaKey() { return this.getMetaKey(); } // eslint-disable-next-line tldraw/no-setter-getter set metaKey(metaKey) { this.setMetaKey(metaKey); } /** * @param metaKey - Whether the meta key is pressed. * @internal */ setMetaKey(metaKey) { this._metaKey.set(metaKey); } _ctrlKey = atom("ctrlKey", false); /** * Whether the ctrl or command key is currently pressed. */ getCtrlKey() { return this._ctrlKey.get(); } /** * @deprecated Use `getCtrlKey()` instead. */ // eslint-disable-next-line tldraw/no-setter-getter get ctrlKey() { return this.getCtrlKey(); } // eslint-disable-next-line tldraw/no-setter-getter set ctrlKey(ctrlKey) { this.setCtrlKey(ctrlKey); } /** * @param ctrlKey - Whether the ctrl key is pressed. * @internal */ setCtrlKey(ctrlKey) { this._ctrlKey.set(ctrlKey); } _altKey = atom("altKey", false); /** * Whether the alt or option key is currently pressed. */ getAltKey() { return this._altKey.get(); } /** * @deprecated Use `getAltKey()` instead. */ // eslint-disable-next-line tldraw/no-setter-getter get altKey() { return this.getAltKey(); } // eslint-disable-next-line tldraw/no-setter-getter set altKey(altKey) { this.setAltKey(altKey); } /** * @param altKey - Whether the alt key is pressed. * @internal */ setAltKey(altKey) { this._altKey.set(altKey); } /** * Is the accelerator key (cmd on mac, ctrl elsewhere) currently pressed. */ getAccelKey() { return isAccelKey({ metaKey: this.getMetaKey(), ctrlKey: this.getCtrlKey() }); } /** * @deprecated Use `getAccelKey()` instead. */ // eslint-disable-next-line tldraw/no-setter-getter get accelKey() { return this.getAccelKey(); } _isDragging = atom("isDragging", false); /** * Whether the user is dragging. */ getIsDragging() { return this._isDragging.get(); } /** * Soon to be deprecated, use `getIsDragging()` instead. */ // eslint-disable-next-line tldraw/no-setter-getter get isDragging() { return this.getIsDragging(); } // eslint-disable-next-line tldraw/no-setter-getter set isDragging(isDragging) { this.setIsDragging(isDragging); } /** * @param isDragging - Whether the user is dragging. */ setIsDragging(isDragging) { this._isDragging.set(isDragging); } _isPointing = atom("isPointing", false); /** * Whether the user is pointing. */ getIsPointing() { return this._isPointing.get(); } /** * @deprecated Use `getIsPointing()` instead. */ // eslint-disable-next-line tldraw/no-setter-getter get isPointing() { return this.getIsPointing(); } // eslint-disable-next-line tldraw/no-setter-getter set isPointing(isPointing) { this.setIsPointing(isPointing); } /** * @param isPointing - Whether the user is pointing. * @internal */ setIsPointing(isPointing) { this._isPointing.set(isPointing); } _isRightPointing = atom("isRightPointing", false); /** * Whether the user is right-click pointing (before drag threshold). */ getIsRightPointing() { return this._isRightPointing.get(); } /** @internal */ setIsRightPointing(isRightPointing) { this._isRightPointing.set(isRightPointing); } _isPinching = atom("isPinching", false); /** * Whether the user is pinching. */ getIsPinching() { return this._isPinching.get(); } /** * @deprecated Use `getIsPinching()` instead. */ // eslint-disable-next-line tldraw/no-setter-getter get isPinching() { return this.getIsPinching(); } // eslint-disable-next-line tldraw/no-setter-getter set isPinching(isPinching) { this.setIsPinching(isPinching); } /** * @param isPinching - Whether the user is pinching. * @internal */ setIsPinching(isPinching) { this._isPinching.set(isPinching); } _isEditing = atom("isEditing", false); /** * Whether the user is editing. */ getIsEditing() { return this._isEditing.get(); } /** * @deprecated Use `getIsEditing()` instead. */ // eslint-disable-next-line tldraw/no-setter-getter get isEditing() { return this.getIsEditing(); } // eslint-disable-next-line tldraw/no-setter-getter set isEditing(isEditing) { this.setIsEditing(isEditing); } /** * @param isEditing - Whether the user is editing. */ setIsEditing(isEditing) { this._isEditing.set(isEditing); } _isPanning = atom("isPanning", false); /** * Whether the user is panning. */ getIsPanning() { return this._isPanning.get(); } /** * @deprecated Use `getIsPanning()` instead. */ // eslint-disable-next-line tldraw/no-setter-getter get isPanning() { return this.getIsPanning(); } // eslint-disable-next-line tldraw/no-setter-getter set isPanning(isPanning) { this.setIsPanning(isPanning); } /** * @param isPanning - Whether the user is panning. * @internal */ setIsPanning(isPanning) { this._isPanning.set(isPanning); } _isSpacebarPanning = atom("isSpacebarPanning", false); /** * Whether the user is spacebar panning. */ getIsSpacebarPanning() { return this._isSpacebarPanning.get(); } /** * @deprecated Use `getIsSpacebarPanning()` instead. */ // eslint-disable-next-line tldraw/no-setter-getter get isSpacebarPanning() { return this.getIsSpacebarPanning(); } // eslint-disable-next-line tldraw/no-setter-getter set isSpacebarPanning(isSpacebarPanning) { this.setIsSpacebarPanning(isSpacebarPanning); } /** * @param isSpacebarPanning - Whether the user is spacebar panning. * @internal */ setIsSpacebarPanning(isSpacebarPanning) { this._isSpacebarPanning.set(isSpacebarPanning); } _getHasCollaborators() { return this.editor.getCollaborators().length > 0; } /** * The previous point used for velocity calculation (updated each tick, not each pointer event). * @internal */ _velocityPrevPoint = new Vec(); /** * Update the pointer velocity based on elapsed time. Called by the tick manager. * @param elapsed - The time elapsed since the last tick in milliseconds. * @internal */ updatePointerVelocity(elapsed) { const currentScreenPoint = this.getCurrentScreenPoint(); const pointerVelocity = this.getPointerVelocity(); if (elapsed === 0) return; const delta = Vec.Sub(currentScreenPoint, this._velocityPrevPoint); this._velocityPrevPoint = currentScreenPoint.clone(); const length = delta.len(); const direction = length ? delta.div(length) : new Vec(0, 0); const next = pointerVelocity.clone().lrp(direction.mul(length / elapsed), 0.5); if (Math.abs(next.x) < 0.01) next.x = 0; if (Math.abs(next.y) < 0.01) next.y = 0; if (!pointerVelocity.equals(next)) { this._pointerVelocity.set(next); } } /** * Update the input points from a pointer, pinch, or wheel event. * * @param info - The event info. * @internal */ updateFromEvent(info) { const currentScreenPoint = this._currentScreenPoint.__unsafe__getWithoutCapture(); const currentPagePoint = this._currentPagePoint.__unsafe__getWithoutCapture(); const isPinching = this._isPinching.__unsafe__getWithoutCapture(); const { screenBounds } = this.editor.store.unsafeGetWithoutCapture(TLINSTANCE_ID); const { x: cx, y: cy, z: cz } = unsafe__withoutCapture(() => this.editor.getCamera()); const sx = info.point.x - screenBounds.x; const sy = info.point.y - screenBounds.y; const sz = info.point.z ?? 0.5; this._previousScreenPoint.set(currentScreenPoint); this._previousPagePoint.set(currentPagePoint); this._currentScreenPoint.set(new Vec(sx, sy)); const nx = sx / cz - cx; const ny = sy / cz - cy; if (isFinite(nx) && isFinite(ny)) { this._currentPagePoint.set(new Vec(nx, ny, sz)); } this._isPen.set(info.type === "pointer" && info.isPen); if (info.name === "pointer_down" || isPinching) { this._pointerVelocity.set(new Vec()); this._originScreenPoint.set(this._currentScreenPoint.__unsafe__getWithoutCapture()); this._originPagePoint.set(this._currentPagePoint.__unsafe__getWithoutCapture()); } if (this._getHasCollaborators()) { this.editor.run( () => { const pagePoint = this._currentPagePoint.__unsafe__getWithoutCapture(); this.editor.store.put([ { id: TLPOINTER_ID, typeName: "pointer", x: pagePoint.x, y: pagePoint.y, lastActivityTimestamp: ( // If our pointer moved only because we're following some other user, then don't // update our last activity timestamp; otherwise, update it to the current timestamp. (info.type === "pointer" && info.pointerId === INTERNAL_POINTER_IDS.CAMERA_MOVE ? this.editor.store.unsafeGetWithoutCapture(TLPOINTER_ID)?.lastActivityTimestamp ?? Date.now() : Date.now()) ), meta: {} } ]); }, { history: "ignore" } ); } } toJson() { return { originPagePoint: this._originPagePoint.get().toJson(), originScreenPoint: this._originScreenPoint.get().toJson(), previousPagePoint: this._previousPagePoint.get().toJson(), previousScreenPoint: this._previousScreenPoint.get().toJson(), currentPagePoint: this._currentPagePoint.get().toJson(), currentScreenPoint: this._currentScreenPoint.get().toJson(), pointerVelocity: this._pointerVelocity.get().toJson(), shiftKey: this._shiftKey.get(), metaKey: this._metaKey.get(), ctrlKey: this._ctrlKey.get(), altKey: this._altKey.get(), isPen: this._isPen.get(), isDragging: this._isDragging.get(), isPointing: this._isPointing.get(), isPinching: this._isPinching.get(), isEditing: this._isEditing.get(), isPanning: this._isPanning.get(), isSpacebarPanning: this._isSpacebarPanning.get(), keys: Array.from(this.keys.keys()), buttons: Array.from(this.buttons.keys()) }; } } __decorateClass([ computed ], InputsManager.prototype, "_getHasCollaborators", 1); export { InputsManager }; //# sourceMappingURL=InputsManager.mjs.map