@fieldnotes/core 0.52.0 → 0.52.1
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 +2 -1
- package/dist/index.cjs +172 -10
- 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 +172 -10
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -80,7 +80,8 @@ card.querySelector('button').addEventListener('click', () => {
|
|
|
80
80
|
const elementId = viewport.addHtmlElement(card, { x: 100, y: 200 }, { w: 250, h: 150 });
|
|
81
81
|
```
|
|
82
82
|
|
|
83
|
-
HTML elements pan, zoom,
|
|
83
|
+
HTML elements pan, zoom, resize, and interleave by layer/`zIndex` with canvas-rendered content. They
|
|
84
|
+
use a **two-mode interaction model**:
|
|
84
85
|
|
|
85
86
|
- **Default** — the element can be selected, dragged, and resized like any other element
|
|
86
87
|
- **Double-click** — enters interact mode, making buttons, inputs, and links work
|
package/dist/index.cjs
CHANGED
|
@@ -4921,6 +4921,57 @@ function createDomLayer() {
|
|
|
4921
4921
|
});
|
|
4922
4922
|
return el;
|
|
4923
4923
|
}
|
|
4924
|
+
function createPaintStack() {
|
|
4925
|
+
const el = createDomLayer();
|
|
4926
|
+
el.dataset["fieldnotesPaintStack"] = "";
|
|
4927
|
+
el.style.transformOrigin = "";
|
|
4928
|
+
return el;
|
|
4929
|
+
}
|
|
4930
|
+
|
|
4931
|
+
// src/canvas/hybrid-render-surface.ts
|
|
4932
|
+
var HybridRenderSurface = class {
|
|
4933
|
+
constructor(root) {
|
|
4934
|
+
this.root = root;
|
|
4935
|
+
}
|
|
4936
|
+
canvases = /* @__PURE__ */ new Map();
|
|
4937
|
+
beginFrame(activeOrders, width, height) {
|
|
4938
|
+
for (const [order, canvas] of this.canvases) {
|
|
4939
|
+
if (!activeOrders.has(order)) {
|
|
4940
|
+
canvas.remove();
|
|
4941
|
+
this.canvases.delete(order);
|
|
4942
|
+
}
|
|
4943
|
+
}
|
|
4944
|
+
for (const order of activeOrders) {
|
|
4945
|
+
const canvas = this.getCanvas(order);
|
|
4946
|
+
if (canvas.width !== width) canvas.width = width;
|
|
4947
|
+
if (canvas.height !== height) canvas.height = height;
|
|
4948
|
+
canvas.style.zIndex = String(order);
|
|
4949
|
+
}
|
|
4950
|
+
}
|
|
4951
|
+
getContext(order) {
|
|
4952
|
+
return this.getCanvas(order).getContext("2d");
|
|
4953
|
+
}
|
|
4954
|
+
clear() {
|
|
4955
|
+
for (const canvas of this.canvases.values()) canvas.remove();
|
|
4956
|
+
this.canvases.clear();
|
|
4957
|
+
}
|
|
4958
|
+
getCanvas(order) {
|
|
4959
|
+
let canvas = this.canvases.get(order);
|
|
4960
|
+
if (canvas) return canvas;
|
|
4961
|
+
canvas = document.createElement("canvas");
|
|
4962
|
+
canvas.dataset["paintOrder"] = String(order);
|
|
4963
|
+
Object.assign(canvas.style, {
|
|
4964
|
+
position: "absolute",
|
|
4965
|
+
inset: "0",
|
|
4966
|
+
width: "100%",
|
|
4967
|
+
height: "100%",
|
|
4968
|
+
pointerEvents: "none"
|
|
4969
|
+
});
|
|
4970
|
+
this.root.appendChild(canvas);
|
|
4971
|
+
this.canvases.set(order, canvas);
|
|
4972
|
+
return canvas;
|
|
4973
|
+
}
|
|
4974
|
+
};
|
|
4924
4975
|
|
|
4925
4976
|
// src/elements/arrow-label-editor.ts
|
|
4926
4977
|
var ArrowLabelEditor = class {
|
|
@@ -6539,6 +6590,7 @@ var DoubleTapDetector = class {
|
|
|
6539
6590
|
// src/canvas/dom-node-manager.ts
|
|
6540
6591
|
var DomNodeManager = class {
|
|
6541
6592
|
domNodes = /* @__PURE__ */ new Map();
|
|
6593
|
+
strata = /* @__PURE__ */ new Map();
|
|
6542
6594
|
htmlContent = /* @__PURE__ */ new Map();
|
|
6543
6595
|
domLayer;
|
|
6544
6596
|
onEditRequest;
|
|
@@ -6547,6 +6599,7 @@ var DomNodeManager = class {
|
|
|
6547
6599
|
lastSyncedVersion = /* @__PURE__ */ new Map();
|
|
6548
6600
|
lastSyncedZIndex = /* @__PURE__ */ new Map();
|
|
6549
6601
|
lastSyncedOpacity = /* @__PURE__ */ new Map();
|
|
6602
|
+
cameraTransform = "";
|
|
6550
6603
|
constructor(deps) {
|
|
6551
6604
|
this.domLayer = deps.domLayer;
|
|
6552
6605
|
this.onEditRequest = deps.onEditRequest;
|
|
@@ -6556,6 +6609,11 @@ var DomNodeManager = class {
|
|
|
6556
6609
|
getNode(id) {
|
|
6557
6610
|
return this.domNodes.get(id);
|
|
6558
6611
|
}
|
|
6612
|
+
setCameraTransform(transform) {
|
|
6613
|
+
if (transform === this.cameraTransform) return;
|
|
6614
|
+
this.cameraTransform = transform;
|
|
6615
|
+
for (const stratum of this.strata.values()) stratum.style.transform = transform;
|
|
6616
|
+
}
|
|
6559
6617
|
storeHtmlContent(elementId, dom) {
|
|
6560
6618
|
this.htmlContent.set(elementId, dom);
|
|
6561
6619
|
}
|
|
@@ -6583,7 +6641,7 @@ var DomNodeManager = class {
|
|
|
6583
6641
|
position: "absolute",
|
|
6584
6642
|
pointerEvents: "auto"
|
|
6585
6643
|
});
|
|
6586
|
-
this.
|
|
6644
|
+
this.getStratum(zIndex).appendChild(node);
|
|
6587
6645
|
this.domNodes.set(element.id, node);
|
|
6588
6646
|
} else if (this.getVersion) {
|
|
6589
6647
|
const currentVersion = this.getVersion(element.id);
|
|
@@ -6594,6 +6652,15 @@ var DomNodeManager = class {
|
|
|
6594
6652
|
return;
|
|
6595
6653
|
}
|
|
6596
6654
|
}
|
|
6655
|
+
if (node.parentElement !== this.getStratum(zIndex)) {
|
|
6656
|
+
const previousStratum = node.parentElement;
|
|
6657
|
+
this.getStratum(zIndex).appendChild(node);
|
|
6658
|
+
if (previousStratum?.childElementCount === 0) {
|
|
6659
|
+
const previousOrder = Number(previousStratum.dataset["paintOrder"]);
|
|
6660
|
+
previousStratum.remove();
|
|
6661
|
+
this.strata.delete(previousOrder);
|
|
6662
|
+
}
|
|
6663
|
+
}
|
|
6597
6664
|
if (this.getVersion) {
|
|
6598
6665
|
this.lastSyncedVersion.set(element.id, this.getVersion(element.id));
|
|
6599
6666
|
this.lastSyncedZIndex.set(element.id, zIndex);
|
|
@@ -6615,7 +6682,10 @@ var DomNodeManager = class {
|
|
|
6615
6682
|
}
|
|
6616
6683
|
hideDomNode(id) {
|
|
6617
6684
|
const node = this.domNodes.get(id);
|
|
6618
|
-
if (node)
|
|
6685
|
+
if (node) {
|
|
6686
|
+
node.style.display = "none";
|
|
6687
|
+
this.lastSyncedVersion.delete(id);
|
|
6688
|
+
}
|
|
6619
6689
|
}
|
|
6620
6690
|
removeDomNode(id) {
|
|
6621
6691
|
this.htmlContent.delete(id);
|
|
@@ -6624,8 +6694,14 @@ var DomNodeManager = class {
|
|
|
6624
6694
|
this.lastSyncedOpacity.delete(id);
|
|
6625
6695
|
const node = this.domNodes.get(id);
|
|
6626
6696
|
if (node) {
|
|
6697
|
+
const stratum = node.parentElement;
|
|
6627
6698
|
node.remove();
|
|
6628
6699
|
this.domNodes.delete(id);
|
|
6700
|
+
if (stratum?.childElementCount === 0) {
|
|
6701
|
+
const order = Number(stratum.dataset["paintOrder"]);
|
|
6702
|
+
stratum.remove();
|
|
6703
|
+
this.strata.delete(order);
|
|
6704
|
+
}
|
|
6629
6705
|
}
|
|
6630
6706
|
}
|
|
6631
6707
|
clearDomNodes() {
|
|
@@ -6635,6 +6711,27 @@ var DomNodeManager = class {
|
|
|
6635
6711
|
this.lastSyncedVersion.clear();
|
|
6636
6712
|
this.lastSyncedZIndex.clear();
|
|
6637
6713
|
this.lastSyncedOpacity.clear();
|
|
6714
|
+
for (const stratum of this.strata.values()) stratum.remove();
|
|
6715
|
+
this.strata.clear();
|
|
6716
|
+
}
|
|
6717
|
+
getStratum(order) {
|
|
6718
|
+
let stratum = this.strata.get(order);
|
|
6719
|
+
if (stratum) return stratum;
|
|
6720
|
+
stratum = document.createElement("div");
|
|
6721
|
+
stratum.dataset["paintOrder"] = String(order);
|
|
6722
|
+
Object.assign(stratum.style, {
|
|
6723
|
+
position: "absolute",
|
|
6724
|
+
inset: "0",
|
|
6725
|
+
width: "100%",
|
|
6726
|
+
height: "100%",
|
|
6727
|
+
pointerEvents: "none",
|
|
6728
|
+
transformOrigin: "0 0",
|
|
6729
|
+
transform: this.cameraTransform,
|
|
6730
|
+
zIndex: String(order)
|
|
6731
|
+
});
|
|
6732
|
+
this.domLayer.appendChild(stratum);
|
|
6733
|
+
this.strata.set(order, stratum);
|
|
6734
|
+
return stratum;
|
|
6638
6735
|
}
|
|
6639
6736
|
reattachHtmlContent(store) {
|
|
6640
6737
|
for (const el of store.getElementsByType("html")) {
|
|
@@ -6816,6 +6913,7 @@ var RenderLoop = class {
|
|
|
6816
6913
|
domNodeManager;
|
|
6817
6914
|
layerCache;
|
|
6818
6915
|
marginViewport;
|
|
6916
|
+
hybridSurface;
|
|
6819
6917
|
activeDrawingLayerId = null;
|
|
6820
6918
|
gridCacheDirty = true;
|
|
6821
6919
|
// set on recenter/viewport-change; consumed by the grid block
|
|
@@ -6835,6 +6933,7 @@ var RenderLoop = class {
|
|
|
6835
6933
|
this.domNodeManager = deps.domNodeManager;
|
|
6836
6934
|
this.layerCache = deps.layerCache;
|
|
6837
6935
|
this.marginViewport = deps.marginViewport;
|
|
6936
|
+
this.hybridSurface = deps.hybridSurface;
|
|
6838
6937
|
}
|
|
6839
6938
|
requestRender() {
|
|
6840
6939
|
this.needsRender = true;
|
|
@@ -6955,9 +7054,19 @@ var RenderLoop = class {
|
|
|
6955
7054
|
h: cullBounds.h + cullPad * 2
|
|
6956
7055
|
};
|
|
6957
7056
|
const allElements = this.store.getAll();
|
|
7057
|
+
const visibleElements = allElements.filter(
|
|
7058
|
+
(element) => this.layerManager.isLayerVisible(element.layerId)
|
|
7059
|
+
);
|
|
7060
|
+
const firstDomIndex = visibleElements.findIndex(
|
|
7061
|
+
(element) => this.renderer.isDomElement(element)
|
|
7062
|
+
);
|
|
7063
|
+
const hybridActive = firstDomIndex >= 0 && visibleElements.slice(firstDomIndex + 1).some((element) => !this.renderer.isDomElement(element));
|
|
7064
|
+
const hybridCanvasRuns = /* @__PURE__ */ new Map();
|
|
7065
|
+
const hybridOrders = /* @__PURE__ */ new Set();
|
|
7066
|
+
let activeHybridOrder = null;
|
|
6958
7067
|
this.layerGroups.clear();
|
|
6959
7068
|
const gridElements = [];
|
|
6960
|
-
let
|
|
7069
|
+
let paintOrder = 0;
|
|
6961
7070
|
for (const element of allElements) {
|
|
6962
7071
|
if (!this.layerManager.isLayerVisible(element.layerId)) {
|
|
6963
7072
|
if (this.renderer.isDomElement(element)) {
|
|
@@ -6965,16 +7074,29 @@ var RenderLoop = class {
|
|
|
6965
7074
|
}
|
|
6966
7075
|
continue;
|
|
6967
7076
|
}
|
|
7077
|
+
const order = ++paintOrder;
|
|
6968
7078
|
if (this.renderer.isDomElement(element)) {
|
|
7079
|
+
activeHybridOrder = null;
|
|
6969
7080
|
const layerOpacity = this.layerManager.getLayer?.(element.layerId)?.opacity ?? 1;
|
|
6970
7081
|
const elBounds = getElementBounds(element);
|
|
6971
7082
|
if (elBounds && !boundsIntersect(elBounds, cullingRect)) {
|
|
6972
7083
|
this.domNodeManager.hideDomNode(element.id);
|
|
6973
7084
|
} else {
|
|
6974
|
-
this.domNodeManager.syncDomNode(element,
|
|
7085
|
+
this.domNodeManager.syncDomNode(element, order, layerOpacity);
|
|
6975
7086
|
}
|
|
6976
7087
|
continue;
|
|
6977
7088
|
}
|
|
7089
|
+
if (hybridActive && paintOrder > firstDomIndex + 1 && element.type !== "grid") {
|
|
7090
|
+
activeHybridOrder ??= order;
|
|
7091
|
+
let run = hybridCanvasRuns.get(activeHybridOrder);
|
|
7092
|
+
if (!run) {
|
|
7093
|
+
run = [];
|
|
7094
|
+
hybridCanvasRuns.set(activeHybridOrder, run);
|
|
7095
|
+
hybridOrders.add(activeHybridOrder);
|
|
7096
|
+
}
|
|
7097
|
+
run.push(element);
|
|
7098
|
+
continue;
|
|
7099
|
+
}
|
|
6978
7100
|
if (element.type === "grid") {
|
|
6979
7101
|
gridElements.push(element);
|
|
6980
7102
|
continue;
|
|
@@ -6986,6 +7108,10 @@ var RenderLoop = class {
|
|
|
6986
7108
|
}
|
|
6987
7109
|
group.push(element);
|
|
6988
7110
|
}
|
|
7111
|
+
const activeTool = this.toolManager.activeTool;
|
|
7112
|
+
const overlayOrder = visibleElements.length + 1;
|
|
7113
|
+
if (hybridActive && activeTool?.renderOverlay) hybridOrders.add(overlayOrder);
|
|
7114
|
+
this.hybridSurface.beginFrame(hybridOrders, this.canvasEl.width, this.canvasEl.height);
|
|
6989
7115
|
for (const [layerId, elements] of this.layerGroups) {
|
|
6990
7116
|
const isActiveDrawingLayer = layerId === this.activeDrawingLayerId;
|
|
6991
7117
|
const layerOpacity = this.layerManager.getLayer?.(layerId)?.opacity ?? 1;
|
|
@@ -7075,9 +7201,37 @@ var RenderLoop = class {
|
|
|
7075
7201
|
} else {
|
|
7076
7202
|
this.lastGridRefs = [];
|
|
7077
7203
|
}
|
|
7204
|
+
for (const [order, elements] of hybridCanvasRuns) {
|
|
7205
|
+
const hybridCtx = this.hybridSurface.getContext(order);
|
|
7206
|
+
if (!hybridCtx) continue;
|
|
7207
|
+
hybridCtx.clearRect(0, 0, this.canvasEl.width, this.canvasEl.height);
|
|
7208
|
+
hybridCtx.save();
|
|
7209
|
+
hybridCtx.scale(dpr, dpr);
|
|
7210
|
+
hybridCtx.translate(this.camera.position.x, this.camera.position.y);
|
|
7211
|
+
hybridCtx.scale(this.camera.zoom, this.camera.zoom);
|
|
7212
|
+
for (const element of elements) {
|
|
7213
|
+
const elBounds = getElementBounds(element);
|
|
7214
|
+
if (elBounds && !boundsIntersect(elBounds, cullingRect)) continue;
|
|
7215
|
+
hybridCtx.save();
|
|
7216
|
+
hybridCtx.globalAlpha = this.layerManager.getLayer?.(element.layerId)?.opacity ?? 1;
|
|
7217
|
+
this.renderer.renderCanvasElement(hybridCtx, element);
|
|
7218
|
+
hybridCtx.restore();
|
|
7219
|
+
}
|
|
7220
|
+
hybridCtx.restore();
|
|
7221
|
+
}
|
|
7078
7222
|
const overlayT0 = performance.now();
|
|
7079
|
-
|
|
7080
|
-
|
|
7223
|
+
if (hybridActive && activeTool?.renderOverlay) {
|
|
7224
|
+
const overlayCtx = this.hybridSurface.getContext(overlayOrder);
|
|
7225
|
+
if (overlayCtx) {
|
|
7226
|
+
overlayCtx.clearRect(0, 0, this.canvasEl.width, this.canvasEl.height);
|
|
7227
|
+
overlayCtx.save();
|
|
7228
|
+
overlayCtx.scale(dpr, dpr);
|
|
7229
|
+
overlayCtx.translate(this.camera.position.x, this.camera.position.y);
|
|
7230
|
+
overlayCtx.scale(this.camera.zoom, this.camera.zoom);
|
|
7231
|
+
activeTool.renderOverlay(overlayCtx);
|
|
7232
|
+
overlayCtx.restore();
|
|
7233
|
+
}
|
|
7234
|
+
} else if (activeTool?.renderOverlay) {
|
|
7081
7235
|
activeTool.renderOverlay(ctx);
|
|
7082
7236
|
}
|
|
7083
7237
|
const overlayMs = performance.now() - overlayT0;
|
|
@@ -7828,8 +7982,11 @@ var Viewport = class {
|
|
|
7828
7982
|
});
|
|
7829
7983
|
this.wrapper = createWrapper();
|
|
7830
7984
|
this.canvasEl = createCanvas();
|
|
7985
|
+
this.paintStack = createPaintStack();
|
|
7831
7986
|
this.domLayer = createDomLayer();
|
|
7987
|
+
this.domLayer.style.zIndex = "2147483647";
|
|
7832
7988
|
this.wrapper.appendChild(this.canvasEl);
|
|
7989
|
+
this.wrapper.appendChild(this.paintStack);
|
|
7833
7990
|
this.wrapper.appendChild(this.domLayer);
|
|
7834
7991
|
this.container.appendChild(this.wrapper);
|
|
7835
7992
|
this.toolContext = {
|
|
@@ -7899,11 +8056,12 @@ var Viewport = class {
|
|
|
7899
8056
|
this.minimap.scheduleDraw();
|
|
7900
8057
|
}
|
|
7901
8058
|
this.domNodeManager = new DomNodeManager({
|
|
7902
|
-
domLayer: this.
|
|
8059
|
+
domLayer: this.paintStack,
|
|
7903
8060
|
onEditRequest: (id) => this.interactions.startEditingElement(id),
|
|
7904
8061
|
isEditingElement: (id) => this.noteEditor.isEditing && this.noteEditor.editingElementId === id,
|
|
7905
8062
|
getVersion: (id) => this.store.getVersion(id)
|
|
7906
8063
|
});
|
|
8064
|
+
this.domNodeManager.setCameraTransform(this.camera.toCSSTransform());
|
|
7907
8065
|
this.interactMode = new InteractMode({
|
|
7908
8066
|
getNode: (id) => this.domNodeManager.getNode(id)
|
|
7909
8067
|
});
|
|
@@ -7924,7 +8082,8 @@ var Viewport = class {
|
|
|
7924
8082
|
layerManager: this.layerManager,
|
|
7925
8083
|
domNodeManager: this.domNodeManager,
|
|
7926
8084
|
layerCache,
|
|
7927
|
-
marginViewport: this.marginViewport
|
|
8085
|
+
marginViewport: this.marginViewport,
|
|
8086
|
+
hybridSurface: new HybridRenderSurface(this.paintStack)
|
|
7928
8087
|
});
|
|
7929
8088
|
this.unsubCamera = this.camera.onChange(() => {
|
|
7930
8089
|
this.applyCameraTransform();
|
|
@@ -8011,6 +8170,7 @@ var Viewport = class {
|
|
|
8011
8170
|
history;
|
|
8012
8171
|
domLayer;
|
|
8013
8172
|
canvasEl;
|
|
8173
|
+
paintStack;
|
|
8014
8174
|
wrapper;
|
|
8015
8175
|
unsubCamera;
|
|
8016
8176
|
unsubToolChange;
|
|
@@ -8366,7 +8526,9 @@ var Viewport = class {
|
|
|
8366
8526
|
}
|
|
8367
8527
|
}
|
|
8368
8528
|
applyCameraTransform() {
|
|
8369
|
-
|
|
8529
|
+
const transform = this.camera.toCSSTransform();
|
|
8530
|
+
this.domLayer.style.transform = transform;
|
|
8531
|
+
this.domNodeManager.setCameraTransform(transform);
|
|
8370
8532
|
}
|
|
8371
8533
|
syncCanvasSize() {
|
|
8372
8534
|
const rect = this.container.getBoundingClientRect();
|
|
@@ -11047,7 +11209,7 @@ var LaserTool = class {
|
|
|
11047
11209
|
};
|
|
11048
11210
|
|
|
11049
11211
|
// src/index.ts
|
|
11050
|
-
var VERSION = "0.52.
|
|
11212
|
+
var VERSION = "0.52.1";
|
|
11051
11213
|
// Annotate the CommonJS export names for ESM import in node:
|
|
11052
11214
|
0 && (module.exports = {
|
|
11053
11215
|
ArrowTool,
|