@fieldnotes/core 0.7.0 → 0.8.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
@@ -67,6 +67,7 @@ interface ImageElement extends BaseElement {
67
67
  interface HtmlElement extends BaseElement {
68
68
  type: 'html';
69
69
  size: Size;
70
+ domId?: string;
70
71
  }
71
72
  interface TextElement extends BaseElement {
72
73
  type: 'text';
@@ -392,6 +393,14 @@ declare class InputHandler {
392
393
  private cancelToolIfActive;
393
394
  }
394
395
 
396
+ interface ExportImageOptions {
397
+ scale?: number;
398
+ padding?: number;
399
+ background?: string;
400
+ filter?: (element: CanvasElement) => boolean;
401
+ }
402
+ declare function exportImage(store: ElementStore, options?: ExportImageOptions, layerManager?: LayerManager): Promise<Blob | null>;
403
+
395
404
  interface ViewportOptions {
396
405
  camera?: CameraOptions;
397
406
  background?: BackgroundOptions;
@@ -429,6 +438,7 @@ declare class Viewport {
429
438
  requestRender(): void;
430
439
  exportState(): CanvasState;
431
440
  exportJSON(): string;
441
+ exportImage(options?: ExportImageOptions): Promise<Blob | null>;
432
442
  loadState(state: CanvasState): void;
433
443
  loadJSON(json: string): void;
434
444
  undo(): boolean;
@@ -477,6 +487,7 @@ declare class Viewport {
477
487
  private hideDomNode;
478
488
  private removeDomNode;
479
489
  private clearDomNodes;
490
+ private reattachHtmlContent;
480
491
  private createWrapper;
481
492
  private createCanvas;
482
493
  private createDomLayer;
@@ -564,6 +575,7 @@ interface ImageInput extends BaseDefaults {
564
575
  interface HtmlInput extends BaseDefaults {
565
576
  position: Point;
566
577
  size: Size;
578
+ domId?: string;
567
579
  }
568
580
  interface TextInput extends BaseDefaults {
569
581
  position: Point;
@@ -858,6 +870,6 @@ declare class UpdateLayerCommand implements Command {
858
870
  undo(_store: ElementStore): void;
859
871
  }
860
872
 
861
- declare const VERSION = "0.6.1";
873
+ declare const VERSION = "0.8.0";
862
874
 
863
- export { AddElementCommand, type ArrowElement, ArrowTool, type ArrowToolOptions, AutoSave, type AutoSaveOptions, Background, type BackgroundOptions, type BackgroundPattern, BatchCommand, type Binding, type Bounds, Camera, type CameraOptions, type CanvasElement, type CanvasState, type Command, CreateLayerCommand, ElementRenderer, ElementStore, type ElementType, type ElementUpdateEvent, EraserTool, type EraserToolOptions, EventBus, type GridElement, HandTool, type HexOrientation, HistoryRecorder, HistoryStack, type HistoryStackOptions, type HtmlElement, type ImageElement, ImageTool, type ImageToolOptions, InputHandler, type Layer, LayerManager, NoteEditor, type NoteElement, NoteTool, type NoteToolOptions, PencilTool, type PencilToolOptions, type Point, type PointerState, RemoveElementCommand, RemoveLayerCommand, SelectTool, type ShapeElement, type ShapeKind, ShapeTool, type ShapeToolOptions, type Size, type StrokeElement, type StrokePoint, type TextElement, TextTool, type TextToolOptions, type Tool, type ToolContext, ToolManager, type ToolName, UpdateElementCommand, UpdateLayerCommand, VERSION, Viewport, type ViewportOptions, clearStaleBindings, createArrow, createGrid, createHtmlElement, createId, createImage, createNote, createShape, createStroke, createText, exportState, findBindTarget, findBoundArrows, getArrowBounds, getArrowControlPoint, getArrowMidpoint, getArrowTangentAngle, getBendFromPoint, getEdgeIntersection, getElementBounds, getElementCenter, isBindable, isNearBezier, parseState, snapPoint, unbindArrow, updateBoundArrow };
875
+ export { AddElementCommand, type ArrowElement, ArrowTool, type ArrowToolOptions, AutoSave, type AutoSaveOptions, Background, type BackgroundOptions, type BackgroundPattern, BatchCommand, type Binding, type Bounds, Camera, type CameraOptions, type CanvasElement, type CanvasState, type Command, CreateLayerCommand, ElementRenderer, ElementStore, type ElementType, type ElementUpdateEvent, EraserTool, type EraserToolOptions, EventBus, type ExportImageOptions, type GridElement, HandTool, type HexOrientation, HistoryRecorder, HistoryStack, type HistoryStackOptions, type HtmlElement, type ImageElement, ImageTool, type ImageToolOptions, InputHandler, type Layer, LayerManager, NoteEditor, type NoteElement, NoteTool, type NoteToolOptions, PencilTool, type PencilToolOptions, type Point, type PointerState, RemoveElementCommand, RemoveLayerCommand, SelectTool, type ShapeElement, type ShapeKind, ShapeTool, type ShapeToolOptions, type Size, type StrokeElement, type StrokePoint, type TextElement, TextTool, type TextToolOptions, type Tool, type ToolContext, ToolManager, type ToolName, UpdateElementCommand, UpdateLayerCommand, VERSION, Viewport, type ViewportOptions, clearStaleBindings, createArrow, createGrid, createHtmlElement, createId, createImage, createNote, createShape, createStroke, createText, exportImage, exportState, findBindTarget, findBoundArrows, getArrowBounds, getArrowControlPoint, getArrowMidpoint, getArrowTangentAngle, getBendFromPoint, getEdgeIntersection, getElementBounds, getElementCenter, isBindable, isNearBezier, parseState, snapPoint, unbindArrow, updateBoundArrow };
package/dist/index.d.ts CHANGED
@@ -67,6 +67,7 @@ interface ImageElement extends BaseElement {
67
67
  interface HtmlElement extends BaseElement {
68
68
  type: 'html';
69
69
  size: Size;
70
+ domId?: string;
70
71
  }
71
72
  interface TextElement extends BaseElement {
72
73
  type: 'text';
@@ -392,6 +393,14 @@ declare class InputHandler {
392
393
  private cancelToolIfActive;
393
394
  }
394
395
 
396
+ interface ExportImageOptions {
397
+ scale?: number;
398
+ padding?: number;
399
+ background?: string;
400
+ filter?: (element: CanvasElement) => boolean;
401
+ }
402
+ declare function exportImage(store: ElementStore, options?: ExportImageOptions, layerManager?: LayerManager): Promise<Blob | null>;
403
+
395
404
  interface ViewportOptions {
396
405
  camera?: CameraOptions;
397
406
  background?: BackgroundOptions;
@@ -429,6 +438,7 @@ declare class Viewport {
429
438
  requestRender(): void;
430
439
  exportState(): CanvasState;
431
440
  exportJSON(): string;
441
+ exportImage(options?: ExportImageOptions): Promise<Blob | null>;
432
442
  loadState(state: CanvasState): void;
433
443
  loadJSON(json: string): void;
434
444
  undo(): boolean;
@@ -477,6 +487,7 @@ declare class Viewport {
477
487
  private hideDomNode;
478
488
  private removeDomNode;
479
489
  private clearDomNodes;
490
+ private reattachHtmlContent;
480
491
  private createWrapper;
481
492
  private createCanvas;
482
493
  private createDomLayer;
@@ -564,6 +575,7 @@ interface ImageInput extends BaseDefaults {
564
575
  interface HtmlInput extends BaseDefaults {
565
576
  position: Point;
566
577
  size: Size;
578
+ domId?: string;
567
579
  }
568
580
  interface TextInput extends BaseDefaults {
569
581
  position: Point;
@@ -858,6 +870,6 @@ declare class UpdateLayerCommand implements Command {
858
870
  undo(_store: ElementStore): void;
859
871
  }
860
872
 
861
- declare const VERSION = "0.6.1";
873
+ declare const VERSION = "0.8.0";
862
874
 
863
- export { AddElementCommand, type ArrowElement, ArrowTool, type ArrowToolOptions, AutoSave, type AutoSaveOptions, Background, type BackgroundOptions, type BackgroundPattern, BatchCommand, type Binding, type Bounds, Camera, type CameraOptions, type CanvasElement, type CanvasState, type Command, CreateLayerCommand, ElementRenderer, ElementStore, type ElementType, type ElementUpdateEvent, EraserTool, type EraserToolOptions, EventBus, type GridElement, HandTool, type HexOrientation, HistoryRecorder, HistoryStack, type HistoryStackOptions, type HtmlElement, type ImageElement, ImageTool, type ImageToolOptions, InputHandler, type Layer, LayerManager, NoteEditor, type NoteElement, NoteTool, type NoteToolOptions, PencilTool, type PencilToolOptions, type Point, type PointerState, RemoveElementCommand, RemoveLayerCommand, SelectTool, type ShapeElement, type ShapeKind, ShapeTool, type ShapeToolOptions, type Size, type StrokeElement, type StrokePoint, type TextElement, TextTool, type TextToolOptions, type Tool, type ToolContext, ToolManager, type ToolName, UpdateElementCommand, UpdateLayerCommand, VERSION, Viewport, type ViewportOptions, clearStaleBindings, createArrow, createGrid, createHtmlElement, createId, createImage, createNote, createShape, createStroke, createText, exportState, findBindTarget, findBoundArrows, getArrowBounds, getArrowControlPoint, getArrowMidpoint, getArrowTangentAngle, getBendFromPoint, getEdgeIntersection, getElementBounds, getElementCenter, isBindable, isNearBezier, parseState, snapPoint, unbindArrow, updateBoundArrow };
875
+ export { AddElementCommand, type ArrowElement, ArrowTool, type ArrowToolOptions, AutoSave, type AutoSaveOptions, Background, type BackgroundOptions, type BackgroundPattern, BatchCommand, type Binding, type Bounds, Camera, type CameraOptions, type CanvasElement, type CanvasState, type Command, CreateLayerCommand, ElementRenderer, ElementStore, type ElementType, type ElementUpdateEvent, EraserTool, type EraserToolOptions, EventBus, type ExportImageOptions, type GridElement, HandTool, type HexOrientation, HistoryRecorder, HistoryStack, type HistoryStackOptions, type HtmlElement, type ImageElement, ImageTool, type ImageToolOptions, InputHandler, type Layer, LayerManager, NoteEditor, type NoteElement, NoteTool, type NoteToolOptions, PencilTool, type PencilToolOptions, type Point, type PointerState, RemoveElementCommand, RemoveLayerCommand, SelectTool, type ShapeElement, type ShapeKind, ShapeTool, type ShapeToolOptions, type Size, type StrokeElement, type StrokePoint, type TextElement, TextTool, type TextToolOptions, type Tool, type ToolContext, ToolManager, type ToolName, UpdateElementCommand, UpdateLayerCommand, VERSION, Viewport, type ViewportOptions, clearStaleBindings, createArrow, createGrid, createHtmlElement, createId, createImage, createNote, createShape, createStroke, createText, exportImage, exportState, findBindTarget, findBoundArrows, getArrowBounds, getArrowControlPoint, getArrowMidpoint, getArrowTangentAngle, getBendFromPoint, getEdgeIntersection, getElementBounds, getElementCenter, isBindable, isNearBezier, parseState, snapPoint, unbindArrow, updateBoundArrow };
package/dist/index.js CHANGED
@@ -1687,7 +1687,7 @@ function createImage(input) {
1687
1687
  };
1688
1688
  }
1689
1689
  function createHtmlElement(input) {
1690
- return {
1690
+ const el = {
1691
1691
  id: createId("html"),
1692
1692
  type: "html",
1693
1693
  position: input.position,
@@ -1696,6 +1696,8 @@ function createHtmlElement(input) {
1696
1696
  layerId: input.layerId ?? "",
1697
1697
  size: input.size
1698
1698
  };
1699
+ if (input.domId) el.domId = input.domId;
1700
+ return el;
1699
1701
  }
1700
1702
  function createShape(input) {
1701
1703
  return {
@@ -1744,6 +1746,256 @@ function createText(input) {
1744
1746
  };
1745
1747
  }
1746
1748
 
1749
+ // src/canvas/export-image.ts
1750
+ function getStrokeBounds(el) {
1751
+ if (el.type !== "stroke") return null;
1752
+ if (el.points.length === 0) return null;
1753
+ let minX = Infinity;
1754
+ let minY = Infinity;
1755
+ let maxX = -Infinity;
1756
+ let maxY = -Infinity;
1757
+ for (const p of el.points) {
1758
+ const px = el.position.x + p.x;
1759
+ const py = el.position.y + p.y;
1760
+ minX = Math.min(minX, px);
1761
+ minY = Math.min(minY, py);
1762
+ maxX = Math.max(maxX, px);
1763
+ maxY = Math.max(maxY, py);
1764
+ }
1765
+ const pad = el.width / 2;
1766
+ return {
1767
+ x: minX - pad,
1768
+ y: minY - pad,
1769
+ w: maxX - minX + el.width,
1770
+ h: maxY - minY + el.width
1771
+ };
1772
+ }
1773
+ function getElementRect(el) {
1774
+ switch (el.type) {
1775
+ case "stroke":
1776
+ return getStrokeBounds(el);
1777
+ case "arrow": {
1778
+ const b = getArrowBounds(el.from, el.to, el.bend);
1779
+ const pad = el.width / 2 + 14;
1780
+ return { x: b.x - pad, y: b.y - pad, w: b.w + pad * 2, h: b.h + pad * 2 };
1781
+ }
1782
+ case "grid":
1783
+ return null;
1784
+ case "note":
1785
+ case "image":
1786
+ case "html":
1787
+ case "text":
1788
+ case "shape":
1789
+ if ("size" in el) {
1790
+ return { x: el.position.x, y: el.position.y, w: el.size.w, h: el.size.h };
1791
+ }
1792
+ return null;
1793
+ default:
1794
+ return null;
1795
+ }
1796
+ }
1797
+ function computeBounds(elements, padding) {
1798
+ let minX = Infinity;
1799
+ let minY = Infinity;
1800
+ let maxX = -Infinity;
1801
+ let maxY = -Infinity;
1802
+ let found = false;
1803
+ for (const el of elements) {
1804
+ const rect = getElementRect(el);
1805
+ if (!rect) continue;
1806
+ found = true;
1807
+ minX = Math.min(minX, rect.x);
1808
+ minY = Math.min(minY, rect.y);
1809
+ maxX = Math.max(maxX, rect.x + rect.w);
1810
+ maxY = Math.max(maxY, rect.y + rect.h);
1811
+ }
1812
+ if (!found) return null;
1813
+ return {
1814
+ x: minX - padding,
1815
+ y: minY - padding,
1816
+ w: maxX - minX + padding * 2,
1817
+ h: maxY - minY + padding * 2
1818
+ };
1819
+ }
1820
+ function renderNoteOnCanvas(ctx, note) {
1821
+ const { x, y } = note.position;
1822
+ const { w, h } = note.size;
1823
+ const r = 4;
1824
+ const pad = 8;
1825
+ ctx.save();
1826
+ ctx.fillStyle = note.backgroundColor;
1827
+ ctx.beginPath();
1828
+ ctx.moveTo(x + r, y);
1829
+ ctx.lineTo(x + w - r, y);
1830
+ ctx.arcTo(x + w, y, x + w, y + r, r);
1831
+ ctx.lineTo(x + w, y + h - r);
1832
+ ctx.arcTo(x + w, y + h, x + w - r, y + h, r);
1833
+ ctx.lineTo(x + r, y + h);
1834
+ ctx.arcTo(x, y + h, x, y + h - r, r);
1835
+ ctx.lineTo(x, y + r);
1836
+ ctx.arcTo(x, y, x + r, y, r);
1837
+ ctx.closePath();
1838
+ ctx.fill();
1839
+ if (note.text) {
1840
+ ctx.fillStyle = note.textColor;
1841
+ ctx.font = "14px system-ui, sans-serif";
1842
+ ctx.textBaseline = "top";
1843
+ wrapText(ctx, note.text, x + pad, y + pad, w - pad * 2, 18);
1844
+ }
1845
+ ctx.restore();
1846
+ }
1847
+ function renderTextOnCanvas(ctx, text) {
1848
+ if (!text.text) return;
1849
+ ctx.save();
1850
+ ctx.fillStyle = text.color;
1851
+ ctx.font = `${text.fontSize}px system-ui, sans-serif`;
1852
+ ctx.textBaseline = "top";
1853
+ ctx.textAlign = text.textAlign;
1854
+ const pad = 2;
1855
+ let textX = text.position.x + pad;
1856
+ if (text.textAlign === "center") {
1857
+ textX = text.position.x + text.size.w / 2;
1858
+ } else if (text.textAlign === "right") {
1859
+ textX = text.position.x + text.size.w - pad;
1860
+ }
1861
+ const lineHeight = text.fontSize * 1.4;
1862
+ const lines = text.text.split("\n");
1863
+ for (let i = 0; i < lines.length; i++) {
1864
+ const line = lines[i];
1865
+ if (line !== void 0) {
1866
+ ctx.fillText(line, textX, text.position.y + pad + i * lineHeight);
1867
+ }
1868
+ }
1869
+ ctx.restore();
1870
+ }
1871
+ function wrapText(ctx, text, x, y, maxWidth, lineHeight) {
1872
+ const words = text.split(" ");
1873
+ let line = "";
1874
+ let offsetY = 0;
1875
+ for (const word of words) {
1876
+ const testLine = line ? `${line} ${word}` : word;
1877
+ const metrics = ctx.measureText(testLine);
1878
+ if (metrics.width > maxWidth && line) {
1879
+ ctx.fillText(line, x, y + offsetY);
1880
+ line = word;
1881
+ offsetY += lineHeight;
1882
+ } else {
1883
+ line = testLine;
1884
+ }
1885
+ }
1886
+ if (line) {
1887
+ ctx.fillText(line, x, y + offsetY);
1888
+ }
1889
+ }
1890
+ function renderGridForBounds(ctx, grid, bounds) {
1891
+ const visibleBounds = {
1892
+ minX: bounds.x,
1893
+ minY: bounds.y,
1894
+ maxX: bounds.x + bounds.w,
1895
+ maxY: bounds.y + bounds.h
1896
+ };
1897
+ if (grid.gridType === "hex") {
1898
+ renderHexGrid(
1899
+ ctx,
1900
+ visibleBounds,
1901
+ grid.cellSize,
1902
+ grid.hexOrientation,
1903
+ grid.strokeColor,
1904
+ grid.strokeWidth,
1905
+ grid.opacity
1906
+ );
1907
+ } else {
1908
+ renderSquareGrid(
1909
+ ctx,
1910
+ visibleBounds,
1911
+ grid.cellSize,
1912
+ grid.strokeColor,
1913
+ grid.strokeWidth,
1914
+ grid.opacity
1915
+ );
1916
+ }
1917
+ }
1918
+ function loadImages(elements) {
1919
+ const imageElements = elements.filter(
1920
+ (el) => el.type === "image" && "src" in el
1921
+ );
1922
+ const cache = /* @__PURE__ */ new Map();
1923
+ if (imageElements.length === 0) return Promise.resolve(cache);
1924
+ return new Promise((resolve) => {
1925
+ let remaining = imageElements.length;
1926
+ const done = () => {
1927
+ remaining--;
1928
+ if (remaining <= 0) resolve(cache);
1929
+ };
1930
+ for (const el of imageElements) {
1931
+ const img = new Image();
1932
+ img.onload = () => {
1933
+ cache.set(el.id, img);
1934
+ done();
1935
+ };
1936
+ img.onerror = done;
1937
+ img.src = el.src;
1938
+ }
1939
+ });
1940
+ }
1941
+ async function exportImage(store, options = {}, layerManager) {
1942
+ const scale = options.scale ?? 2;
1943
+ const padding = options.padding ?? 0;
1944
+ const background = options.background ?? "#ffffff";
1945
+ const filter = options.filter;
1946
+ const allElements = store.getAll();
1947
+ let visibleElements = layerManager ? allElements.filter((el) => layerManager.isLayerVisible(el.layerId)) : allElements;
1948
+ if (filter) {
1949
+ visibleElements = visibleElements.filter(filter);
1950
+ }
1951
+ const bounds = computeBounds(visibleElements, padding);
1952
+ if (!bounds) return null;
1953
+ const imageCache = await loadImages(visibleElements);
1954
+ const canvas = document.createElement("canvas");
1955
+ canvas.width = Math.ceil(bounds.w * scale);
1956
+ canvas.height = Math.ceil(bounds.h * scale);
1957
+ const ctx = canvas.getContext("2d");
1958
+ if (!ctx) return null;
1959
+ ctx.scale(scale, scale);
1960
+ ctx.translate(-bounds.x, -bounds.y);
1961
+ ctx.fillStyle = background;
1962
+ ctx.fillRect(bounds.x, bounds.y, bounds.w, bounds.h);
1963
+ const renderer = new ElementRenderer();
1964
+ renderer.setStore(store);
1965
+ const grids = [];
1966
+ for (const el of visibleElements) {
1967
+ if (el.type === "grid") {
1968
+ grids.push(el);
1969
+ continue;
1970
+ }
1971
+ if (el.type === "note") {
1972
+ renderNoteOnCanvas(ctx, el);
1973
+ continue;
1974
+ }
1975
+ if (el.type === "text") {
1976
+ renderTextOnCanvas(ctx, el);
1977
+ continue;
1978
+ }
1979
+ if (el.type === "html") {
1980
+ continue;
1981
+ }
1982
+ if (el.type === "image") {
1983
+ const img = imageCache.get(el.id);
1984
+ if (img) {
1985
+ ctx.drawImage(img, el.position.x, el.position.y, el.size.w, el.size.h);
1986
+ }
1987
+ continue;
1988
+ }
1989
+ renderer.renderCanvasElement(ctx, el);
1990
+ }
1991
+ for (const grid of grids) {
1992
+ renderGridForBounds(ctx, grid, bounds);
1993
+ }
1994
+ return new Promise((resolve) => {
1995
+ canvas.toBlob((blob) => resolve(blob), "image/png");
1996
+ });
1997
+ }
1998
+
1747
1999
  // src/layers/layer-manager.ts
1748
2000
  var LayerManager = class {
1749
2001
  constructor(store) {
@@ -2005,6 +2257,9 @@ var Viewport = class {
2005
2257
  exportJSON() {
2006
2258
  return JSON.stringify(this.exportState());
2007
2259
  }
2260
+ async exportImage(options) {
2261
+ return exportImage(this.store, options, this.layerManager);
2262
+ }
2008
2263
  loadState(state) {
2009
2264
  this.historyRecorder.pause();
2010
2265
  this.noteEditor.destroy(this.store);
@@ -2013,6 +2268,7 @@ var Viewport = class {
2013
2268
  if (state.layers && state.layers.length > 0) {
2014
2269
  this.layerManager.loadSnapshot(state.layers);
2015
2270
  }
2271
+ this.reattachHtmlContent();
2016
2272
  this.history.clear();
2017
2273
  this.historyRecorder.resume();
2018
2274
  this.camera.moveTo(state.camera.position.x, state.camera.position.y);
@@ -2044,7 +2300,13 @@ var Viewport = class {
2044
2300
  return image.id;
2045
2301
  }
2046
2302
  addHtmlElement(dom, position, size = { w: 200, h: 150 }) {
2047
- const el = createHtmlElement({ position, size, layerId: this.layerManager.activeLayerId });
2303
+ const domId = dom.id || void 0;
2304
+ const el = createHtmlElement({
2305
+ position,
2306
+ size,
2307
+ domId,
2308
+ layerId: this.layerManager.activeLayerId
2309
+ });
2048
2310
  this.htmlContent.set(el.id, dom);
2049
2311
  this.historyRecorder.begin();
2050
2312
  this.store.add(el);
@@ -2413,6 +2675,16 @@ var Viewport = class {
2413
2675
  this.htmlContent.clear();
2414
2676
  this.requestRender();
2415
2677
  }
2678
+ reattachHtmlContent() {
2679
+ for (const el of this.store.getElementsByType("html")) {
2680
+ if (el.domId) {
2681
+ const dom = document.getElementById(el.domId);
2682
+ if (dom) {
2683
+ this.htmlContent.set(el.id, dom);
2684
+ }
2685
+ }
2686
+ }
2687
+ }
2416
2688
  createWrapper() {
2417
2689
  const el = document.createElement("div");
2418
2690
  Object.assign(el.style, {
@@ -2671,10 +2943,11 @@ function applyArrowHandleDrag(handle, elementId, world, ctx) {
2671
2943
  const el = ctx.store.getById(elementId);
2672
2944
  if (!el || el.type !== "arrow") return;
2673
2945
  const threshold = BIND_THRESHOLD / ctx.camera.zoom;
2946
+ const layerFilter = (candidate) => candidate.layerId === el.layerId;
2674
2947
  switch (handle) {
2675
2948
  case "start": {
2676
2949
  const excludeId = el.toBinding?.elementId;
2677
- const target = findBindTarget(world, ctx.store, threshold, excludeId);
2950
+ const target = findBindTarget(world, ctx.store, threshold, excludeId, layerFilter);
2678
2951
  if (target) {
2679
2952
  const center = getElementCenter(target);
2680
2953
  ctx.store.update(elementId, {
@@ -2693,7 +2966,7 @@ function applyArrowHandleDrag(handle, elementId, world, ctx) {
2693
2966
  }
2694
2967
  case "end": {
2695
2968
  const excludeId = el.fromBinding?.elementId;
2696
- const target = findBindTarget(world, ctx.store, threshold, excludeId);
2969
+ const target = findBindTarget(world, ctx.store, threshold, excludeId, layerFilter);
2697
2970
  if (target) {
2698
2971
  const center = getElementCenter(target);
2699
2972
  ctx.store.update(elementId, {
@@ -2722,7 +2995,8 @@ function getArrowHandleDragTarget(handle, elementId, world, ctx) {
2722
2995
  if (!el || el.type !== "arrow") return null;
2723
2996
  const threshold = BIND_THRESHOLD / ctx.camera.zoom;
2724
2997
  const excludeId = handle === "start" ? el.toBinding?.elementId : el.fromBinding?.elementId;
2725
- const target = findBindTarget(world, ctx.store, threshold, excludeId);
2998
+ const layerFilter = (candidate) => candidate.layerId === el.layerId;
2999
+ const target = findBindTarget(world, ctx.store, threshold, excludeId, layerFilter);
2726
3000
  if (!target) return null;
2727
3001
  return getElementBounds(target);
2728
3002
  }
@@ -3182,8 +3456,10 @@ var ArrowTool = class {
3182
3456
  if (options.width !== void 0) this.width = options.width;
3183
3457
  }
3184
3458
  layerFilter(ctx) {
3185
- if (!ctx.isLayerVisible && !ctx.isLayerLocked) return void 0;
3459
+ const activeLayerId = ctx.activeLayerId;
3460
+ if (!activeLayerId && !ctx.isLayerVisible && !ctx.isLayerLocked) return void 0;
3186
3461
  return (el) => {
3462
+ if (activeLayerId && el.layerId !== activeLayerId) return false;
3187
3463
  if (ctx.isLayerVisible && !ctx.isLayerVisible(el.layerId)) return false;
3188
3464
  if (ctx.isLayerLocked && ctx.isLayerLocked(el.layerId)) return false;
3189
3465
  return true;
@@ -3567,7 +3843,7 @@ var UpdateLayerCommand = class {
3567
3843
  };
3568
3844
 
3569
3845
  // src/index.ts
3570
- var VERSION = "0.6.1";
3846
+ var VERSION = "0.8.0";
3571
3847
  export {
3572
3848
  AddElementCommand,
3573
3849
  ArrowTool,
@@ -3609,6 +3885,7 @@ export {
3609
3885
  createShape,
3610
3886
  createStroke,
3611
3887
  createText,
3888
+ exportImage,
3612
3889
  exportState,
3613
3890
  findBindTarget,
3614
3891
  findBoundArrows,