{
  "version": 3,
  "sources": ["../../../src/lib/utils/rotation.ts"],
  "sourcesContent": ["import { isShapeId, TLShape, TLShapePartial } from '@tldraw/tlschema'\nimport { structuredClone } from '@tldraw/utils'\nimport { Editor } from '../editor/Editor'\nimport { Mat } from '../primitives/Mat'\nimport { canonicalizeRotation } from '../primitives/utils'\nimport { Vec } from '../primitives/Vec'\n\n/** @internal */\nexport function getRotationSnapshot({ editor }: { editor: Editor }): TLRotationSnapshot | null {\n\tconst selectedShapes = editor.getSelectedShapes()\n\tconst selectionRotation = editor.getSelectionRotation()\n\tconst selectionBounds = editor.getSelectionRotatedPageBounds()\n\tconst {\n\t\tinputs: { originPagePoint },\n\t} = editor\n\n\t// todo: this assumes we're rotating the selected shapes\n\t// if we try to rotate shapes that aren't selected, this\n\t// will produce the wrong results\n\n\t// Return null if there are no selected shapes\n\tif (!selectionBounds) {\n\t\treturn null\n\t}\n\n\tconst selectionPageCenter = selectionBounds.center\n\t\t.clone()\n\t\t.rotWith(selectionBounds.point, selectionRotation)\n\n\treturn {\n\t\tselectionPageCenter: selectionPageCenter,\n\t\tinitialCursorAngle: selectionPageCenter.angle(originPagePoint),\n\t\tinitialSelectionRotation: selectionRotation,\n\t\tshapeSnapshots: selectedShapes.map((shape) => ({\n\t\t\tshape: structuredClone(shape),\n\t\t\tinitialPagePoint: editor.getShapePageTransform(shape.id)!.point(),\n\t\t})),\n\t}\n}\n\n/**\n * Info about a rotation that can be applied to the editor's selected shapes.\n *\n * @param selectionPageCenter - The center of the selection in page coordinates\n * @param initialCursorAngle - The angle of the cursor relative to the selection center when the rotation started\n * @param initialSelectionRotation - The rotation of the selection when the rotation started\n * @param shapeSnapshots - Info about each shape that is being rotated\n *\n * @public\n **/\nexport interface TLRotationSnapshot {\n\tselectionPageCenter: Vec\n\tinitialCursorAngle: number\n\tinitialSelectionRotation: number\n\tshapeSnapshots: {\n\t\tshape: TLShape\n\t\tinitialPagePoint: Vec\n\t}[]\n}\n\n/** @internal */\nexport function applyRotationToSnapshotShapes({\n\tdelta,\n\teditor,\n\tsnapshot,\n\tstage,\n}: {\n\tdelta: number\n\tsnapshot: TLRotationSnapshot\n\teditor: Editor\n\tstage: 'start' | 'update' | 'end' | 'one-off'\n}) {\n\tconst { selectionPageCenter, shapeSnapshots } = snapshot\n\n\teditor.updateShapes(\n\t\tshapeSnapshots.map(({ shape, initialPagePoint }) => {\n\t\t\t// We need to both rotate each shape individually and rotate the shapes\n\t\t\t// around the pivot point (the average center of all rotating shapes.)\n\n\t\t\tconst parentTransform = isShapeId(shape.parentId)\n\t\t\t\t? editor.getShapePageTransform(shape.parentId)!\n\t\t\t\t: Mat.Identity()\n\n\t\t\tconst newPagePoint = Vec.RotWith(initialPagePoint, selectionPageCenter, delta)\n\n\t\t\tconst newLocalPoint = Mat.applyToPoint(\n\t\t\t\t// use the current parent transform in case it has moved/resized since the start\n\t\t\t\t// (e.g. if rotating a shape at the edge of a group)\n\t\t\t\tMat.Inverse(parentTransform),\n\t\t\t\tnewPagePoint\n\t\t\t)\n\t\t\tconst newRotation = canonicalizeRotation(shape.rotation + delta)\n\n\t\t\treturn {\n\t\t\t\tid: shape.id,\n\t\t\t\ttype: shape.type,\n\t\t\t\tx: newLocalPoint.x,\n\t\t\t\ty: newLocalPoint.y,\n\t\t\t\trotation: newRotation,\n\t\t\t}\n\t\t})\n\t)\n\n\t// Handle change\n\n\tconst changes: TLShapePartial[] = []\n\n\tshapeSnapshots.forEach(({ shape }) => {\n\t\tconst current = editor.getShape(shape.id)\n\t\tif (!current) return\n\t\tconst util = editor.getShapeUtil(shape)\n\n\t\tif (stage === 'start' || stage === 'one-off') {\n\t\t\tconst changeStart = util.onRotateStart?.(shape)\n\t\t\tif (changeStart) changes.push(changeStart)\n\t\t}\n\n\t\tconst changeUpdate = util.onRotate?.(shape, current)\n\t\tif (changeUpdate) changes.push(changeUpdate)\n\n\t\tif (stage === 'end' || stage === 'one-off') {\n\t\t\tconst changeEnd = util.onRotateEnd?.(shape, current)\n\t\t\tif (changeEnd) changes.push(changeEnd)\n\t\t}\n\t})\n\n\tif (changes.length > 0) {\n\t\teditor.updateShapes(changes)\n\t}\n}\n"],
  "mappings": "AAAA,SAAS,iBAA0C;AACnD,SAAS,uBAAuB;AAEhC,SAAS,WAAW;AACpB,SAAS,4BAA4B;AACrC,SAAS,WAAW;AAGb,SAAS,oBAAoB,EAAE,OAAO,GAAkD;AAC9F,QAAM,iBAAiB,OAAO,kBAAkB;AAChD,QAAM,oBAAoB,OAAO,qBAAqB;AACtD,QAAM,kBAAkB,OAAO,8BAA8B;AAC7D,QAAM;AAAA,IACL,QAAQ,EAAE,gBAAgB;AAAA,EAC3B,IAAI;AAOJ,MAAI,CAAC,iBAAiB;AACrB,WAAO;AAAA,EACR;AAEA,QAAM,sBAAsB,gBAAgB,OAC1C,MAAM,EACN,QAAQ,gBAAgB,OAAO,iBAAiB;AAElD,SAAO;AAAA,IACN;AAAA,IACA,oBAAoB,oBAAoB,MAAM,eAAe;AAAA,IAC7D,0BAA0B;AAAA,IAC1B,gBAAgB,eAAe,IAAI,CAAC,WAAW;AAAA,MAC9C,OAAO,gBAAgB,KAAK;AAAA,MAC5B,kBAAkB,OAAO,sBAAsB,MAAM,EAAE,EAAG,MAAM;AAAA,IACjE,EAAE;AAAA,EACH;AACD;AAuBO,SAAS,8BAA8B;AAAA,EAC7C;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACD,GAKG;AACF,QAAM,EAAE,qBAAqB,eAAe,IAAI;AAEhD,SAAO;AAAA,IACN,eAAe,IAAI,CAAC,EAAE,OAAO,iBAAiB,MAAM;AAInD,YAAM,kBAAkB,UAAU,MAAM,QAAQ,IAC7C,OAAO,sBAAsB,MAAM,QAAQ,IAC3C,IAAI,SAAS;AAEhB,YAAM,eAAe,IAAI,QAAQ,kBAAkB,qBAAqB,KAAK;AAE7E,YAAM,gBAAgB,IAAI;AAAA;AAAA;AAAA,QAGzB,IAAI,QAAQ,eAAe;AAAA,QAC3B;AAAA,MACD;AACA,YAAM,cAAc,qBAAqB,MAAM,WAAW,KAAK;AAE/D,aAAO;AAAA,QACN,IAAI,MAAM;AAAA,QACV,MAAM,MAAM;AAAA,QACZ,GAAG,cAAc;AAAA,QACjB,GAAG,cAAc;AAAA,QACjB,UAAU;AAAA,MACX;AAAA,IACD,CAAC;AAAA,EACF;AAIA,QAAM,UAA4B,CAAC;AAEnC,iBAAe,QAAQ,CAAC,EAAE,MAAM,MAAM;AACrC,UAAM,UAAU,OAAO,SAAS,MAAM,EAAE;AACxC,QAAI,CAAC,QAAS;AACd,UAAM,OAAO,OAAO,aAAa,KAAK;AAEtC,QAAI,UAAU,WAAW,UAAU,WAAW;AAC7C,YAAM,cAAc,KAAK,gBAAgB,KAAK;AAC9C,UAAI,YAAa,SAAQ,KAAK,WAAW;AAAA,IAC1C;AAEA,UAAM,eAAe,KAAK,WAAW,OAAO,OAAO;AACnD,QAAI,aAAc,SAAQ,KAAK,YAAY;AAE3C,QAAI,UAAU,SAAS,UAAU,WAAW;AAC3C,YAAM,YAAY,KAAK,cAAc,OAAO,OAAO;AACnD,UAAI,UAAW,SAAQ,KAAK,SAAS;AAAA,IACtC;AAAA,EACD,CAAC;AAED,MAAI,QAAQ,SAAS,GAAG;AACvB,WAAO,aAAa,OAAO;AAAA,EAC5B;AACD;",
  "names": []
}
