@fieldnotes/core 0.57.0 → 0.58.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.js CHANGED
@@ -4695,88 +4695,247 @@ function miniToWorld(t, p) {
4695
4695
  return { x: (p.x - t.offsetX) / t.scale, y: (p.y - t.offsetY) / t.scale };
4696
4696
  }
4697
4697
 
4698
- // src/canvas/minimap.ts
4699
- var WIDTH = 200;
4700
- var HEIGHT = 140;
4701
- var MARGIN = 16;
4702
- var PADDING = 8;
4698
+ // src/canvas/minimap-controller.ts
4699
+ var DEFAULT_WIDTH = 200;
4700
+ var DEFAULT_HEIGHT = 140;
4701
+ var DEFAULT_PADDING = 8;
4702
+ var DEFAULT_DEBOUNCE_MS2 = 200;
4703
+ var DEFAULT_VIEWPORT_STROKE = "#3b82f6";
4703
4704
  var NEUTRAL = "rgba(100,116,139,0.6)";
4704
- var VIEWPORT_STROKE = "#3b82f6";
4705
+ var DOM_FALLBACK_TYPES = /* @__PURE__ */ new Set(["note", "text", "html"]);
4705
4706
  function elementColor(el) {
4706
4707
  return "color" in el && typeof el.color === "string" ? el.color : NEUTRAL;
4707
4708
  }
4708
- var Minimap = class {
4709
- constructor(deps) {
4710
- this.deps = deps;
4711
- const canvas = document.createElement("canvas");
4712
- canvas.width = WIDTH;
4713
- canvas.height = HEIGHT;
4714
- Object.assign(canvas.style, {
4715
- position: "absolute",
4716
- right: `${MARGIN}px`,
4717
- bottom: `${MARGIN}px`,
4718
- width: `${WIDTH}px`,
4719
- height: `${HEIGHT}px`,
4720
- background: "rgba(255,255,255,0.85)",
4721
- border: "1px solid rgba(0,0,0,0.15)",
4722
- borderRadius: "4px",
4723
- touchAction: "none",
4724
- cursor: "pointer",
4725
- zIndex: "10"
4726
- });
4727
- canvas.addEventListener("pointerdown", this.onPointerDown);
4728
- canvas.addEventListener("pointermove", this.onPointerMove);
4729
- canvas.addEventListener("pointerup", this.onPointerUp);
4730
- this.deps.container.appendChild(canvas);
4709
+ function sameBounds(a, b) {
4710
+ return a.x === b.x && a.y === b.y && a.w === b.w && a.h === b.h;
4711
+ }
4712
+ var MinimapController = class {
4713
+ constructor(viewport, canvas, options = {}) {
4714
+ this.viewport = viewport;
4731
4715
  this.canvas = canvas;
4716
+ this.width = options.width ?? DEFAULT_WIDTH;
4717
+ this.height = options.height ?? DEFAULT_HEIGHT;
4718
+ this.padding = options.padding ?? DEFAULT_PADDING;
4719
+ this.background = options.background ?? null;
4720
+ this.viewportStroke = options.viewportStroke ?? DEFAULT_VIEWPORT_STROKE;
4721
+ this.debounceMs = options.debounceMs ?? DEFAULT_DEBOUNCE_MS2;
4722
+ this.interactive = options.interactive !== false;
4723
+ this.requestFrame = options.requestFrame ?? ((cb) => typeof requestAnimationFrame !== "undefined" ? requestAnimationFrame(cb) : 0);
4724
+ this.cancelFrame = options.cancelFrame ?? ((id) => {
4725
+ if (typeof cancelAnimationFrame !== "undefined") cancelAnimationFrame(id);
4726
+ });
4727
+ this.renderer.setStore(viewport.store);
4728
+ this.renderer.setOnImageLoad(() => this.markSceneDirty());
4729
+ this.applyCanvasSize();
4730
+ const onScene = () => this.markSceneDirty();
4731
+ this.unsubs.push(
4732
+ viewport.store.on("add", onScene),
4733
+ viewport.store.on("remove", onScene),
4734
+ viewport.store.on("update", onScene),
4735
+ viewport.store.on("clear", onScene),
4736
+ viewport.layerManager.on("change", onScene),
4737
+ viewport.camera.onChange(() => this.onViewChanged()),
4738
+ viewport.onResize(() => this.onViewChanged())
4739
+ );
4740
+ if (this.interactive) {
4741
+ canvas.style.touchAction = "none";
4742
+ canvas.style.cursor = "pointer";
4743
+ canvas.addEventListener("pointerdown", this.onPointerDown);
4744
+ canvas.addEventListener("pointermove", this.onPointerMove);
4745
+ canvas.addEventListener("pointerup", this.onPointerUp);
4746
+ canvas.addEventListener("pointercancel", this.onPointerEnd);
4747
+ canvas.addEventListener("lostpointercapture", this.onPointerEnd);
4748
+ }
4749
+ this.renderScene();
4750
+ this.requestDraw();
4732
4751
  }
4733
- canvas;
4734
- rafId = null;
4752
+ width;
4753
+ height;
4754
+ padding;
4755
+ background;
4756
+ viewportStroke;
4757
+ debounceMs;
4758
+ interactive;
4759
+ requestFrame;
4760
+ cancelFrame;
4761
+ renderer = new ElementRenderer();
4762
+ scene = null;
4763
+ frameId = null;
4764
+ debounceTimer = null;
4735
4765
  dragging = false;
4736
- scheduleDraw() {
4737
- if (this.rafId !== null) return;
4738
- this.rafId = this.deps.requestFrame(this.draw);
4766
+ disposed = false;
4767
+ unsubs = [];
4768
+ setSize(width, height) {
4769
+ if (this.disposed) return;
4770
+ this.width = width;
4771
+ this.height = height;
4772
+ this.applyCanvasSize();
4773
+ this.clearDebounce();
4774
+ this.renderScene();
4775
+ this.requestDraw();
4739
4776
  }
4740
- destroy() {
4741
- if (this.rafId !== null) {
4742
- this.deps.cancelFrame(this.rafId);
4743
- this.rafId = null;
4777
+ requestDraw() {
4778
+ if (this.disposed || this.frameId !== null) return;
4779
+ this.frameId = this.requestFrame(this.draw);
4780
+ }
4781
+ dispose() {
4782
+ if (this.disposed) return;
4783
+ this.disposed = true;
4784
+ this.clearDebounce();
4785
+ if (this.frameId !== null) {
4786
+ this.cancelFrame(this.frameId);
4787
+ this.frameId = null;
4788
+ }
4789
+ for (const unsub of this.unsubs.splice(0)) unsub();
4790
+ if (this.interactive) {
4791
+ this.canvas.removeEventListener("pointerdown", this.onPointerDown);
4792
+ this.canvas.removeEventListener("pointermove", this.onPointerMove);
4793
+ this.canvas.removeEventListener("pointerup", this.onPointerUp);
4794
+ this.canvas.removeEventListener("pointercancel", this.onPointerEnd);
4795
+ this.canvas.removeEventListener("lostpointercapture", this.onPointerEnd);
4796
+ }
4797
+ }
4798
+ clearDebounce() {
4799
+ if (this.debounceTimer !== null) {
4800
+ clearTimeout(this.debounceTimer);
4801
+ this.debounceTimer = null;
4802
+ }
4803
+ }
4804
+ dpr() {
4805
+ return typeof devicePixelRatio !== "undefined" ? devicePixelRatio : 1;
4806
+ }
4807
+ applyCanvasSize() {
4808
+ const dpr = this.dpr();
4809
+ this.canvas.width = Math.max(1, Math.round(this.width * dpr));
4810
+ this.canvas.height = Math.max(1, Math.round(this.height * dpr));
4811
+ }
4812
+ // Single source for both mapping bounds and rendering: layer-visible,
4813
+ // grids excluded. (getElementBounds already returns null for grids, so they
4814
+ // cannot extend the bounding box today — this filter makes the invariant
4815
+ // structural instead of relying on that special case.)
4816
+ sceneElements() {
4817
+ return this.viewport.store.getAll().filter((el) => el.type !== "grid" && this.viewport.layerManager.isLayerVisible(el.layerId));
4818
+ }
4819
+ currentMapping() {
4820
+ const viewportRect = this.viewport.getVisibleRect();
4821
+ const content = getElementsBoundingBox(this.sceneElements());
4822
+ return content ? unionBounds(content, viewportRect) : viewportRect;
4823
+ }
4824
+ onViewChanged() {
4825
+ if (this.disposed) return;
4826
+ const mapping = this.currentMapping();
4827
+ if (!this.scene || !sameBounds(mapping, this.scene.mapping)) {
4828
+ this.markSceneDirty();
4744
4829
  }
4745
- this.canvas.removeEventListener("pointerdown", this.onPointerDown);
4746
- this.canvas.removeEventListener("pointermove", this.onPointerMove);
4747
- this.canvas.removeEventListener("pointerup", this.onPointerUp);
4748
- this.canvas.remove();
4830
+ this.requestDraw();
4749
4831
  }
4750
- currentTransform() {
4751
- const viewport = this.deps.getViewportRect();
4752
- const content = this.deps.getContentBounds();
4753
- const mapping = content ? unionBounds(content, viewport) : viewport;
4754
- return computeMinimapTransform(mapping, WIDTH, HEIGHT, PADDING);
4832
+ markSceneDirty() {
4833
+ if (this.disposed) return;
4834
+ this.clearDebounce();
4835
+ this.debounceTimer = setTimeout(() => {
4836
+ this.debounceTimer = null;
4837
+ this.renderScene();
4838
+ this.requestDraw();
4839
+ }, this.debounceMs);
4840
+ }
4841
+ renderScene() {
4842
+ if (this.disposed) return;
4843
+ const dpr = this.dpr();
4844
+ const mapping = this.currentMapping();
4845
+ const transform = computeMinimapTransform(mapping, this.width, this.height, this.padding);
4846
+ const sceneCanvas = document.createElement("canvas");
4847
+ sceneCanvas.width = Math.max(1, Math.round(this.width * dpr));
4848
+ sceneCanvas.height = Math.max(1, Math.round(this.height * dpr));
4849
+ const ctx = sceneCanvas.getContext("2d");
4850
+ if (!ctx) return;
4851
+ const byLayer = /* @__PURE__ */ new Map();
4852
+ for (const el of this.sceneElements()) {
4853
+ let list = byLayer.get(el.layerId);
4854
+ if (!list) {
4855
+ list = [];
4856
+ byLayer.set(el.layerId, list);
4857
+ }
4858
+ list.push(el);
4859
+ }
4860
+ for (const layer of this.viewport.layerManager.getLayers()) {
4861
+ const els = byLayer.get(layer.id);
4862
+ if (!els || els.length === 0) continue;
4863
+ const opacity = layer.opacity;
4864
+ if (opacity >= 1) {
4865
+ this.renderLayerElements(ctx, els, transform, dpr);
4866
+ continue;
4867
+ }
4868
+ const layerCanvas = document.createElement("canvas");
4869
+ layerCanvas.width = sceneCanvas.width;
4870
+ layerCanvas.height = sceneCanvas.height;
4871
+ const layerCtx = layerCanvas.getContext("2d");
4872
+ if (!layerCtx) continue;
4873
+ this.renderLayerElements(layerCtx, els, transform, dpr);
4874
+ ctx.save();
4875
+ ctx.globalAlpha = opacity;
4876
+ ctx.drawImage(layerCanvas, 0, 0);
4877
+ ctx.restore();
4878
+ }
4879
+ this.scene = { canvas: sceneCanvas, transform, mapping };
4880
+ }
4881
+ renderLayerElements(ctx, elements, t, dpr) {
4882
+ for (const el of elements) {
4883
+ if (DOM_FALLBACK_TYPES.has(el.type)) {
4884
+ const b = getElementBounds(el);
4885
+ if (!b) continue;
4886
+ const tl = worldToMini(t, { x: b.x, y: b.y });
4887
+ ctx.save();
4888
+ ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
4889
+ ctx.fillStyle = elementColor(el);
4890
+ ctx.fillRect(tl.x, tl.y, Math.max(1, b.w * t.scale), Math.max(1, b.h * t.scale));
4891
+ ctx.restore();
4892
+ continue;
4893
+ }
4894
+ ctx.save();
4895
+ ctx.setTransform(dpr * t.scale, 0, 0, dpr * t.scale, dpr * t.offsetX, dpr * t.offsetY);
4896
+ this.renderer.renderCanvasElement(ctx, el);
4897
+ ctx.restore();
4898
+ }
4755
4899
  }
4756
4900
  draw = () => {
4757
- this.rafId = null;
4901
+ this.frameId = null;
4902
+ if (this.disposed) return;
4758
4903
  const ctx = this.canvas.getContext("2d");
4759
4904
  if (!ctx) return;
4760
- const t = this.currentTransform();
4761
- const viewport = this.deps.getViewportRect();
4762
- ctx.clearRect(0, 0, WIDTH, HEIGHT);
4763
- for (const el of this.deps.getElements()) {
4764
- const b = getElementBounds(el);
4765
- if (!b) continue;
4766
- const tl = worldToMini(t, { x: b.x, y: b.y });
4767
- ctx.fillStyle = elementColor(el);
4768
- ctx.fillRect(tl.x, tl.y, Math.max(1, b.w * t.scale), Math.max(1, b.h * t.scale));
4769
- }
4770
- const vtl = worldToMini(t, { x: viewport.x, y: viewport.y });
4771
- ctx.strokeStyle = VIEWPORT_STROKE;
4905
+ const dpr = this.dpr();
4906
+ ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
4907
+ ctx.clearRect(0, 0, this.width, this.height);
4908
+ if (this.background) {
4909
+ ctx.fillStyle = this.background;
4910
+ ctx.fillRect(0, 0, this.width, this.height);
4911
+ }
4912
+ const scene = this.scene;
4913
+ if (!scene) return;
4914
+ ctx.drawImage(scene.canvas, 0, 0, this.width, this.height);
4915
+ const viewportRect = this.viewport.getVisibleRect();
4916
+ const tl = worldToMini(scene.transform, { x: viewportRect.x, y: viewportRect.y });
4917
+ ctx.strokeStyle = this.viewportStroke;
4772
4918
  ctx.lineWidth = 1.5;
4773
- ctx.strokeRect(vtl.x, vtl.y, viewport.w * t.scale, viewport.h * t.scale);
4919
+ ctx.strokeRect(
4920
+ tl.x,
4921
+ tl.y,
4922
+ viewportRect.w * scene.transform.scale,
4923
+ viewportRect.h * scene.transform.scale
4924
+ );
4774
4925
  };
4926
+ navTransform() {
4927
+ return this.scene?.transform ?? computeMinimapTransform(this.currentMapping(), this.width, this.height, this.padding);
4928
+ }
4775
4929
  navigateFromEvent(e) {
4776
4930
  const rect = this.canvas.getBoundingClientRect();
4777
- const point = { x: e.clientX - rect.left, y: e.clientY - rect.top };
4778
- const world = miniToWorld(this.currentTransform(), point);
4779
- this.deps.navigateTo(world);
4931
+ const scaleX = rect.width > 0 ? this.width / rect.width : 1;
4932
+ const scaleY = rect.height > 0 ? this.height / rect.height : 1;
4933
+ const point = {
4934
+ x: (e.clientX - rect.left) * scaleX,
4935
+ y: (e.clientY - rect.top) * scaleY
4936
+ };
4937
+ const world = miniToWorld(this.navTransform(), point);
4938
+ this.viewport.centerCameraAt(world);
4780
4939
  }
4781
4940
  onPointerDown = (e) => {
4782
4941
  e.stopPropagation();
@@ -4797,6 +4956,45 @@ var Minimap = class {
4797
4956
  } catch {
4798
4957
  }
4799
4958
  };
4959
+ // pointercancel / lostpointercapture: a browser gesture or interrupted touch
4960
+ // can end the interaction without a pointerup — the drag must not stick.
4961
+ onPointerEnd = () => {
4962
+ this.dragging = false;
4963
+ };
4964
+ };
4965
+
4966
+ // src/canvas/minimap.ts
4967
+ var WIDTH = 200;
4968
+ var HEIGHT = 140;
4969
+ var MARGIN = 16;
4970
+ var Minimap = class {
4971
+ canvas;
4972
+ controller;
4973
+ constructor(container, viewport) {
4974
+ const canvas = document.createElement("canvas");
4975
+ Object.assign(canvas.style, {
4976
+ position: "absolute",
4977
+ right: `${MARGIN}px`,
4978
+ bottom: `${MARGIN}px`,
4979
+ width: `${WIDTH}px`,
4980
+ height: `${HEIGHT}px`,
4981
+ background: "rgba(255,255,255,0.85)",
4982
+ border: "1px solid rgba(0,0,0,0.15)",
4983
+ borderRadius: "4px",
4984
+ zIndex: "10"
4985
+ });
4986
+ canvas.dataset.fieldnotesMinimap = "true";
4987
+ container.appendChild(canvas);
4988
+ this.canvas = canvas;
4989
+ this.controller = new MinimapController(viewport, canvas, { width: WIDTH, height: HEIGHT });
4990
+ }
4991
+ scheduleDraw() {
4992
+ this.controller.requestDraw();
4993
+ }
4994
+ destroy() {
4995
+ this.controller.dispose();
4996
+ this.canvas.remove();
4997
+ }
4800
4998
  };
4801
4999
 
4802
5000
  // src/canvas/viewport-dom.ts
@@ -7978,25 +8176,7 @@ var Viewport = class {
7978
8176
  }
7979
8177
  this.unsubToolChange = this.toolManager.onChange(() => this.contextMenu?.close());
7980
8178
  if (options.minimap) {
7981
- const visibleEls = () => this.store.getAll().filter((el) => this.layerManager.isLayerVisible(el.layerId));
7982
- this.minimap = new Minimap({
7983
- container: this.wrapper,
7984
- getElements: visibleEls,
7985
- getContentBounds: () => getElementsBoundingBox(visibleEls()),
7986
- getViewportRect: () => this.camera.getVisibleRect(this.canvasEl.clientWidth, this.canvasEl.clientHeight),
7987
- navigateTo: (w) => {
7988
- const z = this.camera.zoom;
7989
- this.camera.moveTo(
7990
- this.canvasEl.clientWidth / 2 - w.x * z,
7991
- this.canvasEl.clientHeight / 2 - w.y * z
7992
- );
7993
- },
7994
- requestFrame: (cb) => typeof requestAnimationFrame !== "undefined" ? requestAnimationFrame(cb) : 0,
7995
- cancelFrame: (id) => {
7996
- if (typeof cancelAnimationFrame !== "undefined") cancelAnimationFrame(id);
7997
- }
7998
- });
7999
- this.minimap.scheduleDraw();
8179
+ this.minimap = new Minimap(this.wrapper, this);
8000
8180
  }
8001
8181
  this.domNodeManager = new DomNodeManager({
8002
8182
  domLayer: this.paintStack,
@@ -8032,7 +8212,6 @@ var Viewport = class {
8032
8212
  this.applyCameraTransform();
8033
8213
  this.noteEditor.updateToolbarPosition();
8034
8214
  this.contextMenu?.close();
8035
- this.minimap?.scheduleDraw();
8036
8215
  this.requestRender();
8037
8216
  });
8038
8217
  this.gridController = new GridController({
@@ -8047,7 +8226,6 @@ var Viewport = class {
8047
8226
  this.store.on("add", (el) => {
8048
8227
  if (el.type === "grid") this.gridController.syncContext();
8049
8228
  this.renderLoop.markLayerDirty(el.layerId);
8050
- this.minimap?.scheduleDraw();
8051
8229
  this.requestRender();
8052
8230
  }),
8053
8231
  this.store.on("remove", (el) => {
@@ -8055,7 +8233,6 @@ var Viewport = class {
8055
8233
  this.unbindArrowsFrom(el);
8056
8234
  this.domNodeManager.removeDomNode(el.id);
8057
8235
  this.renderLoop.markLayerDirty(el.layerId);
8058
- this.minimap?.scheduleDraw();
8059
8236
  this.requestRender();
8060
8237
  }),
8061
8238
  this.store.on("update", ({ previous, current }) => {
@@ -8064,21 +8241,18 @@ var Viewport = class {
8064
8241
  if (previous.layerId !== current.layerId) {
8065
8242
  this.renderLoop.markLayerDirty(previous.layerId);
8066
8243
  }
8067
- this.minimap?.scheduleDraw();
8068
8244
  this.requestRender();
8069
8245
  }),
8070
8246
  this.store.on("clear", () => {
8071
8247
  this.domNodeManager.clearDomNodes();
8072
8248
  this.renderLoop.markAllLayersDirty();
8073
8249
  this.gridController.syncContext();
8074
- this.minimap?.scheduleDraw();
8075
8250
  this.requestRender();
8076
8251
  })
8077
8252
  ];
8078
8253
  this.layerManager.on("change", () => {
8079
8254
  this.toolContext.activeLayerId = this.layerManager.activeLayerId;
8080
8255
  this.renderLoop.markAllLayersDirty();
8081
- this.minimap?.scheduleDraw();
8082
8256
  this.requestRender();
8083
8257
  });
8084
8258
  this.interactions = new ViewportInteractions({
@@ -8142,6 +8316,7 @@ var Viewport = class {
8142
8316
  contextMenu = null;
8143
8317
  minimap = null;
8144
8318
  htmlRenderers = /* @__PURE__ */ new Map();
8319
+ resizeListeners = /* @__PURE__ */ new Set();
8145
8320
  get ctx() {
8146
8321
  return this.canvasEl.getContext("2d");
8147
8322
  }
@@ -8166,6 +8341,27 @@ var Viewport = class {
8166
8341
  if (!bbox) return;
8167
8342
  this.camera.fitToContent(bbox, this.wrapper.clientWidth, this.wrapper.clientHeight, padding);
8168
8343
  }
8344
+ /** World-space rectangle currently visible through the canvas. */
8345
+ getVisibleRect() {
8346
+ return this.camera.getVisibleRect(this.canvasEl.clientWidth, this.canvasEl.clientHeight);
8347
+ }
8348
+ /** Centers the camera on a world point without changing zoom. */
8349
+ centerCameraAt(world) {
8350
+ const z = this.camera.zoom;
8351
+ this.camera.moveTo(
8352
+ this.canvasEl.clientWidth / 2 - world.x * z,
8353
+ this.canvasEl.clientHeight / 2 - world.y * z
8354
+ );
8355
+ }
8356
+ /**
8357
+ * Notifies after the host container resizes (ResizeObserver-driven). A resize
8358
+ * changes the visible world rect without a camera event; overlays such as the
8359
+ * minimap subscribe to stay current. Returns an idempotent unsubscribe.
8360
+ */
8361
+ onResize(listener) {
8362
+ this.resizeListeners.add(listener);
8363
+ return () => this.resizeListeners.delete(listener);
8364
+ }
8169
8365
  requestRender() {
8170
8366
  this.renderLoop.requestRender();
8171
8367
  }
@@ -8470,6 +8666,7 @@ var Viewport = class {
8470
8666
  this.unsubStore.forEach((fn) => fn());
8471
8667
  this.resizeObserver?.disconnect();
8472
8668
  this.resizeObserver = null;
8669
+ this.resizeListeners.clear();
8473
8670
  this.wrapper.remove();
8474
8671
  }
8475
8672
  stopInteracting() {
@@ -8519,6 +8716,7 @@ var Viewport = class {
8519
8716
  const dpr = typeof devicePixelRatio !== "undefined" ? devicePixelRatio : 1;
8520
8717
  this.renderLoop.setCanvasSize(rect.width * dpr, rect.height * dpr);
8521
8718
  this.requestRender();
8719
+ this.resizeListeners.forEach((fn) => fn());
8522
8720
  }
8523
8721
  observeResize() {
8524
8722
  if (typeof ResizeObserver === "undefined") return;
@@ -8558,7 +8756,7 @@ function toLaserTrailPresence(emission) {
8558
8756
  };
8559
8757
  }
8560
8758
  var DEFAULT_COLOR = "#ff3b30";
8561
- var DEFAULT_WIDTH = 4;
8759
+ var DEFAULT_WIDTH2 = 4;
8562
8760
  var DEFAULT_FADE_MS = 1200;
8563
8761
  var DEFAULT_MAX_POINTS = 512;
8564
8762
  var RemoteLaserOverlay = class {
@@ -8574,7 +8772,7 @@ var RemoteLaserOverlay = class {
8574
8772
  constructor(host, options = {}) {
8575
8773
  this.host = host;
8576
8774
  this.color = options.color ?? DEFAULT_COLOR;
8577
- this.width = options.width ?? DEFAULT_WIDTH;
8775
+ this.width = options.width ?? DEFAULT_WIDTH2;
8578
8776
  this.fadeMs = options.fadeMs ?? DEFAULT_FADE_MS;
8579
8777
  this.maxPointsPerSender = options.maxPointsPerSender ?? DEFAULT_MAX_POINTS;
8580
8778
  this.unregister = host.registerOverlay((ctx) => this.renderTrails(ctx));
@@ -11803,7 +12001,7 @@ var TemplateTool = class {
11803
12001
 
11804
12002
  // src/tools/laser-tool.ts
11805
12003
  var DEFAULT_COLOR5 = "#ff3b30";
11806
- var DEFAULT_WIDTH2 = 4;
12004
+ var DEFAULT_WIDTH3 = 4;
11807
12005
  var DEFAULT_FADE_MS3 = 1200;
11808
12006
  var LaserTool = class {
11809
12007
  name;
@@ -11819,7 +12017,7 @@ var LaserTool = class {
11819
12017
  constructor(options = {}) {
11820
12018
  this.name = options.name ?? "laser";
11821
12019
  this.color = options.color ?? DEFAULT_COLOR5;
11822
- this.width = options.width ?? DEFAULT_WIDTH2;
12020
+ this.width = options.width ?? DEFAULT_WIDTH3;
11823
12021
  this.fadeMs = options.fadeMs ?? DEFAULT_FADE_MS3;
11824
12022
  }
11825
12023
  now() {
@@ -12066,7 +12264,7 @@ var PingTool = class {
12066
12264
  };
12067
12265
 
12068
12266
  // src/index.ts
12069
- var VERSION = "0.57.0";
12267
+ var VERSION = "0.58.0";
12070
12268
  export {
12071
12269
  ArrowTool,
12072
12270
  AutoSave,
@@ -12085,6 +12283,7 @@ export {
12085
12283
  MEASURE_PRESENCE_KIND,
12086
12284
  MeasureTool,
12087
12285
  MemoryAdapter,
12286
+ MinimapController,
12088
12287
  NoteTool,
12089
12288
  PING_PRESENCE_KIND,
12090
12289
  PencilTool,