UNPKG

tldraw

Version:

A tiny little drawing editor.

150 lines (149 loc) • 5.53 kB
"use strict"; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; 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 __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); var Brushing_exports = {}; __export(Brushing_exports, { Brushing: () => Brushing }); module.exports = __toCommonJS(Brushing_exports); var import_editor = require("@tldraw/editor"); class Brushing extends import_editor.StateNode { static id = "brushing"; info = {}; initialSelectedShapeIds = []; excludedShapeIds = /* @__PURE__ */ new Set(); isWrapMode = false; // The shape that the brush started on initialStartShape = null; onEnter(info) { const { altKey, currentPagePoint } = this.editor.inputs; this.isWrapMode = this.editor.user.getIsWrapMode(); if (altKey) { this.parent.transition("scribble_brushing", info); return; } this.excludedShapeIds = new Set( this.editor.getCurrentPageShapes().filter( (shape) => this.editor.isShapeOfType(shape, "group") || this.editor.isShapeOrAncestorLocked(shape) ).map((shape) => shape.id) ); this.info = info; this.initialSelectedShapeIds = this.editor.getSelectedShapeIds().slice(); this.initialStartShape = this.editor.getShapesAtPoint(currentPagePoint)[0]; this.hitTestShapes(); } onExit() { this.initialSelectedShapeIds = []; this.editor.updateInstanceState({ brush: null }); } onTick({ elapsed }) { const { editor } = this; editor.edgeScrollManager.updateEdgeScrolling(elapsed); } onPointerMove() { this.hitTestShapes(); } onPointerUp() { this.complete(); } onComplete() { this.complete(); } onCancel(info) { this.editor.setSelectedShapes(this.initialSelectedShapeIds); this.parent.transition("idle", info); } onKeyDown(info) { if (this.editor.inputs.altKey) { this.parent.transition("scribble_brushing", info); } else { this.hitTestShapes(); } } onKeyUp() { this.hitTestShapes(); } complete() { this.hitTestShapes(); this.parent.transition("idle"); } hitTestShapes() { const { editor, excludedShapeIds, isWrapMode } = this; const { inputs: { originPagePoint, currentPagePoint, shiftKey, ctrlKey } } = editor; const results = new Set(shiftKey ? this.initialSelectedShapeIds : []); const isWrapping = isWrapMode ? !ctrlKey : ctrlKey; const brush = import_editor.Box.FromPoints([originPagePoint, currentPagePoint]); const { corners } = brush; let A, B, shape, pageBounds, pageTransform, localCorners; const currentPageShapes = editor.getCurrentPageRenderingShapesSorted(); const currentPageId = editor.getCurrentPageId(); testAllShapes: for (let i = 0, n = currentPageShapes.length; i < n; i++) { shape = currentPageShapes[i]; if (excludedShapeIds.has(shape.id) || results.has(shape.id)) continue testAllShapes; pageBounds = editor.getShapePageBounds(shape); if (!pageBounds) continue testAllShapes; if (brush.contains(pageBounds)) { this.handleHit(shape, currentPagePoint, currentPageId, results, corners); continue testAllShapes; } if (isWrapping || editor.isShapeOfType(shape, "frame")) { continue testAllShapes; } if (brush.collides(pageBounds)) { pageTransform = editor.getShapePageTransform(shape); if (!pageTransform) continue testAllShapes; localCorners = pageTransform.clone().invert().applyToPoints(corners); const geometry = editor.getShapeGeometry(shape); hitTestBrushEdges: for (let i2 = 0; i2 < 4; i2++) { A = localCorners[i2]; B = localCorners[(i2 + 1) % 4]; if (geometry.hitTestLineSegment(A, B, 0)) { this.handleHit(shape, currentPagePoint, currentPageId, results, corners); break hitTestBrushEdges; } } } } const currentBrush = editor.getInstanceState().brush; if (!currentBrush || !brush.equals(currentBrush)) { editor.updateInstanceState({ brush: { ...brush.toJson() } }); } const current = editor.getSelectedShapeIds(); if (current.length !== results.size || current.some((id) => !results.has(id))) { editor.setSelectedShapes(Array.from(results)); } } onInterrupt() { this.editor.updateInstanceState({ brush: null }); } handleHit(shape, currentPagePoint, currentPageId, results, corners) { if (shape.parentId === currentPageId) { results.add(shape.id); return; } const selectedShape = this.editor.getOutermostSelectableShape(shape); const pageMask = this.editor.getShapeMask(selectedShape.id); if (pageMask && !(0, import_editor.polygonsIntersect)(pageMask, corners) && !(0, import_editor.pointInPolygon)(currentPagePoint, pageMask)) { return; } results.add(selectedShape.id); } } //# sourceMappingURL=Brushing.js.map