@fieldnotes/core 0.41.0 → 0.43.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
@@ -469,6 +469,10 @@ interface ViewportOptions {
469
469
  panBufferMargin?: number;
470
470
  /** Enable the built-in context menu. Default `true`. */
471
471
  contextMenu?: boolean;
472
+ /** Coast (inertial glide) after a pan flick. Default `true`. */
473
+ panInertia?: boolean;
474
+ /** Show an overview minimap (bottom-right) with tap/drag-to-navigate. Default `false`. */
475
+ minimap?: boolean;
472
476
  }
473
477
  declare class Viewport {
474
478
  private readonly container;
@@ -504,6 +508,7 @@ declare class Viewport {
504
508
  private readonly gridController;
505
509
  private readonly interactions;
506
510
  private contextMenu;
511
+ private minimap;
507
512
  private readonly htmlRenderers;
508
513
  constructor(container: HTMLElement, options?: ViewportOptions);
509
514
  get ctx(): CanvasRenderingContext2D | null;
@@ -1055,6 +1060,6 @@ declare class LaserTool implements Tool {
1055
1060
  private notifyOptionsChange;
1056
1061
  }
1057
1062
 
1058
- declare const VERSION = "0.41.0";
1063
+ declare const VERSION = "0.43.0";
1059
1064
 
1060
1065
  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, LaserTool, type LaserToolOptions, type Layer, LayerManager, MeasureTool, type MeasureToolOptions, type Measurement, 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 StrokeElement, type StrokePoint, type TemplateElement, 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
@@ -469,6 +469,10 @@ interface ViewportOptions {
469
469
  panBufferMargin?: number;
470
470
  /** Enable the built-in context menu. Default `true`. */
471
471
  contextMenu?: boolean;
472
+ /** Coast (inertial glide) after a pan flick. Default `true`. */
473
+ panInertia?: boolean;
474
+ /** Show an overview minimap (bottom-right) with tap/drag-to-navigate. Default `false`. */
475
+ minimap?: boolean;
472
476
  }
473
477
  declare class Viewport {
474
478
  private readonly container;
@@ -504,6 +508,7 @@ declare class Viewport {
504
508
  private readonly gridController;
505
509
  private readonly interactions;
506
510
  private contextMenu;
511
+ private minimap;
507
512
  private readonly htmlRenderers;
508
513
  constructor(container: HTMLElement, options?: ViewportOptions);
509
514
  get ctx(): CanvasRenderingContext2D | null;
@@ -1055,6 +1060,6 @@ declare class LaserTool implements Tool {
1055
1060
  private notifyOptionsChange;
1056
1061
  }
1057
1062
 
1058
- declare const VERSION = "0.41.0";
1063
+ declare const VERSION = "0.43.0";
1059
1064
 
1060
1065
  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, LaserTool, type LaserToolOptions, type Layer, LayerManager, MeasureTool, type MeasureToolOptions, type Measurement, 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 StrokeElement, type StrokePoint, type TemplateElement, 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
@@ -1471,6 +1471,81 @@ var KeyboardHandler = class {
1471
1471
  }
1472
1472
  };
1473
1473
 
1474
+ // src/canvas/pan-inertia.ts
1475
+ var VELOCITY_WINDOW_MS = 60;
1476
+ var FRICTION = 0.92;
1477
+ var MIN_START_SPEED = 2;
1478
+ var MIN_STOP_SPEED = 0.3;
1479
+ var PanInertia = class {
1480
+ constructor(deps) {
1481
+ this.deps = deps;
1482
+ }
1483
+ samples = [];
1484
+ vx = 0;
1485
+ vy = 0;
1486
+ rafId = null;
1487
+ sample(dx, dy) {
1488
+ const t = this.deps.now();
1489
+ this.samples.push({ dx, dy, t });
1490
+ this.prune(t);
1491
+ }
1492
+ release() {
1493
+ if (!this.deps.enabled()) {
1494
+ this.reset();
1495
+ return;
1496
+ }
1497
+ const t = this.deps.now();
1498
+ this.prune(t);
1499
+ const recent = this.samples;
1500
+ if (recent.length === 0) {
1501
+ this.reset();
1502
+ return;
1503
+ }
1504
+ let sx = 0;
1505
+ let sy = 0;
1506
+ for (const s of recent) {
1507
+ sx += s.dx;
1508
+ sy += s.dy;
1509
+ }
1510
+ this.vx = sx / recent.length;
1511
+ this.vy = sy / recent.length;
1512
+ this.samples = [];
1513
+ if (Math.hypot(this.vx, this.vy) < MIN_START_SPEED) {
1514
+ this.vx = 0;
1515
+ this.vy = 0;
1516
+ return;
1517
+ }
1518
+ this.rafId = this.deps.requestFrame(this.step);
1519
+ }
1520
+ cancel() {
1521
+ this.reset();
1522
+ }
1523
+ step = () => {
1524
+ if (this.rafId === null) return;
1525
+ this.deps.pan(this.vx, this.vy);
1526
+ this.vx *= FRICTION;
1527
+ this.vy *= FRICTION;
1528
+ if (Math.hypot(this.vx, this.vy) >= MIN_STOP_SPEED) {
1529
+ this.rafId = this.deps.requestFrame(this.step);
1530
+ } else {
1531
+ this.reset();
1532
+ }
1533
+ };
1534
+ prune(now) {
1535
+ const cutoff = now - VELOCITY_WINDOW_MS;
1536
+ this.samples = this.samples.filter((s) => s.t >= cutoff);
1537
+ }
1538
+ reset() {
1539
+ if (this.rafId !== null) {
1540
+ this.deps.cancelFrame(this.rafId);
1541
+ this.rafId = null;
1542
+ }
1543
+ this.samples = [];
1544
+ this.vx = 0;
1545
+ this.vy = 0;
1546
+ }
1547
+ };
1548
+
1474
1549
  // src/canvas/input-handler.ts
1475
1550
  var ZOOM_SENSITIVITY = 1e-3;
1476
1551
  var MIDDLE_BUTTON = 1;
@@ -1496,6 +1571,16 @@ var InputHandler = class {
1496
1571
  getLastPointerWorld: () => this.lastPointerWorld()
1497
1572
  });
1498
1573
  this.openContextMenu = options.openContextMenu;
1574
+ this.panInertiaEnabled = options.panInertia ?? true;
1575
+ this.panInertia = new PanInertia({
1576
+ pan: (dx, dy) => this.camera.pan(dx, dy),
1577
+ now: () => typeof performance !== "undefined" ? performance.now() : Date.now(),
1578
+ requestFrame: (cb) => typeof requestAnimationFrame !== "undefined" ? requestAnimationFrame(cb) : 0,
1579
+ cancelFrame: (id) => {
1580
+ if (typeof cancelAnimationFrame !== "undefined") cancelAnimationFrame(id);
1581
+ },
1582
+ enabled: () => this.panInertiaEnabled
1583
+ });
1499
1584
  this.scope = options.shortcuts?.scope ?? "focus";
1500
1585
  this.keyboard = new KeyboardHandler({
1501
1586
  element: this.element,
@@ -1545,6 +1630,8 @@ var InputHandler = class {
1545
1630
  keyboard;
1546
1631
  scope;
1547
1632
  openContextMenu;
1633
+ panInertia;
1634
+ panInertiaEnabled;
1548
1635
  setToolManager(toolManager, toolContext) {
1549
1636
  this.toolManager = toolManager;
1550
1637
  this.toolContext = toolContext;
@@ -1556,6 +1643,7 @@ var InputHandler = class {
1556
1643
  return this.keyboard.shortcuts;
1557
1644
  }
1558
1645
  destroy() {
1646
+ this.panInertia.cancel();
1559
1647
  this.actions.dispose();
1560
1648
  this.abortController.abort();
1561
1649
  this.inputFilter.reset();
@@ -1579,6 +1667,7 @@ var InputHandler = class {
1579
1667
  }
1580
1668
  onWheel = (e) => {
1581
1669
  e.preventDefault();
1670
+ this.panInertia.cancel();
1582
1671
  const rect = this.element.getBoundingClientRect();
1583
1672
  const zoomFactor = 1 - e.deltaY * ZOOM_SENSITIVITY;
1584
1673
  const newZoom = this.camera.zoom * zoomFactor;
@@ -1588,6 +1677,7 @@ var InputHandler = class {
1588
1677
  });
1589
1678
  };
1590
1679
  onPointerDown = (e) => {
1680
+ this.panInertia.cancel();
1591
1681
  this.focusSelf();
1592
1682
  this.activePointers.set(e.pointerId, { x: e.clientX, y: e.clientY });
1593
1683
  this.element.setPointerCapture?.(e.pointerId);
@@ -1628,6 +1718,7 @@ var InputHandler = class {
1628
1718
  const dy = e.clientY - this.lastPointer.y;
1629
1719
  this.lastPointer = { x: e.clientX, y: e.clientY };
1630
1720
  this.camera.pan(dx, dy);
1721
+ this.panInertia.sample(dx, dy);
1631
1722
  return;
1632
1723
  }
1633
1724
  if (e.pointerType === "pen" && !this.activePointers.has(e.pointerId)) {
@@ -1658,6 +1749,7 @@ var InputHandler = class {
1658
1749
  }
1659
1750
  if (this.isPanning && this.activePointers.size === 0) {
1660
1751
  this.isPanning = false;
1752
+ this.panInertia.release();
1661
1753
  }
1662
1754
  const upResult = this.inputFilter.filterUp(e);
1663
1755
  if (this.isToolActive) {
@@ -1678,6 +1770,7 @@ var InputHandler = class {
1678
1770
  return this.actions.hasClipboard();
1679
1771
  }
1680
1772
  startPinch() {
1773
+ this.panInertia.cancel();
1681
1774
  this.cancelLongPress();
1682
1775
  this.inputFilter.reset();
1683
1776
  this.deferredDown = null;
@@ -1699,6 +1792,7 @@ var InputHandler = class {
1699
1792
  const dx = center2.x - this.lastPointer.x;
1700
1793
  const dy = center2.y - this.lastPointer.y;
1701
1794
  this.camera.pan(dx, dy);
1795
+ this.panInertia.sample(dx, dy);
1702
1796
  this.lastPinchDistance = dist;
1703
1797
  this.lastPinchCenter = center2;
1704
1798
  this.lastPointer = { ...center2 };
@@ -4183,6 +4277,135 @@ var ContextMenu = class {
4183
4277
  }
4184
4278
  };
4185
4279
 
4280
+ // src/canvas/minimap-transform.ts
4281
+ function unionBounds(a, b) {
4282
+ const minX = Math.min(a.x, b.x);
4283
+ const minY = Math.min(a.y, b.y);
4284
+ const maxX = Math.max(a.x + a.w, b.x + b.w);
4285
+ const maxY = Math.max(a.y + a.h, b.y + b.h);
4286
+ return { x: minX, y: minY, w: maxX - minX, h: maxY - minY };
4287
+ }
4288
+ function computeMinimapTransform(mapping, miniW, miniH, padding) {
4289
+ const availW = Math.max(1, miniW - 2 * padding);
4290
+ const availH = Math.max(1, miniH - 2 * padding);
4291
+ const w = Math.max(mapping.w, 1);
4292
+ const h = Math.max(mapping.h, 1);
4293
+ const scale = Math.min(availW / w, availH / h);
4294
+ const offsetX = (miniW - mapping.w * scale) / 2 - mapping.x * scale;
4295
+ const offsetY = (miniH - mapping.h * scale) / 2 - mapping.y * scale;
4296
+ return { scale, offsetX, offsetY };
4297
+ }
4298
+ function worldToMini(t, p) {
4299
+ return { x: p.x * t.scale + t.offsetX, y: p.y * t.scale + t.offsetY };
4300
+ }
4301
+ function miniToWorld(t, p) {
4302
+ return { x: (p.x - t.offsetX) / t.scale, y: (p.y - t.offsetY) / t.scale };
4303
+ }
4304
+
4305
+ // src/canvas/minimap.ts
4306
+ var WIDTH = 200;
4307
+ var HEIGHT = 140;
4308
+ var MARGIN = 16;
4309
+ var PADDING = 8;
4310
+ var NEUTRAL = "rgba(100,116,139,0.6)";
4311
+ var VIEWPORT_STROKE = "#3b82f6";
4312
+ function elementColor(el) {
4313
+ return "color" in el && typeof el.color === "string" ? el.color : NEUTRAL;
4314
+ }
4315
+ var Minimap = class {
4316
+ constructor(deps) {
4317
+ this.deps = deps;
4318
+ const canvas = document.createElement("canvas");
4319
+ canvas.width = WIDTH;
4320
+ canvas.height = HEIGHT;
4321
+ Object.assign(canvas.style, {
4322
+ position: "absolute",
4323
+ right: `${MARGIN}px`,
4324
+ bottom: `${MARGIN}px`,
4325
+ width: `${WIDTH}px`,
4326
+ height: `${HEIGHT}px`,
4327
+ background: "rgba(255,255,255,0.85)",
4328
+ border: "1px solid rgba(0,0,0,0.15)",
4329
+ borderRadius: "4px",
4330
+ touchAction: "none",
4331
+ cursor: "pointer",
4332
+ zIndex: "10"
4333
+ });
4334
+ canvas.addEventListener("pointerdown", this.onPointerDown);
4335
+ canvas.addEventListener("pointermove", this.onPointerMove);
4336
+ canvas.addEventListener("pointerup", this.onPointerUp);
4337
+ this.deps.container.appendChild(canvas);
4338
+ this.canvas = canvas;
4339
+ }
4340
+ canvas;
4341
+ rafId = null;
4342
+ dragging = false;
4343
+ scheduleDraw() {
4344
+ if (this.rafId !== null) return;
4345
+ this.rafId = this.deps.requestFrame(this.draw);
4346
+ }
4347
+ destroy() {
4348
+ if (this.rafId !== null) {
4349
+ this.deps.cancelFrame(this.rafId);
4350
+ this.rafId = null;
4351
+ }
4352
+ this.canvas.removeEventListener("pointerdown", this.onPointerDown);
4353
+ this.canvas.removeEventListener("pointermove", this.onPointerMove);
4354
+ this.canvas.removeEventListener("pointerup", this.onPointerUp);
4355
+ this.canvas.remove();
4356
+ }
4357
+ currentTransform() {
4358
+ const viewport = this.deps.getViewportRect();
4359
+ const content = this.deps.getContentBounds();
4360
+ const mapping = content ? unionBounds(content, viewport) : viewport;
4361
+ return computeMinimapTransform(mapping, WIDTH, HEIGHT, PADDING);
4362
+ }
4363
+ draw = () => {
4364
+ this.rafId = null;
4365
+ const ctx = this.canvas.getContext("2d");
4366
+ if (!ctx) return;
4367
+ const t = this.currentTransform();
4368
+ const viewport = this.deps.getViewportRect();
4369
+ ctx.clearRect(0, 0, WIDTH, HEIGHT);
4370
+ for (const el of this.deps.getElements()) {
4371
+ const b = getElementBounds(el);
4372
+ if (!b) continue;
4373
+ const tl = worldToMini(t, { x: b.x, y: b.y });
4374
+ ctx.fillStyle = elementColor(el);
4375
+ ctx.fillRect(tl.x, tl.y, Math.max(1, b.w * t.scale), Math.max(1, b.h * t.scale));
4376
+ }
4377
+ const vtl = worldToMini(t, { x: viewport.x, y: viewport.y });
4378
+ ctx.strokeStyle = VIEWPORT_STROKE;
4379
+ ctx.lineWidth = 1.5;
4380
+ ctx.strokeRect(vtl.x, vtl.y, viewport.w * t.scale, viewport.h * t.scale);
4381
+ };
4382
+ navigateFromEvent(e) {
4383
+ const rect = this.canvas.getBoundingClientRect();
4384
+ const point = { x: e.clientX - rect.left, y: e.clientY - rect.top };
4385
+ const world = miniToWorld(this.currentTransform(), point);
4386
+ this.deps.navigateTo(world);
4387
+ }
4388
+ onPointerDown = (e) => {
4389
+ e.stopPropagation();
4390
+ e.preventDefault();
4391
+ this.dragging = true;
4392
+ this.canvas.setPointerCapture?.(e.pointerId);
4393
+ this.navigateFromEvent(e);
4394
+ };
4395
+ onPointerMove = (e) => {
4396
+ if (!this.dragging) return;
4397
+ e.stopPropagation();
4398
+ this.navigateFromEvent(e);
4399
+ };
4400
+ onPointerUp = (e) => {
4401
+ this.dragging = false;
4402
+ try {
4403
+ this.canvas.releasePointerCapture(e.pointerId);
4404
+ } catch {
4405
+ }
4406
+ };
4407
+ };
4408
+
4186
4409
  // src/canvas/viewport-dom.ts
4187
4410
  function createWrapper() {
4188
4411
  const el = document.createElement("div");
@@ -6308,7 +6531,7 @@ function getElementStyle(element) {
6308
6531
  }
6309
6532
 
6310
6533
  // src/canvas/selection-ops.ts
6311
- function unionBounds(list) {
6534
+ function unionBounds2(list) {
6312
6535
  let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;
6313
6536
  for (const b of list) {
6314
6537
  minX = Math.min(minX, b.x);
@@ -6403,7 +6626,7 @@ var SelectionOps = class {
6403
6626
  align(edge) {
6404
6627
  const bounded = this.boundedSelection();
6405
6628
  if (bounded.length < 2) return;
6406
- const B = unionBounds(bounded.map((e) => e.bounds));
6629
+ const B = unionBounds2(bounded.map((e) => e.bounds));
6407
6630
  this.deps.recorder.begin();
6408
6631
  const moved = [];
6409
6632
  for (const { id, el, bounds: b } of bounded) {
@@ -6800,7 +7023,8 @@ var Viewport = class {
6800
7023
  shortcuts: options.shortcuts,
6801
7024
  addImage: (src, world) => this.addImage(src, world),
6802
7025
  getCenteredWorld: () => this.centeredPosition({ w: 300, h: 200 }),
6803
- onPaste: options.onPaste
7026
+ onPaste: options.onPaste,
7027
+ panInertia: options.panInertia
6804
7028
  });
6805
7029
  if (options.contextMenu !== false) {
6806
7030
  this.contextMenu = new ContextMenu({
@@ -6809,6 +7033,27 @@ var Viewport = class {
6809
7033
  });
6810
7034
  }
6811
7035
  this.unsubToolChange = this.toolManager.onChange(() => this.contextMenu?.close());
7036
+ if (options.minimap) {
7037
+ const visibleEls = () => this.store.getAll().filter((el) => this.layerManager.isLayerVisible(el.layerId));
7038
+ this.minimap = new Minimap({
7039
+ container: this.wrapper,
7040
+ getElements: visibleEls,
7041
+ getContentBounds: () => getElementsBoundingBox(visibleEls()),
7042
+ getViewportRect: () => this.camera.getVisibleRect(this.canvasEl.clientWidth, this.canvasEl.clientHeight),
7043
+ navigateTo: (w) => {
7044
+ const z = this.camera.zoom;
7045
+ this.camera.moveTo(
7046
+ this.canvasEl.clientWidth / 2 - w.x * z,
7047
+ this.canvasEl.clientHeight / 2 - w.y * z
7048
+ );
7049
+ },
7050
+ requestFrame: (cb) => typeof requestAnimationFrame !== "undefined" ? requestAnimationFrame(cb) : 0,
7051
+ cancelFrame: (id) => {
7052
+ if (typeof cancelAnimationFrame !== "undefined") cancelAnimationFrame(id);
7053
+ }
7054
+ });
7055
+ this.minimap.scheduleDraw();
7056
+ }
6812
7057
  this.domNodeManager = new DomNodeManager({
6813
7058
  domLayer: this.domLayer,
6814
7059
  onEditRequest: (id) => this.interactions.startEditingElement(id),
@@ -6841,6 +7086,7 @@ var Viewport = class {
6841
7086
  this.applyCameraTransform();
6842
7087
  this.noteEditor.updateToolbarPosition();
6843
7088
  this.contextMenu?.close();
7089
+ this.minimap?.scheduleDraw();
6844
7090
  this.requestRender();
6845
7091
  });
6846
7092
  this.gridController = new GridController({
@@ -6855,6 +7101,7 @@ var Viewport = class {
6855
7101
  this.store.on("add", (el) => {
6856
7102
  if (el.type === "grid") this.gridController.syncContext();
6857
7103
  this.renderLoop.markLayerDirty(el.layerId);
7104
+ this.minimap?.scheduleDraw();
6858
7105
  this.requestRender();
6859
7106
  }),
6860
7107
  this.store.on("remove", (el) => {
@@ -6862,6 +7109,7 @@ var Viewport = class {
6862
7109
  this.unbindArrowsFrom(el);
6863
7110
  this.domNodeManager.removeDomNode(el.id);
6864
7111
  this.renderLoop.markLayerDirty(el.layerId);
7112
+ this.minimap?.scheduleDraw();
6865
7113
  this.requestRender();
6866
7114
  }),
6867
7115
  this.store.on("update", ({ previous, current }) => {
@@ -6870,17 +7118,20 @@ var Viewport = class {
6870
7118
  if (previous.layerId !== current.layerId) {
6871
7119
  this.renderLoop.markLayerDirty(previous.layerId);
6872
7120
  }
7121
+ this.minimap?.scheduleDraw();
6873
7122
  this.requestRender();
6874
7123
  }),
6875
7124
  this.store.on("clear", () => {
6876
7125
  this.domNodeManager.clearDomNodes();
6877
7126
  this.renderLoop.markAllLayersDirty();
6878
7127
  this.gridController.syncContext();
7128
+ this.minimap?.scheduleDraw();
6879
7129
  this.requestRender();
6880
7130
  })
6881
7131
  ];
6882
7132
  this.layerManager.on("change", () => {
6883
7133
  this.toolContext.activeLayerId = this.layerManager.activeLayerId;
7134
+ this.minimap?.scheduleDraw();
6884
7135
  this.requestRender();
6885
7136
  });
6886
7137
  this.interactions = new ViewportInteractions({
@@ -6940,6 +7191,7 @@ var Viewport = class {
6940
7191
  gridController;
6941
7192
  interactions;
6942
7193
  contextMenu = null;
7194
+ minimap = null;
6943
7195
  htmlRenderers = /* @__PURE__ */ new Map();
6944
7196
  get ctx() {
6945
7197
  return this.canvasEl.getContext("2d");
@@ -7213,6 +7465,7 @@ var Viewport = class {
7213
7465
  this.arrowLabelEditor.cancel();
7214
7466
  this.historyRecorder.destroy();
7215
7467
  this.contextMenu?.dispose();
7468
+ this.minimap?.destroy();
7216
7469
  this.wrapper.removeEventListener("pointerdown", this.interactions.onTapDown);
7217
7470
  this.wrapper.removeEventListener("pointerup", this.interactions.onDoubleTap);
7218
7471
  this.wrapper.removeEventListener("dragover", this.interactions.onDragOver);
@@ -9715,7 +9968,7 @@ var LaserTool = class {
9715
9968
  };
9716
9969
 
9717
9970
  // src/index.ts
9718
- var VERSION = "0.41.0";
9971
+ var VERSION = "0.43.0";
9719
9972
  export {
9720
9973
  ArrowTool,
9721
9974
  AutoSave,