@fieldnotes/core 0.52.0 → 0.52.2
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/README.md +705 -704
- package/dist/index.cjs +181 -16
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +181 -16
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -983,6 +983,12 @@ function getElementBounds(element) {
|
|
|
983
983
|
}
|
|
984
984
|
return null;
|
|
985
985
|
}
|
|
986
|
+
function getElementVisualBounds(element) {
|
|
987
|
+
const bounds = getElementBounds(element);
|
|
988
|
+
if (!bounds) return null;
|
|
989
|
+
const rotation = element.rotation ?? 0;
|
|
990
|
+
return rotation === 0 ? bounds : rotatedAABB(bounds, rotation);
|
|
991
|
+
}
|
|
986
992
|
function getArrowBoundsAnalytical(from, to, bend) {
|
|
987
993
|
if (bend === 0) {
|
|
988
994
|
const minX2 = Math.min(from.x, to.x);
|
|
@@ -2754,10 +2760,7 @@ var ElementStore = class {
|
|
|
2754
2760
|
// Spatial index stores the rotation-expanded AABB so rotated elements remain
|
|
2755
2761
|
// broad-phase hit-test/marquee candidates; precise tests run against local bounds.
|
|
2756
2762
|
indexBounds(element) {
|
|
2757
|
-
|
|
2758
|
-
if (!bounds) return null;
|
|
2759
|
-
const angle = element.rotation ?? 0;
|
|
2760
|
-
return angle === 0 ? bounds : rotatedAABB(bounds, angle);
|
|
2763
|
+
return getElementVisualBounds(element);
|
|
2761
2764
|
}
|
|
2762
2765
|
add(element, meta) {
|
|
2763
2766
|
element = sanitizeRichText(element);
|
|
@@ -4921,6 +4924,57 @@ function createDomLayer() {
|
|
|
4921
4924
|
});
|
|
4922
4925
|
return el;
|
|
4923
4926
|
}
|
|
4927
|
+
function createPaintStack() {
|
|
4928
|
+
const el = createDomLayer();
|
|
4929
|
+
el.dataset["fieldnotesPaintStack"] = "";
|
|
4930
|
+
el.style.transformOrigin = "";
|
|
4931
|
+
return el;
|
|
4932
|
+
}
|
|
4933
|
+
|
|
4934
|
+
// src/canvas/hybrid-render-surface.ts
|
|
4935
|
+
var HybridRenderSurface = class {
|
|
4936
|
+
constructor(root) {
|
|
4937
|
+
this.root = root;
|
|
4938
|
+
}
|
|
4939
|
+
canvases = /* @__PURE__ */ new Map();
|
|
4940
|
+
beginFrame(activeOrders, width, height) {
|
|
4941
|
+
for (const [order, canvas] of this.canvases) {
|
|
4942
|
+
if (!activeOrders.has(order)) {
|
|
4943
|
+
canvas.remove();
|
|
4944
|
+
this.canvases.delete(order);
|
|
4945
|
+
}
|
|
4946
|
+
}
|
|
4947
|
+
for (const order of activeOrders) {
|
|
4948
|
+
const canvas = this.getCanvas(order);
|
|
4949
|
+
if (canvas.width !== width) canvas.width = width;
|
|
4950
|
+
if (canvas.height !== height) canvas.height = height;
|
|
4951
|
+
canvas.style.zIndex = String(order);
|
|
4952
|
+
}
|
|
4953
|
+
}
|
|
4954
|
+
getContext(order) {
|
|
4955
|
+
return this.getCanvas(order).getContext("2d");
|
|
4956
|
+
}
|
|
4957
|
+
clear() {
|
|
4958
|
+
for (const canvas of this.canvases.values()) canvas.remove();
|
|
4959
|
+
this.canvases.clear();
|
|
4960
|
+
}
|
|
4961
|
+
getCanvas(order) {
|
|
4962
|
+
let canvas = this.canvases.get(order);
|
|
4963
|
+
if (canvas) return canvas;
|
|
4964
|
+
canvas = document.createElement("canvas");
|
|
4965
|
+
canvas.dataset["paintOrder"] = String(order);
|
|
4966
|
+
Object.assign(canvas.style, {
|
|
4967
|
+
position: "absolute",
|
|
4968
|
+
inset: "0",
|
|
4969
|
+
width: "100%",
|
|
4970
|
+
height: "100%",
|
|
4971
|
+
pointerEvents: "none"
|
|
4972
|
+
});
|
|
4973
|
+
this.root.appendChild(canvas);
|
|
4974
|
+
this.canvases.set(order, canvas);
|
|
4975
|
+
return canvas;
|
|
4976
|
+
}
|
|
4977
|
+
};
|
|
4924
4978
|
|
|
4925
4979
|
// src/elements/arrow-label-editor.ts
|
|
4926
4980
|
var ArrowLabelEditor = class {
|
|
@@ -6539,6 +6593,7 @@ var DoubleTapDetector = class {
|
|
|
6539
6593
|
// src/canvas/dom-node-manager.ts
|
|
6540
6594
|
var DomNodeManager = class {
|
|
6541
6595
|
domNodes = /* @__PURE__ */ new Map();
|
|
6596
|
+
strata = /* @__PURE__ */ new Map();
|
|
6542
6597
|
htmlContent = /* @__PURE__ */ new Map();
|
|
6543
6598
|
domLayer;
|
|
6544
6599
|
onEditRequest;
|
|
@@ -6547,6 +6602,7 @@ var DomNodeManager = class {
|
|
|
6547
6602
|
lastSyncedVersion = /* @__PURE__ */ new Map();
|
|
6548
6603
|
lastSyncedZIndex = /* @__PURE__ */ new Map();
|
|
6549
6604
|
lastSyncedOpacity = /* @__PURE__ */ new Map();
|
|
6605
|
+
cameraTransform = "";
|
|
6550
6606
|
constructor(deps) {
|
|
6551
6607
|
this.domLayer = deps.domLayer;
|
|
6552
6608
|
this.onEditRequest = deps.onEditRequest;
|
|
@@ -6556,6 +6612,11 @@ var DomNodeManager = class {
|
|
|
6556
6612
|
getNode(id) {
|
|
6557
6613
|
return this.domNodes.get(id);
|
|
6558
6614
|
}
|
|
6615
|
+
setCameraTransform(transform) {
|
|
6616
|
+
if (transform === this.cameraTransform) return;
|
|
6617
|
+
this.cameraTransform = transform;
|
|
6618
|
+
for (const stratum of this.strata.values()) stratum.style.transform = transform;
|
|
6619
|
+
}
|
|
6559
6620
|
storeHtmlContent(elementId, dom) {
|
|
6560
6621
|
this.htmlContent.set(elementId, dom);
|
|
6561
6622
|
}
|
|
@@ -6583,7 +6644,7 @@ var DomNodeManager = class {
|
|
|
6583
6644
|
position: "absolute",
|
|
6584
6645
|
pointerEvents: "auto"
|
|
6585
6646
|
});
|
|
6586
|
-
this.
|
|
6647
|
+
this.getStratum(zIndex).appendChild(node);
|
|
6587
6648
|
this.domNodes.set(element.id, node);
|
|
6588
6649
|
} else if (this.getVersion) {
|
|
6589
6650
|
const currentVersion = this.getVersion(element.id);
|
|
@@ -6594,6 +6655,15 @@ var DomNodeManager = class {
|
|
|
6594
6655
|
return;
|
|
6595
6656
|
}
|
|
6596
6657
|
}
|
|
6658
|
+
if (node.parentElement !== this.getStratum(zIndex)) {
|
|
6659
|
+
const previousStratum = node.parentElement;
|
|
6660
|
+
this.getStratum(zIndex).appendChild(node);
|
|
6661
|
+
if (previousStratum?.childElementCount === 0) {
|
|
6662
|
+
const previousOrder = Number(previousStratum.dataset["paintOrder"]);
|
|
6663
|
+
previousStratum.remove();
|
|
6664
|
+
this.strata.delete(previousOrder);
|
|
6665
|
+
}
|
|
6666
|
+
}
|
|
6597
6667
|
if (this.getVersion) {
|
|
6598
6668
|
this.lastSyncedVersion.set(element.id, this.getVersion(element.id));
|
|
6599
6669
|
this.lastSyncedZIndex.set(element.id, zIndex);
|
|
@@ -6615,7 +6685,10 @@ var DomNodeManager = class {
|
|
|
6615
6685
|
}
|
|
6616
6686
|
hideDomNode(id) {
|
|
6617
6687
|
const node = this.domNodes.get(id);
|
|
6618
|
-
if (node)
|
|
6688
|
+
if (node) {
|
|
6689
|
+
node.style.display = "none";
|
|
6690
|
+
this.lastSyncedVersion.delete(id);
|
|
6691
|
+
}
|
|
6619
6692
|
}
|
|
6620
6693
|
removeDomNode(id) {
|
|
6621
6694
|
this.htmlContent.delete(id);
|
|
@@ -6624,8 +6697,14 @@ var DomNodeManager = class {
|
|
|
6624
6697
|
this.lastSyncedOpacity.delete(id);
|
|
6625
6698
|
const node = this.domNodes.get(id);
|
|
6626
6699
|
if (node) {
|
|
6700
|
+
const stratum = node.parentElement;
|
|
6627
6701
|
node.remove();
|
|
6628
6702
|
this.domNodes.delete(id);
|
|
6703
|
+
if (stratum?.childElementCount === 0) {
|
|
6704
|
+
const order = Number(stratum.dataset["paintOrder"]);
|
|
6705
|
+
stratum.remove();
|
|
6706
|
+
this.strata.delete(order);
|
|
6707
|
+
}
|
|
6629
6708
|
}
|
|
6630
6709
|
}
|
|
6631
6710
|
clearDomNodes() {
|
|
@@ -6635,6 +6714,27 @@ var DomNodeManager = class {
|
|
|
6635
6714
|
this.lastSyncedVersion.clear();
|
|
6636
6715
|
this.lastSyncedZIndex.clear();
|
|
6637
6716
|
this.lastSyncedOpacity.clear();
|
|
6717
|
+
for (const stratum of this.strata.values()) stratum.remove();
|
|
6718
|
+
this.strata.clear();
|
|
6719
|
+
}
|
|
6720
|
+
getStratum(order) {
|
|
6721
|
+
let stratum = this.strata.get(order);
|
|
6722
|
+
if (stratum) return stratum;
|
|
6723
|
+
stratum = document.createElement("div");
|
|
6724
|
+
stratum.dataset["paintOrder"] = String(order);
|
|
6725
|
+
Object.assign(stratum.style, {
|
|
6726
|
+
position: "absolute",
|
|
6727
|
+
inset: "0",
|
|
6728
|
+
width: "100%",
|
|
6729
|
+
height: "100%",
|
|
6730
|
+
pointerEvents: "none",
|
|
6731
|
+
transformOrigin: "0 0",
|
|
6732
|
+
transform: this.cameraTransform,
|
|
6733
|
+
zIndex: String(order)
|
|
6734
|
+
});
|
|
6735
|
+
this.domLayer.appendChild(stratum);
|
|
6736
|
+
this.strata.set(order, stratum);
|
|
6737
|
+
return stratum;
|
|
6638
6738
|
}
|
|
6639
6739
|
reattachHtmlContent(store) {
|
|
6640
6740
|
for (const el of store.getElementsByType("html")) {
|
|
@@ -6816,6 +6916,7 @@ var RenderLoop = class {
|
|
|
6816
6916
|
domNodeManager;
|
|
6817
6917
|
layerCache;
|
|
6818
6918
|
marginViewport;
|
|
6919
|
+
hybridSurface;
|
|
6819
6920
|
activeDrawingLayerId = null;
|
|
6820
6921
|
gridCacheDirty = true;
|
|
6821
6922
|
// set on recenter/viewport-change; consumed by the grid block
|
|
@@ -6835,6 +6936,7 @@ var RenderLoop = class {
|
|
|
6835
6936
|
this.domNodeManager = deps.domNodeManager;
|
|
6836
6937
|
this.layerCache = deps.layerCache;
|
|
6837
6938
|
this.marginViewport = deps.marginViewport;
|
|
6939
|
+
this.hybridSurface = deps.hybridSurface;
|
|
6838
6940
|
}
|
|
6839
6941
|
requestRender() {
|
|
6840
6942
|
this.needsRender = true;
|
|
@@ -6955,9 +7057,19 @@ var RenderLoop = class {
|
|
|
6955
7057
|
h: cullBounds.h + cullPad * 2
|
|
6956
7058
|
};
|
|
6957
7059
|
const allElements = this.store.getAll();
|
|
7060
|
+
const visibleElements = allElements.filter(
|
|
7061
|
+
(element) => this.layerManager.isLayerVisible(element.layerId)
|
|
7062
|
+
);
|
|
7063
|
+
const firstDomIndex = visibleElements.findIndex(
|
|
7064
|
+
(element) => this.renderer.isDomElement(element)
|
|
7065
|
+
);
|
|
7066
|
+
const hybridActive = firstDomIndex >= 0 && visibleElements.slice(firstDomIndex + 1).some((element) => !this.renderer.isDomElement(element));
|
|
7067
|
+
const hybridCanvasRuns = /* @__PURE__ */ new Map();
|
|
7068
|
+
const hybridOrders = /* @__PURE__ */ new Set();
|
|
7069
|
+
let activeHybridOrder = null;
|
|
6958
7070
|
this.layerGroups.clear();
|
|
6959
7071
|
const gridElements = [];
|
|
6960
|
-
let
|
|
7072
|
+
let paintOrder = 0;
|
|
6961
7073
|
for (const element of allElements) {
|
|
6962
7074
|
if (!this.layerManager.isLayerVisible(element.layerId)) {
|
|
6963
7075
|
if (this.renderer.isDomElement(element)) {
|
|
@@ -6965,14 +7077,27 @@ var RenderLoop = class {
|
|
|
6965
7077
|
}
|
|
6966
7078
|
continue;
|
|
6967
7079
|
}
|
|
7080
|
+
const order = ++paintOrder;
|
|
6968
7081
|
if (this.renderer.isDomElement(element)) {
|
|
7082
|
+
activeHybridOrder = null;
|
|
6969
7083
|
const layerOpacity = this.layerManager.getLayer?.(element.layerId)?.opacity ?? 1;
|
|
6970
|
-
const elBounds =
|
|
7084
|
+
const elBounds = getElementVisualBounds(element);
|
|
6971
7085
|
if (elBounds && !boundsIntersect(elBounds, cullingRect)) {
|
|
6972
7086
|
this.domNodeManager.hideDomNode(element.id);
|
|
6973
7087
|
} else {
|
|
6974
|
-
this.domNodeManager.syncDomNode(element,
|
|
7088
|
+
this.domNodeManager.syncDomNode(element, order, layerOpacity);
|
|
7089
|
+
}
|
|
7090
|
+
continue;
|
|
7091
|
+
}
|
|
7092
|
+
if (hybridActive && paintOrder > firstDomIndex + 1 && element.type !== "grid") {
|
|
7093
|
+
activeHybridOrder ??= order;
|
|
7094
|
+
let run = hybridCanvasRuns.get(activeHybridOrder);
|
|
7095
|
+
if (!run) {
|
|
7096
|
+
run = [];
|
|
7097
|
+
hybridCanvasRuns.set(activeHybridOrder, run);
|
|
7098
|
+
hybridOrders.add(activeHybridOrder);
|
|
6975
7099
|
}
|
|
7100
|
+
run.push(element);
|
|
6976
7101
|
continue;
|
|
6977
7102
|
}
|
|
6978
7103
|
if (element.type === "grid") {
|
|
@@ -6986,6 +7111,10 @@ var RenderLoop = class {
|
|
|
6986
7111
|
}
|
|
6987
7112
|
group.push(element);
|
|
6988
7113
|
}
|
|
7114
|
+
const activeTool = this.toolManager.activeTool;
|
|
7115
|
+
const overlayOrder = visibleElements.length + 1;
|
|
7116
|
+
if (hybridActive && activeTool?.renderOverlay) hybridOrders.add(overlayOrder);
|
|
7117
|
+
this.hybridSurface.beginFrame(hybridOrders, this.canvasEl.width, this.canvasEl.height);
|
|
6989
7118
|
for (const [layerId, elements] of this.layerGroups) {
|
|
6990
7119
|
const isActiveDrawingLayer = layerId === this.activeDrawingLayerId;
|
|
6991
7120
|
const layerOpacity = this.layerManager.getLayer?.(layerId)?.opacity ?? 1;
|
|
@@ -7009,7 +7138,7 @@ var RenderLoop = class {
|
|
|
7009
7138
|
offCtx.save();
|
|
7010
7139
|
this.marginViewport.applyRenderTransform(offCtx);
|
|
7011
7140
|
for (const element of elements) {
|
|
7012
|
-
const elBounds =
|
|
7141
|
+
const elBounds = getElementVisualBounds(element);
|
|
7013
7142
|
if (elBounds && !boundsIntersect(elBounds, cullingRect)) continue;
|
|
7014
7143
|
this.renderer.renderCanvasElement(offCtx, element);
|
|
7015
7144
|
}
|
|
@@ -7075,9 +7204,37 @@ var RenderLoop = class {
|
|
|
7075
7204
|
} else {
|
|
7076
7205
|
this.lastGridRefs = [];
|
|
7077
7206
|
}
|
|
7207
|
+
for (const [order, elements] of hybridCanvasRuns) {
|
|
7208
|
+
const hybridCtx = this.hybridSurface.getContext(order);
|
|
7209
|
+
if (!hybridCtx) continue;
|
|
7210
|
+
hybridCtx.clearRect(0, 0, this.canvasEl.width, this.canvasEl.height);
|
|
7211
|
+
hybridCtx.save();
|
|
7212
|
+
hybridCtx.scale(dpr, dpr);
|
|
7213
|
+
hybridCtx.translate(this.camera.position.x, this.camera.position.y);
|
|
7214
|
+
hybridCtx.scale(this.camera.zoom, this.camera.zoom);
|
|
7215
|
+
for (const element of elements) {
|
|
7216
|
+
const elBounds = getElementVisualBounds(element);
|
|
7217
|
+
if (elBounds && !boundsIntersect(elBounds, cullingRect)) continue;
|
|
7218
|
+
hybridCtx.save();
|
|
7219
|
+
hybridCtx.globalAlpha = this.layerManager.getLayer?.(element.layerId)?.opacity ?? 1;
|
|
7220
|
+
this.renderer.renderCanvasElement(hybridCtx, element);
|
|
7221
|
+
hybridCtx.restore();
|
|
7222
|
+
}
|
|
7223
|
+
hybridCtx.restore();
|
|
7224
|
+
}
|
|
7078
7225
|
const overlayT0 = performance.now();
|
|
7079
|
-
|
|
7080
|
-
|
|
7226
|
+
if (hybridActive && activeTool?.renderOverlay) {
|
|
7227
|
+
const overlayCtx = this.hybridSurface.getContext(overlayOrder);
|
|
7228
|
+
if (overlayCtx) {
|
|
7229
|
+
overlayCtx.clearRect(0, 0, this.canvasEl.width, this.canvasEl.height);
|
|
7230
|
+
overlayCtx.save();
|
|
7231
|
+
overlayCtx.scale(dpr, dpr);
|
|
7232
|
+
overlayCtx.translate(this.camera.position.x, this.camera.position.y);
|
|
7233
|
+
overlayCtx.scale(this.camera.zoom, this.camera.zoom);
|
|
7234
|
+
activeTool.renderOverlay(overlayCtx);
|
|
7235
|
+
overlayCtx.restore();
|
|
7236
|
+
}
|
|
7237
|
+
} else if (activeTool?.renderOverlay) {
|
|
7081
7238
|
activeTool.renderOverlay(ctx);
|
|
7082
7239
|
}
|
|
7083
7240
|
const overlayMs = performance.now() - overlayT0;
|
|
@@ -7828,8 +7985,11 @@ var Viewport = class {
|
|
|
7828
7985
|
});
|
|
7829
7986
|
this.wrapper = createWrapper();
|
|
7830
7987
|
this.canvasEl = createCanvas();
|
|
7988
|
+
this.paintStack = createPaintStack();
|
|
7831
7989
|
this.domLayer = createDomLayer();
|
|
7990
|
+
this.domLayer.style.zIndex = "2147483647";
|
|
7832
7991
|
this.wrapper.appendChild(this.canvasEl);
|
|
7992
|
+
this.wrapper.appendChild(this.paintStack);
|
|
7833
7993
|
this.wrapper.appendChild(this.domLayer);
|
|
7834
7994
|
this.container.appendChild(this.wrapper);
|
|
7835
7995
|
this.toolContext = {
|
|
@@ -7899,11 +8059,12 @@ var Viewport = class {
|
|
|
7899
8059
|
this.minimap.scheduleDraw();
|
|
7900
8060
|
}
|
|
7901
8061
|
this.domNodeManager = new DomNodeManager({
|
|
7902
|
-
domLayer: this.
|
|
8062
|
+
domLayer: this.paintStack,
|
|
7903
8063
|
onEditRequest: (id) => this.interactions.startEditingElement(id),
|
|
7904
8064
|
isEditingElement: (id) => this.noteEditor.isEditing && this.noteEditor.editingElementId === id,
|
|
7905
8065
|
getVersion: (id) => this.store.getVersion(id)
|
|
7906
8066
|
});
|
|
8067
|
+
this.domNodeManager.setCameraTransform(this.camera.toCSSTransform());
|
|
7907
8068
|
this.interactMode = new InteractMode({
|
|
7908
8069
|
getNode: (id) => this.domNodeManager.getNode(id)
|
|
7909
8070
|
});
|
|
@@ -7924,7 +8085,8 @@ var Viewport = class {
|
|
|
7924
8085
|
layerManager: this.layerManager,
|
|
7925
8086
|
domNodeManager: this.domNodeManager,
|
|
7926
8087
|
layerCache,
|
|
7927
|
-
marginViewport: this.marginViewport
|
|
8088
|
+
marginViewport: this.marginViewport,
|
|
8089
|
+
hybridSurface: new HybridRenderSurface(this.paintStack)
|
|
7928
8090
|
});
|
|
7929
8091
|
this.unsubCamera = this.camera.onChange(() => {
|
|
7930
8092
|
this.applyCameraTransform();
|
|
@@ -8011,6 +8173,7 @@ var Viewport = class {
|
|
|
8011
8173
|
history;
|
|
8012
8174
|
domLayer;
|
|
8013
8175
|
canvasEl;
|
|
8176
|
+
paintStack;
|
|
8014
8177
|
wrapper;
|
|
8015
8178
|
unsubCamera;
|
|
8016
8179
|
unsubToolChange;
|
|
@@ -8366,7 +8529,9 @@ var Viewport = class {
|
|
|
8366
8529
|
}
|
|
8367
8530
|
}
|
|
8368
8531
|
applyCameraTransform() {
|
|
8369
|
-
|
|
8532
|
+
const transform = this.camera.toCSSTransform();
|
|
8533
|
+
this.domLayer.style.transform = transform;
|
|
8534
|
+
this.domNodeManager.setCameraTransform(transform);
|
|
8370
8535
|
}
|
|
8371
8536
|
syncCanvasSize() {
|
|
8372
8537
|
const rect = this.container.getBoundingClientRect();
|
|
@@ -11047,7 +11212,7 @@ var LaserTool = class {
|
|
|
11047
11212
|
};
|
|
11048
11213
|
|
|
11049
11214
|
// src/index.ts
|
|
11050
|
-
var VERSION = "0.52.
|
|
11215
|
+
var VERSION = "0.52.2";
|
|
11051
11216
|
// Annotate the CommonJS export names for ESM import in node:
|
|
11052
11217
|
0 && (module.exports = {
|
|
11053
11218
|
ArrowTool,
|