Files
excalidraw/packages/excalidraw/tests/rotate.test.tsx
T
Márk Tolmács a70417f23f feat(editor): visualize binding midpoints + support for simple arrows (#10611)
* feat: Force exact center focus point

When the projected point is close to center snap it to the exact center.

Signed-off-by: Mark Tolmacs <mark@lazycat.hu>

* fix: Tests

Signed-off-by: Mark Tolmacs <mark@lazycat.hu>

* fix: Snap to center around side mid point.

Signed-off-by: Mark Tolmacs <mark@lazycat.hu>

* Trigger CI

* fix: Midpoint outline focus point

Signed-off-by: Mark Tolmacs <mark@lazycat.hu>

* fix: Tests

Signed-off-by: Mark Tolmacs <mark@lazycat.hu>

* fix: Dragging existing arrow reset focus point on outline

Signed-off-by: Mark Tolmacs <mark@lazycat.hu>

* fix: Tests

Signed-off-by: Mark Tolmacs <mark@lazycat.hu>

* feat: Midpoint indicator

Signed-off-by: Mark Tolmacs <mark@lazycat.hu>

* fix: Rotated mid points

Signed-off-by: Mark Tolmacs <mark@lazycat.hu>

* fix: No hole

Signed-off-by: Mark Tolmacs <mark@lazycat.hu>

* feat: Cache hits and scene lookups

Signed-off-by: Mark Tolmacs <mark@lazycat.hu>

* chore: Remove debug

Signed-off-by: Mark Tolmacs <mark@lazycat.hu>

* fix: Consider hit threshold and inside override too

Signed-off-by: Mark Tolmacs <mark@lazycat.hu>

* fix: Increase outline midpoint sticky distance

Signed-off-by: Mark Tolmacs <mark@lazycat.hu>

* fix: Don't show midpoint indicator when no snapping is possible

Signed-off-by: Mark Tolmacs <mark@lazycat.hu>

* feat: Indicate lock-in

Signed-off-by: Mark Tolmacs <mark@lazycat.hu>

* chore: Remove Map caching

Signed-off-by: Mark Tolmacs <mark@lazycat.hu>

* fix: incorrect threshold

Signed-off-by: Mark Tolmacs <mark@lazycat.hu>

* fix: threshold setting

Signed-off-by: Mark Tolmacs <mark@lazycat.hu>

* fix: Hit caching

Signed-off-by: Mark Tolmacs <mark@lazycat.hu>

* fix: Simple arrow mid point selection inconsistency

Signed-off-by: Mark Tolmacs <mark@lazycat.hu>

* fix: cache override

Signed-off-by: Mark Tolmacs <mark@lazycat.hu>

* fix: Precise know dragging with midpoint refactor

Signed-off-by: Mark Tolmacs <mark@lazycat.hu>

* fear: Frame support

Signed-off-by: Mark Tolmacs <mark@lazycat.hu>

* fix: Crossing arrow won't trigger mid point

Signed-off-by: Mark Tolmacs <mark@lazycat.hu>

* fix: Arrow creation point highlight

Signed-off-by: Mark Tolmacs <mark@lazycat.hu>

* fix: Restore types & tests

Signed-off-by: Mark Tolmacs <mark@lazycat.hu>

* chore: Restore restore.ts

Signed-off-by: Mark Tolmacs <mark@lazycat.hu>

* fix: restore.ts

Signed-off-by: Mark Tolmacs <mark@lazycat.hu>

* fix: Elbow arrows reliably highlight center point

Signed-off-by: Mark Tolmacs <mark@lazycat.hu>

* fix: Highlight point ordering

Signed-off-by: Mark Tolmacs <mark@lazycat.hu>

* feat: Bind with focus point across shape

Signed-off-by: Mark Tolmacs <mark@lazycat.hu>

* fix: Lint

* fix: Midpoint and binding alignment

Signed-off-by: Mark Tolmacs <mark@lazycat.hu>

* chore: Indicator color

Signed-off-by: Mark Tolmacs <mark@lazycat.hu>

* chore: More knob tuning

Signed-off-by: Mark Tolmacs <mark@lazycat.hu>

* fix: Radius

Signed-off-by: Mark Tolmacs <mark@lazycat.hu>

* fix: Tests

Signed-off-by: Mark Tolmacs <mark@lazycat.hu>

* simplify point indicators

---------

Signed-off-by: Mark Tolmacs <mark@lazycat.hu>
Co-authored-by: dwelle <5153846+dwelle@users.noreply.github.com>
2026-02-11 11:06:27 +01:00

86 lines
2.3 KiB
TypeScript

import React from "react";
import { expect } from "vitest";
import { reseed } from "@excalidraw/common";
import { Excalidraw } from "../index";
import { UI } from "./helpers/ui";
import { render, unmountComponent } from "./test-utils";
unmountComponent();
beforeEach(() => {
localStorage.clear();
reseed(7);
});
test("unselected bound arrow updates when rotating its target element", async () => {
await render(<Excalidraw />);
const rectangle = UI.createElement("rectangle", {
width: 200,
height: 100,
});
const arrow = UI.createElement("arrow", {
x: -80,
y: 50,
width: 85,
height: 0,
});
expect(arrow.endBinding?.elementId).toEqual(rectangle.id);
UI.rotate(rectangle, [60, 36], { shift: true });
expect(arrow.endBinding?.elementId).toEqual(rectangle.id);
expect(arrow.x).toBeCloseTo(-80);
expect(arrow.y).toBeCloseTo(50);
expect(arrow.width).toBeCloseTo(132.491, 1);
expect(arrow.height).toBeCloseTo(82.267, 1);
});
test("unselected bound arrows update when rotating their target elements", async () => {
await render(<Excalidraw />);
const ellipse = UI.createElement("ellipse", {
x: 0,
y: 80,
width: 300,
height: 120,
});
const ellipseArrow = UI.createElement("arrow", {
x: -10,
y: 80,
width: 50,
height: 60,
});
const text = UI.createElement("text", {
position: 220,
});
await UI.editText(text, "test");
const textArrow = UI.createElement("arrow", {
x: 360,
y: 300,
width: -140,
height: -60,
});
expect(ellipseArrow.endBinding?.elementId).toEqual(ellipse.id);
expect(textArrow.endBinding?.elementId).toEqual(text.id);
UI.rotate([ellipse, text], [-82, 23], { shift: true });
expect(ellipseArrow.endBinding?.elementId).toEqual(ellipse.id);
expect(ellipseArrow.x).toEqual(-10);
expect(ellipseArrow.y).toEqual(80);
expect(ellipseArrow.points[0]).toEqual([0, 0]);
expect(ellipseArrow.points[1][0]).toBeCloseTo(66.317, 1);
expect(ellipseArrow.points[1][1]).toBeCloseTo(144.38, 1);
expect(textArrow.endBinding?.elementId).toEqual(text.id);
expect(textArrow.x).toEqual(360);
expect(textArrow.y).toEqual(300);
expect(textArrow.points[0]).toEqual([0, 0]);
expect(textArrow.points[1][0]).toBeCloseTo(-95.4635969899922, 0);
expect(textArrow.points[1][1]).toBeCloseTo(-126.8785027399889, 0);
});