UNPKG

tldraw

Version:

A tiny little drawing editor.

8 lines (7 loc) • 10.8 kB
{ "version": 3, "sources": ["../../../../src/lib/tools/SelectTool/DragAndDropManager.ts"], "sourcesContent": ["import {\n\tEditor,\n\tIndexKey,\n\tTLGroupShape,\n\tTLParentId,\n\tTLShape,\n\tTLShapeId,\n\tVec,\n\tbind,\n\tcompact,\n\tisShapeId,\n} from '@tldraw/editor'\n\nconst SLOW_POINTER_LAG_DURATION = 320\nconst FAST_POINTER_LAG_DURATION = 60\n\n/** @public */\nexport class DragAndDropManager {\n\tconstructor(public editor: Editor) {\n\t\teditor.disposables.add(this.dispose)\n\t}\n\n\tshapesToActuallyMove: TLShape[] = []\n\tdraggedOverShapeIds = new Set<TLShapeId>()\n\n\tinitialGroupIds = new Map<TLShapeId, TLShapeId>()\n\tinitialParentIds = new Map<TLShapeId, TLParentId>()\n\tinitialIndices = new Map<TLShapeId, IndexKey>()\n\n\tinitialDraggingOverShape?: TLShape\n\tprevDraggingOverShape?: TLShape\n\tprevPagePoint = new Vec()\n\n\tintervalTimerId = -1\n\n\tstartDraggingShapes(movingShapes: TLShape[], point: Vec, cb: () => void) {\n\t\tconst { editor } = this\n\n\t\t// Only start dragging if we're not already dragging\n\t\tif (this.intervalTimerId !== -1) return\n\n\t\tconst shapesToActuallyMove = new Set(movingShapes)\n\t\tconst movingGroups = new Set<TLGroupShape>()\n\n\t\tfor (const shape of shapesToActuallyMove) {\n\t\t\tconst parent = editor.getShapeParent(shape)\n\t\t\tif (parent && editor.isShapeOfType(parent, 'group')) {\n\t\t\t\tif (!movingGroups.has(parent)) {\n\t\t\t\t\tmovingGroups.add(parent)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// If all of a group's children are moving, then move the group instead\n\t\tfor (const movingGroup of movingGroups) {\n\t\t\tconst children = compact(\n\t\t\t\teditor.getSortedChildIdsForParent(movingGroup).map((id) => editor.getShape(id))\n\t\t\t)\n\t\t\tshapesToActuallyMove.add(movingGroup)\n\t\t\tfor (const child of children) {\n\t\t\t\tshapesToActuallyMove.delete(child)\n\t\t\t}\n\t\t}\n\n\t\tthis.initialParentIds.clear()\n\t\tfor (const shape of shapesToActuallyMove) {\n\t\t\tconst parent = editor.getShapeParent(shape)\n\t\t\tif (parent) {\n\t\t\t\tthis.initialParentIds.set(shape.id, parent.id)\n\t\t\t}\n\t\t\tthis.initialIndices.set(shape.id, shape.index)\n\n\t\t\tconst group = editor.findShapeAncestor(shape, (s) => editor.isShapeOfType(s, 'group'))\n\t\t\tif (group) {\n\t\t\t\tthis.initialGroupIds.set(shape.id, group.id)\n\t\t\t}\n\t\t}\n\n\t\tconst allShapes = editor.getCurrentPageShapesSorted()\n\t\tthis.shapesToActuallyMove = Array.from(shapesToActuallyMove)\n\t\t\t.filter((s) => !s.isLocked)\n\t\t\t.sort((a, b) => allShapes.indexOf(a) - allShapes.indexOf(b))\n\n\t\tthis.initialDraggingOverShape = editor.getDraggingOverShape(point, this.shapesToActuallyMove)\n\t\tthis.prevDraggingOverShape = this.initialDraggingOverShape\n\n\t\t// run once on first frame\n\t\tthis.updateDraggingShapes(point, cb)\n\n\t\t// then once on an interval, skipping frames if moving quickly\n\t\tlet skip2of3FramesWhileMovingFast = 0\n\t\tthis.intervalTimerId = this.editor.timers.setInterval(\n\t\t\t() => {\n\t\t\t\tskip2of3FramesWhileMovingFast++\n\t\t\t\tif (\n\t\t\t\t\tskip2of3FramesWhileMovingFast % 3 &&\n\t\t\t\t\tthis.editor.inputs.getPointerVelocity().len() > 0.5\n\t\t\t\t) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tthis.updateDraggingShapes(editor.inputs.getCurrentPagePoint(), cb)\n\t\t\t},\n\t\t\tmovingShapes.length > 10 ? SLOW_POINTER_LAG_DURATION : FAST_POINTER_LAG_DURATION\n\t\t)\n\t}\n\n\tdropShapes(shapes: TLShape[]) {\n\t\tconst { editor } = this\n\t\tconst currentPagePoint = editor.inputs.getCurrentPagePoint()\n\t\tthis.updateDraggingShapes(currentPagePoint)\n\n\t\tconst draggingOverShape = editor.getDraggingOverShape(currentPagePoint, shapes)\n\n\t\tif (draggingOverShape) {\n\t\t\tconst util = editor.getShapeUtil(draggingOverShape)\n\t\t\tutil.onDropShapesOver?.(draggingOverShape, shapes, {\n\t\t\t\tinitialDraggingOverShapeId: this.initialDraggingOverShape?.id ?? null,\n\t\t\t\tinitialParentIds: this.initialParentIds,\n\t\t\t\tinitialIndices: this.initialIndices,\n\t\t\t})\n\t\t}\n\n\t\tthis.dispose()\n\t}\n\n\tclear() {\n\t\tclearInterval(this.intervalTimerId)\n\t\tthis.intervalTimerId = -1\n\n\t\tthis.initialParentIds.clear()\n\t\tthis.initialIndices.clear()\n\t\tthis.shapesToActuallyMove = []\n\t\tthis.initialDraggingOverShape = undefined\n\t\tthis.prevDraggingOverShape = undefined\n\t\tthis.editor.setHintingShapes([])\n\t}\n\n\t@bind\n\tdispose() {\n\t\tthis.clear()\n\t}\n\n\tprivate updateDraggingShapes(point: Vec, cb?: () => void): void {\n\t\tconst { editor } = this\n\n\t\t// get fresh moving shapes\n\t\tconst draggingShapes = compact(this.shapesToActuallyMove.map((s) => editor.getShape(s)))\n\n\t\tif (!draggingShapes.length) return\n\n\t\t// This is the shape under the pointer that can handle at least one of the dragging shapes\n\t\tconst nextDraggingOverShape = editor.getDraggingOverShape(point, this.shapesToActuallyMove)\n\n\t\tconst currentPagePoint = editor.inputs.getCurrentPagePoint()\n\t\tconst cursorDidMove = !this.prevPagePoint.equals(currentPagePoint)\n\t\tthis.prevPagePoint.setTo(currentPagePoint)\n\n\t\teditor.run(() => {\n\t\t\tif (this.prevDraggingOverShape?.id === nextDraggingOverShape?.id) {\n\t\t\t\tif (\n\t\t\t\t\tcursorDidMove &&\n\t\t\t\t\tnextDraggingOverShape &&\n\t\t\t\t\tisShapeId(nextDraggingOverShape.id) &&\n\t\t\t\t\t!editor.inputs.getPreviousPagePoint().equals(currentPagePoint)\n\t\t\t\t) {\n\t\t\t\t\t// If the cursor moved, call onDragShapesOver for the previous dragging over shape\n\t\t\t\t\tconst util = editor.getShapeUtil(nextDraggingOverShape)\n\t\t\t\t\tutil.onDragShapesOver?.(nextDraggingOverShape, draggingShapes, {\n\t\t\t\t\t\tinitialDraggingOverShapeId: this.initialDraggingOverShape?.id ?? null,\n\t\t\t\t\t\tinitialParentIds: this.initialParentIds,\n\t\t\t\t\t\tinitialIndices: this.initialIndices,\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tif (this.prevDraggingOverShape) {\n\t\t\t\tconst util = editor.getShapeUtil(this.prevDraggingOverShape)\n\t\t\t\tutil.onDragShapesOut?.(this.editor.getShape(this.prevDraggingOverShape)!, draggingShapes, {\n\t\t\t\t\tnextDraggingOverShapeId: nextDraggingOverShape?.id ?? null,\n\t\t\t\t\tinitialDraggingOverShapeId: this.initialDraggingOverShape?.id ?? null,\n\t\t\t\t\tinitialParentIds: this.initialParentIds,\n\t\t\t\t\tinitialIndices: this.initialIndices,\n\t\t\t\t})\n\t\t\t}\n\n\t\t\tif (nextDraggingOverShape) {\n\t\t\t\tconst util = editor.getShapeUtil(nextDraggingOverShape)\n\t\t\t\tutil.onDragShapesIn?.(nextDraggingOverShape, draggingShapes, {\n\t\t\t\t\tinitialDraggingOverShapeId: this.initialDraggingOverShape?.id ?? null,\n\t\t\t\t\tprevDraggingOverShapeId: this.prevDraggingOverShape?.id ?? null,\n\t\t\t\t\tinitialParentIds: this.initialParentIds,\n\t\t\t\t\tinitialIndices: this.initialIndices,\n\t\t\t\t})\n\t\t\t\teditor.setHintingShapes([nextDraggingOverShape.id])\n\t\t\t} else if (this.prevDraggingOverShape) {\n\t\t\t\teditor.setHintingShapes([])\n\t\t\t}\n\n\t\t\t// This is the reparenting logic\n\t\t\tcb?.()\n\t\t})\n\n\t\tthis.prevDraggingOverShape = nextDraggingOverShape\n\t}\n}\n"], "mappings": "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", "names": [] }