@fieldnotes/core 0.12.0 → 0.13.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 +16 -243
- package/dist/index.d.cts +2 -36
- package/dist/index.d.ts +2 -36
- package/dist/index.js +16 -242
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -37,7 +37,6 @@ __export(index_exports, {
|
|
|
37
37
|
HistoryRecorder: () => HistoryRecorder,
|
|
38
38
|
HistoryStack: () => HistoryStack,
|
|
39
39
|
ImageTool: () => ImageTool,
|
|
40
|
-
InputFilter: () => InputFilter,
|
|
41
40
|
InputHandler: () => InputHandler,
|
|
42
41
|
LayerManager: () => LayerManager,
|
|
43
42
|
MeasureTool: () => MeasureTool,
|
|
@@ -399,13 +398,7 @@ function exportState(elements, camera, layers = []) {
|
|
|
399
398
|
position: { ...camera.position },
|
|
400
399
|
zoom: camera.zoom
|
|
401
400
|
},
|
|
402
|
-
elements: elements.map((el) =>
|
|
403
|
-
const clone = structuredClone(el);
|
|
404
|
-
if (clone.type === "arrow") {
|
|
405
|
-
delete clone.cachedControlPoint;
|
|
406
|
-
}
|
|
407
|
-
return clone;
|
|
408
|
-
}),
|
|
401
|
+
elements: elements.map((el) => structuredClone(el)),
|
|
409
402
|
layers: layers.map((l) => ({ ...l }))
|
|
410
403
|
};
|
|
411
404
|
}
|
|
@@ -843,67 +836,6 @@ var Background = class {
|
|
|
843
836
|
}
|
|
844
837
|
};
|
|
845
838
|
|
|
846
|
-
// src/canvas/input-filter.ts
|
|
847
|
-
var InputFilter = class _InputFilter {
|
|
848
|
-
activePenId = null;
|
|
849
|
-
pendingTap = null;
|
|
850
|
-
static MIN_MOVE_DISTANCE = 3;
|
|
851
|
-
filterDown(e) {
|
|
852
|
-
if (e.pointerType === "pen") {
|
|
853
|
-
this.activePenId = e.pointerId;
|
|
854
|
-
return { event: e, action: "dispatch" };
|
|
855
|
-
}
|
|
856
|
-
if (e.pointerType === "touch" && this.activePenId !== null) {
|
|
857
|
-
return { event: e, action: "suppress" };
|
|
858
|
-
}
|
|
859
|
-
if (e.pointerType === "touch") {
|
|
860
|
-
this.pendingTap = { pointerId: e.pointerId, x: e.clientX, y: e.clientY };
|
|
861
|
-
return { event: e, action: "defer" };
|
|
862
|
-
}
|
|
863
|
-
return { event: e, action: "dispatch" };
|
|
864
|
-
}
|
|
865
|
-
filterMove(e) {
|
|
866
|
-
if (e.pointerType === "touch" && this.activePenId !== null) {
|
|
867
|
-
return { event: e, action: "suppress" };
|
|
868
|
-
}
|
|
869
|
-
if (this.pendingTap && e.pointerId === this.pendingTap.pointerId) {
|
|
870
|
-
const dx = e.clientX - this.pendingTap.x;
|
|
871
|
-
const dy = e.clientY - this.pendingTap.y;
|
|
872
|
-
if (dx * dx + dy * dy > _InputFilter.MIN_MOVE_DISTANCE * _InputFilter.MIN_MOVE_DISTANCE) {
|
|
873
|
-
this.pendingTap = null;
|
|
874
|
-
return { event: e, action: "dispatch" };
|
|
875
|
-
}
|
|
876
|
-
return { event: e, action: "suppress" };
|
|
877
|
-
}
|
|
878
|
-
return { event: e, action: "dispatch" };
|
|
879
|
-
}
|
|
880
|
-
filterUp(e) {
|
|
881
|
-
if (e.pointerId === this.activePenId) {
|
|
882
|
-
this.activePenId = null;
|
|
883
|
-
return { event: e, action: "dispatch" };
|
|
884
|
-
}
|
|
885
|
-
if (e.pointerType === "touch" && this.activePenId !== null) {
|
|
886
|
-
return { event: e, action: "suppress" };
|
|
887
|
-
}
|
|
888
|
-
if (this.pendingTap && e.pointerId === this.pendingTap.pointerId) {
|
|
889
|
-
const tap = { x: this.pendingTap.x, y: this.pendingTap.y };
|
|
890
|
-
this.pendingTap = null;
|
|
891
|
-
return { event: e, action: "dispatch", pendingTap: tap };
|
|
892
|
-
}
|
|
893
|
-
return { event: e, action: "dispatch" };
|
|
894
|
-
}
|
|
895
|
-
reset() {
|
|
896
|
-
this.activePenId = null;
|
|
897
|
-
this.pendingTap = null;
|
|
898
|
-
}
|
|
899
|
-
};
|
|
900
|
-
|
|
901
|
-
// src/elements/create-id.ts
|
|
902
|
-
var counter = 0;
|
|
903
|
-
function createId(prefix) {
|
|
904
|
-
return `${prefix}_${Date.now().toString(36)}_${(counter++).toString(36)}`;
|
|
905
|
-
}
|
|
906
|
-
|
|
907
839
|
// src/canvas/input-handler.ts
|
|
908
840
|
var ZOOM_SENSITIVITY = 1e-3;
|
|
909
841
|
var MIDDLE_BUTTON = 1;
|
|
@@ -929,21 +861,13 @@ var InputHandler = class {
|
|
|
929
861
|
historyRecorder;
|
|
930
862
|
historyStack;
|
|
931
863
|
isToolActive = false;
|
|
932
|
-
lastPointerEvent = null;
|
|
933
|
-
inputFilter = new InputFilter();
|
|
934
|
-
deferredDown = null;
|
|
935
864
|
abortController = new AbortController();
|
|
936
|
-
clipboard = [];
|
|
937
|
-
pasteCount = 0;
|
|
938
865
|
setToolManager(toolManager, toolContext) {
|
|
939
866
|
this.toolManager = toolManager;
|
|
940
867
|
this.toolContext = toolContext;
|
|
941
868
|
}
|
|
942
869
|
destroy() {
|
|
943
870
|
this.abortController.abort();
|
|
944
|
-
this.inputFilter.reset();
|
|
945
|
-
this.deferredDown = null;
|
|
946
|
-
this.lastPointerEvent = null;
|
|
947
871
|
}
|
|
948
872
|
bind() {
|
|
949
873
|
const opts = { signal: this.abortController.signal };
|
|
@@ -979,18 +903,11 @@ var InputHandler = class {
|
|
|
979
903
|
this.lastPointer = { x: e.clientX, y: e.clientY };
|
|
980
904
|
return;
|
|
981
905
|
}
|
|
982
|
-
if (this.activePointers.size === 1 &&
|
|
983
|
-
const result = this.inputFilter.filterDown(e);
|
|
984
|
-
if (result.action === "suppress") return;
|
|
985
|
-
if (result.action === "defer") {
|
|
986
|
-
this.deferredDown = e;
|
|
987
|
-
return;
|
|
988
|
-
}
|
|
906
|
+
if (this.activePointers.size === 1 && e.button === 0) {
|
|
989
907
|
this.dispatchToolDown(e);
|
|
990
908
|
}
|
|
991
909
|
};
|
|
992
910
|
onPointerMove = (e) => {
|
|
993
|
-
this.lastPointerEvent = e;
|
|
994
911
|
if (this.activePointers.has(e.pointerId)) {
|
|
995
912
|
this.activePointers.set(e.pointerId, { x: e.clientX, y: e.clientY });
|
|
996
913
|
}
|
|
@@ -1007,22 +924,11 @@ var InputHandler = class {
|
|
|
1007
924
|
}
|
|
1008
925
|
if (this.isToolActive) {
|
|
1009
926
|
this.dispatchToolMove(e);
|
|
1010
|
-
} else if (this.deferredDown) {
|
|
1011
|
-
const result = this.inputFilter.filterMove(e);
|
|
1012
|
-
if (result.action === "dispatch") {
|
|
1013
|
-
this.dispatchToolDown(this.deferredDown);
|
|
1014
|
-
this.deferredDown = null;
|
|
1015
|
-
this.dispatchToolMove(e);
|
|
1016
|
-
}
|
|
1017
927
|
} else if (this.activePointers.size === 0) {
|
|
1018
928
|
this.dispatchToolHover(e);
|
|
1019
929
|
}
|
|
1020
930
|
};
|
|
1021
931
|
onPointerUp = (e) => {
|
|
1022
|
-
try {
|
|
1023
|
-
this.element.releasePointerCapture(e.pointerId);
|
|
1024
|
-
} catch {
|
|
1025
|
-
}
|
|
1026
932
|
this.activePointers.delete(e.pointerId);
|
|
1027
933
|
if (this.activePointers.size < 2) {
|
|
1028
934
|
this.lastPinchDistance = 0;
|
|
@@ -1030,16 +936,9 @@ var InputHandler = class {
|
|
|
1030
936
|
if (this.isPanning && this.activePointers.size === 0) {
|
|
1031
937
|
this.isPanning = false;
|
|
1032
938
|
}
|
|
1033
|
-
const upResult = this.inputFilter.filterUp(e);
|
|
1034
939
|
if (this.isToolActive) {
|
|
1035
940
|
this.dispatchToolUp(e);
|
|
1036
941
|
this.isToolActive = false;
|
|
1037
|
-
} else if (this.deferredDown && upResult.pendingTap) {
|
|
1038
|
-
this.dispatchToolDown(this.deferredDown);
|
|
1039
|
-
this.dispatchToolUp(e);
|
|
1040
|
-
this.deferredDown = null;
|
|
1041
|
-
} else {
|
|
1042
|
-
this.deferredDown = null;
|
|
1043
942
|
}
|
|
1044
943
|
};
|
|
1045
944
|
onKeyDown = (e) => {
|
|
@@ -1058,30 +957,13 @@ var InputHandler = class {
|
|
|
1058
957
|
e.preventDefault();
|
|
1059
958
|
this.handleRedo();
|
|
1060
959
|
}
|
|
1061
|
-
if ((e.ctrlKey || e.metaKey) && e.key === "c") {
|
|
1062
|
-
e.preventDefault();
|
|
1063
|
-
this.handleCopy();
|
|
1064
|
-
}
|
|
1065
|
-
if ((e.ctrlKey || e.metaKey) && e.key === "v") {
|
|
1066
|
-
e.preventDefault();
|
|
1067
|
-
this.handlePaste();
|
|
1068
|
-
}
|
|
1069
960
|
};
|
|
1070
961
|
onKeyUp = (e) => {
|
|
1071
962
|
if (e.key === " ") {
|
|
1072
963
|
this.spaceHeld = false;
|
|
1073
|
-
if (this.activePointers.size === 0) {
|
|
1074
|
-
if (this.lastPointerEvent) {
|
|
1075
|
-
this.dispatchToolHover(this.lastPointerEvent);
|
|
1076
|
-
} else {
|
|
1077
|
-
this.toolContext?.setCursor?.("default");
|
|
1078
|
-
}
|
|
1079
|
-
}
|
|
1080
964
|
}
|
|
1081
965
|
};
|
|
1082
966
|
startPinch() {
|
|
1083
|
-
this.inputFilter.reset();
|
|
1084
|
-
this.deferredDown = null;
|
|
1085
967
|
this.isPanning = true;
|
|
1086
968
|
const [a, b] = this.getPinchPoints();
|
|
1087
969
|
this.lastPinchDistance = this.distance(a, b);
|
|
@@ -1121,9 +1003,7 @@ var InputHandler = class {
|
|
|
1121
1003
|
return {
|
|
1122
1004
|
x: e.clientX - rect.left,
|
|
1123
1005
|
y: e.clientY - rect.top,
|
|
1124
|
-
pressure: e.pressure
|
|
1125
|
-
pointerType: e.pointerType === "touch" || e.pointerType === "pen" ? e.pointerType : "mouse",
|
|
1126
|
-
shiftKey: e.shiftKey
|
|
1006
|
+
pressure: e.pressure
|
|
1127
1007
|
};
|
|
1128
1008
|
}
|
|
1129
1009
|
dispatchToolDown(e) {
|
|
@@ -1176,78 +1056,11 @@ var InputHandler = class {
|
|
|
1176
1056
|
this.historyRecorder?.resume();
|
|
1177
1057
|
this.toolContext.requestRender();
|
|
1178
1058
|
}
|
|
1179
|
-
handleCopy() {
|
|
1180
|
-
if (!this.toolManager || !this.toolContext || this.isToolActive) return;
|
|
1181
|
-
const tool = this.toolManager.activeTool;
|
|
1182
|
-
if (tool?.name !== "select") return;
|
|
1183
|
-
const selectTool = tool;
|
|
1184
|
-
const ids = selectTool.selectedIds;
|
|
1185
|
-
if (ids.length === 0) return;
|
|
1186
|
-
this.clipboard = [];
|
|
1187
|
-
for (const id of ids) {
|
|
1188
|
-
const el = this.toolContext.store.getById(id);
|
|
1189
|
-
if (el) this.clipboard.push(structuredClone(el));
|
|
1190
|
-
}
|
|
1191
|
-
this.pasteCount = 0;
|
|
1192
|
-
}
|
|
1193
|
-
handlePaste() {
|
|
1194
|
-
if (!this.toolManager || !this.toolContext || this.clipboard.length === 0 || this.isToolActive)
|
|
1195
|
-
return;
|
|
1196
|
-
const tool = this.toolManager.activeTool;
|
|
1197
|
-
if (tool?.name !== "select") return;
|
|
1198
|
-
const selectTool = tool;
|
|
1199
|
-
this.pasteCount++;
|
|
1200
|
-
const offset = this.pasteCount * 20;
|
|
1201
|
-
const idMap = /* @__PURE__ */ new Map();
|
|
1202
|
-
for (const el of this.clipboard) {
|
|
1203
|
-
idMap.set(el.id, createId(el.type));
|
|
1204
|
-
}
|
|
1205
|
-
const newIds = [];
|
|
1206
|
-
this.historyRecorder?.begin();
|
|
1207
|
-
for (const el of this.clipboard) {
|
|
1208
|
-
const clone = structuredClone(el);
|
|
1209
|
-
const newId = idMap.get(el.id);
|
|
1210
|
-
if (!newId) continue;
|
|
1211
|
-
clone.id = newId;
|
|
1212
|
-
clone.position = { x: clone.position.x + offset, y: clone.position.y + offset };
|
|
1213
|
-
if (clone.type === "arrow") {
|
|
1214
|
-
const arrow = clone;
|
|
1215
|
-
arrow.from = { x: arrow.from.x + offset, y: arrow.from.y + offset };
|
|
1216
|
-
arrow.to = { x: arrow.to.x + offset, y: arrow.to.y + offset };
|
|
1217
|
-
delete arrow.cachedControlPoint;
|
|
1218
|
-
if (arrow.fromBinding) {
|
|
1219
|
-
const newTarget = idMap.get(arrow.fromBinding.elementId);
|
|
1220
|
-
if (newTarget) {
|
|
1221
|
-
arrow.fromBinding = { elementId: newTarget };
|
|
1222
|
-
} else {
|
|
1223
|
-
delete arrow.fromBinding;
|
|
1224
|
-
}
|
|
1225
|
-
}
|
|
1226
|
-
if (arrow.toBinding) {
|
|
1227
|
-
const newTarget = idMap.get(arrow.toBinding.elementId);
|
|
1228
|
-
if (newTarget) {
|
|
1229
|
-
arrow.toBinding = { elementId: newTarget };
|
|
1230
|
-
} else {
|
|
1231
|
-
delete arrow.toBinding;
|
|
1232
|
-
}
|
|
1233
|
-
}
|
|
1234
|
-
}
|
|
1235
|
-
if (this.toolContext.activeLayerId) {
|
|
1236
|
-
clone.layerId = this.toolContext.activeLayerId;
|
|
1237
|
-
}
|
|
1238
|
-
this.toolContext.store.add(clone);
|
|
1239
|
-
newIds.push(clone.id);
|
|
1240
|
-
}
|
|
1241
|
-
this.historyRecorder?.commit();
|
|
1242
|
-
selectTool.setSelection(newIds);
|
|
1243
|
-
this.toolContext.requestRender();
|
|
1244
|
-
}
|
|
1245
1059
|
cancelToolIfActive(e) {
|
|
1246
1060
|
if (this.isToolActive) {
|
|
1247
1061
|
this.dispatchToolUp(e);
|
|
1248
1062
|
this.isToolActive = false;
|
|
1249
1063
|
}
|
|
1250
|
-
this.deferredDown = null;
|
|
1251
1064
|
}
|
|
1252
1065
|
};
|
|
1253
1066
|
|
|
@@ -1495,23 +1308,19 @@ var ElementStore = class {
|
|
|
1495
1308
|
bus = new EventBus();
|
|
1496
1309
|
layerOrderMap = /* @__PURE__ */ new Map();
|
|
1497
1310
|
spatialIndex = new Quadtree({ x: -1e5, y: -1e5, w: 2e5, h: 2e5 });
|
|
1498
|
-
sortedCache = null;
|
|
1499
1311
|
get count() {
|
|
1500
1312
|
return this.elements.size;
|
|
1501
1313
|
}
|
|
1502
1314
|
setLayerOrder(order) {
|
|
1503
1315
|
this.layerOrderMap = new Map(order);
|
|
1504
|
-
this.sortedCache = null;
|
|
1505
1316
|
}
|
|
1506
1317
|
getAll() {
|
|
1507
|
-
|
|
1508
|
-
this.sortedCache = [...this.elements.values()].sort((a, b) => {
|
|
1318
|
+
return [...this.elements.values()].sort((a, b) => {
|
|
1509
1319
|
const layerA = this.layerOrderMap.get(a.layerId) ?? 0;
|
|
1510
1320
|
const layerB = this.layerOrderMap.get(b.layerId) ?? 0;
|
|
1511
1321
|
if (layerA !== layerB) return layerA - layerB;
|
|
1512
1322
|
return a.zIndex - b.zIndex;
|
|
1513
1323
|
});
|
|
1514
|
-
return this.sortedCache;
|
|
1515
1324
|
}
|
|
1516
1325
|
getById(id) {
|
|
1517
1326
|
return this.elements.get(id);
|
|
@@ -1522,7 +1331,6 @@ var ElementStore = class {
|
|
|
1522
1331
|
);
|
|
1523
1332
|
}
|
|
1524
1333
|
add(element) {
|
|
1525
|
-
this.sortedCache = null;
|
|
1526
1334
|
this.elements.set(element.id, element);
|
|
1527
1335
|
const bounds = getElementBounds(element);
|
|
1528
1336
|
if (bounds) this.spatialIndex.insert(element.id, bounds);
|
|
@@ -1531,15 +1339,11 @@ var ElementStore = class {
|
|
|
1531
1339
|
update(id, partial) {
|
|
1532
1340
|
const existing = this.elements.get(id);
|
|
1533
1341
|
if (!existing) return;
|
|
1534
|
-
this.sortedCache = null;
|
|
1535
1342
|
const updated = { ...existing, ...partial, id: existing.id, type: existing.type };
|
|
1536
1343
|
if (updated.type === "arrow") {
|
|
1537
1344
|
const arrow = updated;
|
|
1538
1345
|
arrow.cachedControlPoint = getArrowControlPoint(arrow.from, arrow.to, arrow.bend);
|
|
1539
1346
|
}
|
|
1540
|
-
if (updated.type === "note" && "text" in partial) {
|
|
1541
|
-
updated.text = sanitizeNoteHtml(updated.text);
|
|
1542
|
-
}
|
|
1543
1347
|
this.elements.set(id, updated);
|
|
1544
1348
|
const newBounds = getElementBounds(updated);
|
|
1545
1349
|
if (newBounds) {
|
|
@@ -1550,13 +1354,11 @@ var ElementStore = class {
|
|
|
1550
1354
|
remove(id) {
|
|
1551
1355
|
const element = this.elements.get(id);
|
|
1552
1356
|
if (!element) return;
|
|
1553
|
-
this.sortedCache = null;
|
|
1554
1357
|
this.elements.delete(id);
|
|
1555
1358
|
this.spatialIndex.remove(id);
|
|
1556
1359
|
this.bus.emit("remove", element);
|
|
1557
1360
|
}
|
|
1558
1361
|
clear() {
|
|
1559
|
-
this.sortedCache = null;
|
|
1560
1362
|
this.elements.clear();
|
|
1561
1363
|
this.spatialIndex.clear();
|
|
1562
1364
|
this.bus.emit("clear", null);
|
|
@@ -1565,7 +1367,6 @@ var ElementStore = class {
|
|
|
1565
1367
|
return this.getAll().map((el) => ({ ...el }));
|
|
1566
1368
|
}
|
|
1567
1369
|
loadSnapshot(elements) {
|
|
1568
|
-
this.sortedCache = null;
|
|
1569
1370
|
this.elements.clear();
|
|
1570
1371
|
this.spatialIndex.clear();
|
|
1571
1372
|
for (const el of elements) {
|
|
@@ -1573,10 +1374,6 @@ var ElementStore = class {
|
|
|
1573
1374
|
const bounds = getElementBounds(el);
|
|
1574
1375
|
if (bounds) this.spatialIndex.insert(el.id, bounds);
|
|
1575
1376
|
}
|
|
1576
|
-
this.bus.emit("clear", null);
|
|
1577
|
-
for (const el of elements) {
|
|
1578
|
-
this.bus.emit("add", el);
|
|
1579
|
-
}
|
|
1580
1377
|
}
|
|
1581
1378
|
queryRect(rect) {
|
|
1582
1379
|
const ids = this.spatialIndex.query(rect);
|
|
@@ -2626,6 +2423,12 @@ var ElementRenderer = class {
|
|
|
2626
2423
|
}
|
|
2627
2424
|
};
|
|
2628
2425
|
|
|
2426
|
+
// src/elements/create-id.ts
|
|
2427
|
+
var counter = 0;
|
|
2428
|
+
function createId(prefix) {
|
|
2429
|
+
return `${prefix}_${Date.now().toString(36)}_${(counter++).toString(36)}`;
|
|
2430
|
+
}
|
|
2431
|
+
|
|
2629
2432
|
// src/elements/element-factory.ts
|
|
2630
2433
|
var DEFAULT_NOTE_FONT_SIZE = 18;
|
|
2631
2434
|
function createStroke(input) {
|
|
@@ -2651,7 +2454,7 @@ function createNote(input) {
|
|
|
2651
2454
|
locked: input.locked ?? false,
|
|
2652
2455
|
layerId: input.layerId ?? "",
|
|
2653
2456
|
size: input.size ?? { w: 200, h: 100 },
|
|
2654
|
-
text:
|
|
2457
|
+
text: input.text ?? "",
|
|
2655
2458
|
backgroundColor: input.backgroundColor ?? "#ffeb3b",
|
|
2656
2459
|
textColor: input.textColor ?? "#000000",
|
|
2657
2460
|
fontSize: input.fontSize ?? DEFAULT_NOTE_FONT_SIZE
|
|
@@ -4758,10 +4561,7 @@ var Viewport = class {
|
|
|
4758
4561
|
position: "relative",
|
|
4759
4562
|
width: "100%",
|
|
4760
4563
|
height: "100%",
|
|
4761
|
-
overflow: "hidden"
|
|
4762
|
-
overscrollBehavior: "none",
|
|
4763
|
-
userSelect: "none",
|
|
4764
|
-
webkitUserSelect: "none"
|
|
4564
|
+
overflow: "hidden"
|
|
4765
4565
|
});
|
|
4766
4566
|
return el;
|
|
4767
4567
|
}
|
|
@@ -5176,15 +4976,9 @@ var SelectTool = class {
|
|
|
5176
4976
|
lastWorld = { x: 0, y: 0 };
|
|
5177
4977
|
currentWorld = { x: 0, y: 0 };
|
|
5178
4978
|
ctx = null;
|
|
5179
|
-
pendingSingleSelectId = null;
|
|
5180
|
-
hasDragged = false;
|
|
5181
4979
|
get selectedIds() {
|
|
5182
4980
|
return [...this._selectedIds];
|
|
5183
4981
|
}
|
|
5184
|
-
setSelection(ids) {
|
|
5185
|
-
this._selectedIds = ids;
|
|
5186
|
-
this.ctx?.requestRender();
|
|
5187
|
-
}
|
|
5188
4982
|
get isMarqueeActive() {
|
|
5189
4983
|
return this.mode.type === "marquee";
|
|
5190
4984
|
}
|
|
@@ -5233,27 +5027,13 @@ var SelectTool = class {
|
|
|
5233
5027
|
return;
|
|
5234
5028
|
}
|
|
5235
5029
|
}
|
|
5236
|
-
this.pendingSingleSelectId = null;
|
|
5237
|
-
this.hasDragged = false;
|
|
5238
5030
|
const hit = this.hitTest(world, ctx);
|
|
5239
5031
|
if (hit) {
|
|
5240
5032
|
const alreadySelected = this._selectedIds.includes(hit.id);
|
|
5241
|
-
if (
|
|
5242
|
-
|
|
5243
|
-
this._selectedIds = this._selectedIds.filter((id) => id !== hit.id);
|
|
5244
|
-
this.mode = { type: "idle" };
|
|
5245
|
-
} else {
|
|
5246
|
-
this._selectedIds = [...this._selectedIds, hit.id];
|
|
5247
|
-
this.mode = hit.locked ? { type: "idle" } : { type: "dragging" };
|
|
5248
|
-
}
|
|
5249
|
-
} else {
|
|
5250
|
-
if (!alreadySelected) {
|
|
5251
|
-
this._selectedIds = [hit.id];
|
|
5252
|
-
} else if (this._selectedIds.length > 1) {
|
|
5253
|
-
this.pendingSingleSelectId = hit.id;
|
|
5254
|
-
}
|
|
5255
|
-
this.mode = hit.locked ? { type: "idle" } : { type: "dragging" };
|
|
5033
|
+
if (!alreadySelected) {
|
|
5034
|
+
this._selectedIds = [hit.id];
|
|
5256
5035
|
}
|
|
5036
|
+
this.mode = hit.locked ? { type: "idle" } : { type: "dragging" };
|
|
5257
5037
|
} else {
|
|
5258
5038
|
this._selectedIds = [];
|
|
5259
5039
|
this.mode = { type: "marquee", start: world };
|
|
@@ -5279,7 +5059,6 @@ var SelectTool = class {
|
|
|
5279
5059
|
return;
|
|
5280
5060
|
}
|
|
5281
5061
|
if (this.mode.type === "dragging" && this._selectedIds.length > 0) {
|
|
5282
|
-
this.hasDragged = true;
|
|
5283
5062
|
ctx.setCursor?.("move");
|
|
5284
5063
|
const snapped = this.snap(world, ctx);
|
|
5285
5064
|
const dx = snapped.x - this.lastWorld.x;
|
|
@@ -5348,11 +5127,6 @@ var SelectTool = class {
|
|
|
5348
5127
|
}
|
|
5349
5128
|
ctx.requestRender();
|
|
5350
5129
|
}
|
|
5351
|
-
if (!this.hasDragged && this.pendingSingleSelectId !== null) {
|
|
5352
|
-
this._selectedIds = [this.pendingSingleSelectId];
|
|
5353
|
-
}
|
|
5354
|
-
this.pendingSingleSelectId = null;
|
|
5355
|
-
this.hasDragged = false;
|
|
5356
5130
|
this.mode = { type: "idle" };
|
|
5357
5131
|
ctx.setCursor?.("default");
|
|
5358
5132
|
}
|
|
@@ -6533,7 +6307,7 @@ var UpdateLayerCommand = class {
|
|
|
6533
6307
|
};
|
|
6534
6308
|
|
|
6535
6309
|
// src/index.ts
|
|
6536
|
-
var VERSION = "0.
|
|
6310
|
+
var VERSION = "0.11.0";
|
|
6537
6311
|
// Annotate the CommonJS export names for ESM import in node:
|
|
6538
6312
|
0 && (module.exports = {
|
|
6539
6313
|
AddElementCommand,
|
|
@@ -6553,7 +6327,6 @@ var VERSION = "0.12.0";
|
|
|
6553
6327
|
HistoryRecorder,
|
|
6554
6328
|
HistoryStack,
|
|
6555
6329
|
ImageTool,
|
|
6556
|
-
InputFilter,
|
|
6557
6330
|
InputHandler,
|
|
6558
6331
|
LayerManager,
|
|
6559
6332
|
MeasureTool,
|
package/dist/index.d.cts
CHANGED
|
@@ -200,7 +200,6 @@ declare class ElementStore {
|
|
|
200
200
|
private bus;
|
|
201
201
|
private layerOrderMap;
|
|
202
202
|
private spatialIndex;
|
|
203
|
-
private sortedCache;
|
|
204
203
|
get count(): number;
|
|
205
204
|
setLayerOrder(order: Map<string, number>): void;
|
|
206
205
|
getAll(): CanvasElement[];
|
|
@@ -239,8 +238,6 @@ interface PointerState {
|
|
|
239
238
|
x: number;
|
|
240
239
|
y: number;
|
|
241
240
|
pressure: number;
|
|
242
|
-
pointerType: 'mouse' | 'touch' | 'pen';
|
|
243
|
-
shiftKey: boolean;
|
|
244
241
|
}
|
|
245
242
|
interface Tool {
|
|
246
243
|
readonly name: string;
|
|
@@ -426,12 +423,7 @@ declare class InputHandler {
|
|
|
426
423
|
private historyRecorder;
|
|
427
424
|
private historyStack;
|
|
428
425
|
private isToolActive;
|
|
429
|
-
private lastPointerEvent;
|
|
430
|
-
private readonly inputFilter;
|
|
431
|
-
private deferredDown;
|
|
432
426
|
private readonly abortController;
|
|
433
|
-
private clipboard;
|
|
434
|
-
private pasteCount;
|
|
435
427
|
constructor(element: HTMLElement, camera: Camera, options?: InputHandlerOptions);
|
|
436
428
|
setToolManager(toolManager: ToolManager, toolContext: ToolContext): void;
|
|
437
429
|
destroy(): void;
|
|
@@ -455,32 +447,9 @@ declare class InputHandler {
|
|
|
455
447
|
private deleteSelected;
|
|
456
448
|
private handleUndo;
|
|
457
449
|
private handleRedo;
|
|
458
|
-
private handleCopy;
|
|
459
|
-
private handlePaste;
|
|
460
450
|
private cancelToolIfActive;
|
|
461
451
|
}
|
|
462
452
|
|
|
463
|
-
type FilterAction = 'dispatch' | 'suppress' | 'defer';
|
|
464
|
-
interface FilteredEvent {
|
|
465
|
-
event: PointerEvent;
|
|
466
|
-
action: FilterAction;
|
|
467
|
-
}
|
|
468
|
-
interface FilteredUpEvent extends FilteredEvent {
|
|
469
|
-
pendingTap?: {
|
|
470
|
-
x: number;
|
|
471
|
-
y: number;
|
|
472
|
-
};
|
|
473
|
-
}
|
|
474
|
-
declare class InputFilter {
|
|
475
|
-
private activePenId;
|
|
476
|
-
private pendingTap;
|
|
477
|
-
static readonly MIN_MOVE_DISTANCE = 3;
|
|
478
|
-
filterDown(e: PointerEvent): FilteredEvent;
|
|
479
|
-
filterMove(e: PointerEvent): FilteredEvent;
|
|
480
|
-
filterUp(e: PointerEvent): FilteredUpEvent;
|
|
481
|
-
reset(): void;
|
|
482
|
-
}
|
|
483
|
-
|
|
484
453
|
interface FontSizePreset {
|
|
485
454
|
label: string;
|
|
486
455
|
size: number;
|
|
@@ -905,10 +874,7 @@ declare class SelectTool implements Tool {
|
|
|
905
874
|
private lastWorld;
|
|
906
875
|
private currentWorld;
|
|
907
876
|
private ctx;
|
|
908
|
-
private pendingSingleSelectId;
|
|
909
|
-
private hasDragged;
|
|
910
877
|
get selectedIds(): string[];
|
|
911
|
-
setSelection(ids: string[]): void;
|
|
912
878
|
get isMarqueeActive(): boolean;
|
|
913
879
|
onActivate(ctx: ToolContext): void;
|
|
914
880
|
onDeactivate(ctx: ToolContext): void;
|
|
@@ -1153,6 +1119,6 @@ declare class UpdateLayerCommand implements Command {
|
|
|
1153
1119
|
undo(_store: ElementStore): void;
|
|
1154
1120
|
}
|
|
1155
1121
|
|
|
1156
|
-
declare const VERSION = "0.
|
|
1122
|
+
declare const VERSION = "0.11.0";
|
|
1157
1123
|
|
|
1158
|
-
export { type ActiveFormats, AddElementCommand, type ArrowElement, ArrowTool, type ArrowToolOptions, AutoSave, type AutoSaveOptions, Background, type BackgroundOptions, type BackgroundPattern, BatchCommand, type Binding, type Bounds, Camera, type CameraChangeInfo, type CameraOptions, type CanvasElement, type CanvasState, type Command, CreateLayerCommand, DEFAULT_FONT_SIZE_PRESETS, DEFAULT_NOTE_FONT_SIZE, ElementRenderer, ElementStore, type ElementType, type ElementUpdateEvent, EraserTool, type EraserToolOptions, EventBus, type ExportImageOptions, type
|
|
1124
|
+
export { type ActiveFormats, AddElementCommand, type ArrowElement, ArrowTool, type ArrowToolOptions, AutoSave, type AutoSaveOptions, Background, type BackgroundOptions, type BackgroundPattern, BatchCommand, type Binding, type Bounds, Camera, type CameraChangeInfo, type CameraOptions, type CanvasElement, type CanvasState, type Command, CreateLayerCommand, DEFAULT_FONT_SIZE_PRESETS, DEFAULT_NOTE_FONT_SIZE, ElementRenderer, ElementStore, type ElementType, type ElementUpdateEvent, EraserTool, type EraserToolOptions, EventBus, type ExportImageOptions, type FontSizePreset, type GridElement, type GridInfo, HandTool, type HexOrientation, HistoryRecorder, HistoryStack, type HistoryStackOptions, type HtmlElement, type ImageElement, ImageTool, type ImageToolOptions, InputHandler, type Layer, LayerManager, MeasureTool, type MeasureToolOptions, type Measurement, NoteEditor, type NoteEditorOptions, type NoteElement, NoteTool, type NoteToolOptions, NoteToolbar, PencilTool, type PencilToolOptions, type Point, type PointerState, Quadtree, RemoveElementCommand, RemoveLayerCommand, type RenderStatsSnapshot, SelectTool, type ShapeElement, type ShapeKind, ShapeTool, type ShapeToolOptions, type Size, type StrokeElement, type StrokePoint, type StyledRun, type TemplateElement, type TemplateShape, TemplateTool, type TemplateToolOptions, type TextElement, TextTool, type TextToolOptions, type Tool, type ToolContext, ToolManager, type ToolName, UpdateElementCommand, UpdateLayerCommand, VERSION, Viewport, type ViewportOptions, boundsIntersect, clearStaleBindings, createArrow, createGrid, createHtmlElement, createId, createImage, createNote, createShape, createStroke, createTemplate, createText, drawHexPath, exportImage, exportState, findBindTarget, findBoundArrows, getActiveFormats, getArrowBounds, getArrowControlPoint, getArrowMidpoint, getArrowTangentAngle, getBendFromPoint, getEdgeIntersection, getElementBounds, getElementCenter, getHexCellsInCone, getHexCellsInLine, getHexCellsInRadius, getHexCellsInSquare, getHexDistance, isBindable, isNearBezier, parseState, sanitizeNoteHtml, setFontSize, smartSnap, snapPoint, snapToHexCenter, toggleBold, toggleItalic, toggleStrikethrough, toggleUnderline, unbindArrow, updateBoundArrow };
|
package/dist/index.d.ts
CHANGED
|
@@ -200,7 +200,6 @@ declare class ElementStore {
|
|
|
200
200
|
private bus;
|
|
201
201
|
private layerOrderMap;
|
|
202
202
|
private spatialIndex;
|
|
203
|
-
private sortedCache;
|
|
204
203
|
get count(): number;
|
|
205
204
|
setLayerOrder(order: Map<string, number>): void;
|
|
206
205
|
getAll(): CanvasElement[];
|
|
@@ -239,8 +238,6 @@ interface PointerState {
|
|
|
239
238
|
x: number;
|
|
240
239
|
y: number;
|
|
241
240
|
pressure: number;
|
|
242
|
-
pointerType: 'mouse' | 'touch' | 'pen';
|
|
243
|
-
shiftKey: boolean;
|
|
244
241
|
}
|
|
245
242
|
interface Tool {
|
|
246
243
|
readonly name: string;
|
|
@@ -426,12 +423,7 @@ declare class InputHandler {
|
|
|
426
423
|
private historyRecorder;
|
|
427
424
|
private historyStack;
|
|
428
425
|
private isToolActive;
|
|
429
|
-
private lastPointerEvent;
|
|
430
|
-
private readonly inputFilter;
|
|
431
|
-
private deferredDown;
|
|
432
426
|
private readonly abortController;
|
|
433
|
-
private clipboard;
|
|
434
|
-
private pasteCount;
|
|
435
427
|
constructor(element: HTMLElement, camera: Camera, options?: InputHandlerOptions);
|
|
436
428
|
setToolManager(toolManager: ToolManager, toolContext: ToolContext): void;
|
|
437
429
|
destroy(): void;
|
|
@@ -455,32 +447,9 @@ declare class InputHandler {
|
|
|
455
447
|
private deleteSelected;
|
|
456
448
|
private handleUndo;
|
|
457
449
|
private handleRedo;
|
|
458
|
-
private handleCopy;
|
|
459
|
-
private handlePaste;
|
|
460
450
|
private cancelToolIfActive;
|
|
461
451
|
}
|
|
462
452
|
|
|
463
|
-
type FilterAction = 'dispatch' | 'suppress' | 'defer';
|
|
464
|
-
interface FilteredEvent {
|
|
465
|
-
event: PointerEvent;
|
|
466
|
-
action: FilterAction;
|
|
467
|
-
}
|
|
468
|
-
interface FilteredUpEvent extends FilteredEvent {
|
|
469
|
-
pendingTap?: {
|
|
470
|
-
x: number;
|
|
471
|
-
y: number;
|
|
472
|
-
};
|
|
473
|
-
}
|
|
474
|
-
declare class InputFilter {
|
|
475
|
-
private activePenId;
|
|
476
|
-
private pendingTap;
|
|
477
|
-
static readonly MIN_MOVE_DISTANCE = 3;
|
|
478
|
-
filterDown(e: PointerEvent): FilteredEvent;
|
|
479
|
-
filterMove(e: PointerEvent): FilteredEvent;
|
|
480
|
-
filterUp(e: PointerEvent): FilteredUpEvent;
|
|
481
|
-
reset(): void;
|
|
482
|
-
}
|
|
483
|
-
|
|
484
453
|
interface FontSizePreset {
|
|
485
454
|
label: string;
|
|
486
455
|
size: number;
|
|
@@ -905,10 +874,7 @@ declare class SelectTool implements Tool {
|
|
|
905
874
|
private lastWorld;
|
|
906
875
|
private currentWorld;
|
|
907
876
|
private ctx;
|
|
908
|
-
private pendingSingleSelectId;
|
|
909
|
-
private hasDragged;
|
|
910
877
|
get selectedIds(): string[];
|
|
911
|
-
setSelection(ids: string[]): void;
|
|
912
878
|
get isMarqueeActive(): boolean;
|
|
913
879
|
onActivate(ctx: ToolContext): void;
|
|
914
880
|
onDeactivate(ctx: ToolContext): void;
|
|
@@ -1153,6 +1119,6 @@ declare class UpdateLayerCommand implements Command {
|
|
|
1153
1119
|
undo(_store: ElementStore): void;
|
|
1154
1120
|
}
|
|
1155
1121
|
|
|
1156
|
-
declare const VERSION = "0.
|
|
1122
|
+
declare const VERSION = "0.11.0";
|
|
1157
1123
|
|
|
1158
|
-
export { type ActiveFormats, AddElementCommand, type ArrowElement, ArrowTool, type ArrowToolOptions, AutoSave, type AutoSaveOptions, Background, type BackgroundOptions, type BackgroundPattern, BatchCommand, type Binding, type Bounds, Camera, type CameraChangeInfo, type CameraOptions, type CanvasElement, type CanvasState, type Command, CreateLayerCommand, DEFAULT_FONT_SIZE_PRESETS, DEFAULT_NOTE_FONT_SIZE, ElementRenderer, ElementStore, type ElementType, type ElementUpdateEvent, EraserTool, type EraserToolOptions, EventBus, type ExportImageOptions, type
|
|
1124
|
+
export { type ActiveFormats, AddElementCommand, type ArrowElement, ArrowTool, type ArrowToolOptions, AutoSave, type AutoSaveOptions, Background, type BackgroundOptions, type BackgroundPattern, BatchCommand, type Binding, type Bounds, Camera, type CameraChangeInfo, type CameraOptions, type CanvasElement, type CanvasState, type Command, CreateLayerCommand, DEFAULT_FONT_SIZE_PRESETS, DEFAULT_NOTE_FONT_SIZE, ElementRenderer, ElementStore, type ElementType, type ElementUpdateEvent, EraserTool, type EraserToolOptions, EventBus, type ExportImageOptions, type FontSizePreset, type GridElement, type GridInfo, HandTool, type HexOrientation, HistoryRecorder, HistoryStack, type HistoryStackOptions, type HtmlElement, type ImageElement, ImageTool, type ImageToolOptions, InputHandler, type Layer, LayerManager, MeasureTool, type MeasureToolOptions, type Measurement, NoteEditor, type NoteEditorOptions, type NoteElement, NoteTool, type NoteToolOptions, NoteToolbar, PencilTool, type PencilToolOptions, type Point, type PointerState, Quadtree, RemoveElementCommand, RemoveLayerCommand, type RenderStatsSnapshot, SelectTool, type ShapeElement, type ShapeKind, ShapeTool, type ShapeToolOptions, type Size, type StrokeElement, type StrokePoint, type StyledRun, type TemplateElement, type TemplateShape, TemplateTool, type TemplateToolOptions, type TextElement, TextTool, type TextToolOptions, type Tool, type ToolContext, ToolManager, type ToolName, UpdateElementCommand, UpdateLayerCommand, VERSION, Viewport, type ViewportOptions, boundsIntersect, clearStaleBindings, createArrow, createGrid, createHtmlElement, createId, createImage, createNote, createShape, createStroke, createTemplate, createText, drawHexPath, exportImage, exportState, findBindTarget, findBoundArrows, getActiveFormats, getArrowBounds, getArrowControlPoint, getArrowMidpoint, getArrowTangentAngle, getBendFromPoint, getEdgeIntersection, getElementBounds, getElementCenter, getHexCellsInCone, getHexCellsInLine, getHexCellsInRadius, getHexCellsInSquare, getHexDistance, isBindable, isNearBezier, parseState, sanitizeNoteHtml, setFontSize, smartSnap, snapPoint, snapToHexCenter, toggleBold, toggleItalic, toggleStrikethrough, toggleUnderline, unbindArrow, updateBoundArrow };
|
package/dist/index.js
CHANGED
|
@@ -292,13 +292,7 @@ function exportState(elements, camera, layers = []) {
|
|
|
292
292
|
position: { ...camera.position },
|
|
293
293
|
zoom: camera.zoom
|
|
294
294
|
},
|
|
295
|
-
elements: elements.map((el) =>
|
|
296
|
-
const clone = structuredClone(el);
|
|
297
|
-
if (clone.type === "arrow") {
|
|
298
|
-
delete clone.cachedControlPoint;
|
|
299
|
-
}
|
|
300
|
-
return clone;
|
|
301
|
-
}),
|
|
295
|
+
elements: elements.map((el) => structuredClone(el)),
|
|
302
296
|
layers: layers.map((l) => ({ ...l }))
|
|
303
297
|
};
|
|
304
298
|
}
|
|
@@ -736,67 +730,6 @@ var Background = class {
|
|
|
736
730
|
}
|
|
737
731
|
};
|
|
738
732
|
|
|
739
|
-
// src/canvas/input-filter.ts
|
|
740
|
-
var InputFilter = class _InputFilter {
|
|
741
|
-
activePenId = null;
|
|
742
|
-
pendingTap = null;
|
|
743
|
-
static MIN_MOVE_DISTANCE = 3;
|
|
744
|
-
filterDown(e) {
|
|
745
|
-
if (e.pointerType === "pen") {
|
|
746
|
-
this.activePenId = e.pointerId;
|
|
747
|
-
return { event: e, action: "dispatch" };
|
|
748
|
-
}
|
|
749
|
-
if (e.pointerType === "touch" && this.activePenId !== null) {
|
|
750
|
-
return { event: e, action: "suppress" };
|
|
751
|
-
}
|
|
752
|
-
if (e.pointerType === "touch") {
|
|
753
|
-
this.pendingTap = { pointerId: e.pointerId, x: e.clientX, y: e.clientY };
|
|
754
|
-
return { event: e, action: "defer" };
|
|
755
|
-
}
|
|
756
|
-
return { event: e, action: "dispatch" };
|
|
757
|
-
}
|
|
758
|
-
filterMove(e) {
|
|
759
|
-
if (e.pointerType === "touch" && this.activePenId !== null) {
|
|
760
|
-
return { event: e, action: "suppress" };
|
|
761
|
-
}
|
|
762
|
-
if (this.pendingTap && e.pointerId === this.pendingTap.pointerId) {
|
|
763
|
-
const dx = e.clientX - this.pendingTap.x;
|
|
764
|
-
const dy = e.clientY - this.pendingTap.y;
|
|
765
|
-
if (dx * dx + dy * dy > _InputFilter.MIN_MOVE_DISTANCE * _InputFilter.MIN_MOVE_DISTANCE) {
|
|
766
|
-
this.pendingTap = null;
|
|
767
|
-
return { event: e, action: "dispatch" };
|
|
768
|
-
}
|
|
769
|
-
return { event: e, action: "suppress" };
|
|
770
|
-
}
|
|
771
|
-
return { event: e, action: "dispatch" };
|
|
772
|
-
}
|
|
773
|
-
filterUp(e) {
|
|
774
|
-
if (e.pointerId === this.activePenId) {
|
|
775
|
-
this.activePenId = null;
|
|
776
|
-
return { event: e, action: "dispatch" };
|
|
777
|
-
}
|
|
778
|
-
if (e.pointerType === "touch" && this.activePenId !== null) {
|
|
779
|
-
return { event: e, action: "suppress" };
|
|
780
|
-
}
|
|
781
|
-
if (this.pendingTap && e.pointerId === this.pendingTap.pointerId) {
|
|
782
|
-
const tap = { x: this.pendingTap.x, y: this.pendingTap.y };
|
|
783
|
-
this.pendingTap = null;
|
|
784
|
-
return { event: e, action: "dispatch", pendingTap: tap };
|
|
785
|
-
}
|
|
786
|
-
return { event: e, action: "dispatch" };
|
|
787
|
-
}
|
|
788
|
-
reset() {
|
|
789
|
-
this.activePenId = null;
|
|
790
|
-
this.pendingTap = null;
|
|
791
|
-
}
|
|
792
|
-
};
|
|
793
|
-
|
|
794
|
-
// src/elements/create-id.ts
|
|
795
|
-
var counter = 0;
|
|
796
|
-
function createId(prefix) {
|
|
797
|
-
return `${prefix}_${Date.now().toString(36)}_${(counter++).toString(36)}`;
|
|
798
|
-
}
|
|
799
|
-
|
|
800
733
|
// src/canvas/input-handler.ts
|
|
801
734
|
var ZOOM_SENSITIVITY = 1e-3;
|
|
802
735
|
var MIDDLE_BUTTON = 1;
|
|
@@ -822,21 +755,13 @@ var InputHandler = class {
|
|
|
822
755
|
historyRecorder;
|
|
823
756
|
historyStack;
|
|
824
757
|
isToolActive = false;
|
|
825
|
-
lastPointerEvent = null;
|
|
826
|
-
inputFilter = new InputFilter();
|
|
827
|
-
deferredDown = null;
|
|
828
758
|
abortController = new AbortController();
|
|
829
|
-
clipboard = [];
|
|
830
|
-
pasteCount = 0;
|
|
831
759
|
setToolManager(toolManager, toolContext) {
|
|
832
760
|
this.toolManager = toolManager;
|
|
833
761
|
this.toolContext = toolContext;
|
|
834
762
|
}
|
|
835
763
|
destroy() {
|
|
836
764
|
this.abortController.abort();
|
|
837
|
-
this.inputFilter.reset();
|
|
838
|
-
this.deferredDown = null;
|
|
839
|
-
this.lastPointerEvent = null;
|
|
840
765
|
}
|
|
841
766
|
bind() {
|
|
842
767
|
const opts = { signal: this.abortController.signal };
|
|
@@ -872,18 +797,11 @@ var InputHandler = class {
|
|
|
872
797
|
this.lastPointer = { x: e.clientX, y: e.clientY };
|
|
873
798
|
return;
|
|
874
799
|
}
|
|
875
|
-
if (this.activePointers.size === 1 &&
|
|
876
|
-
const result = this.inputFilter.filterDown(e);
|
|
877
|
-
if (result.action === "suppress") return;
|
|
878
|
-
if (result.action === "defer") {
|
|
879
|
-
this.deferredDown = e;
|
|
880
|
-
return;
|
|
881
|
-
}
|
|
800
|
+
if (this.activePointers.size === 1 && e.button === 0) {
|
|
882
801
|
this.dispatchToolDown(e);
|
|
883
802
|
}
|
|
884
803
|
};
|
|
885
804
|
onPointerMove = (e) => {
|
|
886
|
-
this.lastPointerEvent = e;
|
|
887
805
|
if (this.activePointers.has(e.pointerId)) {
|
|
888
806
|
this.activePointers.set(e.pointerId, { x: e.clientX, y: e.clientY });
|
|
889
807
|
}
|
|
@@ -900,22 +818,11 @@ var InputHandler = class {
|
|
|
900
818
|
}
|
|
901
819
|
if (this.isToolActive) {
|
|
902
820
|
this.dispatchToolMove(e);
|
|
903
|
-
} else if (this.deferredDown) {
|
|
904
|
-
const result = this.inputFilter.filterMove(e);
|
|
905
|
-
if (result.action === "dispatch") {
|
|
906
|
-
this.dispatchToolDown(this.deferredDown);
|
|
907
|
-
this.deferredDown = null;
|
|
908
|
-
this.dispatchToolMove(e);
|
|
909
|
-
}
|
|
910
821
|
} else if (this.activePointers.size === 0) {
|
|
911
822
|
this.dispatchToolHover(e);
|
|
912
823
|
}
|
|
913
824
|
};
|
|
914
825
|
onPointerUp = (e) => {
|
|
915
|
-
try {
|
|
916
|
-
this.element.releasePointerCapture(e.pointerId);
|
|
917
|
-
} catch {
|
|
918
|
-
}
|
|
919
826
|
this.activePointers.delete(e.pointerId);
|
|
920
827
|
if (this.activePointers.size < 2) {
|
|
921
828
|
this.lastPinchDistance = 0;
|
|
@@ -923,16 +830,9 @@ var InputHandler = class {
|
|
|
923
830
|
if (this.isPanning && this.activePointers.size === 0) {
|
|
924
831
|
this.isPanning = false;
|
|
925
832
|
}
|
|
926
|
-
const upResult = this.inputFilter.filterUp(e);
|
|
927
833
|
if (this.isToolActive) {
|
|
928
834
|
this.dispatchToolUp(e);
|
|
929
835
|
this.isToolActive = false;
|
|
930
|
-
} else if (this.deferredDown && upResult.pendingTap) {
|
|
931
|
-
this.dispatchToolDown(this.deferredDown);
|
|
932
|
-
this.dispatchToolUp(e);
|
|
933
|
-
this.deferredDown = null;
|
|
934
|
-
} else {
|
|
935
|
-
this.deferredDown = null;
|
|
936
836
|
}
|
|
937
837
|
};
|
|
938
838
|
onKeyDown = (e) => {
|
|
@@ -951,30 +851,13 @@ var InputHandler = class {
|
|
|
951
851
|
e.preventDefault();
|
|
952
852
|
this.handleRedo();
|
|
953
853
|
}
|
|
954
|
-
if ((e.ctrlKey || e.metaKey) && e.key === "c") {
|
|
955
|
-
e.preventDefault();
|
|
956
|
-
this.handleCopy();
|
|
957
|
-
}
|
|
958
|
-
if ((e.ctrlKey || e.metaKey) && e.key === "v") {
|
|
959
|
-
e.preventDefault();
|
|
960
|
-
this.handlePaste();
|
|
961
|
-
}
|
|
962
854
|
};
|
|
963
855
|
onKeyUp = (e) => {
|
|
964
856
|
if (e.key === " ") {
|
|
965
857
|
this.spaceHeld = false;
|
|
966
|
-
if (this.activePointers.size === 0) {
|
|
967
|
-
if (this.lastPointerEvent) {
|
|
968
|
-
this.dispatchToolHover(this.lastPointerEvent);
|
|
969
|
-
} else {
|
|
970
|
-
this.toolContext?.setCursor?.("default");
|
|
971
|
-
}
|
|
972
|
-
}
|
|
973
858
|
}
|
|
974
859
|
};
|
|
975
860
|
startPinch() {
|
|
976
|
-
this.inputFilter.reset();
|
|
977
|
-
this.deferredDown = null;
|
|
978
861
|
this.isPanning = true;
|
|
979
862
|
const [a, b] = this.getPinchPoints();
|
|
980
863
|
this.lastPinchDistance = this.distance(a, b);
|
|
@@ -1014,9 +897,7 @@ var InputHandler = class {
|
|
|
1014
897
|
return {
|
|
1015
898
|
x: e.clientX - rect.left,
|
|
1016
899
|
y: e.clientY - rect.top,
|
|
1017
|
-
pressure: e.pressure
|
|
1018
|
-
pointerType: e.pointerType === "touch" || e.pointerType === "pen" ? e.pointerType : "mouse",
|
|
1019
|
-
shiftKey: e.shiftKey
|
|
900
|
+
pressure: e.pressure
|
|
1020
901
|
};
|
|
1021
902
|
}
|
|
1022
903
|
dispatchToolDown(e) {
|
|
@@ -1069,78 +950,11 @@ var InputHandler = class {
|
|
|
1069
950
|
this.historyRecorder?.resume();
|
|
1070
951
|
this.toolContext.requestRender();
|
|
1071
952
|
}
|
|
1072
|
-
handleCopy() {
|
|
1073
|
-
if (!this.toolManager || !this.toolContext || this.isToolActive) return;
|
|
1074
|
-
const tool = this.toolManager.activeTool;
|
|
1075
|
-
if (tool?.name !== "select") return;
|
|
1076
|
-
const selectTool = tool;
|
|
1077
|
-
const ids = selectTool.selectedIds;
|
|
1078
|
-
if (ids.length === 0) return;
|
|
1079
|
-
this.clipboard = [];
|
|
1080
|
-
for (const id of ids) {
|
|
1081
|
-
const el = this.toolContext.store.getById(id);
|
|
1082
|
-
if (el) this.clipboard.push(structuredClone(el));
|
|
1083
|
-
}
|
|
1084
|
-
this.pasteCount = 0;
|
|
1085
|
-
}
|
|
1086
|
-
handlePaste() {
|
|
1087
|
-
if (!this.toolManager || !this.toolContext || this.clipboard.length === 0 || this.isToolActive)
|
|
1088
|
-
return;
|
|
1089
|
-
const tool = this.toolManager.activeTool;
|
|
1090
|
-
if (tool?.name !== "select") return;
|
|
1091
|
-
const selectTool = tool;
|
|
1092
|
-
this.pasteCount++;
|
|
1093
|
-
const offset = this.pasteCount * 20;
|
|
1094
|
-
const idMap = /* @__PURE__ */ new Map();
|
|
1095
|
-
for (const el of this.clipboard) {
|
|
1096
|
-
idMap.set(el.id, createId(el.type));
|
|
1097
|
-
}
|
|
1098
|
-
const newIds = [];
|
|
1099
|
-
this.historyRecorder?.begin();
|
|
1100
|
-
for (const el of this.clipboard) {
|
|
1101
|
-
const clone = structuredClone(el);
|
|
1102
|
-
const newId = idMap.get(el.id);
|
|
1103
|
-
if (!newId) continue;
|
|
1104
|
-
clone.id = newId;
|
|
1105
|
-
clone.position = { x: clone.position.x + offset, y: clone.position.y + offset };
|
|
1106
|
-
if (clone.type === "arrow") {
|
|
1107
|
-
const arrow = clone;
|
|
1108
|
-
arrow.from = { x: arrow.from.x + offset, y: arrow.from.y + offset };
|
|
1109
|
-
arrow.to = { x: arrow.to.x + offset, y: arrow.to.y + offset };
|
|
1110
|
-
delete arrow.cachedControlPoint;
|
|
1111
|
-
if (arrow.fromBinding) {
|
|
1112
|
-
const newTarget = idMap.get(arrow.fromBinding.elementId);
|
|
1113
|
-
if (newTarget) {
|
|
1114
|
-
arrow.fromBinding = { elementId: newTarget };
|
|
1115
|
-
} else {
|
|
1116
|
-
delete arrow.fromBinding;
|
|
1117
|
-
}
|
|
1118
|
-
}
|
|
1119
|
-
if (arrow.toBinding) {
|
|
1120
|
-
const newTarget = idMap.get(arrow.toBinding.elementId);
|
|
1121
|
-
if (newTarget) {
|
|
1122
|
-
arrow.toBinding = { elementId: newTarget };
|
|
1123
|
-
} else {
|
|
1124
|
-
delete arrow.toBinding;
|
|
1125
|
-
}
|
|
1126
|
-
}
|
|
1127
|
-
}
|
|
1128
|
-
if (this.toolContext.activeLayerId) {
|
|
1129
|
-
clone.layerId = this.toolContext.activeLayerId;
|
|
1130
|
-
}
|
|
1131
|
-
this.toolContext.store.add(clone);
|
|
1132
|
-
newIds.push(clone.id);
|
|
1133
|
-
}
|
|
1134
|
-
this.historyRecorder?.commit();
|
|
1135
|
-
selectTool.setSelection(newIds);
|
|
1136
|
-
this.toolContext.requestRender();
|
|
1137
|
-
}
|
|
1138
953
|
cancelToolIfActive(e) {
|
|
1139
954
|
if (this.isToolActive) {
|
|
1140
955
|
this.dispatchToolUp(e);
|
|
1141
956
|
this.isToolActive = false;
|
|
1142
957
|
}
|
|
1143
|
-
this.deferredDown = null;
|
|
1144
958
|
}
|
|
1145
959
|
};
|
|
1146
960
|
|
|
@@ -1388,23 +1202,19 @@ var ElementStore = class {
|
|
|
1388
1202
|
bus = new EventBus();
|
|
1389
1203
|
layerOrderMap = /* @__PURE__ */ new Map();
|
|
1390
1204
|
spatialIndex = new Quadtree({ x: -1e5, y: -1e5, w: 2e5, h: 2e5 });
|
|
1391
|
-
sortedCache = null;
|
|
1392
1205
|
get count() {
|
|
1393
1206
|
return this.elements.size;
|
|
1394
1207
|
}
|
|
1395
1208
|
setLayerOrder(order) {
|
|
1396
1209
|
this.layerOrderMap = new Map(order);
|
|
1397
|
-
this.sortedCache = null;
|
|
1398
1210
|
}
|
|
1399
1211
|
getAll() {
|
|
1400
|
-
|
|
1401
|
-
this.sortedCache = [...this.elements.values()].sort((a, b) => {
|
|
1212
|
+
return [...this.elements.values()].sort((a, b) => {
|
|
1402
1213
|
const layerA = this.layerOrderMap.get(a.layerId) ?? 0;
|
|
1403
1214
|
const layerB = this.layerOrderMap.get(b.layerId) ?? 0;
|
|
1404
1215
|
if (layerA !== layerB) return layerA - layerB;
|
|
1405
1216
|
return a.zIndex - b.zIndex;
|
|
1406
1217
|
});
|
|
1407
|
-
return this.sortedCache;
|
|
1408
1218
|
}
|
|
1409
1219
|
getById(id) {
|
|
1410
1220
|
return this.elements.get(id);
|
|
@@ -1415,7 +1225,6 @@ var ElementStore = class {
|
|
|
1415
1225
|
);
|
|
1416
1226
|
}
|
|
1417
1227
|
add(element) {
|
|
1418
|
-
this.sortedCache = null;
|
|
1419
1228
|
this.elements.set(element.id, element);
|
|
1420
1229
|
const bounds = getElementBounds(element);
|
|
1421
1230
|
if (bounds) this.spatialIndex.insert(element.id, bounds);
|
|
@@ -1424,15 +1233,11 @@ var ElementStore = class {
|
|
|
1424
1233
|
update(id, partial) {
|
|
1425
1234
|
const existing = this.elements.get(id);
|
|
1426
1235
|
if (!existing) return;
|
|
1427
|
-
this.sortedCache = null;
|
|
1428
1236
|
const updated = { ...existing, ...partial, id: existing.id, type: existing.type };
|
|
1429
1237
|
if (updated.type === "arrow") {
|
|
1430
1238
|
const arrow = updated;
|
|
1431
1239
|
arrow.cachedControlPoint = getArrowControlPoint(arrow.from, arrow.to, arrow.bend);
|
|
1432
1240
|
}
|
|
1433
|
-
if (updated.type === "note" && "text" in partial) {
|
|
1434
|
-
updated.text = sanitizeNoteHtml(updated.text);
|
|
1435
|
-
}
|
|
1436
1241
|
this.elements.set(id, updated);
|
|
1437
1242
|
const newBounds = getElementBounds(updated);
|
|
1438
1243
|
if (newBounds) {
|
|
@@ -1443,13 +1248,11 @@ var ElementStore = class {
|
|
|
1443
1248
|
remove(id) {
|
|
1444
1249
|
const element = this.elements.get(id);
|
|
1445
1250
|
if (!element) return;
|
|
1446
|
-
this.sortedCache = null;
|
|
1447
1251
|
this.elements.delete(id);
|
|
1448
1252
|
this.spatialIndex.remove(id);
|
|
1449
1253
|
this.bus.emit("remove", element);
|
|
1450
1254
|
}
|
|
1451
1255
|
clear() {
|
|
1452
|
-
this.sortedCache = null;
|
|
1453
1256
|
this.elements.clear();
|
|
1454
1257
|
this.spatialIndex.clear();
|
|
1455
1258
|
this.bus.emit("clear", null);
|
|
@@ -1458,7 +1261,6 @@ var ElementStore = class {
|
|
|
1458
1261
|
return this.getAll().map((el) => ({ ...el }));
|
|
1459
1262
|
}
|
|
1460
1263
|
loadSnapshot(elements) {
|
|
1461
|
-
this.sortedCache = null;
|
|
1462
1264
|
this.elements.clear();
|
|
1463
1265
|
this.spatialIndex.clear();
|
|
1464
1266
|
for (const el of elements) {
|
|
@@ -1466,10 +1268,6 @@ var ElementStore = class {
|
|
|
1466
1268
|
const bounds = getElementBounds(el);
|
|
1467
1269
|
if (bounds) this.spatialIndex.insert(el.id, bounds);
|
|
1468
1270
|
}
|
|
1469
|
-
this.bus.emit("clear", null);
|
|
1470
|
-
for (const el of elements) {
|
|
1471
|
-
this.bus.emit("add", el);
|
|
1472
|
-
}
|
|
1473
1271
|
}
|
|
1474
1272
|
queryRect(rect) {
|
|
1475
1273
|
const ids = this.spatialIndex.query(rect);
|
|
@@ -2519,6 +2317,12 @@ var ElementRenderer = class {
|
|
|
2519
2317
|
}
|
|
2520
2318
|
};
|
|
2521
2319
|
|
|
2320
|
+
// src/elements/create-id.ts
|
|
2321
|
+
var counter = 0;
|
|
2322
|
+
function createId(prefix) {
|
|
2323
|
+
return `${prefix}_${Date.now().toString(36)}_${(counter++).toString(36)}`;
|
|
2324
|
+
}
|
|
2325
|
+
|
|
2522
2326
|
// src/elements/element-factory.ts
|
|
2523
2327
|
var DEFAULT_NOTE_FONT_SIZE = 18;
|
|
2524
2328
|
function createStroke(input) {
|
|
@@ -2544,7 +2348,7 @@ function createNote(input) {
|
|
|
2544
2348
|
locked: input.locked ?? false,
|
|
2545
2349
|
layerId: input.layerId ?? "",
|
|
2546
2350
|
size: input.size ?? { w: 200, h: 100 },
|
|
2547
|
-
text:
|
|
2351
|
+
text: input.text ?? "",
|
|
2548
2352
|
backgroundColor: input.backgroundColor ?? "#ffeb3b",
|
|
2549
2353
|
textColor: input.textColor ?? "#000000",
|
|
2550
2354
|
fontSize: input.fontSize ?? DEFAULT_NOTE_FONT_SIZE
|
|
@@ -4651,10 +4455,7 @@ var Viewport = class {
|
|
|
4651
4455
|
position: "relative",
|
|
4652
4456
|
width: "100%",
|
|
4653
4457
|
height: "100%",
|
|
4654
|
-
overflow: "hidden"
|
|
4655
|
-
overscrollBehavior: "none",
|
|
4656
|
-
userSelect: "none",
|
|
4657
|
-
webkitUserSelect: "none"
|
|
4458
|
+
overflow: "hidden"
|
|
4658
4459
|
});
|
|
4659
4460
|
return el;
|
|
4660
4461
|
}
|
|
@@ -5069,15 +4870,9 @@ var SelectTool = class {
|
|
|
5069
4870
|
lastWorld = { x: 0, y: 0 };
|
|
5070
4871
|
currentWorld = { x: 0, y: 0 };
|
|
5071
4872
|
ctx = null;
|
|
5072
|
-
pendingSingleSelectId = null;
|
|
5073
|
-
hasDragged = false;
|
|
5074
4873
|
get selectedIds() {
|
|
5075
4874
|
return [...this._selectedIds];
|
|
5076
4875
|
}
|
|
5077
|
-
setSelection(ids) {
|
|
5078
|
-
this._selectedIds = ids;
|
|
5079
|
-
this.ctx?.requestRender();
|
|
5080
|
-
}
|
|
5081
4876
|
get isMarqueeActive() {
|
|
5082
4877
|
return this.mode.type === "marquee";
|
|
5083
4878
|
}
|
|
@@ -5126,27 +4921,13 @@ var SelectTool = class {
|
|
|
5126
4921
|
return;
|
|
5127
4922
|
}
|
|
5128
4923
|
}
|
|
5129
|
-
this.pendingSingleSelectId = null;
|
|
5130
|
-
this.hasDragged = false;
|
|
5131
4924
|
const hit = this.hitTest(world, ctx);
|
|
5132
4925
|
if (hit) {
|
|
5133
4926
|
const alreadySelected = this._selectedIds.includes(hit.id);
|
|
5134
|
-
if (
|
|
5135
|
-
|
|
5136
|
-
this._selectedIds = this._selectedIds.filter((id) => id !== hit.id);
|
|
5137
|
-
this.mode = { type: "idle" };
|
|
5138
|
-
} else {
|
|
5139
|
-
this._selectedIds = [...this._selectedIds, hit.id];
|
|
5140
|
-
this.mode = hit.locked ? { type: "idle" } : { type: "dragging" };
|
|
5141
|
-
}
|
|
5142
|
-
} else {
|
|
5143
|
-
if (!alreadySelected) {
|
|
5144
|
-
this._selectedIds = [hit.id];
|
|
5145
|
-
} else if (this._selectedIds.length > 1) {
|
|
5146
|
-
this.pendingSingleSelectId = hit.id;
|
|
5147
|
-
}
|
|
5148
|
-
this.mode = hit.locked ? { type: "idle" } : { type: "dragging" };
|
|
4927
|
+
if (!alreadySelected) {
|
|
4928
|
+
this._selectedIds = [hit.id];
|
|
5149
4929
|
}
|
|
4930
|
+
this.mode = hit.locked ? { type: "idle" } : { type: "dragging" };
|
|
5150
4931
|
} else {
|
|
5151
4932
|
this._selectedIds = [];
|
|
5152
4933
|
this.mode = { type: "marquee", start: world };
|
|
@@ -5172,7 +4953,6 @@ var SelectTool = class {
|
|
|
5172
4953
|
return;
|
|
5173
4954
|
}
|
|
5174
4955
|
if (this.mode.type === "dragging" && this._selectedIds.length > 0) {
|
|
5175
|
-
this.hasDragged = true;
|
|
5176
4956
|
ctx.setCursor?.("move");
|
|
5177
4957
|
const snapped = this.snap(world, ctx);
|
|
5178
4958
|
const dx = snapped.x - this.lastWorld.x;
|
|
@@ -5241,11 +5021,6 @@ var SelectTool = class {
|
|
|
5241
5021
|
}
|
|
5242
5022
|
ctx.requestRender();
|
|
5243
5023
|
}
|
|
5244
|
-
if (!this.hasDragged && this.pendingSingleSelectId !== null) {
|
|
5245
|
-
this._selectedIds = [this.pendingSingleSelectId];
|
|
5246
|
-
}
|
|
5247
|
-
this.pendingSingleSelectId = null;
|
|
5248
|
-
this.hasDragged = false;
|
|
5249
5024
|
this.mode = { type: "idle" };
|
|
5250
5025
|
ctx.setCursor?.("default");
|
|
5251
5026
|
}
|
|
@@ -6426,7 +6201,7 @@ var UpdateLayerCommand = class {
|
|
|
6426
6201
|
};
|
|
6427
6202
|
|
|
6428
6203
|
// src/index.ts
|
|
6429
|
-
var VERSION = "0.
|
|
6204
|
+
var VERSION = "0.11.0";
|
|
6430
6205
|
export {
|
|
6431
6206
|
AddElementCommand,
|
|
6432
6207
|
ArrowTool,
|
|
@@ -6445,7 +6220,6 @@ export {
|
|
|
6445
6220
|
HistoryRecorder,
|
|
6446
6221
|
HistoryStack,
|
|
6447
6222
|
ImageTool,
|
|
6448
|
-
InputFilter,
|
|
6449
6223
|
InputHandler,
|
|
6450
6224
|
LayerManager,
|
|
6451
6225
|
MeasureTool,
|