@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.d.cts CHANGED
@@ -583,6 +583,7 @@ declare class Viewport {
583
583
  private readonly noteEditor;
584
584
  private readonly arrowLabelEditor;
585
585
  private readonly historyRecorder;
586
+ private transactionDepth;
586
587
  private readonly selectionOps;
587
588
  readonly toolContext: ToolContext;
588
589
  private readonly marginViewport;
@@ -616,6 +617,14 @@ declare class Viewport {
616
617
  loadJSON(json: string): void;
617
618
  setTool(name: string): void;
618
619
  get shortcuts(): ShortcutsApi;
620
+ /**
621
+ * Groups synchronous local store and layer mutations into one undo step.
622
+ * Nested calls join the outer transaction. If the callback throws, mutations
623
+ * already applied remain undoable and the original error is rethrown.
624
+ */
625
+ transaction<T>(operation: () => T): T;
626
+ /** Removes existing elements as one undoable operation and returns the number removed. */
627
+ removeElements(ids: Iterable<string>): number;
619
628
  undo(): boolean;
620
629
  redo(): boolean;
621
630
  addImage(src: string, position: {
@@ -1158,6 +1167,6 @@ declare class LaserTool implements Tool {
1158
1167
  private notifyOptionsChange;
1159
1168
  }
1160
1169
 
1161
- declare const VERSION = "0.52.1";
1170
+ declare const VERSION = "0.53.0";
1162
1171
 
1163
1172
  export { type ActiveFormats, type AlignEdge, type ArrowElement, type ArrowStrokeStyle, ArrowTool, type ArrowToolOptions, AutoSave, type AutoSaveOptions, type BackgroundOptions, type BackgroundPattern, type Binding, type Bounds, Camera, type CameraChangeInfo, type CameraOptions, type CanvasElement, type CanvasState, type Command, DEFAULT_NOTE_FONT_SIZE, type DistributeAxis, type ElementChangeMeta, ElementStore, type ElementStyle, type ElementType, type ElementUpdateEvent, EraserTool, type EraserToolOptions, type ExportAssetError, type ExportAssetErrorReason, type ExportImageOptions, type ExportResourceOptions, type ExportSvgOptions, type FontSizePreset, type GridElement, type GridInfo, HandTool, type HexOrientation, HistoryStack, type HistoryStackOptions, type HtmlElement, type HtmlExportError, type HtmlExportErrorReason, type HtmlExportOptions, type HtmlExportRenderer, type ImageElement, ImageTool, type ImageToolOptions, IndexedDBAdapter, type IndexedDBAdapterOptions, LaserTool, type LaserToolOptions, type Layer, LayerManager, LocalStorageAdapter, MeasureTool, type MeasureToolOptions, type Measurement, MemoryAdapter, type NoteElement, NoteTool, type NoteToolOptions, PencilTool, type PencilToolOptions, type Point, type PointerState, type RenderStatsSnapshot, type RotateDirection, SelectTool, type ShapeElement, type ShapeKind, ShapeTool, type ShapeToolOptions, type ShortcutBindings, type ShortcutOptions, type ShortcutsApi, type Size, type StorageAdapter, type StrokeElement, type StrokePoint, type TemplateElement, type TemplateRenderStyle, type TemplateShape, TemplateTool, type TemplateToolOptions, type TextElement, TextTool, type TextToolOptions, type Tool, type ToolContext, ToolManager, type ToolName, VERSION, Viewport, type ViewportOptions, boundsIntersect, createArrow, createGrid, createHtmlElement, createImage, createNote, createShape, createStroke, createTemplate, createText, drawHexPath, exportImage, exportSvg, getActiveFormats, getArrowBounds, getArrowControlPoint, getArrowMidpoint, getArrowTangentAngle, getBendFromPoint, getElementBounds, getElementStyle, getElementsBoundingBox, getHexCellsInCone, getHexCellsInLine, getHexCellsInRadius, getHexCellsInRectangle, getHexCellsInSquare, getHexDistance, isNearBezier, setFontSize, smartSnap, snapPoint, snapToHexCenter, styleToPatch, toggleBold, toggleItalic, toggleStrikethrough, toggleUnderline };
package/dist/index.d.ts CHANGED
@@ -583,6 +583,7 @@ declare class Viewport {
583
583
  private readonly noteEditor;
584
584
  private readonly arrowLabelEditor;
585
585
  private readonly historyRecorder;
586
+ private transactionDepth;
586
587
  private readonly selectionOps;
587
588
  readonly toolContext: ToolContext;
588
589
  private readonly marginViewport;
@@ -616,6 +617,14 @@ declare class Viewport {
616
617
  loadJSON(json: string): void;
617
618
  setTool(name: string): void;
618
619
  get shortcuts(): ShortcutsApi;
620
+ /**
621
+ * Groups synchronous local store and layer mutations into one undo step.
622
+ * Nested calls join the outer transaction. If the callback throws, mutations
623
+ * already applied remain undoable and the original error is rethrown.
624
+ */
625
+ transaction<T>(operation: () => T): T;
626
+ /** Removes existing elements as one undoable operation and returns the number removed. */
627
+ removeElements(ids: Iterable<string>): number;
619
628
  undo(): boolean;
620
629
  redo(): boolean;
621
630
  addImage(src: string, position: {
@@ -1158,6 +1167,6 @@ declare class LaserTool implements Tool {
1158
1167
  private notifyOptionsChange;
1159
1168
  }
1160
1169
 
1161
- declare const VERSION = "0.52.1";
1170
+ declare const VERSION = "0.53.0";
1162
1171
 
1163
1172
  export { type ActiveFormats, type AlignEdge, type ArrowElement, type ArrowStrokeStyle, ArrowTool, type ArrowToolOptions, AutoSave, type AutoSaveOptions, type BackgroundOptions, type BackgroundPattern, type Binding, type Bounds, Camera, type CameraChangeInfo, type CameraOptions, type CanvasElement, type CanvasState, type Command, DEFAULT_NOTE_FONT_SIZE, type DistributeAxis, type ElementChangeMeta, ElementStore, type ElementStyle, type ElementType, type ElementUpdateEvent, EraserTool, type EraserToolOptions, type ExportAssetError, type ExportAssetErrorReason, type ExportImageOptions, type ExportResourceOptions, type ExportSvgOptions, type FontSizePreset, type GridElement, type GridInfo, HandTool, type HexOrientation, HistoryStack, type HistoryStackOptions, type HtmlElement, type HtmlExportError, type HtmlExportErrorReason, type HtmlExportOptions, type HtmlExportRenderer, type ImageElement, ImageTool, type ImageToolOptions, IndexedDBAdapter, type IndexedDBAdapterOptions, LaserTool, type LaserToolOptions, type Layer, LayerManager, LocalStorageAdapter, MeasureTool, type MeasureToolOptions, type Measurement, MemoryAdapter, type NoteElement, NoteTool, type NoteToolOptions, PencilTool, type PencilToolOptions, type Point, type PointerState, type RenderStatsSnapshot, type RotateDirection, SelectTool, type ShapeElement, type ShapeKind, ShapeTool, type ShapeToolOptions, type ShortcutBindings, type ShortcutOptions, type ShortcutsApi, type Size, type StorageAdapter, type StrokeElement, type StrokePoint, type TemplateElement, type TemplateRenderStyle, type TemplateShape, TemplateTool, type TemplateToolOptions, type TextElement, TextTool, type TextToolOptions, type Tool, type ToolContext, ToolManager, type ToolName, VERSION, Viewport, type ViewportOptions, boundsIntersect, createArrow, createGrid, createHtmlElement, createImage, createNote, createShape, createStroke, createTemplate, createText, drawHexPath, exportImage, exportSvg, getActiveFormats, getArrowBounds, getArrowControlPoint, getArrowMidpoint, getArrowTangentAngle, getBendFromPoint, getElementBounds, getElementStyle, getElementsBoundingBox, getHexCellsInCone, getHexCellsInLine, getHexCellsInRadius, getHexCellsInRectangle, getHexCellsInSquare, getHexDistance, isNearBezier, setFontSize, smartSnap, snapPoint, snapToHexCenter, styleToPatch, toggleBold, toggleItalic, toggleStrikethrough, toggleUnderline };
package/dist/index.js CHANGED
@@ -896,6 +896,12 @@ function getElementBounds(element) {
896
896
  }
897
897
  return null;
898
898
  }
899
+ function getElementVisualBounds(element) {
900
+ const bounds = getElementBounds(element);
901
+ if (!bounds) return null;
902
+ const rotation = element.rotation ?? 0;
903
+ return rotation === 0 ? bounds : rotatedAABB(bounds, rotation);
904
+ }
899
905
  function getArrowBoundsAnalytical(from, to, bend) {
900
906
  if (bend === 0) {
901
907
  const minX2 = Math.min(from.x, to.x);
@@ -2667,10 +2673,7 @@ var ElementStore = class {
2667
2673
  // Spatial index stores the rotation-expanded AABB so rotated elements remain
2668
2674
  // broad-phase hit-test/marquee candidates; precise tests run against local bounds.
2669
2675
  indexBounds(element) {
2670
- const bounds = getElementBounds(element);
2671
- if (!bounds) return null;
2672
- const angle = element.rotation ?? 0;
2673
- return angle === 0 ? bounds : rotatedAABB(bounds, angle);
2676
+ return getElementVisualBounds(element);
2674
2677
  }
2675
2678
  add(element, meta) {
2676
2679
  element = sanitizeRichText(element);
@@ -6991,7 +6994,7 @@ var RenderLoop = class {
6991
6994
  if (this.renderer.isDomElement(element)) {
6992
6995
  activeHybridOrder = null;
6993
6996
  const layerOpacity = this.layerManager.getLayer?.(element.layerId)?.opacity ?? 1;
6994
- const elBounds = getElementBounds(element);
6997
+ const elBounds = getElementVisualBounds(element);
6995
6998
  if (elBounds && !boundsIntersect(elBounds, cullingRect)) {
6996
6999
  this.domNodeManager.hideDomNode(element.id);
6997
7000
  } else {
@@ -7048,7 +7051,7 @@ var RenderLoop = class {
7048
7051
  offCtx.save();
7049
7052
  this.marginViewport.applyRenderTransform(offCtx);
7050
7053
  for (const element of elements) {
7051
- const elBounds = getElementBounds(element);
7054
+ const elBounds = getElementVisualBounds(element);
7052
7055
  if (elBounds && !boundsIntersect(elBounds, cullingRect)) continue;
7053
7056
  this.renderer.renderCanvasElement(offCtx, element);
7054
7057
  }
@@ -7123,7 +7126,7 @@ var RenderLoop = class {
7123
7126
  hybridCtx.translate(this.camera.position.x, this.camera.position.y);
7124
7127
  hybridCtx.scale(this.camera.zoom, this.camera.zoom);
7125
7128
  for (const element of elements) {
7126
- const elBounds = getElementBounds(element);
7129
+ const elBounds = getElementVisualBounds(element);
7127
7130
  if (elBounds && !boundsIntersect(elBounds, cullingRect)) continue;
7128
7131
  hybridCtx.save();
7129
7132
  hybridCtx.globalAlpha = this.layerManager.getLayer?.(element.layerId)?.opacity ?? 1;
@@ -8094,6 +8097,7 @@ var Viewport = class {
8094
8097
  noteEditor;
8095
8098
  arrowLabelEditor;
8096
8099
  historyRecorder;
8100
+ transactionDepth = 0;
8097
8101
  selectionOps;
8098
8102
  toolContext;
8099
8103
  marginViewport;
@@ -8207,6 +8211,35 @@ var Viewport = class {
8207
8211
  get shortcuts() {
8208
8212
  return this.inputHandler.shortcuts;
8209
8213
  }
8214
+ /**
8215
+ * Groups synchronous local store and layer mutations into one undo step.
8216
+ * Nested calls join the outer transaction. If the callback throws, mutations
8217
+ * already applied remain undoable and the original error is rethrown.
8218
+ */
8219
+ transaction(operation) {
8220
+ const isOuterTransaction = this.transactionDepth === 0;
8221
+ if (isOuterTransaction) {
8222
+ this.inputHandler.flushPendingHistory();
8223
+ this.historyRecorder.begin();
8224
+ }
8225
+ this.transactionDepth += 1;
8226
+ try {
8227
+ return operation();
8228
+ } finally {
8229
+ this.transactionDepth -= 1;
8230
+ if (isOuterTransaction) this.historyRecorder.commit();
8231
+ }
8232
+ }
8233
+ /** Removes existing elements as one undoable operation and returns the number removed. */
8234
+ removeElements(ids) {
8235
+ const existingIds = [...new Set(ids)].filter((id) => this.store.getById(id) !== void 0);
8236
+ if (existingIds.length === 0) return 0;
8237
+ this.transaction(() => {
8238
+ for (const id of existingIds) this.store.remove(id);
8239
+ });
8240
+ this.requestRender();
8241
+ return existingIds.length;
8242
+ }
8210
8243
  undo() {
8211
8244
  this.inputHandler.flushPendingHistory();
8212
8245
  this.historyRecorder.pause();
@@ -11122,7 +11155,7 @@ var LaserTool = class {
11122
11155
  };
11123
11156
 
11124
11157
  // src/index.ts
11125
- var VERSION = "0.52.1";
11158
+ var VERSION = "0.53.0";
11126
11159
  export {
11127
11160
  ArrowTool,
11128
11161
  AutoSave,