UNPKG

@tldraw/editor

Version:

tldraw infinite canvas SDK (editor).

248 lines (247 loc) • 9.08 kB
"use strict"; var __create = Object.create; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( // If the importer is in node compatibility mode or this is not an ESM // file that has been converted to a CommonJS file using a Babel- // compatible transform (i.e. "__esModule" has not been set), then set // "default" to the CommonJS "module.exports" for node compatibility. isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod )); var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); var useGestureEvents_exports = {}; __export(useGestureEvents_exports, { useGestureEvents: () => useGestureEvents }); module.exports = __toCommonJS(useGestureEvents_exports); var import_react = require("@use-gesture/react"); var React = __toESM(require("react")); var import_Vec = require("../primitives/Vec"); var import_dom = require("../utils/dom"); var import_keyboard = require("../utils/keyboard"); var import_normalizeWheel = require("../utils/normalizeWheel"); var import_useEditor = require("./useEditor"); const useGesture = (0, import_react.createUseGesture)([import_react.wheelAction, import_react.pinchAction]); let lastWheelTime = void 0; const isWheelEndEvent = (time) => { if (lastWheelTime === void 0) { lastWheelTime = time; return false; } if (time - lastWheelTime > 120 && time - lastWheelTime < 160) { lastWheelTime = time; return true; } lastWheelTime = time; return false; }; function useGestureEvents(ref) { const editor = (0, import_useEditor.useEditor)(); const events = React.useMemo(() => { let pinchState = "not sure"; const onWheel = ({ event }) => { if (!editor.getInstanceState().isFocused) { return; } pinchState = "not sure"; if (isWheelEndEvent(Date.now())) { return; } const editingShapeId = editor.getEditingShapeId(); if (editingShapeId) { const shape = editor.getShape(editingShapeId); if (shape) { const util = editor.getShapeUtil(shape); if (util.canScroll(shape)) { const bounds = editor.getShapePageBounds(editingShapeId); if (bounds?.containsPoint(editor.inputs.currentPagePoint)) { return; } } } } (0, import_dom.preventDefault)(event); (0, import_dom.stopEventPropagation)(event); const delta = (0, import_normalizeWheel.normalizeWheel)(event); if (delta.x === 0 && delta.y === 0) return; const info = { type: "wheel", name: "wheel", delta, point: new import_Vec.Vec(event.clientX, event.clientY), shiftKey: event.shiftKey, altKey: event.altKey, ctrlKey: event.metaKey || event.ctrlKey, metaKey: event.metaKey, accelKey: (0, import_keyboard.isAccelKey)(event) }; editor.dispatch(info); }; let initDistanceBetweenFingers = 1; let initZoom = 1; let currDistanceBetweenFingers = 0; const initPointBetweenFingers = new import_Vec.Vec(); const prevPointBetweenFingers = new import_Vec.Vec(); const onPinchStart = (gesture) => { const elm = ref.current; pinchState = "not sure"; const { event, origin, da } = gesture; if (event instanceof WheelEvent) return; if (!(event.target === elm || elm?.contains(event.target))) return; prevPointBetweenFingers.x = origin[0]; prevPointBetweenFingers.y = origin[1]; initPointBetweenFingers.x = origin[0]; initPointBetweenFingers.y = origin[1]; initDistanceBetweenFingers = da[0]; initZoom = editor.getZoomLevel(); editor.dispatch({ type: "pinch", name: "pinch_start", point: { x: origin[0], y: origin[1], z: editor.getZoomLevel() }, delta: { x: 0, y: 0 }, shiftKey: event.shiftKey, altKey: event.altKey, ctrlKey: event.metaKey || event.ctrlKey, metaKey: event.metaKey, accelKey: (0, import_keyboard.isAccelKey)(event) }); }; const updatePinchState = (isSafariTrackpadPinch) => { if (isSafariTrackpadPinch) { pinchState = "zooming"; } if (pinchState === "zooming") { return; } const touchDistance = Math.abs(currDistanceBetweenFingers - initDistanceBetweenFingers); const originDistance = import_Vec.Vec.Dist(initPointBetweenFingers, prevPointBetweenFingers); switch (pinchState) { case "not sure": { if (touchDistance > 24) { pinchState = "zooming"; } else if (originDistance > 16) { pinchState = "panning"; } break; } case "panning": { if (touchDistance > 64) { pinchState = "zooming"; } break; } } }; const onPinch = (gesture) => { const elm = ref.current; const { event, origin, offset, da } = gesture; if (event instanceof WheelEvent) return; if (!(event.target === elm || elm?.contains(event.target))) return; const isSafariTrackpadPinch = gesture.type === "gesturechange" || gesture.type === "gestureend"; currDistanceBetweenFingers = da[0]; const dx = origin[0] - prevPointBetweenFingers.x; const dy = origin[1] - prevPointBetweenFingers.y; prevPointBetweenFingers.x = origin[0]; prevPointBetweenFingers.y = origin[1]; updatePinchState(isSafariTrackpadPinch); switch (pinchState) { case "zooming": { const currZoom = offset[0] ** editor.getCameraOptions().zoomSpeed; editor.dispatch({ type: "pinch", name: "pinch", point: { x: origin[0], y: origin[1], z: currZoom }, delta: { x: dx, y: dy }, shiftKey: event.shiftKey, altKey: event.altKey, ctrlKey: event.metaKey || event.ctrlKey, metaKey: event.metaKey, accelKey: (0, import_keyboard.isAccelKey)(event) }); break; } case "panning": { editor.dispatch({ type: "pinch", name: "pinch", point: { x: origin[0], y: origin[1], z: initZoom }, delta: { x: dx, y: dy }, shiftKey: event.shiftKey, altKey: event.altKey, ctrlKey: event.metaKey || event.ctrlKey, metaKey: event.metaKey, accelKey: (0, import_keyboard.isAccelKey)(event) }); break; } } }; const onPinchEnd = (gesture) => { const elm = ref.current; const { event, origin, offset } = gesture; if (event instanceof WheelEvent) return; if (!(event.target === elm || elm?.contains(event.target))) return; const scale = offset[0] ** editor.getCameraOptions().zoomSpeed; pinchState = "not sure"; editor.timers.requestAnimationFrame(() => { editor.dispatch({ type: "pinch", name: "pinch_end", point: { x: origin[0], y: origin[1], z: scale }, delta: { x: origin[0], y: origin[1] }, shiftKey: event.shiftKey, altKey: event.altKey, ctrlKey: event.metaKey || event.ctrlKey, metaKey: event.metaKey, accelKey: (0, import_keyboard.isAccelKey)(event) }); }); }; return { onWheel, onPinchStart, onPinchEnd, onPinch }; }, [editor, ref]); useGesture(events, { target: ref, eventOptions: { passive: false }, pinch: { from: () => { const { zoomSpeed } = editor.getCameraOptions(); const level = editor.getZoomLevel() ** (1 / zoomSpeed); return [level, 0]; }, // Return the camera z to use when pinch starts scaleBounds: () => { const baseZoom = editor.getBaseZoom(); const { zoomSteps, zoomSpeed } = editor.getCameraOptions(); const zoomMin = zoomSteps[0] * baseZoom; const zoomMax = zoomSteps[zoomSteps.length - 1] * baseZoom; return { max: zoomMax ** (1 / zoomSpeed), min: zoomMin ** (1 / zoomSpeed) }; } } }); } //# sourceMappingURL=useGestureEvents.js.map