@fieldnotes/core 0.52.1 → 0.53.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
@@ -983,6 +983,12 @@ function getElementBounds(element) {
983
983
  }
984
984
  return null;
985
985
  }
986
+ function getElementVisualBounds(element) {
987
+ const bounds = getElementBounds(element);
988
+ if (!bounds) return null;
989
+ const rotation = element.rotation ?? 0;
990
+ return rotation === 0 ? bounds : rotatedAABB(bounds, rotation);
991
+ }
986
992
  function getArrowBoundsAnalytical(from, to, bend) {
987
993
  if (bend === 0) {
988
994
  const minX2 = Math.min(from.x, to.x);
@@ -2754,10 +2760,7 @@ var ElementStore = class {
2754
2760
  // Spatial index stores the rotation-expanded AABB so rotated elements remain
2755
2761
  // broad-phase hit-test/marquee candidates; precise tests run against local bounds.
2756
2762
  indexBounds(element) {
2757
- const bounds = getElementBounds(element);
2758
- if (!bounds) return null;
2759
- const angle = element.rotation ?? 0;
2760
- return angle === 0 ? bounds : rotatedAABB(bounds, angle);
2763
+ return getElementVisualBounds(element);
2761
2764
  }
2762
2765
  add(element, meta) {
2763
2766
  element = sanitizeRichText(element);
@@ -7078,7 +7081,7 @@ var RenderLoop = class {
7078
7081
  if (this.renderer.isDomElement(element)) {
7079
7082
  activeHybridOrder = null;
7080
7083
  const layerOpacity = this.layerManager.getLayer?.(element.layerId)?.opacity ?? 1;
7081
- const elBounds = getElementBounds(element);
7084
+ const elBounds = getElementVisualBounds(element);
7082
7085
  if (elBounds && !boundsIntersect(elBounds, cullingRect)) {
7083
7086
  this.domNodeManager.hideDomNode(element.id);
7084
7087
  } else {
@@ -7135,7 +7138,7 @@ var RenderLoop = class {
7135
7138
  offCtx.save();
7136
7139
  this.marginViewport.applyRenderTransform(offCtx);
7137
7140
  for (const element of elements) {
7138
- const elBounds = getElementBounds(element);
7141
+ const elBounds = getElementVisualBounds(element);
7139
7142
  if (elBounds && !boundsIntersect(elBounds, cullingRect)) continue;
7140
7143
  this.renderer.renderCanvasElement(offCtx, element);
7141
7144
  }
@@ -7210,7 +7213,7 @@ var RenderLoop = class {
7210
7213
  hybridCtx.translate(this.camera.position.x, this.camera.position.y);
7211
7214
  hybridCtx.scale(this.camera.zoom, this.camera.zoom);
7212
7215
  for (const element of elements) {
7213
- const elBounds = getElementBounds(element);
7216
+ const elBounds = getElementVisualBounds(element);
7214
7217
  if (elBounds && !boundsIntersect(elBounds, cullingRect)) continue;
7215
7218
  hybridCtx.save();
7216
7219
  hybridCtx.globalAlpha = this.layerManager.getLayer?.(element.layerId)?.opacity ?? 1;
@@ -8181,6 +8184,7 @@ var Viewport = class {
8181
8184
  noteEditor;
8182
8185
  arrowLabelEditor;
8183
8186
  historyRecorder;
8187
+ transactionDepth = 0;
8184
8188
  selectionOps;
8185
8189
  toolContext;
8186
8190
  marginViewport;
@@ -8294,6 +8298,35 @@ var Viewport = class {
8294
8298
  get shortcuts() {
8295
8299
  return this.inputHandler.shortcuts;
8296
8300
  }
8301
+ /**
8302
+ * Groups synchronous local store and layer mutations into one undo step.
8303
+ * Nested calls join the outer transaction. If the callback throws, mutations
8304
+ * already applied remain undoable and the original error is rethrown.
8305
+ */
8306
+ transaction(operation) {
8307
+ const isOuterTransaction = this.transactionDepth === 0;
8308
+ if (isOuterTransaction) {
8309
+ this.inputHandler.flushPendingHistory();
8310
+ this.historyRecorder.begin();
8311
+ }
8312
+ this.transactionDepth += 1;
8313
+ try {
8314
+ return operation();
8315
+ } finally {
8316
+ this.transactionDepth -= 1;
8317
+ if (isOuterTransaction) this.historyRecorder.commit();
8318
+ }
8319
+ }
8320
+ /** Removes existing elements as one undoable operation and returns the number removed. */
8321
+ removeElements(ids) {
8322
+ const existingIds = [...new Set(ids)].filter((id) => this.store.getById(id) !== void 0);
8323
+ if (existingIds.length === 0) return 0;
8324
+ this.transaction(() => {
8325
+ for (const id of existingIds) this.store.remove(id);
8326
+ });
8327
+ this.requestRender();
8328
+ return existingIds.length;
8329
+ }
8297
8330
  undo() {
8298
8331
  this.inputHandler.flushPendingHistory();
8299
8332
  this.historyRecorder.pause();
@@ -11209,7 +11242,7 @@ var LaserTool = class {
11209
11242
  };
11210
11243
 
11211
11244
  // src/index.ts
11212
- var VERSION = "0.52.1";
11245
+ var VERSION = "0.53.0";
11213
11246
  // Annotate the CommonJS export names for ESM import in node:
11214
11247
  0 && (module.exports = {
11215
11248
  ArrowTool,