@fieldnotes/core 0.45.0 → 0.46.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
@@ -162,6 +162,14 @@ interface ElementUpdateEvent {
162
162
  previous: CanvasElement;
163
163
  current: CanvasElement;
164
164
  }
165
+ interface ElementChangeMeta {
166
+ /**
167
+ * Identifies what caused the change. `undefined` or `'local'` = a local change (recorded to undo
168
+ * history and observed as local). Any other value (e.g. `'remote'`) marks an externally-applied
169
+ * change: it is NOT recorded to undo history, and is tagged so observers can avoid re-broadcasting it.
170
+ */
171
+ origin?: string;
172
+ }
165
173
  interface ElementStoreEvents {
166
174
  add: CanvasElement;
167
175
  remove: CanvasElement;
@@ -184,19 +192,19 @@ declare class ElementStore {
184
192
  type: T;
185
193
  }>[];
186
194
  private indexBounds;
187
- add(element: CanvasElement): void;
188
- update(id: string, partial: Partial<CanvasElement>): void;
189
- remove(id: string): void;
190
- clear(): void;
195
+ add(element: CanvasElement, meta?: ElementChangeMeta): void;
196
+ update(id: string, partial: Partial<CanvasElement>, meta?: ElementChangeMeta): void;
197
+ remove(id: string, meta?: ElementChangeMeta): void;
198
+ clear(meta?: ElementChangeMeta): void;
191
199
  snapshot(): CanvasElement[];
192
- loadSnapshot(elements: CanvasElement[]): void;
200
+ loadSnapshot(elements: CanvasElement[], meta?: ElementChangeMeta): void;
193
201
  bringToFront(id: string): void;
194
202
  sendToBack(id: string): void;
195
203
  bringForward(id: string): void;
196
204
  sendBackward(id: string): void;
197
205
  queryRect(rect: Bounds): CanvasElement[];
198
206
  queryPoint(point: Point): CanvasElement[];
199
- on<K extends keyof ElementStoreEvents>(event: K, listener: (data: ElementStoreEvents[K]) => void): () => void;
207
+ on<K extends keyof ElementStoreEvents>(event: K, listener: (data: ElementStoreEvents[K], meta: ElementChangeMeta) => void): () => void;
200
208
  onChange(listener: () => void): () => void;
201
209
  }
202
210
 
@@ -1105,6 +1113,6 @@ declare class LaserTool implements Tool {
1105
1113
  private notifyOptionsChange;
1106
1114
  }
1107
1115
 
1108
- declare const VERSION = "0.45.0";
1116
+ declare const VERSION = "0.46.0";
1109
1117
 
1110
- 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, ElementStore, type ElementStyle, type ElementType, type ElementUpdateEvent, EraserTool, type EraserToolOptions, type ExportImageOptions, type ExportSvgOptions, type FontSizePreset, type GridElement, type GridInfo, HandTool, type HexOrientation, HistoryStack, type HistoryStackOptions, type HtmlElement, 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, 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, getHexCellsInSquare, getHexDistance, isNearBezier, setFontSize, smartSnap, snapPoint, snapToHexCenter, styleToPatch, toggleBold, toggleItalic, toggleStrikethrough, toggleUnderline };
1118
+ 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 ExportImageOptions, type ExportSvgOptions, type FontSizePreset, type GridElement, type GridInfo, HandTool, type HexOrientation, HistoryStack, type HistoryStackOptions, type HtmlElement, 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, 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, getHexCellsInSquare, getHexDistance, isNearBezier, setFontSize, smartSnap, snapPoint, snapToHexCenter, styleToPatch, toggleBold, toggleItalic, toggleStrikethrough, toggleUnderline };
package/dist/index.d.ts CHANGED
@@ -162,6 +162,14 @@ interface ElementUpdateEvent {
162
162
  previous: CanvasElement;
163
163
  current: CanvasElement;
164
164
  }
165
+ interface ElementChangeMeta {
166
+ /**
167
+ * Identifies what caused the change. `undefined` or `'local'` = a local change (recorded to undo
168
+ * history and observed as local). Any other value (e.g. `'remote'`) marks an externally-applied
169
+ * change: it is NOT recorded to undo history, and is tagged so observers can avoid re-broadcasting it.
170
+ */
171
+ origin?: string;
172
+ }
165
173
  interface ElementStoreEvents {
166
174
  add: CanvasElement;
167
175
  remove: CanvasElement;
@@ -184,19 +192,19 @@ declare class ElementStore {
184
192
  type: T;
185
193
  }>[];
186
194
  private indexBounds;
187
- add(element: CanvasElement): void;
188
- update(id: string, partial: Partial<CanvasElement>): void;
189
- remove(id: string): void;
190
- clear(): void;
195
+ add(element: CanvasElement, meta?: ElementChangeMeta): void;
196
+ update(id: string, partial: Partial<CanvasElement>, meta?: ElementChangeMeta): void;
197
+ remove(id: string, meta?: ElementChangeMeta): void;
198
+ clear(meta?: ElementChangeMeta): void;
191
199
  snapshot(): CanvasElement[];
192
- loadSnapshot(elements: CanvasElement[]): void;
200
+ loadSnapshot(elements: CanvasElement[], meta?: ElementChangeMeta): void;
193
201
  bringToFront(id: string): void;
194
202
  sendToBack(id: string): void;
195
203
  bringForward(id: string): void;
196
204
  sendBackward(id: string): void;
197
205
  queryRect(rect: Bounds): CanvasElement[];
198
206
  queryPoint(point: Point): CanvasElement[];
199
- on<K extends keyof ElementStoreEvents>(event: K, listener: (data: ElementStoreEvents[K]) => void): () => void;
207
+ on<K extends keyof ElementStoreEvents>(event: K, listener: (data: ElementStoreEvents[K], meta: ElementChangeMeta) => void): () => void;
200
208
  onChange(listener: () => void): () => void;
201
209
  }
202
210
 
@@ -1105,6 +1113,6 @@ declare class LaserTool implements Tool {
1105
1113
  private notifyOptionsChange;
1106
1114
  }
1107
1115
 
1108
- declare const VERSION = "0.45.0";
1116
+ declare const VERSION = "0.46.0";
1109
1117
 
1110
- 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, ElementStore, type ElementStyle, type ElementType, type ElementUpdateEvent, EraserTool, type EraserToolOptions, type ExportImageOptions, type ExportSvgOptions, type FontSizePreset, type GridElement, type GridInfo, HandTool, type HexOrientation, HistoryStack, type HistoryStackOptions, type HtmlElement, 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, 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, getHexCellsInSquare, getHexDistance, isNearBezier, setFontSize, smartSnap, snapPoint, snapToHexCenter, styleToPatch, toggleBold, toggleItalic, toggleStrikethrough, toggleUnderline };
1118
+ 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 ExportImageOptions, type ExportSvgOptions, type FontSizePreset, type GridElement, type GridInfo, HandTool, type HexOrientation, HistoryStack, type HistoryStackOptions, type HtmlElement, 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, 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, getHexCellsInSquare, getHexDistance, isNearBezier, setFontSize, smartSnap, snapPoint, snapToHexCenter, styleToPatch, toggleBold, toggleItalic, toggleStrikethrough, toggleUnderline };
package/dist/index.js CHANGED
@@ -2146,6 +2146,7 @@ var Background = class {
2146
2146
  };
2147
2147
 
2148
2148
  // src/core/event-bus.ts
2149
+ var EMPTY_META = Object.freeze({});
2149
2150
  var EventBus = class {
2150
2151
  listeners = /* @__PURE__ */ new Map();
2151
2152
  on(event, listener) {
@@ -2161,10 +2162,10 @@ var EventBus = class {
2161
2162
  off(event, listener) {
2162
2163
  this.listeners.get(event)?.delete(listener);
2163
2164
  }
2164
- emit(event, data) {
2165
+ emit(event, data, meta = EMPTY_META) {
2165
2166
  this.listeners.get(event)?.forEach((listener) => {
2166
2167
  try {
2167
- listener(data);
2168
+ listener(data, meta);
2168
2169
  } catch (err) {
2169
2170
  console.error(`[fieldnotes] listener error for "${String(event)}"`, err);
2170
2171
  }
@@ -2484,15 +2485,15 @@ var ElementStore = class {
2484
2485
  const angle = element.rotation ?? 0;
2485
2486
  return angle === 0 ? bounds : rotatedAABB(bounds, angle);
2486
2487
  }
2487
- add(element) {
2488
+ add(element, meta) {
2488
2489
  this.sortedCache = null;
2489
2490
  this._versions.set(element.id, 0);
2490
2491
  this.elements.set(element.id, element);
2491
2492
  const bounds = this.indexBounds(element);
2492
2493
  if (bounds) this.spatialIndex.insert(element.id, bounds);
2493
- this.bus.emit("add", element);
2494
+ this.bus.emit("add", element, meta);
2494
2495
  }
2495
- update(id, partial) {
2496
+ update(id, partial, meta) {
2496
2497
  const existing = this.elements.get(id);
2497
2498
  if (!existing) return;
2498
2499
  this.sortedCache = null;
@@ -2519,28 +2520,28 @@ var ElementStore = class {
2519
2520
  if (newBounds) {
2520
2521
  this.spatialIndex.update(id, newBounds);
2521
2522
  }
2522
- this.bus.emit("update", { previous: existing, current: updated });
2523
+ this.bus.emit("update", { previous: existing, current: updated }, meta);
2523
2524
  }
2524
- remove(id) {
2525
+ remove(id, meta) {
2525
2526
  const element = this.elements.get(id);
2526
2527
  if (!element) return;
2527
2528
  this.sortedCache = null;
2528
2529
  this._versions.delete(id);
2529
2530
  this.elements.delete(id);
2530
2531
  this.spatialIndex.remove(id);
2531
- this.bus.emit("remove", element);
2532
+ this.bus.emit("remove", element, meta);
2532
2533
  }
2533
- clear() {
2534
+ clear(meta) {
2534
2535
  this.sortedCache = null;
2535
2536
  this._versions.clear();
2536
2537
  this.elements.clear();
2537
2538
  this.spatialIndex.clear();
2538
- this.bus.emit("clear", null);
2539
+ this.bus.emit("clear", null, meta);
2539
2540
  }
2540
2541
  snapshot() {
2541
2542
  return this.getAll().map((el) => ({ ...el }));
2542
2543
  }
2543
- loadSnapshot(elements) {
2544
+ loadSnapshot(elements, meta) {
2544
2545
  this.sortedCache = null;
2545
2546
  this._versions.clear();
2546
2547
  this.elements.clear();
@@ -2557,9 +2558,9 @@ var ElementStore = class {
2557
2558
  el.cachedControlPoint = getArrowControlPoint(el.from, el.to, el.bend);
2558
2559
  }
2559
2560
  }
2560
- this.bus.emit("clear", null);
2561
+ this.bus.emit("clear", null, meta);
2561
2562
  for (const el of elements) {
2562
- this.bus.emit("add", el);
2563
+ this.bus.emit("add", el, meta);
2563
2564
  }
2564
2565
  }
2565
2566
  bringToFront(id) {
@@ -4834,15 +4835,18 @@ var UpdateLayerCommand = class {
4834
4835
  };
4835
4836
 
4836
4837
  // src/history/history-recorder.ts
4838
+ function isExternalChange(meta) {
4839
+ return meta.origin !== void 0 && meta.origin !== "local";
4840
+ }
4837
4841
  var HistoryRecorder = class {
4838
4842
  constructor(store, stack, layerManager) {
4839
4843
  this.store = store;
4840
4844
  this.stack = stack;
4841
4845
  this.layerManager = layerManager;
4842
4846
  this.unsubscribers = [
4843
- store.on("add", (el) => this.onAdd(el)),
4844
- store.on("remove", (el) => this.onRemove(el)),
4845
- store.on("update", ({ previous, current }) => this.onUpdate(previous, current))
4847
+ store.on("add", (el, meta) => this.onAdd(el, meta)),
4848
+ store.on("remove", (el, meta) => this.onRemove(el, meta)),
4849
+ store.on("update", ({ previous, current }, meta) => this.onUpdate(previous, current, meta))
4846
4850
  ];
4847
4851
  if (layerManager) {
4848
4852
  this.unsubscribers.push(
@@ -4898,18 +4902,21 @@ var HistoryRecorder = class {
4898
4902
  this.stack.push(command);
4899
4903
  }
4900
4904
  }
4901
- onAdd(element) {
4905
+ onAdd(element, meta) {
4906
+ if (isExternalChange(meta)) return;
4902
4907
  if (!this.recording) return;
4903
4908
  this.record(new AddElementCommand(element));
4904
4909
  }
4905
- onRemove(element) {
4910
+ onRemove(element, meta) {
4911
+ if (isExternalChange(meta)) return;
4906
4912
  if (!this.recording) return;
4907
4913
  if (this.transaction && this.updateSnapshots.has(element.id)) {
4908
4914
  this.updateSnapshots.delete(element.id);
4909
4915
  }
4910
4916
  this.record(new RemoveElementCommand(element));
4911
4917
  }
4912
- onUpdate(previous, current) {
4918
+ onUpdate(previous, current, meta) {
4919
+ if (isExternalChange(meta)) return;
4913
4920
  if (!this.recording) return;
4914
4921
  if (this.transaction) {
4915
4922
  if (!this.updateSnapshots.has(current.id)) {
@@ -10081,7 +10088,7 @@ var LaserTool = class {
10081
10088
  };
10082
10089
 
10083
10090
  // src/index.ts
10084
- var VERSION = "0.45.0";
10091
+ var VERSION = "0.46.0";
10085
10092
  export {
10086
10093
  ArrowTool,
10087
10094
  AutoSave,