@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.cjs +294 -94
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +81 -2
- package/dist/index.d.ts +81 -2
- package/dist/index.js +293 -94
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
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
|
|
4700
|
-
var
|
|
4701
|
-
var
|
|
4702
|
-
var
|
|
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
|
|
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
|
-
|
|
4709
|
-
|
|
4710
|
-
|
|
4711
|
-
|
|
4712
|
-
|
|
4713
|
-
|
|
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
|
-
|
|
4734
|
-
|
|
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
|
-
|
|
4737
|
-
|
|
4738
|
-
|
|
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
|
-
|
|
4741
|
-
if (this.
|
|
4742
|
-
|
|
4743
|
-
|
|
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.
|
|
4746
|
-
this.canvas.removeEventListener("pointermove", this.onPointerMove);
|
|
4747
|
-
this.canvas.removeEventListener("pointerup", this.onPointerUp);
|
|
4748
|
-
this.canvas.remove();
|
|
4830
|
+
this.requestDraw();
|
|
4749
4831
|
}
|
|
4750
|
-
|
|
4751
|
-
|
|
4752
|
-
|
|
4753
|
-
|
|
4754
|
-
|
|
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.
|
|
4901
|
+
this.frameId = null;
|
|
4902
|
+
if (this.disposed) return;
|
|
4758
4903
|
const ctx = this.canvas.getContext("2d");
|
|
4759
4904
|
if (!ctx) return;
|
|
4760
|
-
const
|
|
4761
|
-
|
|
4762
|
-
ctx.clearRect(0, 0,
|
|
4763
|
-
|
|
4764
|
-
|
|
4765
|
-
|
|
4766
|
-
|
|
4767
|
-
|
|
4768
|
-
|
|
4769
|
-
|
|
4770
|
-
const
|
|
4771
|
-
|
|
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(
|
|
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
|
|
4778
|
-
const
|
|
4779
|
-
|
|
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
|
-
|
|
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
|
|
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 ??
|
|
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
|
|
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 ??
|
|
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.
|
|
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,
|