{
  "version": 3,
  "sources": ["../../../../../../../src/lib/tools/SelectTool/childStates/Crop/children/Cropping.ts"],
  "sourcesContent": ["import {\n\tBox,\n\tHALF_PI,\n\tSelectionHandle,\n\tShapeWithCrop,\n\tStateNode,\n\tTLPointerEventInfo,\n\tVec,\n\tisAccelKey,\n\tkickoutOccludedShapes,\n\trotateSelectionHandle,\n} from '@tldraw/editor'\nimport { getCropBox, getDefaultCrop, getUncroppedSize } from '../../../../../shapes/shared/crop'\nimport { CursorTypeMap } from '../../PointingResizeHandle'\n\ntype Snapshot = ReturnType<Cropping['createSnapshot']>\n\nexport class Cropping extends StateNode {\n\tstatic override id = 'cropping'\n\tstatic override trackPerformance = true\n\n\tinfo = {} as TLPointerEventInfo & {\n\t\ttarget: 'selection'\n\t\thandle: SelectionHandle\n\t\tonInteractionEnd?: string | (() => void)\n\t}\n\n\tmarkId = ''\n\n\tprivate snapshot = {} as any as Snapshot\n\n\toverride onEnter(\n\t\tinfo: TLPointerEventInfo & {\n\t\t\ttarget: 'selection'\n\t\t\thandle: SelectionHandle\n\t\t\tonInteractionEnd?: string | (() => void)\n\t\t}\n\t) {\n\t\tthis.info = info\n\t\tif (typeof info.onInteractionEnd === 'string') {\n\t\t\tthis.parent.setCurrentToolIdMask(info.onInteractionEnd)\n\t\t}\n\t\tthis.markId = this.editor.markHistoryStoppingPoint('cropping')\n\t\tthis.snapshot = this.createSnapshot()\n\t\tthis.updateShapes()\n\t}\n\n\toverride onPointerMove() {\n\t\tthis.updateShapes()\n\t}\n\n\toverride onKeyDown() {\n\t\tthis.updateShapes()\n\t}\n\n\toverride onKeyUp() {\n\t\tthis.updateShapes()\n\t}\n\n\toverride onPointerUp() {\n\t\tthis.complete()\n\t}\n\n\toverride onComplete() {\n\t\tthis.complete()\n\t}\n\n\toverride onCancel() {\n\t\tthis.cancel()\n\t}\n\n\toverride onExit() {\n\t\tthis.parent.setCurrentToolIdMask(undefined)\n\t\tthis.editor.snaps.clearIndicators()\n\t}\n\n\tprivate updateCursor() {\n\t\tconst selectedShape = this.editor.getSelectedShapes()[0]\n\t\tif (!selectedShape) return\n\n\t\tconst cursorType = CursorTypeMap[this.info.handle!]\n\t\tthis.editor.setCursor({ type: cursorType, rotation: this.editor.getSelectionRotation() })\n\t}\n\n\tprivate updateShapes() {\n\t\tconst { editor } = this\n\t\tconst { shape, cursorHandleOffset, initialSelectionPageBounds, selectionRotation } =\n\t\t\tthis.snapshot\n\n\t\tif (!shape) return\n\t\tconst util = editor.getShapeUtil<ShapeWithCrop>(shape.type)\n\t\tif (!util) return\n\n\t\tconst shiftKey = editor.inputs.getShiftKey()\n\t\tconst altKey = editor.inputs.getAltKey()\n\t\tconst isHoldingAccel = isAccelKey(editor.inputs)\n\n\t\tconst currentPagePoint = editor.inputs.getCurrentPagePoint().clone().sub(cursorHandleOffset)\n\t\tconst originPagePoint = editor.inputs.getOriginPagePoint().clone().sub(cursorHandleOffset)\n\n\t\t// Grid snapping (matches resize): snap the cropped frame to the grid.\n\t\tif (editor.getInstanceState().isGridMode && !isHoldingAccel) {\n\t\t\tconst { gridSize } = editor.getDocumentSettings()\n\t\t\tcurrentPagePoint.snapToGrid(gridSize)\n\t\t}\n\n\t\t// Shape-bounds snapping: the visible crop frame is the shape's page bounds and its\n\t\t// dragged edge moves 1:1 with the unrotated drag delta, so we can reuse the same\n\t\t// snapping the resize uses. Gate it exactly like resize, and skip when rotated.\n\t\teditor.snaps.clearIndicators()\n\t\tconst shouldSnap = editor.user.getIsSnapMode() ? !isHoldingAccel : isHoldingAccel\n\t\tlet didSnap = false\n\t\tif (shouldSnap && initialSelectionPageBounds && selectionRotation % HALF_PI === 0) {\n\t\t\tconst { nudge } = editor.snaps.shapeBounds.snapResizeShapes({\n\t\t\t\tdragDelta: Vec.Sub(currentPagePoint, originPagePoint),\n\t\t\t\tinitialSelectionPageBounds,\n\t\t\t\thandle: rotateSelectionHandle(this.info.handle, selectionRotation),\n\t\t\t\tisAspectRatioLocked: shiftKey,\n\t\t\t\tisResizingFromCenter: altKey,\n\t\t\t})\n\t\t\tcurrentPagePoint.add(nudge)\n\t\t\tdidSnap = true\n\t\t}\n\n\t\tconst change = currentPagePoint.clone().sub(originPagePoint).rot(-shape.rotation)\n\n\t\tconst crop = shape.props.crop ?? getDefaultCrop()\n\t\tconst uncroppedSize = getUncroppedSize(shape.props, crop)\n\n\t\tconst cropFn = util.onCrop?.bind(util) ?? getCropBox\n\t\tconst partial = cropFn(shape, {\n\t\t\thandle: this.info.handle,\n\t\t\tchange,\n\t\t\tcrop,\n\t\t\tuncroppedSize,\n\t\t\tinitialShape: this.snapshot.shape,\n\t\t\taspectRatioLocked: shiftKey,\n\t\t\tisResizingFromCenter: altKey,\n\t\t})\n\t\tif (partial) {\n\t\t\teditor.updateShapes([\n\t\t\t\t{\n\t\t\t\t\tid: shape.id,\n\t\t\t\t\ttype: shape.type,\n\t\t\t\t\t...partial,\n\t\t\t\t},\n\t\t\t])\n\t\t}\n\n\t\t// If the crop's content limit stopped the frame edge short of the snap target,\n\t\t// clear the now-misleading snap line so it doesn't float past the image content.\n\t\tif (didSnap && initialSelectionPageBounds) {\n\t\t\tthis.reconcileSnapIndicators(\n\t\t\t\tinitialSelectionPageBounds,\n\t\t\t\tVec.Sub(currentPagePoint, originPagePoint),\n\t\t\t\trotateSelectionHandle(this.info.handle, selectionRotation),\n\t\t\t\tshiftKey,\n\t\t\t\taltKey\n\t\t\t)\n\t\t}\n\n\t\tif (partial) this.updateCursor()\n\t}\n\n\tprivate reconcileSnapIndicators(\n\t\tinitialSelectionPageBounds: Box,\n\t\tsnappedDelta: Vec,\n\t\thandle: SelectionHandle,\n\t\tisAspectRatioLocked: boolean,\n\t\tisResizingFromCenter: boolean\n\t) {\n\t\tconst { editor } = this\n\t\tif (!editor.snaps.getIndicators().length) return\n\n\t\tconst actual = editor.getShapePageBounds(this.snapshot.shape.id)\n\t\tif (!actual) return\n\n\t\tconst { box } = Box.Resize(\n\t\t\tinitialSelectionPageBounds,\n\t\t\thandle,\n\t\t\tisResizingFromCenter ? snappedDelta.x * 2 : snappedDelta.x,\n\t\t\tisResizingFromCenter ? snappedDelta.y * 2 : snappedDelta.y,\n\t\t\tisAspectRatioLocked\n\t\t)\n\t\tif (isResizingFromCenter) box.center = initialSelectionPageBounds.center\n\n\t\tconst EPSILON = 1\n\t\tif (\n\t\t\tMath.abs(actual.minX - box.minX) > EPSILON ||\n\t\t\tMath.abs(actual.maxX - box.maxX) > EPSILON ||\n\t\t\tMath.abs(actual.minY - box.minY) > EPSILON ||\n\t\t\tMath.abs(actual.maxY - box.maxY) > EPSILON\n\t\t) {\n\t\t\teditor.snaps.clearIndicators()\n\t\t}\n\t}\n\n\tprivate complete() {\n\t\tthis.updateShapes()\n\t\tkickoutOccludedShapes(this.editor, [this.snapshot.shape.id])\n\t\tconst { onInteractionEnd } = this.info\n\t\tif (onInteractionEnd) {\n\t\t\tif (typeof onInteractionEnd === 'string') {\n\t\t\t\tthis.editor.setCurrentTool(onInteractionEnd, this.info)\n\t\t\t} else {\n\t\t\t\tonInteractionEnd()\n\t\t\t}\n\t\t} else {\n\t\t\tthis.editor.setCroppingShape(null)\n\t\t\tthis.editor.setCurrentTool('select.idle')\n\t\t}\n\t}\n\n\tprivate cancel() {\n\t\tthis.editor.bailToMark(this.markId)\n\t\tconst { onInteractionEnd } = this.info\n\t\tif (onInteractionEnd) {\n\t\t\tif (typeof onInteractionEnd === 'string') {\n\t\t\t\tthis.editor.setCurrentTool(onInteractionEnd, this.info)\n\t\t\t} else {\n\t\t\t\tonInteractionEnd()\n\t\t\t}\n\t\t} else {\n\t\t\tthis.editor.setCroppingShape(null)\n\t\t\tthis.editor.setCurrentTool('select.idle')\n\t\t}\n\t}\n\n\tprivate createSnapshot() {\n\t\tconst selectionRotation = this.editor.getSelectionRotation()\n\t\tconst originPagePoint = this.editor.inputs.getOriginPagePoint()\n\n\t\tconst shape = this.editor.getOnlySelectedShape() as ShapeWithCrop\n\n\t\tconst selectionBounds = this.editor.getSelectionRotatedPageBounds()!\n\n\t\tconst dragHandlePoint = Vec.RotWith(\n\t\t\tselectionBounds.getHandlePoint(this.info.handle!),\n\t\t\tselectionBounds.point,\n\t\t\tselectionRotation\n\t\t)\n\n\t\tconst cursorHandleOffset = Vec.Sub(originPagePoint, dragHandlePoint)\n\n\t\t// Axis-aligned page bounds of the crop frame, used for shape-bounds snapping.\n\t\t// (selectionBounds above is rotated and only used for the cursor handle offset.)\n\t\tconst initialSelectionPageBounds = this.editor.getSelectionPageBounds()\n\n\t\treturn {\n\t\t\tshape,\n\t\t\tcursorHandleOffset,\n\t\t\tinitialSelectionPageBounds,\n\t\t\tselectionRotation,\n\t\t}\n\t}\n}\n"],
  "mappings": "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",
  "names": []
}
