@fieldnotes/core 0.15.0 → 0.17.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 +471 -220
- package/dist/index.d.cts +31 -11
- package/dist/index.d.ts +31 -11
- package/dist/index.js +471 -220
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -920,9 +920,228 @@ function createId(prefix) {
|
|
|
920
920
|
return `${prefix}_${Date.now().toString(36)}_${(counter++).toString(36)}`;
|
|
921
921
|
}
|
|
922
922
|
|
|
923
|
+
// src/canvas/keyboard-actions.ts
|
|
924
|
+
var KeyboardActions = class {
|
|
925
|
+
constructor(deps) {
|
|
926
|
+
this.deps = deps;
|
|
927
|
+
}
|
|
928
|
+
clipboard = [];
|
|
929
|
+
pasteCount = 0;
|
|
930
|
+
nudgeTimer = null;
|
|
931
|
+
dispose() {
|
|
932
|
+
this.flushPendingNudge();
|
|
933
|
+
}
|
|
934
|
+
selectTool() {
|
|
935
|
+
const tm = this.deps.getToolManager();
|
|
936
|
+
const ctx = this.deps.getToolContext();
|
|
937
|
+
if (!tm || !ctx) return null;
|
|
938
|
+
const tool = tm.activeTool;
|
|
939
|
+
if (tool?.name !== "select") return null;
|
|
940
|
+
return { tool, ctx };
|
|
941
|
+
}
|
|
942
|
+
nudge(dx, dy, byCell) {
|
|
943
|
+
if (this.deps.isToolActive()) return false;
|
|
944
|
+
const sel = this.selectTool();
|
|
945
|
+
if (!sel) return false;
|
|
946
|
+
if (sel.tool.selectedIds.length === 0) return false;
|
|
947
|
+
const step = byCell ? sel.ctx.gridSize ?? 10 : 1;
|
|
948
|
+
if (this.nudgeTimer === null) {
|
|
949
|
+
this.deps.getHistoryRecorder()?.begin();
|
|
950
|
+
} else {
|
|
951
|
+
clearTimeout(this.nudgeTimer);
|
|
952
|
+
}
|
|
953
|
+
const moved = sel.tool.nudgeSelection(dx * step, dy * step, sel.ctx);
|
|
954
|
+
this.nudgeTimer = setTimeout(() => this.flushPendingNudge(), 400);
|
|
955
|
+
return moved;
|
|
956
|
+
}
|
|
957
|
+
flushPendingNudge() {
|
|
958
|
+
if (this.nudgeTimer === null) return;
|
|
959
|
+
clearTimeout(this.nudgeTimer);
|
|
960
|
+
this.nudgeTimer = null;
|
|
961
|
+
this.deps.getHistoryRecorder()?.commit();
|
|
962
|
+
}
|
|
963
|
+
deleteSelected() {
|
|
964
|
+
this.flushPendingNudge();
|
|
965
|
+
const sel = this.selectTool();
|
|
966
|
+
if (!sel) return;
|
|
967
|
+
const ids = sel.tool.selectedIds;
|
|
968
|
+
if (ids.length === 0) return;
|
|
969
|
+
const recorder = this.deps.getHistoryRecorder();
|
|
970
|
+
recorder?.begin();
|
|
971
|
+
for (const id of ids) {
|
|
972
|
+
sel.ctx.store.remove(id);
|
|
973
|
+
}
|
|
974
|
+
recorder?.commit();
|
|
975
|
+
sel.ctx.requestRender();
|
|
976
|
+
}
|
|
977
|
+
undo() {
|
|
978
|
+
this.flushPendingNudge();
|
|
979
|
+
const ctx = this.deps.getToolContext();
|
|
980
|
+
const stack = this.deps.getHistoryStack();
|
|
981
|
+
if (!stack || !ctx) return;
|
|
982
|
+
const recorder = this.deps.getHistoryRecorder();
|
|
983
|
+
recorder?.pause();
|
|
984
|
+
stack.undo(ctx.store);
|
|
985
|
+
recorder?.resume();
|
|
986
|
+
ctx.requestRender();
|
|
987
|
+
}
|
|
988
|
+
redo() {
|
|
989
|
+
this.flushPendingNudge();
|
|
990
|
+
const ctx = this.deps.getToolContext();
|
|
991
|
+
const stack = this.deps.getHistoryStack();
|
|
992
|
+
if (!stack || !ctx) return;
|
|
993
|
+
const recorder = this.deps.getHistoryRecorder();
|
|
994
|
+
recorder?.pause();
|
|
995
|
+
stack.redo(ctx.store);
|
|
996
|
+
recorder?.resume();
|
|
997
|
+
ctx.requestRender();
|
|
998
|
+
}
|
|
999
|
+
copy() {
|
|
1000
|
+
if (this.deps.isToolActive()) return;
|
|
1001
|
+
const sel = this.selectTool();
|
|
1002
|
+
if (!sel) return;
|
|
1003
|
+
const ids = sel.tool.selectedIds;
|
|
1004
|
+
if (ids.length === 0) return;
|
|
1005
|
+
this.clipboard = [];
|
|
1006
|
+
for (const id of ids) {
|
|
1007
|
+
const el = sel.ctx.store.getById(id);
|
|
1008
|
+
if (el) this.clipboard.push(structuredClone(el));
|
|
1009
|
+
}
|
|
1010
|
+
this.pasteCount = 0;
|
|
1011
|
+
}
|
|
1012
|
+
paste() {
|
|
1013
|
+
this.flushPendingNudge();
|
|
1014
|
+
if (this.clipboard.length === 0 || this.deps.isToolActive()) return;
|
|
1015
|
+
const sel = this.selectTool();
|
|
1016
|
+
if (!sel) return;
|
|
1017
|
+
this.pasteCount++;
|
|
1018
|
+
this.insertClones(this.clipboard, this.pasteCount * 20, sel);
|
|
1019
|
+
}
|
|
1020
|
+
duplicate() {
|
|
1021
|
+
this.flushPendingNudge();
|
|
1022
|
+
if (this.deps.isToolActive()) return;
|
|
1023
|
+
const sel = this.selectTool();
|
|
1024
|
+
if (!sel) return;
|
|
1025
|
+
const source = [];
|
|
1026
|
+
for (const id of sel.tool.selectedIds) {
|
|
1027
|
+
const el = sel.ctx.store.getById(id);
|
|
1028
|
+
if (el) source.push(el);
|
|
1029
|
+
}
|
|
1030
|
+
if (source.length === 0) return;
|
|
1031
|
+
this.insertClones(source, 20, sel);
|
|
1032
|
+
}
|
|
1033
|
+
deselect() {
|
|
1034
|
+
if (this.deps.isToolActive()) return;
|
|
1035
|
+
const sel = this.selectTool();
|
|
1036
|
+
if (!sel) return;
|
|
1037
|
+
if (sel.tool.selectedIds.length === 0) return;
|
|
1038
|
+
sel.tool.setSelection([]);
|
|
1039
|
+
sel.ctx.requestRender();
|
|
1040
|
+
}
|
|
1041
|
+
selectAll() {
|
|
1042
|
+
if (this.deps.isToolActive()) return;
|
|
1043
|
+
const tm = this.deps.getToolManager();
|
|
1044
|
+
const ctx = this.deps.getToolContext();
|
|
1045
|
+
if (!tm || !ctx) return;
|
|
1046
|
+
if (tm.activeTool?.name !== "select") {
|
|
1047
|
+
ctx.switchTool?.("select");
|
|
1048
|
+
}
|
|
1049
|
+
const sel = this.selectTool();
|
|
1050
|
+
if (!sel) return;
|
|
1051
|
+
const ids = sel.ctx.store.getAll().filter(
|
|
1052
|
+
(el) => !el.locked && (sel.ctx.isLayerVisible?.(el.layerId) ?? true) && !(sel.ctx.isLayerLocked?.(el.layerId) ?? false)
|
|
1053
|
+
).map((el) => el.id);
|
|
1054
|
+
sel.tool.setSelection(ids);
|
|
1055
|
+
sel.ctx.requestRender();
|
|
1056
|
+
}
|
|
1057
|
+
zoomToFit() {
|
|
1058
|
+
if (this.deps.isToolActive()) return;
|
|
1059
|
+
this.deps.fitToContent?.();
|
|
1060
|
+
}
|
|
1061
|
+
zOrder(operation) {
|
|
1062
|
+
this.flushPendingNudge();
|
|
1063
|
+
const sel = this.selectTool();
|
|
1064
|
+
if (!sel) return;
|
|
1065
|
+
const ids = sel.tool.selectedIds;
|
|
1066
|
+
if (ids.length === 0) return;
|
|
1067
|
+
const recorder = this.deps.getHistoryRecorder();
|
|
1068
|
+
recorder?.begin();
|
|
1069
|
+
for (const id of ids) {
|
|
1070
|
+
switch (operation) {
|
|
1071
|
+
case "forward":
|
|
1072
|
+
sel.ctx.store.bringForward(id);
|
|
1073
|
+
break;
|
|
1074
|
+
case "backward":
|
|
1075
|
+
sel.ctx.store.sendBackward(id);
|
|
1076
|
+
break;
|
|
1077
|
+
case "front":
|
|
1078
|
+
sel.ctx.store.bringToFront(id);
|
|
1079
|
+
break;
|
|
1080
|
+
case "back":
|
|
1081
|
+
sel.ctx.store.sendToBack(id);
|
|
1082
|
+
break;
|
|
1083
|
+
}
|
|
1084
|
+
}
|
|
1085
|
+
recorder?.commit();
|
|
1086
|
+
sel.ctx.requestRender();
|
|
1087
|
+
}
|
|
1088
|
+
insertClones(source, offset, sel) {
|
|
1089
|
+
const idMap = /* @__PURE__ */ new Map();
|
|
1090
|
+
for (const el of source) {
|
|
1091
|
+
idMap.set(el.id, createId(el.type));
|
|
1092
|
+
}
|
|
1093
|
+
const newIds = [];
|
|
1094
|
+
const recorder = this.deps.getHistoryRecorder();
|
|
1095
|
+
recorder?.begin();
|
|
1096
|
+
for (const el of source) {
|
|
1097
|
+
const clone = structuredClone(el);
|
|
1098
|
+
const newId = idMap.get(el.id);
|
|
1099
|
+
if (!newId) continue;
|
|
1100
|
+
clone.id = newId;
|
|
1101
|
+
clone.position = { x: clone.position.x + offset, y: clone.position.y + offset };
|
|
1102
|
+
if (clone.type === "arrow") {
|
|
1103
|
+
const arrow = clone;
|
|
1104
|
+
arrow.from = { x: arrow.from.x + offset, y: arrow.from.y + offset };
|
|
1105
|
+
arrow.to = { x: arrow.to.x + offset, y: arrow.to.y + offset };
|
|
1106
|
+
delete arrow.cachedControlPoint;
|
|
1107
|
+
if (arrow.fromBinding) {
|
|
1108
|
+
const newTarget = idMap.get(arrow.fromBinding.elementId);
|
|
1109
|
+
if (newTarget) {
|
|
1110
|
+
arrow.fromBinding = { elementId: newTarget };
|
|
1111
|
+
} else {
|
|
1112
|
+
delete arrow.fromBinding;
|
|
1113
|
+
}
|
|
1114
|
+
}
|
|
1115
|
+
if (arrow.toBinding) {
|
|
1116
|
+
const newTarget = idMap.get(arrow.toBinding.elementId);
|
|
1117
|
+
if (newTarget) {
|
|
1118
|
+
arrow.toBinding = { elementId: newTarget };
|
|
1119
|
+
} else {
|
|
1120
|
+
delete arrow.toBinding;
|
|
1121
|
+
}
|
|
1122
|
+
}
|
|
1123
|
+
}
|
|
1124
|
+
if (sel.ctx.activeLayerId) {
|
|
1125
|
+
clone.layerId = sel.ctx.activeLayerId;
|
|
1126
|
+
}
|
|
1127
|
+
sel.ctx.store.add(clone);
|
|
1128
|
+
newIds.push(clone.id);
|
|
1129
|
+
}
|
|
1130
|
+
recorder?.commit();
|
|
1131
|
+
sel.tool.setSelection(newIds);
|
|
1132
|
+
sel.ctx.requestRender();
|
|
1133
|
+
}
|
|
1134
|
+
};
|
|
1135
|
+
|
|
923
1136
|
// src/canvas/input-handler.ts
|
|
924
1137
|
var ZOOM_SENSITIVITY = 1e-3;
|
|
925
1138
|
var MIDDLE_BUTTON = 1;
|
|
1139
|
+
var NUDGE_KEYS = {
|
|
1140
|
+
ArrowLeft: [-1, 0],
|
|
1141
|
+
ArrowRight: [1, 0],
|
|
1142
|
+
ArrowUp: [0, -1],
|
|
1143
|
+
ArrowDown: [0, 1]
|
|
1144
|
+
};
|
|
926
1145
|
var InputHandler = class {
|
|
927
1146
|
constructor(element, camera, options = {}) {
|
|
928
1147
|
this.element = element;
|
|
@@ -931,6 +1150,14 @@ var InputHandler = class {
|
|
|
931
1150
|
this.toolContext = options.toolContext ?? null;
|
|
932
1151
|
this.historyRecorder = options.historyRecorder ?? null;
|
|
933
1152
|
this.historyStack = options.historyStack ?? null;
|
|
1153
|
+
this.actions = new KeyboardActions({
|
|
1154
|
+
getToolManager: () => this.toolManager,
|
|
1155
|
+
getToolContext: () => this.toolContext,
|
|
1156
|
+
getHistoryRecorder: () => this.historyRecorder,
|
|
1157
|
+
getHistoryStack: () => this.historyStack,
|
|
1158
|
+
isToolActive: () => this.isToolActive,
|
|
1159
|
+
fitToContent: options.fitToContent
|
|
1160
|
+
});
|
|
934
1161
|
this.element.style.touchAction = "none";
|
|
935
1162
|
this.bind();
|
|
936
1163
|
}
|
|
@@ -949,13 +1176,16 @@ var InputHandler = class {
|
|
|
949
1176
|
inputFilter = new InputFilter();
|
|
950
1177
|
deferredDown = null;
|
|
951
1178
|
abortController = new AbortController();
|
|
952
|
-
|
|
953
|
-
pasteCount = 0;
|
|
1179
|
+
actions;
|
|
954
1180
|
setToolManager(toolManager, toolContext) {
|
|
955
1181
|
this.toolManager = toolManager;
|
|
956
1182
|
this.toolContext = toolContext;
|
|
957
1183
|
}
|
|
1184
|
+
flushPendingHistory() {
|
|
1185
|
+
this.actions.flushPendingNudge();
|
|
1186
|
+
}
|
|
958
1187
|
destroy() {
|
|
1188
|
+
this.actions.dispose();
|
|
959
1189
|
this.abortController.abort();
|
|
960
1190
|
this.inputFilter.reset();
|
|
961
1191
|
this.deferredDown = null;
|
|
@@ -1061,36 +1291,61 @@ var InputHandler = class {
|
|
|
1061
1291
|
}
|
|
1062
1292
|
};
|
|
1063
1293
|
onKeyDown = (e) => {
|
|
1064
|
-
|
|
1294
|
+
const target = e.target;
|
|
1295
|
+
if (target?.isContentEditable) return;
|
|
1296
|
+
const tag = target?.tagName;
|
|
1297
|
+
if (tag === "INPUT" || tag === "TEXTAREA" || tag === "SELECT") return;
|
|
1065
1298
|
if (e.key === " ") {
|
|
1066
1299
|
this.spaceHeld = true;
|
|
1067
1300
|
}
|
|
1068
1301
|
if (e.key === "Delete" || e.key === "Backspace") {
|
|
1069
|
-
this.deleteSelected();
|
|
1302
|
+
this.actions.deleteSelected();
|
|
1303
|
+
}
|
|
1304
|
+
if (e.key === "Escape") {
|
|
1305
|
+
this.actions.deselect();
|
|
1070
1306
|
}
|
|
1071
1307
|
if ((e.ctrlKey || e.metaKey) && e.key === "z" && !e.shiftKey) {
|
|
1072
1308
|
e.preventDefault();
|
|
1073
|
-
this.
|
|
1309
|
+
this.actions.undo();
|
|
1074
1310
|
}
|
|
1075
1311
|
if ((e.ctrlKey || e.metaKey) && (e.key === "y" || e.key === "z" && e.shiftKey)) {
|
|
1076
1312
|
e.preventDefault();
|
|
1077
|
-
this.
|
|
1313
|
+
this.actions.redo();
|
|
1314
|
+
}
|
|
1315
|
+
if ((e.ctrlKey || e.metaKey) && e.key === "a") {
|
|
1316
|
+
e.preventDefault();
|
|
1317
|
+
this.actions.selectAll();
|
|
1078
1318
|
}
|
|
1079
1319
|
if ((e.ctrlKey || e.metaKey) && e.key === "c") {
|
|
1080
1320
|
e.preventDefault();
|
|
1081
|
-
this.
|
|
1321
|
+
this.actions.copy();
|
|
1082
1322
|
}
|
|
1083
1323
|
if ((e.ctrlKey || e.metaKey) && e.key === "v") {
|
|
1084
1324
|
e.preventDefault();
|
|
1085
|
-
this.
|
|
1325
|
+
this.actions.paste();
|
|
1326
|
+
}
|
|
1327
|
+
if ((e.ctrlKey || e.metaKey) && e.key === "d") {
|
|
1328
|
+
e.preventDefault();
|
|
1329
|
+
this.actions.duplicate();
|
|
1086
1330
|
}
|
|
1087
1331
|
if (e.key === "]") {
|
|
1088
1332
|
e.preventDefault();
|
|
1089
|
-
this.
|
|
1333
|
+
this.actions.zOrder(e.ctrlKey || e.metaKey ? "front" : "forward");
|
|
1090
1334
|
}
|
|
1091
1335
|
if (e.key === "[") {
|
|
1092
1336
|
e.preventDefault();
|
|
1093
|
-
this.
|
|
1337
|
+
this.actions.zOrder(e.ctrlKey || e.metaKey ? "back" : "backward");
|
|
1338
|
+
}
|
|
1339
|
+
if (e.shiftKey && e.code === "Digit1" && !e.ctrlKey && !e.metaKey && !e.altKey) {
|
|
1340
|
+
e.preventDefault();
|
|
1341
|
+
this.actions.zoomToFit();
|
|
1342
|
+
}
|
|
1343
|
+
const nudgeDelta = NUDGE_KEYS[e.key];
|
|
1344
|
+
if (nudgeDelta) {
|
|
1345
|
+
const [dx, dy] = nudgeDelta;
|
|
1346
|
+
if (this.actions.nudge(dx, dy, e.shiftKey)) {
|
|
1347
|
+
e.preventDefault();
|
|
1348
|
+
}
|
|
1094
1349
|
}
|
|
1095
1350
|
};
|
|
1096
1351
|
onKeyUp = (e) => {
|
|
@@ -1154,6 +1409,7 @@ var InputHandler = class {
|
|
|
1154
1409
|
}
|
|
1155
1410
|
dispatchToolDown(e) {
|
|
1156
1411
|
if (!this.toolManager || !this.toolContext) return;
|
|
1412
|
+
this.actions.flushPendingNudge();
|
|
1157
1413
|
this.historyRecorder?.begin();
|
|
1158
1414
|
this.isToolActive = true;
|
|
1159
1415
|
this.toolManager.handlePointerDown(this.toPointerState(e), this.toolContext);
|
|
@@ -1174,127 +1430,6 @@ var InputHandler = class {
|
|
|
1174
1430
|
this.toolManager.handlePointerUp(this.toPointerState(e), this.toolContext);
|
|
1175
1431
|
this.historyRecorder?.commit();
|
|
1176
1432
|
}
|
|
1177
|
-
deleteSelected() {
|
|
1178
|
-
if (!this.toolManager || !this.toolContext) return;
|
|
1179
|
-
const tool = this.toolManager.activeTool;
|
|
1180
|
-
if (tool?.name !== "select") return;
|
|
1181
|
-
const selectTool = tool;
|
|
1182
|
-
const ids = selectTool.selectedIds;
|
|
1183
|
-
if (ids.length === 0) return;
|
|
1184
|
-
this.historyRecorder?.begin();
|
|
1185
|
-
for (const id of ids) {
|
|
1186
|
-
this.toolContext.store.remove(id);
|
|
1187
|
-
}
|
|
1188
|
-
this.historyRecorder?.commit();
|
|
1189
|
-
this.toolContext.requestRender();
|
|
1190
|
-
}
|
|
1191
|
-
handleUndo() {
|
|
1192
|
-
if (!this.historyStack || !this.toolContext) return;
|
|
1193
|
-
this.historyRecorder?.pause();
|
|
1194
|
-
this.historyStack.undo(this.toolContext.store);
|
|
1195
|
-
this.historyRecorder?.resume();
|
|
1196
|
-
this.toolContext.requestRender();
|
|
1197
|
-
}
|
|
1198
|
-
handleRedo() {
|
|
1199
|
-
if (!this.historyStack || !this.toolContext) return;
|
|
1200
|
-
this.historyRecorder?.pause();
|
|
1201
|
-
this.historyStack.redo(this.toolContext.store);
|
|
1202
|
-
this.historyRecorder?.resume();
|
|
1203
|
-
this.toolContext.requestRender();
|
|
1204
|
-
}
|
|
1205
|
-
handleCopy() {
|
|
1206
|
-
if (!this.toolManager || !this.toolContext || this.isToolActive) return;
|
|
1207
|
-
const tool = this.toolManager.activeTool;
|
|
1208
|
-
if (tool?.name !== "select") return;
|
|
1209
|
-
const selectTool = tool;
|
|
1210
|
-
const ids = selectTool.selectedIds;
|
|
1211
|
-
if (ids.length === 0) return;
|
|
1212
|
-
this.clipboard = [];
|
|
1213
|
-
for (const id of ids) {
|
|
1214
|
-
const el = this.toolContext.store.getById(id);
|
|
1215
|
-
if (el) this.clipboard.push(structuredClone(el));
|
|
1216
|
-
}
|
|
1217
|
-
this.pasteCount = 0;
|
|
1218
|
-
}
|
|
1219
|
-
handlePaste() {
|
|
1220
|
-
if (!this.toolManager || !this.toolContext || this.clipboard.length === 0 || this.isToolActive)
|
|
1221
|
-
return;
|
|
1222
|
-
const tool = this.toolManager.activeTool;
|
|
1223
|
-
if (tool?.name !== "select") return;
|
|
1224
|
-
const selectTool = tool;
|
|
1225
|
-
this.pasteCount++;
|
|
1226
|
-
const offset = this.pasteCount * 20;
|
|
1227
|
-
const idMap = /* @__PURE__ */ new Map();
|
|
1228
|
-
for (const el of this.clipboard) {
|
|
1229
|
-
idMap.set(el.id, createId(el.type));
|
|
1230
|
-
}
|
|
1231
|
-
const newIds = [];
|
|
1232
|
-
this.historyRecorder?.begin();
|
|
1233
|
-
for (const el of this.clipboard) {
|
|
1234
|
-
const clone = structuredClone(el);
|
|
1235
|
-
const newId = idMap.get(el.id);
|
|
1236
|
-
if (!newId) continue;
|
|
1237
|
-
clone.id = newId;
|
|
1238
|
-
clone.position = { x: clone.position.x + offset, y: clone.position.y + offset };
|
|
1239
|
-
if (clone.type === "arrow") {
|
|
1240
|
-
const arrow = clone;
|
|
1241
|
-
arrow.from = { x: arrow.from.x + offset, y: arrow.from.y + offset };
|
|
1242
|
-
arrow.to = { x: arrow.to.x + offset, y: arrow.to.y + offset };
|
|
1243
|
-
delete arrow.cachedControlPoint;
|
|
1244
|
-
if (arrow.fromBinding) {
|
|
1245
|
-
const newTarget = idMap.get(arrow.fromBinding.elementId);
|
|
1246
|
-
if (newTarget) {
|
|
1247
|
-
arrow.fromBinding = { elementId: newTarget };
|
|
1248
|
-
} else {
|
|
1249
|
-
delete arrow.fromBinding;
|
|
1250
|
-
}
|
|
1251
|
-
}
|
|
1252
|
-
if (arrow.toBinding) {
|
|
1253
|
-
const newTarget = idMap.get(arrow.toBinding.elementId);
|
|
1254
|
-
if (newTarget) {
|
|
1255
|
-
arrow.toBinding = { elementId: newTarget };
|
|
1256
|
-
} else {
|
|
1257
|
-
delete arrow.toBinding;
|
|
1258
|
-
}
|
|
1259
|
-
}
|
|
1260
|
-
}
|
|
1261
|
-
if (this.toolContext.activeLayerId) {
|
|
1262
|
-
clone.layerId = this.toolContext.activeLayerId;
|
|
1263
|
-
}
|
|
1264
|
-
this.toolContext.store.add(clone);
|
|
1265
|
-
newIds.push(clone.id);
|
|
1266
|
-
}
|
|
1267
|
-
this.historyRecorder?.commit();
|
|
1268
|
-
selectTool.setSelection(newIds);
|
|
1269
|
-
this.toolContext.requestRender();
|
|
1270
|
-
}
|
|
1271
|
-
handleZOrder(operation) {
|
|
1272
|
-
if (!this.toolManager || !this.toolContext) return;
|
|
1273
|
-
const tool = this.toolManager.activeTool;
|
|
1274
|
-
if (tool?.name !== "select") return;
|
|
1275
|
-
const selectTool = tool;
|
|
1276
|
-
const ids = selectTool.selectedIds;
|
|
1277
|
-
if (ids.length === 0) return;
|
|
1278
|
-
this.historyRecorder?.begin();
|
|
1279
|
-
for (const id of ids) {
|
|
1280
|
-
switch (operation) {
|
|
1281
|
-
case "forward":
|
|
1282
|
-
this.toolContext.store.bringForward(id);
|
|
1283
|
-
break;
|
|
1284
|
-
case "backward":
|
|
1285
|
-
this.toolContext.store.sendBackward(id);
|
|
1286
|
-
break;
|
|
1287
|
-
case "front":
|
|
1288
|
-
this.toolContext.store.bringToFront(id);
|
|
1289
|
-
break;
|
|
1290
|
-
case "back":
|
|
1291
|
-
this.toolContext.store.sendToBack(id);
|
|
1292
|
-
break;
|
|
1293
|
-
}
|
|
1294
|
-
}
|
|
1295
|
-
this.historyRecorder?.commit();
|
|
1296
|
-
this.toolContext.requestRender();
|
|
1297
|
-
}
|
|
1298
1433
|
cancelToolIfActive(e) {
|
|
1299
1434
|
if (this.isToolActive) {
|
|
1300
1435
|
this.dispatchToolUp(e);
|
|
@@ -3247,6 +3382,26 @@ var NoteEditor = class {
|
|
|
3247
3382
|
}
|
|
3248
3383
|
};
|
|
3249
3384
|
|
|
3385
|
+
// src/elements/bounds.ts
|
|
3386
|
+
function getElementsBoundingBox(elements) {
|
|
3387
|
+
let minX = Infinity;
|
|
3388
|
+
let minY = Infinity;
|
|
3389
|
+
let maxX = -Infinity;
|
|
3390
|
+
let maxY = -Infinity;
|
|
3391
|
+
let found = false;
|
|
3392
|
+
for (const el of elements) {
|
|
3393
|
+
const b = getElementBounds(el);
|
|
3394
|
+
if (!b) continue;
|
|
3395
|
+
found = true;
|
|
3396
|
+
if (b.x < minX) minX = b.x;
|
|
3397
|
+
if (b.y < minY) minY = b.y;
|
|
3398
|
+
if (b.x + b.w > maxX) maxX = b.x + b.w;
|
|
3399
|
+
if (b.y + b.h > maxY) maxY = b.y + b.h;
|
|
3400
|
+
}
|
|
3401
|
+
if (!found) return null;
|
|
3402
|
+
return { x: minX, y: minY, w: maxX - minX, h: maxY - minY };
|
|
3403
|
+
}
|
|
3404
|
+
|
|
3250
3405
|
// src/tools/tool-manager.ts
|
|
3251
3406
|
var ToolManager = class {
|
|
3252
3407
|
tools = /* @__PURE__ */ new Map();
|
|
@@ -3402,16 +3557,64 @@ var BatchCommand = class {
|
|
|
3402
3557
|
}
|
|
3403
3558
|
};
|
|
3404
3559
|
|
|
3560
|
+
// src/history/layer-commands.ts
|
|
3561
|
+
var CreateLayerCommand = class {
|
|
3562
|
+
constructor(manager, layer) {
|
|
3563
|
+
this.manager = manager;
|
|
3564
|
+
this.layer = layer;
|
|
3565
|
+
}
|
|
3566
|
+
execute(_store) {
|
|
3567
|
+
this.manager.addLayerDirect(this.layer);
|
|
3568
|
+
}
|
|
3569
|
+
undo(_store) {
|
|
3570
|
+
this.manager.removeLayerDirect(this.layer.id);
|
|
3571
|
+
}
|
|
3572
|
+
};
|
|
3573
|
+
var RemoveLayerCommand = class {
|
|
3574
|
+
constructor(manager, layer) {
|
|
3575
|
+
this.manager = manager;
|
|
3576
|
+
this.layer = layer;
|
|
3577
|
+
}
|
|
3578
|
+
execute(_store) {
|
|
3579
|
+
this.manager.removeLayerDirect(this.layer.id);
|
|
3580
|
+
}
|
|
3581
|
+
undo(_store) {
|
|
3582
|
+
this.manager.addLayerDirect(this.layer);
|
|
3583
|
+
}
|
|
3584
|
+
};
|
|
3585
|
+
var UpdateLayerCommand = class {
|
|
3586
|
+
constructor(manager, layerId, previous, current) {
|
|
3587
|
+
this.manager = manager;
|
|
3588
|
+
this.layerId = layerId;
|
|
3589
|
+
this.previous = previous;
|
|
3590
|
+
this.current = current;
|
|
3591
|
+
}
|
|
3592
|
+
execute(_store) {
|
|
3593
|
+
this.manager.updateLayerDirect(this.layerId, { ...this.current });
|
|
3594
|
+
}
|
|
3595
|
+
undo(_store) {
|
|
3596
|
+
this.manager.updateLayerDirect(this.layerId, { ...this.previous });
|
|
3597
|
+
}
|
|
3598
|
+
};
|
|
3599
|
+
|
|
3405
3600
|
// src/history/history-recorder.ts
|
|
3406
3601
|
var HistoryRecorder = class {
|
|
3407
|
-
constructor(store, stack) {
|
|
3602
|
+
constructor(store, stack, layerManager) {
|
|
3408
3603
|
this.store = store;
|
|
3409
3604
|
this.stack = stack;
|
|
3605
|
+
this.layerManager = layerManager;
|
|
3410
3606
|
this.unsubscribers = [
|
|
3411
3607
|
store.on("add", (el) => this.onAdd(el)),
|
|
3412
3608
|
store.on("remove", (el) => this.onRemove(el)),
|
|
3413
3609
|
store.on("update", ({ previous, current }) => this.onUpdate(previous, current))
|
|
3414
3610
|
];
|
|
3611
|
+
if (layerManager) {
|
|
3612
|
+
this.unsubscribers.push(
|
|
3613
|
+
layerManager.on("create", (layer) => this.onLayerCreate(layer)),
|
|
3614
|
+
layerManager.on("remove", (layer) => this.onLayerRemove(layer)),
|
|
3615
|
+
layerManager.on("update", ({ previous, current }) => this.onLayerUpdate(previous, current))
|
|
3616
|
+
);
|
|
3617
|
+
}
|
|
3415
3618
|
}
|
|
3416
3619
|
recording = true;
|
|
3417
3620
|
transaction = null;
|
|
@@ -3424,6 +3627,9 @@ var HistoryRecorder = class {
|
|
|
3424
3627
|
this.recording = true;
|
|
3425
3628
|
}
|
|
3426
3629
|
begin() {
|
|
3630
|
+
if (this.transaction !== null) {
|
|
3631
|
+
this.commit();
|
|
3632
|
+
}
|
|
3427
3633
|
this.transaction = [];
|
|
3428
3634
|
this.updateSnapshots.clear();
|
|
3429
3635
|
}
|
|
@@ -3472,6 +3678,21 @@ var HistoryRecorder = class {
|
|
|
3472
3678
|
this.stack.push(new UpdateElementCommand(current.id, previous, current));
|
|
3473
3679
|
}
|
|
3474
3680
|
}
|
|
3681
|
+
onLayerCreate(layer) {
|
|
3682
|
+
if (!this.recording) return;
|
|
3683
|
+
if (!this.layerManager) return;
|
|
3684
|
+
this.record(new CreateLayerCommand(this.layerManager, layer));
|
|
3685
|
+
}
|
|
3686
|
+
onLayerRemove(layer) {
|
|
3687
|
+
if (!this.recording) return;
|
|
3688
|
+
if (!this.layerManager) return;
|
|
3689
|
+
this.record(new RemoveLayerCommand(this.layerManager, layer));
|
|
3690
|
+
}
|
|
3691
|
+
onLayerUpdate(previous, current) {
|
|
3692
|
+
if (!this.recording) return;
|
|
3693
|
+
if (!this.layerManager) return;
|
|
3694
|
+
this.record(new UpdateLayerCommand(this.layerManager, current.id, previous, current));
|
|
3695
|
+
}
|
|
3475
3696
|
flushUpdateSnapshots() {
|
|
3476
3697
|
const commands = [];
|
|
3477
3698
|
for (const [id, previous] of this.updateSnapshots) {
|
|
@@ -3904,18 +4125,23 @@ var LayerManager = class {
|
|
|
3904
4125
|
addLayerDirect(layer) {
|
|
3905
4126
|
this.layers.set(layer.id, { ...layer });
|
|
3906
4127
|
this.syncLayerOrder();
|
|
4128
|
+
this.bus.emit("create", { ...layer });
|
|
3907
4129
|
this.bus.emit("change", null);
|
|
3908
4130
|
}
|
|
3909
4131
|
removeLayerDirect(id) {
|
|
4132
|
+
const layer = this.layers.get(id);
|
|
3910
4133
|
this.layers.delete(id);
|
|
3911
4134
|
this.syncLayerOrder();
|
|
4135
|
+
if (layer) this.bus.emit("remove", { ...layer });
|
|
3912
4136
|
this.bus.emit("change", null);
|
|
3913
4137
|
}
|
|
3914
4138
|
updateLayerDirect(id, props) {
|
|
3915
4139
|
const layer = this.layers.get(id);
|
|
3916
4140
|
if (!layer) return;
|
|
4141
|
+
const previous = { ...layer };
|
|
3917
4142
|
Object.assign(layer, props);
|
|
3918
4143
|
if ("order" in props) this.syncLayerOrder();
|
|
4144
|
+
this.bus.emit("update", { previous, current: { ...layer } });
|
|
3919
4145
|
this.bus.emit("change", null);
|
|
3920
4146
|
}
|
|
3921
4147
|
syncLayerOrder() {
|
|
@@ -4008,6 +4234,20 @@ var DomNodeManager = class {
|
|
|
4008
4234
|
storeHtmlContent(elementId, dom) {
|
|
4009
4235
|
this.htmlContent.set(elementId, dom);
|
|
4010
4236
|
}
|
|
4237
|
+
hasContent(elementId) {
|
|
4238
|
+
return this.htmlContent.has(elementId);
|
|
4239
|
+
}
|
|
4240
|
+
resetHtmlContent(elementId) {
|
|
4241
|
+
this.htmlContent.delete(elementId);
|
|
4242
|
+
this.lastSyncedVersion.delete(elementId);
|
|
4243
|
+
this.lastSyncedZIndex.delete(elementId);
|
|
4244
|
+
const node = this.domNodes.get(elementId);
|
|
4245
|
+
if (!node) return;
|
|
4246
|
+
while (node.firstChild) {
|
|
4247
|
+
node.removeChild(node.firstChild);
|
|
4248
|
+
}
|
|
4249
|
+
delete node.dataset["initialized"];
|
|
4250
|
+
}
|
|
4011
4251
|
syncDomNode(element, zIndex = 0) {
|
|
4012
4252
|
let node = this.domNodes.get(element.id);
|
|
4013
4253
|
if (!node) {
|
|
@@ -4549,8 +4789,10 @@ var Viewport = class {
|
|
|
4549
4789
|
toolbar: options.toolbar
|
|
4550
4790
|
});
|
|
4551
4791
|
this.noteEditor.setOnStop((id) => this.onTextEditStop(id));
|
|
4792
|
+
this.onHtmlElementMount = options.onHtmlElementMount;
|
|
4793
|
+
this.dropHandler = options.onDrop;
|
|
4552
4794
|
this.history = new HistoryStack();
|
|
4553
|
-
this.historyRecorder = new HistoryRecorder(this.store, this.history);
|
|
4795
|
+
this.historyRecorder = new HistoryRecorder(this.store, this.history, this.layerManager);
|
|
4554
4796
|
this.wrapper = this.createWrapper();
|
|
4555
4797
|
this.canvasEl = this.createCanvas();
|
|
4556
4798
|
this.domLayer = this.createDomLayer();
|
|
@@ -4576,7 +4818,8 @@ var Viewport = class {
|
|
|
4576
4818
|
toolManager: this.toolManager,
|
|
4577
4819
|
toolContext: this.toolContext,
|
|
4578
4820
|
historyRecorder: this.historyRecorder,
|
|
4579
|
-
historyStack: this.history
|
|
4821
|
+
historyStack: this.history,
|
|
4822
|
+
fitToContent: () => this.fitToContent()
|
|
4580
4823
|
});
|
|
4581
4824
|
this.domNodeManager = new DomNodeManager({
|
|
4582
4825
|
domLayer: this.domLayer,
|
|
@@ -4670,6 +4913,8 @@ var Viewport = class {
|
|
|
4670
4913
|
renderLoop;
|
|
4671
4914
|
domNodeManager;
|
|
4672
4915
|
interactMode;
|
|
4916
|
+
onHtmlElementMount;
|
|
4917
|
+
dropHandler;
|
|
4673
4918
|
gridChangeListeners = /* @__PURE__ */ new Set();
|
|
4674
4919
|
doubleTapDetector = new DoubleTapDetector();
|
|
4675
4920
|
tapDownX = 0;
|
|
@@ -4684,6 +4929,13 @@ var Viewport = class {
|
|
|
4684
4929
|
this._snapToGrid = enabled;
|
|
4685
4930
|
this.toolContext.snapToGrid = enabled;
|
|
4686
4931
|
}
|
|
4932
|
+
fitToContent(padding = 40) {
|
|
4933
|
+
if (this.wrapper.clientWidth === 0 || this.wrapper.clientHeight === 0) return;
|
|
4934
|
+
const visibleElements = this.store.getAll().filter((el) => this.layerManager.isLayerVisible(el.layerId));
|
|
4935
|
+
const bbox = getElementsBoundingBox(visibleElements);
|
|
4936
|
+
if (!bbox) return;
|
|
4937
|
+
this.camera.fitToContent(bbox, this.wrapper.clientWidth, this.wrapper.clientHeight, padding);
|
|
4938
|
+
}
|
|
4687
4939
|
requestRender() {
|
|
4688
4940
|
this.renderLoop.requestRender();
|
|
4689
4941
|
}
|
|
@@ -4702,6 +4954,7 @@ var Viewport = class {
|
|
|
4702
4954
|
return exportImage(this.store, options, this.layerManager);
|
|
4703
4955
|
}
|
|
4704
4956
|
loadState(state) {
|
|
4957
|
+
this.inputHandler.flushPendingHistory();
|
|
4705
4958
|
this.historyRecorder.pause();
|
|
4706
4959
|
this.noteEditor.destroy(this.store);
|
|
4707
4960
|
this.domNodeManager.clearDomNodes();
|
|
@@ -4713,6 +4966,22 @@ var Viewport = class {
|
|
|
4713
4966
|
this.layerManager.setActiveLayer(state.activeLayerId);
|
|
4714
4967
|
}
|
|
4715
4968
|
this.domNodeManager.reattachHtmlContent(this.store);
|
|
4969
|
+
if (this.onHtmlElementMount) {
|
|
4970
|
+
for (const el of this.store.getElementsByType("html")) {
|
|
4971
|
+
if (!this.domNodeManager.hasContent(el.id)) {
|
|
4972
|
+
this.domNodeManager.syncDomNode(el);
|
|
4973
|
+
const node = this.domNodeManager.getNode(el.id);
|
|
4974
|
+
if (node) {
|
|
4975
|
+
this.onHtmlElementMount(el.id, el.domId, node);
|
|
4976
|
+
node.dataset["initialized"] = "true";
|
|
4977
|
+
Object.assign(node.style, {
|
|
4978
|
+
overflow: "hidden",
|
|
4979
|
+
pointerEvents: el.interactive ? "auto" : "none"
|
|
4980
|
+
});
|
|
4981
|
+
}
|
|
4982
|
+
}
|
|
4983
|
+
}
|
|
4984
|
+
}
|
|
4716
4985
|
this.history.clear();
|
|
4717
4986
|
this.historyRecorder.resume();
|
|
4718
4987
|
this.camera.moveTo(state.camera.position.x, state.camera.position.y);
|
|
@@ -4722,6 +4991,7 @@ var Viewport = class {
|
|
|
4722
4991
|
this.loadState(parseState(json));
|
|
4723
4992
|
}
|
|
4724
4993
|
undo() {
|
|
4994
|
+
this.inputHandler.flushPendingHistory();
|
|
4725
4995
|
this.historyRecorder.pause();
|
|
4726
4996
|
const result = this.history.undo(this.store);
|
|
4727
4997
|
this.historyRecorder.resume();
|
|
@@ -4729,6 +4999,7 @@ var Viewport = class {
|
|
|
4729
4999
|
return result;
|
|
4730
5000
|
}
|
|
4731
5001
|
redo() {
|
|
5002
|
+
this.inputHandler.flushPendingHistory();
|
|
4732
5003
|
this.historyRecorder.pause();
|
|
4733
5004
|
const result = this.history.redo(this.store);
|
|
4734
5005
|
this.historyRecorder.resume();
|
|
@@ -4758,6 +5029,19 @@ var Viewport = class {
|
|
|
4758
5029
|
this.requestRender();
|
|
4759
5030
|
return el.id;
|
|
4760
5031
|
}
|
|
5032
|
+
removeLayer(id) {
|
|
5033
|
+
this.historyRecorder.begin();
|
|
5034
|
+
this.layerManager.removeLayer(id);
|
|
5035
|
+
this.historyRecorder.commit();
|
|
5036
|
+
}
|
|
5037
|
+
updateHtmlElement(id, newContent) {
|
|
5038
|
+
const el = this.store.getById(id);
|
|
5039
|
+
if (!el) throw new Error(`Element not found: ${id}`);
|
|
5040
|
+
if (el.type !== "html") throw new Error(`Element ${id} is not an HTML element`);
|
|
5041
|
+
this.domNodeManager.resetHtmlContent(id);
|
|
5042
|
+
this.domNodeManager.storeHtmlContent(id, newContent);
|
|
5043
|
+
this.requestRender();
|
|
5044
|
+
}
|
|
4761
5045
|
addGrid(input) {
|
|
4762
5046
|
const existing = this.store.getElementsByType("grid")[0];
|
|
4763
5047
|
this.historyRecorder.begin();
|
|
@@ -4909,17 +5193,21 @@ var Viewport = class {
|
|
|
4909
5193
|
};
|
|
4910
5194
|
onDrop = (e) => {
|
|
4911
5195
|
e.preventDefault();
|
|
5196
|
+
const rect = this.wrapper.getBoundingClientRect();
|
|
5197
|
+
const screenPos = { x: e.clientX - rect.left, y: e.clientY - rect.top };
|
|
5198
|
+
const worldPos = this.camera.screenToWorld(screenPos);
|
|
5199
|
+
if (this.dropHandler) {
|
|
5200
|
+
this.dropHandler(e, worldPos);
|
|
5201
|
+
return;
|
|
5202
|
+
}
|
|
4912
5203
|
const files = e.dataTransfer?.files;
|
|
4913
5204
|
if (!files) return;
|
|
4914
|
-
const rect = this.wrapper.getBoundingClientRect();
|
|
4915
5205
|
for (const file of files) {
|
|
4916
5206
|
if (!file.type.startsWith("image/")) continue;
|
|
4917
5207
|
const reader = new FileReader();
|
|
4918
5208
|
reader.onload = () => {
|
|
4919
5209
|
const src = reader.result;
|
|
4920
5210
|
if (typeof src !== "string") return;
|
|
4921
|
-
const screenPos = { x: e.clientX - rect.left, y: e.clientY - rect.top };
|
|
4922
|
-
const worldPos = this.camera.screenToWorld(screenPos);
|
|
4923
5211
|
this.addImage(src, worldPos);
|
|
4924
5212
|
};
|
|
4925
5213
|
reader.readAsDataURL(file);
|
|
@@ -5031,26 +5319,6 @@ var Viewport = class {
|
|
|
5031
5319
|
}
|
|
5032
5320
|
};
|
|
5033
5321
|
|
|
5034
|
-
// src/elements/bounds.ts
|
|
5035
|
-
function getElementsBoundingBox(elements) {
|
|
5036
|
-
let minX = Infinity;
|
|
5037
|
-
let minY = Infinity;
|
|
5038
|
-
let maxX = -Infinity;
|
|
5039
|
-
let maxY = -Infinity;
|
|
5040
|
-
let found = false;
|
|
5041
|
-
for (const el of elements) {
|
|
5042
|
-
const b = getElementBounds(el);
|
|
5043
|
-
if (!b) continue;
|
|
5044
|
-
found = true;
|
|
5045
|
-
if (b.x < minX) minX = b.x;
|
|
5046
|
-
if (b.y < minY) minY = b.y;
|
|
5047
|
-
if (b.x + b.w > maxX) maxX = b.x + b.w;
|
|
5048
|
-
if (b.y + b.h > maxY) maxY = b.y + b.h;
|
|
5049
|
-
}
|
|
5050
|
-
if (!found) return null;
|
|
5051
|
-
return { x: minX, y: minY, w: maxX - minX, h: maxY - minY };
|
|
5052
|
-
}
|
|
5053
|
-
|
|
5054
5322
|
// src/tools/hand-tool.ts
|
|
5055
5323
|
var HandTool = class {
|
|
5056
5324
|
name = "hand";
|
|
@@ -5542,23 +5810,7 @@ var SelectTool = class {
|
|
|
5542
5810
|
});
|
|
5543
5811
|
}
|
|
5544
5812
|
}
|
|
5545
|
-
|
|
5546
|
-
for (const id of this._selectedIds) {
|
|
5547
|
-
const el = ctx.store.getById(id);
|
|
5548
|
-
if (el && el.type !== "arrow") movedNonArrowIds.add(id);
|
|
5549
|
-
}
|
|
5550
|
-
if (movedNonArrowIds.size > 0) {
|
|
5551
|
-
const updatedArrows = /* @__PURE__ */ new Set();
|
|
5552
|
-
for (const id of movedNonArrowIds) {
|
|
5553
|
-
const boundArrows = findBoundArrows(id, ctx.store);
|
|
5554
|
-
for (const ba of boundArrows) {
|
|
5555
|
-
if (updatedArrows.has(ba.id)) continue;
|
|
5556
|
-
updatedArrows.add(ba.id);
|
|
5557
|
-
const updates = updateBoundArrow(ba, ctx.store);
|
|
5558
|
-
if (updates) ctx.store.update(ba.id, updates);
|
|
5559
|
-
}
|
|
5560
|
-
}
|
|
5561
|
-
}
|
|
5813
|
+
this.updateArrowsBoundTo(this._selectedIds, ctx);
|
|
5562
5814
|
ctx.requestRender();
|
|
5563
5815
|
return;
|
|
5564
5816
|
}
|
|
@@ -5609,6 +5861,49 @@ var SelectTool = class {
|
|
|
5609
5861
|
}
|
|
5610
5862
|
}
|
|
5611
5863
|
}
|
|
5864
|
+
updateArrowsBoundTo(ids, ctx) {
|
|
5865
|
+
const movedNonArrowIds = /* @__PURE__ */ new Set();
|
|
5866
|
+
for (const id of ids) {
|
|
5867
|
+
const el = ctx.store.getById(id);
|
|
5868
|
+
if (el && el.type !== "arrow") movedNonArrowIds.add(id);
|
|
5869
|
+
}
|
|
5870
|
+
if (movedNonArrowIds.size === 0) return;
|
|
5871
|
+
const updatedArrows = /* @__PURE__ */ new Set();
|
|
5872
|
+
for (const id of movedNonArrowIds) {
|
|
5873
|
+
const boundArrows = findBoundArrows(id, ctx.store);
|
|
5874
|
+
for (const ba of boundArrows) {
|
|
5875
|
+
if (updatedArrows.has(ba.id)) continue;
|
|
5876
|
+
updatedArrows.add(ba.id);
|
|
5877
|
+
const updates = updateBoundArrow(ba, ctx.store);
|
|
5878
|
+
if (updates) ctx.store.update(ba.id, updates);
|
|
5879
|
+
}
|
|
5880
|
+
}
|
|
5881
|
+
}
|
|
5882
|
+
nudgeSelection(dx, dy, ctx) {
|
|
5883
|
+
let moved = false;
|
|
5884
|
+
for (const id of this._selectedIds) {
|
|
5885
|
+
const el = ctx.store.getById(id);
|
|
5886
|
+
if (!el || el.locked) continue;
|
|
5887
|
+
if (el.type === "arrow") {
|
|
5888
|
+
if (el.fromBinding || el.toBinding) continue;
|
|
5889
|
+
ctx.store.update(id, {
|
|
5890
|
+
position: { x: el.position.x + dx, y: el.position.y + dy },
|
|
5891
|
+
from: { x: el.from.x + dx, y: el.from.y + dy },
|
|
5892
|
+
to: { x: el.to.x + dx, y: el.to.y + dy }
|
|
5893
|
+
});
|
|
5894
|
+
} else {
|
|
5895
|
+
ctx.store.update(id, {
|
|
5896
|
+
position: { x: el.position.x + dx, y: el.position.y + dy }
|
|
5897
|
+
});
|
|
5898
|
+
}
|
|
5899
|
+
moved = true;
|
|
5900
|
+
}
|
|
5901
|
+
if (moved) {
|
|
5902
|
+
this.updateArrowsBoundTo(this._selectedIds, ctx);
|
|
5903
|
+
ctx.requestRender();
|
|
5904
|
+
}
|
|
5905
|
+
return moved;
|
|
5906
|
+
}
|
|
5612
5907
|
updateHoverCursor(world, ctx) {
|
|
5613
5908
|
const arrowHit = hitTestArrowHandles(world, this._selectedIds, ctx);
|
|
5614
5909
|
if (arrowHit) {
|
|
@@ -5686,11 +5981,7 @@ var SelectTool = class {
|
|
|
5686
5981
|
position: { x, y },
|
|
5687
5982
|
size: { w, h }
|
|
5688
5983
|
});
|
|
5689
|
-
|
|
5690
|
-
for (const ba of boundArrows) {
|
|
5691
|
-
const updates = updateBoundArrow(ba, ctx.store);
|
|
5692
|
-
if (updates) ctx.store.update(ba.id, updates);
|
|
5693
|
-
}
|
|
5984
|
+
this.updateArrowsBoundTo([this.mode.elementId], ctx);
|
|
5694
5985
|
ctx.requestRender();
|
|
5695
5986
|
}
|
|
5696
5987
|
hitTestResizeHandle(world, ctx) {
|
|
@@ -6736,48 +7027,8 @@ var TemplateTool = class {
|
|
|
6736
7027
|
}
|
|
6737
7028
|
};
|
|
6738
7029
|
|
|
6739
|
-
// src/history/layer-commands.ts
|
|
6740
|
-
var CreateLayerCommand = class {
|
|
6741
|
-
constructor(manager, layer) {
|
|
6742
|
-
this.manager = manager;
|
|
6743
|
-
this.layer = layer;
|
|
6744
|
-
}
|
|
6745
|
-
execute(_store) {
|
|
6746
|
-
this.manager.addLayerDirect(this.layer);
|
|
6747
|
-
}
|
|
6748
|
-
undo(_store) {
|
|
6749
|
-
this.manager.removeLayerDirect(this.layer.id);
|
|
6750
|
-
}
|
|
6751
|
-
};
|
|
6752
|
-
var RemoveLayerCommand = class {
|
|
6753
|
-
constructor(manager, layer) {
|
|
6754
|
-
this.manager = manager;
|
|
6755
|
-
this.layer = layer;
|
|
6756
|
-
}
|
|
6757
|
-
execute(_store) {
|
|
6758
|
-
this.manager.removeLayerDirect(this.layer.id);
|
|
6759
|
-
}
|
|
6760
|
-
undo(_store) {
|
|
6761
|
-
this.manager.addLayerDirect(this.layer);
|
|
6762
|
-
}
|
|
6763
|
-
};
|
|
6764
|
-
var UpdateLayerCommand = class {
|
|
6765
|
-
constructor(manager, layerId, previous, current) {
|
|
6766
|
-
this.manager = manager;
|
|
6767
|
-
this.layerId = layerId;
|
|
6768
|
-
this.previous = previous;
|
|
6769
|
-
this.current = current;
|
|
6770
|
-
}
|
|
6771
|
-
execute(_store) {
|
|
6772
|
-
this.manager.updateLayerDirect(this.layerId, { ...this.current });
|
|
6773
|
-
}
|
|
6774
|
-
undo(_store) {
|
|
6775
|
-
this.manager.updateLayerDirect(this.layerId, { ...this.previous });
|
|
6776
|
-
}
|
|
6777
|
-
};
|
|
6778
|
-
|
|
6779
7030
|
// src/index.ts
|
|
6780
|
-
var VERSION = "0.
|
|
7031
|
+
var VERSION = "0.17.0";
|
|
6781
7032
|
// Annotate the CommonJS export names for ESM import in node:
|
|
6782
7033
|
0 && (module.exports = {
|
|
6783
7034
|
AddElementCommand,
|