UNPKG

tldraw

Version:

A tiny little drawing editor.

138 lines (137 loc) 4.52 kB
import { StateNode, Vec } from "@tldraw/editor"; import { getArrowBodyGeometry, getArrowLabelDefaultPosition } from "../../../shapes/arrow/arrowLabel.mjs"; import { startEditingShapeWithRichText } from "../selectHelpers.mjs"; class PointingArrowLabel extends StateNode { static id = "pointing_arrow_label"; shapeId = ""; markId = ""; wasAlreadySelected = false; didDrag = false; didCtrlOnEnter = false; info = {}; updateCursor() { this.editor.setCursor({ type: "grabbing", rotation: 0 }); } onEnter(info) { const { shape } = info; if (typeof info.onInteractionEnd === "string") { this.parent.setCurrentToolIdMask(info.onInteractionEnd); } this.info = info; this.shapeId = shape.id; this.didDrag = false; this.didCtrlOnEnter = info.accelKey; this.wasAlreadySelected = this.editor.getOnlySelectedShapeId() === shape.id; this.updateCursor(); const geometry = this.editor.getShapeGeometry(shape); const labelGeometry = geometry.children[1]; if (!labelGeometry) { throw Error(`Expected to find an arrow label geometry for shape: ${shape.id}`); } const currentPagePoint = this.editor.inputs.getCurrentPagePoint(); const pointInShapeSpace = this.editor.getPointInShapeSpace(shape, currentPagePoint); this._labelDragOffset = Vec.Sub(labelGeometry.center, pointInShapeSpace); this.markId = this.editor.markHistoryStoppingPoint("label-drag start"); const additiveSelectionKey = info.shiftKey || info.accelKey; if (additiveSelectionKey) { const selectedShapeIds = this.editor.getSelectedShapeIds(); this.editor.setSelectedShapes([...selectedShapeIds, this.shapeId]); return; } this.editor.setSelectedShapes([this.shapeId]); } onExit() { this.parent.setCurrentToolIdMask(void 0); this.editor.setCursor({ type: "default", rotation: 0 }); } _labelDragOffset = new Vec(0, 0); onPointerMove() { const isDragging = this.editor.inputs.getIsDragging(); if (!isDragging) return; if (this.didCtrlOnEnter) { this.parent.transition("brushing", this.info); return; } const shape = this.editor.getShape(this.shapeId); if (!shape) return; const options = this.editor.getShapeUtil("arrow").options; const geometry = getArrowBodyGeometry(this.editor, shape); const transform = this.editor.getShapePageTransform(shape.id); const pointInShapeSpace = this.editor.getPointInShapeSpace(shape, this.editor.inputs.getCurrentPagePoint()).add(this._labelDragOffset); const defaultLabelPosition = getArrowLabelDefaultPosition(this.editor, shape); let nextLabelPosition = geometry.uninterpolateAlongEdge(pointInShapeSpace); if (isNaN(nextLabelPosition)) { nextLabelPosition = defaultLabelPosition; } const nextLabelPoint = transform.applyToPoint(geometry.interpolateAlongEdge(nextLabelPosition)); const labelDefaultPoint = transform.applyToPoint( geometry.interpolateAlongEdge(defaultLabelPosition) ); if (Vec.DistMin( nextLabelPoint, labelDefaultPoint, options.labelCenterSnapDistance / this.editor.getZoomLevel() )) { nextLabelPosition = defaultLabelPosition; } this.didDrag = true; this.editor.updateShape({ id: shape.id, type: shape.type, props: { labelPosition: nextLabelPosition } }); } onPointerUp() { const shape = this.editor.getShape(this.shapeId); if (!shape) return; if (this.didDrag || !this.wasAlreadySelected) { this.complete(); } else if (this.editor.canEditShape(shape)) { startEditingShapeWithRichText(this.editor, shape.id); } } onCancel() { this.cancel(); } onComplete() { this.cancel(); } onInterrupt() { this.cancel(); } complete() { const { onInteractionEnd } = this.info; if (onInteractionEnd) { if (typeof onInteractionEnd === "string") { this.editor.setCurrentTool(onInteractionEnd, {}); } else { onInteractionEnd(); } return; } this.parent.transition("idle"); } cancel() { this.editor.bailToMark(this.markId); const { onInteractionEnd } = this.info; if (onInteractionEnd) { if (typeof onInteractionEnd === "string") { this.editor.setCurrentTool(onInteractionEnd, {}); } else { onInteractionEnd(); } return; } this.parent.transition("idle"); } } export { PointingArrowLabel }; //# sourceMappingURL=PointingArrowLabel.mjs.map