@fieldnotes/core 0.48.0 → 0.49.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -1242,6 +1242,14 @@ var KeyboardActions = class {
1242
1242
  if (this.deps.isToolActive()) return;
1243
1243
  this.deps.toggleLock?.();
1244
1244
  }
1245
+ rotate(direction) {
1246
+ if (this.deps.isToolActive()) return;
1247
+ this.flushPendingNudge();
1248
+ const sel = this.selectTool();
1249
+ if (!sel) return;
1250
+ if (sel.tool.selectedIds.length === 0) return;
1251
+ this.deps.rotate?.(direction);
1252
+ }
1245
1253
  zOrder(operation) {
1246
1254
  if (this.deps.isToolActive()) return;
1247
1255
  this.flushPendingNudge();
@@ -1346,6 +1354,8 @@ var DEFAULT_BINDINGS = [
1346
1354
  ["ungroup", ["mod+shift+g"]],
1347
1355
  ["cut", ["mod+x"]],
1348
1356
  ["toggle-lock", ["mod+shift+l"]],
1357
+ ["rotate-cw", ["r"]],
1358
+ ["rotate-ccw", ["shift+r"]],
1349
1359
  ["nudge-left", ["arrowleft"]],
1350
1360
  ["nudge-right", ["arrowright"]],
1351
1361
  ["nudge-up", ["arrowup"]],
@@ -1658,6 +1668,14 @@ var KeyboardHandler = class {
1658
1668
  e?.preventDefault();
1659
1669
  this.deps.actions.toggleLock();
1660
1670
  return;
1671
+ case "rotate-cw":
1672
+ e?.preventDefault();
1673
+ this.deps.actions.rotate("cw");
1674
+ return;
1675
+ case "rotate-ccw":
1676
+ e?.preventDefault();
1677
+ this.deps.actions.rotate("ccw");
1678
+ return;
1661
1679
  case "zoom-in":
1662
1680
  e?.preventDefault();
1663
1681
  this.zoomByFactor(ZOOM_STEP);
@@ -1794,6 +1812,7 @@ var InputHandler = class {
1794
1812
  group: options.group,
1795
1813
  ungroup: options.ungroup,
1796
1814
  toggleLock: options.toggleLock,
1815
+ rotate: options.rotate,
1797
1816
  getLastPointerWorld: () => this.lastPointerWorld()
1798
1817
  });
1799
1818
  this.openContextMenu = options.openContextMenu;
@@ -6882,7 +6901,7 @@ function getElementStyle(element) {
6882
6901
  }
6883
6902
  }
6884
6903
 
6885
- // src/canvas/selection-ops.ts
6904
+ // src/canvas/selection-rotate.ts
6886
6905
  function unionBounds2(list) {
6887
6906
  let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;
6888
6907
  for (const b of list) {
@@ -6893,6 +6912,39 @@ function unionBounds2(list) {
6893
6912
  }
6894
6913
  return { x: minX, y: minY, w: maxX - minX, h: maxY - minY };
6895
6914
  }
6915
+ function rotationPivot(items) {
6916
+ const first = items[0];
6917
+ if (items.length === 1 && first) {
6918
+ return { x: first.bounds.x + first.bounds.w / 2, y: first.bounds.y + first.bounds.h / 2 };
6919
+ }
6920
+ const u = unionBounds2(items.map((it) => rotatedAABB(it.bounds, it.el.rotation ?? 0)));
6921
+ return { x: u.x + u.w / 2, y: u.y + u.h / 2 };
6922
+ }
6923
+ function rotateElementPatch(el, bounds, pivot, delta) {
6924
+ if (el.type === "arrow") {
6925
+ const center3 = { x: bounds.x + bounds.w / 2, y: bounds.y + bounds.h / 2 };
6926
+ const moved2 = rotatePoint(center3, pivot, delta);
6927
+ return {
6928
+ position: { x: el.position.x + moved2.x - center3.x, y: el.position.y + moved2.y - center3.y },
6929
+ from: rotatePoint(el.from, pivot, delta),
6930
+ to: rotatePoint(el.to, pivot, delta)
6931
+ };
6932
+ }
6933
+ if (el.type === "template") {
6934
+ return {
6935
+ position: rotatePoint(el.position, pivot, delta),
6936
+ angle: normalizeAngle(el.angle + delta)
6937
+ };
6938
+ }
6939
+ const center2 = { x: bounds.x + bounds.w / 2, y: bounds.y + bounds.h / 2 };
6940
+ const moved = rotatePoint(center2, pivot, delta);
6941
+ return {
6942
+ position: { x: el.position.x + moved.x - center2.x, y: el.position.y + moved.y - center2.y },
6943
+ rotation: normalizeAngle((el.rotation ?? 0) + delta)
6944
+ };
6945
+ }
6946
+
6947
+ // src/canvas/selection-ops.ts
6896
6948
  function sharedValue(values) {
6897
6949
  const present = values.filter((v) => v !== void 0);
6898
6950
  if (present.length === 0) return void 0;
@@ -7040,6 +7092,21 @@ var SelectionOps = class {
7040
7092
  this.deps.recorder.commit();
7041
7093
  this.deps.requestRender();
7042
7094
  }
7095
+ rotateSelection(direction) {
7096
+ const eligible = this.boundedSelection().filter(({ el }) => this.isMovable(el));
7097
+ if (eligible.length === 0) return;
7098
+ const delta = direction === "cw" ? Math.PI / 2 : -Math.PI / 2;
7099
+ const pivot = rotationPivot(eligible);
7100
+ this.deps.recorder.begin();
7101
+ const moved = [];
7102
+ for (const { id, el, bounds } of eligible) {
7103
+ this.deps.store.update(id, rotateElementPatch(el, bounds, pivot, delta));
7104
+ moved.push(id);
7105
+ }
7106
+ updateArrowsBoundToElements(moved, this.deps.store);
7107
+ this.deps.recorder.commit();
7108
+ this.deps.requestRender();
7109
+ }
7043
7110
  boundedSelection() {
7044
7111
  const out = [];
7045
7112
  for (const id of this.deps.getSelectedIds()) {
@@ -7368,6 +7435,7 @@ var Viewport = class {
7368
7435
  group: () => this.groupSelection(),
7369
7436
  ungroup: () => this.ungroupSelection(),
7370
7437
  toggleLock: () => this.toggleLockSelection(),
7438
+ rotate: (direction) => this.rotateSelection(direction),
7371
7439
  openContextMenu: (screenPos, world) => {
7372
7440
  this.getSelectTool()?.selectAtPoint(world, this.toolContext);
7373
7441
  this.openContextMenu(screenPos);
@@ -7765,6 +7833,8 @@ var Viewport = class {
7765
7833
  items.push({ label: "Bring Forward", action: "z-forward" });
7766
7834
  items.push({ label: "Send Backward", action: "z-backward" });
7767
7835
  items.push({ label: "Send to Back", action: "z-back" });
7836
+ items.push({ label: "Rotate 90\xB0 CW", action: "rotate-cw" });
7837
+ items.push({ label: "Rotate 90\xB0 CCW", action: "rotate-ccw" });
7768
7838
  const allLocked = ids.every((id) => this.store.getById(id)?.locked);
7769
7839
  items.push({ label: allLocked ? "Unlock" : "Lock", action: "toggle-lock" });
7770
7840
  } else if (this.canPaste()) {
@@ -7798,6 +7868,9 @@ var Viewport = class {
7798
7868
  distributeSelection(axis) {
7799
7869
  this.selectionOps.distribute(axis);
7800
7870
  }
7871
+ rotateSelection(direction) {
7872
+ this.selectionOps.rotateSelection(direction);
7873
+ }
7801
7874
  getRenderStats() {
7802
7875
  return this.renderLoop.getStats();
7803
7876
  }
@@ -10540,7 +10613,7 @@ var LaserTool = class {
10540
10613
  };
10541
10614
 
10542
10615
  // src/index.ts
10543
- var VERSION = "0.48.0";
10616
+ var VERSION = "0.49.0";
10544
10617
  // Annotate the CommonJS export names for ESM import in node:
10545
10618
  0 && (module.exports = {
10546
10619
  ArrowTool,