@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.js
CHANGED
|
@@ -811,9 +811,228 @@ function createId(prefix) {
|
|
|
811
811
|
return `${prefix}_${Date.now().toString(36)}_${(counter++).toString(36)}`;
|
|
812
812
|
}
|
|
813
813
|
|
|
814
|
+
// src/canvas/keyboard-actions.ts
|
|
815
|
+
var KeyboardActions = class {
|
|
816
|
+
constructor(deps) {
|
|
817
|
+
this.deps = deps;
|
|
818
|
+
}
|
|
819
|
+
clipboard = [];
|
|
820
|
+
pasteCount = 0;
|
|
821
|
+
nudgeTimer = null;
|
|
822
|
+
dispose() {
|
|
823
|
+
this.flushPendingNudge();
|
|
824
|
+
}
|
|
825
|
+
selectTool() {
|
|
826
|
+
const tm = this.deps.getToolManager();
|
|
827
|
+
const ctx = this.deps.getToolContext();
|
|
828
|
+
if (!tm || !ctx) return null;
|
|
829
|
+
const tool = tm.activeTool;
|
|
830
|
+
if (tool?.name !== "select") return null;
|
|
831
|
+
return { tool, ctx };
|
|
832
|
+
}
|
|
833
|
+
nudge(dx, dy, byCell) {
|
|
834
|
+
if (this.deps.isToolActive()) return false;
|
|
835
|
+
const sel = this.selectTool();
|
|
836
|
+
if (!sel) return false;
|
|
837
|
+
if (sel.tool.selectedIds.length === 0) return false;
|
|
838
|
+
const step = byCell ? sel.ctx.gridSize ?? 10 : 1;
|
|
839
|
+
if (this.nudgeTimer === null) {
|
|
840
|
+
this.deps.getHistoryRecorder()?.begin();
|
|
841
|
+
} else {
|
|
842
|
+
clearTimeout(this.nudgeTimer);
|
|
843
|
+
}
|
|
844
|
+
const moved = sel.tool.nudgeSelection(dx * step, dy * step, sel.ctx);
|
|
845
|
+
this.nudgeTimer = setTimeout(() => this.flushPendingNudge(), 400);
|
|
846
|
+
return moved;
|
|
847
|
+
}
|
|
848
|
+
flushPendingNudge() {
|
|
849
|
+
if (this.nudgeTimer === null) return;
|
|
850
|
+
clearTimeout(this.nudgeTimer);
|
|
851
|
+
this.nudgeTimer = null;
|
|
852
|
+
this.deps.getHistoryRecorder()?.commit();
|
|
853
|
+
}
|
|
854
|
+
deleteSelected() {
|
|
855
|
+
this.flushPendingNudge();
|
|
856
|
+
const sel = this.selectTool();
|
|
857
|
+
if (!sel) return;
|
|
858
|
+
const ids = sel.tool.selectedIds;
|
|
859
|
+
if (ids.length === 0) return;
|
|
860
|
+
const recorder = this.deps.getHistoryRecorder();
|
|
861
|
+
recorder?.begin();
|
|
862
|
+
for (const id of ids) {
|
|
863
|
+
sel.ctx.store.remove(id);
|
|
864
|
+
}
|
|
865
|
+
recorder?.commit();
|
|
866
|
+
sel.ctx.requestRender();
|
|
867
|
+
}
|
|
868
|
+
undo() {
|
|
869
|
+
this.flushPendingNudge();
|
|
870
|
+
const ctx = this.deps.getToolContext();
|
|
871
|
+
const stack = this.deps.getHistoryStack();
|
|
872
|
+
if (!stack || !ctx) return;
|
|
873
|
+
const recorder = this.deps.getHistoryRecorder();
|
|
874
|
+
recorder?.pause();
|
|
875
|
+
stack.undo(ctx.store);
|
|
876
|
+
recorder?.resume();
|
|
877
|
+
ctx.requestRender();
|
|
878
|
+
}
|
|
879
|
+
redo() {
|
|
880
|
+
this.flushPendingNudge();
|
|
881
|
+
const ctx = this.deps.getToolContext();
|
|
882
|
+
const stack = this.deps.getHistoryStack();
|
|
883
|
+
if (!stack || !ctx) return;
|
|
884
|
+
const recorder = this.deps.getHistoryRecorder();
|
|
885
|
+
recorder?.pause();
|
|
886
|
+
stack.redo(ctx.store);
|
|
887
|
+
recorder?.resume();
|
|
888
|
+
ctx.requestRender();
|
|
889
|
+
}
|
|
890
|
+
copy() {
|
|
891
|
+
if (this.deps.isToolActive()) return;
|
|
892
|
+
const sel = this.selectTool();
|
|
893
|
+
if (!sel) return;
|
|
894
|
+
const ids = sel.tool.selectedIds;
|
|
895
|
+
if (ids.length === 0) return;
|
|
896
|
+
this.clipboard = [];
|
|
897
|
+
for (const id of ids) {
|
|
898
|
+
const el = sel.ctx.store.getById(id);
|
|
899
|
+
if (el) this.clipboard.push(structuredClone(el));
|
|
900
|
+
}
|
|
901
|
+
this.pasteCount = 0;
|
|
902
|
+
}
|
|
903
|
+
paste() {
|
|
904
|
+
this.flushPendingNudge();
|
|
905
|
+
if (this.clipboard.length === 0 || this.deps.isToolActive()) return;
|
|
906
|
+
const sel = this.selectTool();
|
|
907
|
+
if (!sel) return;
|
|
908
|
+
this.pasteCount++;
|
|
909
|
+
this.insertClones(this.clipboard, this.pasteCount * 20, sel);
|
|
910
|
+
}
|
|
911
|
+
duplicate() {
|
|
912
|
+
this.flushPendingNudge();
|
|
913
|
+
if (this.deps.isToolActive()) return;
|
|
914
|
+
const sel = this.selectTool();
|
|
915
|
+
if (!sel) return;
|
|
916
|
+
const source = [];
|
|
917
|
+
for (const id of sel.tool.selectedIds) {
|
|
918
|
+
const el = sel.ctx.store.getById(id);
|
|
919
|
+
if (el) source.push(el);
|
|
920
|
+
}
|
|
921
|
+
if (source.length === 0) return;
|
|
922
|
+
this.insertClones(source, 20, sel);
|
|
923
|
+
}
|
|
924
|
+
deselect() {
|
|
925
|
+
if (this.deps.isToolActive()) return;
|
|
926
|
+
const sel = this.selectTool();
|
|
927
|
+
if (!sel) return;
|
|
928
|
+
if (sel.tool.selectedIds.length === 0) return;
|
|
929
|
+
sel.tool.setSelection([]);
|
|
930
|
+
sel.ctx.requestRender();
|
|
931
|
+
}
|
|
932
|
+
selectAll() {
|
|
933
|
+
if (this.deps.isToolActive()) return;
|
|
934
|
+
const tm = this.deps.getToolManager();
|
|
935
|
+
const ctx = this.deps.getToolContext();
|
|
936
|
+
if (!tm || !ctx) return;
|
|
937
|
+
if (tm.activeTool?.name !== "select") {
|
|
938
|
+
ctx.switchTool?.("select");
|
|
939
|
+
}
|
|
940
|
+
const sel = this.selectTool();
|
|
941
|
+
if (!sel) return;
|
|
942
|
+
const ids = sel.ctx.store.getAll().filter(
|
|
943
|
+
(el) => !el.locked && (sel.ctx.isLayerVisible?.(el.layerId) ?? true) && !(sel.ctx.isLayerLocked?.(el.layerId) ?? false)
|
|
944
|
+
).map((el) => el.id);
|
|
945
|
+
sel.tool.setSelection(ids);
|
|
946
|
+
sel.ctx.requestRender();
|
|
947
|
+
}
|
|
948
|
+
zoomToFit() {
|
|
949
|
+
if (this.deps.isToolActive()) return;
|
|
950
|
+
this.deps.fitToContent?.();
|
|
951
|
+
}
|
|
952
|
+
zOrder(operation) {
|
|
953
|
+
this.flushPendingNudge();
|
|
954
|
+
const sel = this.selectTool();
|
|
955
|
+
if (!sel) return;
|
|
956
|
+
const ids = sel.tool.selectedIds;
|
|
957
|
+
if (ids.length === 0) return;
|
|
958
|
+
const recorder = this.deps.getHistoryRecorder();
|
|
959
|
+
recorder?.begin();
|
|
960
|
+
for (const id of ids) {
|
|
961
|
+
switch (operation) {
|
|
962
|
+
case "forward":
|
|
963
|
+
sel.ctx.store.bringForward(id);
|
|
964
|
+
break;
|
|
965
|
+
case "backward":
|
|
966
|
+
sel.ctx.store.sendBackward(id);
|
|
967
|
+
break;
|
|
968
|
+
case "front":
|
|
969
|
+
sel.ctx.store.bringToFront(id);
|
|
970
|
+
break;
|
|
971
|
+
case "back":
|
|
972
|
+
sel.ctx.store.sendToBack(id);
|
|
973
|
+
break;
|
|
974
|
+
}
|
|
975
|
+
}
|
|
976
|
+
recorder?.commit();
|
|
977
|
+
sel.ctx.requestRender();
|
|
978
|
+
}
|
|
979
|
+
insertClones(source, offset, sel) {
|
|
980
|
+
const idMap = /* @__PURE__ */ new Map();
|
|
981
|
+
for (const el of source) {
|
|
982
|
+
idMap.set(el.id, createId(el.type));
|
|
983
|
+
}
|
|
984
|
+
const newIds = [];
|
|
985
|
+
const recorder = this.deps.getHistoryRecorder();
|
|
986
|
+
recorder?.begin();
|
|
987
|
+
for (const el of source) {
|
|
988
|
+
const clone = structuredClone(el);
|
|
989
|
+
const newId = idMap.get(el.id);
|
|
990
|
+
if (!newId) continue;
|
|
991
|
+
clone.id = newId;
|
|
992
|
+
clone.position = { x: clone.position.x + offset, y: clone.position.y + offset };
|
|
993
|
+
if (clone.type === "arrow") {
|
|
994
|
+
const arrow = clone;
|
|
995
|
+
arrow.from = { x: arrow.from.x + offset, y: arrow.from.y + offset };
|
|
996
|
+
arrow.to = { x: arrow.to.x + offset, y: arrow.to.y + offset };
|
|
997
|
+
delete arrow.cachedControlPoint;
|
|
998
|
+
if (arrow.fromBinding) {
|
|
999
|
+
const newTarget = idMap.get(arrow.fromBinding.elementId);
|
|
1000
|
+
if (newTarget) {
|
|
1001
|
+
arrow.fromBinding = { elementId: newTarget };
|
|
1002
|
+
} else {
|
|
1003
|
+
delete arrow.fromBinding;
|
|
1004
|
+
}
|
|
1005
|
+
}
|
|
1006
|
+
if (arrow.toBinding) {
|
|
1007
|
+
const newTarget = idMap.get(arrow.toBinding.elementId);
|
|
1008
|
+
if (newTarget) {
|
|
1009
|
+
arrow.toBinding = { elementId: newTarget };
|
|
1010
|
+
} else {
|
|
1011
|
+
delete arrow.toBinding;
|
|
1012
|
+
}
|
|
1013
|
+
}
|
|
1014
|
+
}
|
|
1015
|
+
if (sel.ctx.activeLayerId) {
|
|
1016
|
+
clone.layerId = sel.ctx.activeLayerId;
|
|
1017
|
+
}
|
|
1018
|
+
sel.ctx.store.add(clone);
|
|
1019
|
+
newIds.push(clone.id);
|
|
1020
|
+
}
|
|
1021
|
+
recorder?.commit();
|
|
1022
|
+
sel.tool.setSelection(newIds);
|
|
1023
|
+
sel.ctx.requestRender();
|
|
1024
|
+
}
|
|
1025
|
+
};
|
|
1026
|
+
|
|
814
1027
|
// src/canvas/input-handler.ts
|
|
815
1028
|
var ZOOM_SENSITIVITY = 1e-3;
|
|
816
1029
|
var MIDDLE_BUTTON = 1;
|
|
1030
|
+
var NUDGE_KEYS = {
|
|
1031
|
+
ArrowLeft: [-1, 0],
|
|
1032
|
+
ArrowRight: [1, 0],
|
|
1033
|
+
ArrowUp: [0, -1],
|
|
1034
|
+
ArrowDown: [0, 1]
|
|
1035
|
+
};
|
|
817
1036
|
var InputHandler = class {
|
|
818
1037
|
constructor(element, camera, options = {}) {
|
|
819
1038
|
this.element = element;
|
|
@@ -822,6 +1041,14 @@ var InputHandler = class {
|
|
|
822
1041
|
this.toolContext = options.toolContext ?? null;
|
|
823
1042
|
this.historyRecorder = options.historyRecorder ?? null;
|
|
824
1043
|
this.historyStack = options.historyStack ?? null;
|
|
1044
|
+
this.actions = new KeyboardActions({
|
|
1045
|
+
getToolManager: () => this.toolManager,
|
|
1046
|
+
getToolContext: () => this.toolContext,
|
|
1047
|
+
getHistoryRecorder: () => this.historyRecorder,
|
|
1048
|
+
getHistoryStack: () => this.historyStack,
|
|
1049
|
+
isToolActive: () => this.isToolActive,
|
|
1050
|
+
fitToContent: options.fitToContent
|
|
1051
|
+
});
|
|
825
1052
|
this.element.style.touchAction = "none";
|
|
826
1053
|
this.bind();
|
|
827
1054
|
}
|
|
@@ -840,13 +1067,16 @@ var InputHandler = class {
|
|
|
840
1067
|
inputFilter = new InputFilter();
|
|
841
1068
|
deferredDown = null;
|
|
842
1069
|
abortController = new AbortController();
|
|
843
|
-
|
|
844
|
-
pasteCount = 0;
|
|
1070
|
+
actions;
|
|
845
1071
|
setToolManager(toolManager, toolContext) {
|
|
846
1072
|
this.toolManager = toolManager;
|
|
847
1073
|
this.toolContext = toolContext;
|
|
848
1074
|
}
|
|
1075
|
+
flushPendingHistory() {
|
|
1076
|
+
this.actions.flushPendingNudge();
|
|
1077
|
+
}
|
|
849
1078
|
destroy() {
|
|
1079
|
+
this.actions.dispose();
|
|
850
1080
|
this.abortController.abort();
|
|
851
1081
|
this.inputFilter.reset();
|
|
852
1082
|
this.deferredDown = null;
|
|
@@ -952,36 +1182,61 @@ var InputHandler = class {
|
|
|
952
1182
|
}
|
|
953
1183
|
};
|
|
954
1184
|
onKeyDown = (e) => {
|
|
955
|
-
|
|
1185
|
+
const target = e.target;
|
|
1186
|
+
if (target?.isContentEditable) return;
|
|
1187
|
+
const tag = target?.tagName;
|
|
1188
|
+
if (tag === "INPUT" || tag === "TEXTAREA" || tag === "SELECT") return;
|
|
956
1189
|
if (e.key === " ") {
|
|
957
1190
|
this.spaceHeld = true;
|
|
958
1191
|
}
|
|
959
1192
|
if (e.key === "Delete" || e.key === "Backspace") {
|
|
960
|
-
this.deleteSelected();
|
|
1193
|
+
this.actions.deleteSelected();
|
|
1194
|
+
}
|
|
1195
|
+
if (e.key === "Escape") {
|
|
1196
|
+
this.actions.deselect();
|
|
961
1197
|
}
|
|
962
1198
|
if ((e.ctrlKey || e.metaKey) && e.key === "z" && !e.shiftKey) {
|
|
963
1199
|
e.preventDefault();
|
|
964
|
-
this.
|
|
1200
|
+
this.actions.undo();
|
|
965
1201
|
}
|
|
966
1202
|
if ((e.ctrlKey || e.metaKey) && (e.key === "y" || e.key === "z" && e.shiftKey)) {
|
|
967
1203
|
e.preventDefault();
|
|
968
|
-
this.
|
|
1204
|
+
this.actions.redo();
|
|
1205
|
+
}
|
|
1206
|
+
if ((e.ctrlKey || e.metaKey) && e.key === "a") {
|
|
1207
|
+
e.preventDefault();
|
|
1208
|
+
this.actions.selectAll();
|
|
969
1209
|
}
|
|
970
1210
|
if ((e.ctrlKey || e.metaKey) && e.key === "c") {
|
|
971
1211
|
e.preventDefault();
|
|
972
|
-
this.
|
|
1212
|
+
this.actions.copy();
|
|
973
1213
|
}
|
|
974
1214
|
if ((e.ctrlKey || e.metaKey) && e.key === "v") {
|
|
975
1215
|
e.preventDefault();
|
|
976
|
-
this.
|
|
1216
|
+
this.actions.paste();
|
|
1217
|
+
}
|
|
1218
|
+
if ((e.ctrlKey || e.metaKey) && e.key === "d") {
|
|
1219
|
+
e.preventDefault();
|
|
1220
|
+
this.actions.duplicate();
|
|
977
1221
|
}
|
|
978
1222
|
if (e.key === "]") {
|
|
979
1223
|
e.preventDefault();
|
|
980
|
-
this.
|
|
1224
|
+
this.actions.zOrder(e.ctrlKey || e.metaKey ? "front" : "forward");
|
|
981
1225
|
}
|
|
982
1226
|
if (e.key === "[") {
|
|
983
1227
|
e.preventDefault();
|
|
984
|
-
this.
|
|
1228
|
+
this.actions.zOrder(e.ctrlKey || e.metaKey ? "back" : "backward");
|
|
1229
|
+
}
|
|
1230
|
+
if (e.shiftKey && e.code === "Digit1" && !e.ctrlKey && !e.metaKey && !e.altKey) {
|
|
1231
|
+
e.preventDefault();
|
|
1232
|
+
this.actions.zoomToFit();
|
|
1233
|
+
}
|
|
1234
|
+
const nudgeDelta = NUDGE_KEYS[e.key];
|
|
1235
|
+
if (nudgeDelta) {
|
|
1236
|
+
const [dx, dy] = nudgeDelta;
|
|
1237
|
+
if (this.actions.nudge(dx, dy, e.shiftKey)) {
|
|
1238
|
+
e.preventDefault();
|
|
1239
|
+
}
|
|
985
1240
|
}
|
|
986
1241
|
};
|
|
987
1242
|
onKeyUp = (e) => {
|
|
@@ -1045,6 +1300,7 @@ var InputHandler = class {
|
|
|
1045
1300
|
}
|
|
1046
1301
|
dispatchToolDown(e) {
|
|
1047
1302
|
if (!this.toolManager || !this.toolContext) return;
|
|
1303
|
+
this.actions.flushPendingNudge();
|
|
1048
1304
|
this.historyRecorder?.begin();
|
|
1049
1305
|
this.isToolActive = true;
|
|
1050
1306
|
this.toolManager.handlePointerDown(this.toPointerState(e), this.toolContext);
|
|
@@ -1065,127 +1321,6 @@ var InputHandler = class {
|
|
|
1065
1321
|
this.toolManager.handlePointerUp(this.toPointerState(e), this.toolContext);
|
|
1066
1322
|
this.historyRecorder?.commit();
|
|
1067
1323
|
}
|
|
1068
|
-
deleteSelected() {
|
|
1069
|
-
if (!this.toolManager || !this.toolContext) return;
|
|
1070
|
-
const tool = this.toolManager.activeTool;
|
|
1071
|
-
if (tool?.name !== "select") return;
|
|
1072
|
-
const selectTool = tool;
|
|
1073
|
-
const ids = selectTool.selectedIds;
|
|
1074
|
-
if (ids.length === 0) return;
|
|
1075
|
-
this.historyRecorder?.begin();
|
|
1076
|
-
for (const id of ids) {
|
|
1077
|
-
this.toolContext.store.remove(id);
|
|
1078
|
-
}
|
|
1079
|
-
this.historyRecorder?.commit();
|
|
1080
|
-
this.toolContext.requestRender();
|
|
1081
|
-
}
|
|
1082
|
-
handleUndo() {
|
|
1083
|
-
if (!this.historyStack || !this.toolContext) return;
|
|
1084
|
-
this.historyRecorder?.pause();
|
|
1085
|
-
this.historyStack.undo(this.toolContext.store);
|
|
1086
|
-
this.historyRecorder?.resume();
|
|
1087
|
-
this.toolContext.requestRender();
|
|
1088
|
-
}
|
|
1089
|
-
handleRedo() {
|
|
1090
|
-
if (!this.historyStack || !this.toolContext) return;
|
|
1091
|
-
this.historyRecorder?.pause();
|
|
1092
|
-
this.historyStack.redo(this.toolContext.store);
|
|
1093
|
-
this.historyRecorder?.resume();
|
|
1094
|
-
this.toolContext.requestRender();
|
|
1095
|
-
}
|
|
1096
|
-
handleCopy() {
|
|
1097
|
-
if (!this.toolManager || !this.toolContext || this.isToolActive) return;
|
|
1098
|
-
const tool = this.toolManager.activeTool;
|
|
1099
|
-
if (tool?.name !== "select") return;
|
|
1100
|
-
const selectTool = tool;
|
|
1101
|
-
const ids = selectTool.selectedIds;
|
|
1102
|
-
if (ids.length === 0) return;
|
|
1103
|
-
this.clipboard = [];
|
|
1104
|
-
for (const id of ids) {
|
|
1105
|
-
const el = this.toolContext.store.getById(id);
|
|
1106
|
-
if (el) this.clipboard.push(structuredClone(el));
|
|
1107
|
-
}
|
|
1108
|
-
this.pasteCount = 0;
|
|
1109
|
-
}
|
|
1110
|
-
handlePaste() {
|
|
1111
|
-
if (!this.toolManager || !this.toolContext || this.clipboard.length === 0 || this.isToolActive)
|
|
1112
|
-
return;
|
|
1113
|
-
const tool = this.toolManager.activeTool;
|
|
1114
|
-
if (tool?.name !== "select") return;
|
|
1115
|
-
const selectTool = tool;
|
|
1116
|
-
this.pasteCount++;
|
|
1117
|
-
const offset = this.pasteCount * 20;
|
|
1118
|
-
const idMap = /* @__PURE__ */ new Map();
|
|
1119
|
-
for (const el of this.clipboard) {
|
|
1120
|
-
idMap.set(el.id, createId(el.type));
|
|
1121
|
-
}
|
|
1122
|
-
const newIds = [];
|
|
1123
|
-
this.historyRecorder?.begin();
|
|
1124
|
-
for (const el of this.clipboard) {
|
|
1125
|
-
const clone = structuredClone(el);
|
|
1126
|
-
const newId = idMap.get(el.id);
|
|
1127
|
-
if (!newId) continue;
|
|
1128
|
-
clone.id = newId;
|
|
1129
|
-
clone.position = { x: clone.position.x + offset, y: clone.position.y + offset };
|
|
1130
|
-
if (clone.type === "arrow") {
|
|
1131
|
-
const arrow = clone;
|
|
1132
|
-
arrow.from = { x: arrow.from.x + offset, y: arrow.from.y + offset };
|
|
1133
|
-
arrow.to = { x: arrow.to.x + offset, y: arrow.to.y + offset };
|
|
1134
|
-
delete arrow.cachedControlPoint;
|
|
1135
|
-
if (arrow.fromBinding) {
|
|
1136
|
-
const newTarget = idMap.get(arrow.fromBinding.elementId);
|
|
1137
|
-
if (newTarget) {
|
|
1138
|
-
arrow.fromBinding = { elementId: newTarget };
|
|
1139
|
-
} else {
|
|
1140
|
-
delete arrow.fromBinding;
|
|
1141
|
-
}
|
|
1142
|
-
}
|
|
1143
|
-
if (arrow.toBinding) {
|
|
1144
|
-
const newTarget = idMap.get(arrow.toBinding.elementId);
|
|
1145
|
-
if (newTarget) {
|
|
1146
|
-
arrow.toBinding = { elementId: newTarget };
|
|
1147
|
-
} else {
|
|
1148
|
-
delete arrow.toBinding;
|
|
1149
|
-
}
|
|
1150
|
-
}
|
|
1151
|
-
}
|
|
1152
|
-
if (this.toolContext.activeLayerId) {
|
|
1153
|
-
clone.layerId = this.toolContext.activeLayerId;
|
|
1154
|
-
}
|
|
1155
|
-
this.toolContext.store.add(clone);
|
|
1156
|
-
newIds.push(clone.id);
|
|
1157
|
-
}
|
|
1158
|
-
this.historyRecorder?.commit();
|
|
1159
|
-
selectTool.setSelection(newIds);
|
|
1160
|
-
this.toolContext.requestRender();
|
|
1161
|
-
}
|
|
1162
|
-
handleZOrder(operation) {
|
|
1163
|
-
if (!this.toolManager || !this.toolContext) return;
|
|
1164
|
-
const tool = this.toolManager.activeTool;
|
|
1165
|
-
if (tool?.name !== "select") return;
|
|
1166
|
-
const selectTool = tool;
|
|
1167
|
-
const ids = selectTool.selectedIds;
|
|
1168
|
-
if (ids.length === 0) return;
|
|
1169
|
-
this.historyRecorder?.begin();
|
|
1170
|
-
for (const id of ids) {
|
|
1171
|
-
switch (operation) {
|
|
1172
|
-
case "forward":
|
|
1173
|
-
this.toolContext.store.bringForward(id);
|
|
1174
|
-
break;
|
|
1175
|
-
case "backward":
|
|
1176
|
-
this.toolContext.store.sendBackward(id);
|
|
1177
|
-
break;
|
|
1178
|
-
case "front":
|
|
1179
|
-
this.toolContext.store.bringToFront(id);
|
|
1180
|
-
break;
|
|
1181
|
-
case "back":
|
|
1182
|
-
this.toolContext.store.sendToBack(id);
|
|
1183
|
-
break;
|
|
1184
|
-
}
|
|
1185
|
-
}
|
|
1186
|
-
this.historyRecorder?.commit();
|
|
1187
|
-
this.toolContext.requestRender();
|
|
1188
|
-
}
|
|
1189
1324
|
cancelToolIfActive(e) {
|
|
1190
1325
|
if (this.isToolActive) {
|
|
1191
1326
|
this.dispatchToolUp(e);
|
|
@@ -3138,6 +3273,26 @@ var NoteEditor = class {
|
|
|
3138
3273
|
}
|
|
3139
3274
|
};
|
|
3140
3275
|
|
|
3276
|
+
// src/elements/bounds.ts
|
|
3277
|
+
function getElementsBoundingBox(elements) {
|
|
3278
|
+
let minX = Infinity;
|
|
3279
|
+
let minY = Infinity;
|
|
3280
|
+
let maxX = -Infinity;
|
|
3281
|
+
let maxY = -Infinity;
|
|
3282
|
+
let found = false;
|
|
3283
|
+
for (const el of elements) {
|
|
3284
|
+
const b = getElementBounds(el);
|
|
3285
|
+
if (!b) continue;
|
|
3286
|
+
found = true;
|
|
3287
|
+
if (b.x < minX) minX = b.x;
|
|
3288
|
+
if (b.y < minY) minY = b.y;
|
|
3289
|
+
if (b.x + b.w > maxX) maxX = b.x + b.w;
|
|
3290
|
+
if (b.y + b.h > maxY) maxY = b.y + b.h;
|
|
3291
|
+
}
|
|
3292
|
+
if (!found) return null;
|
|
3293
|
+
return { x: minX, y: minY, w: maxX - minX, h: maxY - minY };
|
|
3294
|
+
}
|
|
3295
|
+
|
|
3141
3296
|
// src/tools/tool-manager.ts
|
|
3142
3297
|
var ToolManager = class {
|
|
3143
3298
|
tools = /* @__PURE__ */ new Map();
|
|
@@ -3293,16 +3448,64 @@ var BatchCommand = class {
|
|
|
3293
3448
|
}
|
|
3294
3449
|
};
|
|
3295
3450
|
|
|
3451
|
+
// src/history/layer-commands.ts
|
|
3452
|
+
var CreateLayerCommand = class {
|
|
3453
|
+
constructor(manager, layer) {
|
|
3454
|
+
this.manager = manager;
|
|
3455
|
+
this.layer = layer;
|
|
3456
|
+
}
|
|
3457
|
+
execute(_store) {
|
|
3458
|
+
this.manager.addLayerDirect(this.layer);
|
|
3459
|
+
}
|
|
3460
|
+
undo(_store) {
|
|
3461
|
+
this.manager.removeLayerDirect(this.layer.id);
|
|
3462
|
+
}
|
|
3463
|
+
};
|
|
3464
|
+
var RemoveLayerCommand = class {
|
|
3465
|
+
constructor(manager, layer) {
|
|
3466
|
+
this.manager = manager;
|
|
3467
|
+
this.layer = layer;
|
|
3468
|
+
}
|
|
3469
|
+
execute(_store) {
|
|
3470
|
+
this.manager.removeLayerDirect(this.layer.id);
|
|
3471
|
+
}
|
|
3472
|
+
undo(_store) {
|
|
3473
|
+
this.manager.addLayerDirect(this.layer);
|
|
3474
|
+
}
|
|
3475
|
+
};
|
|
3476
|
+
var UpdateLayerCommand = class {
|
|
3477
|
+
constructor(manager, layerId, previous, current) {
|
|
3478
|
+
this.manager = manager;
|
|
3479
|
+
this.layerId = layerId;
|
|
3480
|
+
this.previous = previous;
|
|
3481
|
+
this.current = current;
|
|
3482
|
+
}
|
|
3483
|
+
execute(_store) {
|
|
3484
|
+
this.manager.updateLayerDirect(this.layerId, { ...this.current });
|
|
3485
|
+
}
|
|
3486
|
+
undo(_store) {
|
|
3487
|
+
this.manager.updateLayerDirect(this.layerId, { ...this.previous });
|
|
3488
|
+
}
|
|
3489
|
+
};
|
|
3490
|
+
|
|
3296
3491
|
// src/history/history-recorder.ts
|
|
3297
3492
|
var HistoryRecorder = class {
|
|
3298
|
-
constructor(store, stack) {
|
|
3493
|
+
constructor(store, stack, layerManager) {
|
|
3299
3494
|
this.store = store;
|
|
3300
3495
|
this.stack = stack;
|
|
3496
|
+
this.layerManager = layerManager;
|
|
3301
3497
|
this.unsubscribers = [
|
|
3302
3498
|
store.on("add", (el) => this.onAdd(el)),
|
|
3303
3499
|
store.on("remove", (el) => this.onRemove(el)),
|
|
3304
3500
|
store.on("update", ({ previous, current }) => this.onUpdate(previous, current))
|
|
3305
3501
|
];
|
|
3502
|
+
if (layerManager) {
|
|
3503
|
+
this.unsubscribers.push(
|
|
3504
|
+
layerManager.on("create", (layer) => this.onLayerCreate(layer)),
|
|
3505
|
+
layerManager.on("remove", (layer) => this.onLayerRemove(layer)),
|
|
3506
|
+
layerManager.on("update", ({ previous, current }) => this.onLayerUpdate(previous, current))
|
|
3507
|
+
);
|
|
3508
|
+
}
|
|
3306
3509
|
}
|
|
3307
3510
|
recording = true;
|
|
3308
3511
|
transaction = null;
|
|
@@ -3315,6 +3518,9 @@ var HistoryRecorder = class {
|
|
|
3315
3518
|
this.recording = true;
|
|
3316
3519
|
}
|
|
3317
3520
|
begin() {
|
|
3521
|
+
if (this.transaction !== null) {
|
|
3522
|
+
this.commit();
|
|
3523
|
+
}
|
|
3318
3524
|
this.transaction = [];
|
|
3319
3525
|
this.updateSnapshots.clear();
|
|
3320
3526
|
}
|
|
@@ -3363,6 +3569,21 @@ var HistoryRecorder = class {
|
|
|
3363
3569
|
this.stack.push(new UpdateElementCommand(current.id, previous, current));
|
|
3364
3570
|
}
|
|
3365
3571
|
}
|
|
3572
|
+
onLayerCreate(layer) {
|
|
3573
|
+
if (!this.recording) return;
|
|
3574
|
+
if (!this.layerManager) return;
|
|
3575
|
+
this.record(new CreateLayerCommand(this.layerManager, layer));
|
|
3576
|
+
}
|
|
3577
|
+
onLayerRemove(layer) {
|
|
3578
|
+
if (!this.recording) return;
|
|
3579
|
+
if (!this.layerManager) return;
|
|
3580
|
+
this.record(new RemoveLayerCommand(this.layerManager, layer));
|
|
3581
|
+
}
|
|
3582
|
+
onLayerUpdate(previous, current) {
|
|
3583
|
+
if (!this.recording) return;
|
|
3584
|
+
if (!this.layerManager) return;
|
|
3585
|
+
this.record(new UpdateLayerCommand(this.layerManager, current.id, previous, current));
|
|
3586
|
+
}
|
|
3366
3587
|
flushUpdateSnapshots() {
|
|
3367
3588
|
const commands = [];
|
|
3368
3589
|
for (const [id, previous] of this.updateSnapshots) {
|
|
@@ -3795,18 +4016,23 @@ var LayerManager = class {
|
|
|
3795
4016
|
addLayerDirect(layer) {
|
|
3796
4017
|
this.layers.set(layer.id, { ...layer });
|
|
3797
4018
|
this.syncLayerOrder();
|
|
4019
|
+
this.bus.emit("create", { ...layer });
|
|
3798
4020
|
this.bus.emit("change", null);
|
|
3799
4021
|
}
|
|
3800
4022
|
removeLayerDirect(id) {
|
|
4023
|
+
const layer = this.layers.get(id);
|
|
3801
4024
|
this.layers.delete(id);
|
|
3802
4025
|
this.syncLayerOrder();
|
|
4026
|
+
if (layer) this.bus.emit("remove", { ...layer });
|
|
3803
4027
|
this.bus.emit("change", null);
|
|
3804
4028
|
}
|
|
3805
4029
|
updateLayerDirect(id, props) {
|
|
3806
4030
|
const layer = this.layers.get(id);
|
|
3807
4031
|
if (!layer) return;
|
|
4032
|
+
const previous = { ...layer };
|
|
3808
4033
|
Object.assign(layer, props);
|
|
3809
4034
|
if ("order" in props) this.syncLayerOrder();
|
|
4035
|
+
this.bus.emit("update", { previous, current: { ...layer } });
|
|
3810
4036
|
this.bus.emit("change", null);
|
|
3811
4037
|
}
|
|
3812
4038
|
syncLayerOrder() {
|
|
@@ -3899,6 +4125,20 @@ var DomNodeManager = class {
|
|
|
3899
4125
|
storeHtmlContent(elementId, dom) {
|
|
3900
4126
|
this.htmlContent.set(elementId, dom);
|
|
3901
4127
|
}
|
|
4128
|
+
hasContent(elementId) {
|
|
4129
|
+
return this.htmlContent.has(elementId);
|
|
4130
|
+
}
|
|
4131
|
+
resetHtmlContent(elementId) {
|
|
4132
|
+
this.htmlContent.delete(elementId);
|
|
4133
|
+
this.lastSyncedVersion.delete(elementId);
|
|
4134
|
+
this.lastSyncedZIndex.delete(elementId);
|
|
4135
|
+
const node = this.domNodes.get(elementId);
|
|
4136
|
+
if (!node) return;
|
|
4137
|
+
while (node.firstChild) {
|
|
4138
|
+
node.removeChild(node.firstChild);
|
|
4139
|
+
}
|
|
4140
|
+
delete node.dataset["initialized"];
|
|
4141
|
+
}
|
|
3902
4142
|
syncDomNode(element, zIndex = 0) {
|
|
3903
4143
|
let node = this.domNodes.get(element.id);
|
|
3904
4144
|
if (!node) {
|
|
@@ -4440,8 +4680,10 @@ var Viewport = class {
|
|
|
4440
4680
|
toolbar: options.toolbar
|
|
4441
4681
|
});
|
|
4442
4682
|
this.noteEditor.setOnStop((id) => this.onTextEditStop(id));
|
|
4683
|
+
this.onHtmlElementMount = options.onHtmlElementMount;
|
|
4684
|
+
this.dropHandler = options.onDrop;
|
|
4443
4685
|
this.history = new HistoryStack();
|
|
4444
|
-
this.historyRecorder = new HistoryRecorder(this.store, this.history);
|
|
4686
|
+
this.historyRecorder = new HistoryRecorder(this.store, this.history, this.layerManager);
|
|
4445
4687
|
this.wrapper = this.createWrapper();
|
|
4446
4688
|
this.canvasEl = this.createCanvas();
|
|
4447
4689
|
this.domLayer = this.createDomLayer();
|
|
@@ -4467,7 +4709,8 @@ var Viewport = class {
|
|
|
4467
4709
|
toolManager: this.toolManager,
|
|
4468
4710
|
toolContext: this.toolContext,
|
|
4469
4711
|
historyRecorder: this.historyRecorder,
|
|
4470
|
-
historyStack: this.history
|
|
4712
|
+
historyStack: this.history,
|
|
4713
|
+
fitToContent: () => this.fitToContent()
|
|
4471
4714
|
});
|
|
4472
4715
|
this.domNodeManager = new DomNodeManager({
|
|
4473
4716
|
domLayer: this.domLayer,
|
|
@@ -4561,6 +4804,8 @@ var Viewport = class {
|
|
|
4561
4804
|
renderLoop;
|
|
4562
4805
|
domNodeManager;
|
|
4563
4806
|
interactMode;
|
|
4807
|
+
onHtmlElementMount;
|
|
4808
|
+
dropHandler;
|
|
4564
4809
|
gridChangeListeners = /* @__PURE__ */ new Set();
|
|
4565
4810
|
doubleTapDetector = new DoubleTapDetector();
|
|
4566
4811
|
tapDownX = 0;
|
|
@@ -4575,6 +4820,13 @@ var Viewport = class {
|
|
|
4575
4820
|
this._snapToGrid = enabled;
|
|
4576
4821
|
this.toolContext.snapToGrid = enabled;
|
|
4577
4822
|
}
|
|
4823
|
+
fitToContent(padding = 40) {
|
|
4824
|
+
if (this.wrapper.clientWidth === 0 || this.wrapper.clientHeight === 0) return;
|
|
4825
|
+
const visibleElements = this.store.getAll().filter((el) => this.layerManager.isLayerVisible(el.layerId));
|
|
4826
|
+
const bbox = getElementsBoundingBox(visibleElements);
|
|
4827
|
+
if (!bbox) return;
|
|
4828
|
+
this.camera.fitToContent(bbox, this.wrapper.clientWidth, this.wrapper.clientHeight, padding);
|
|
4829
|
+
}
|
|
4578
4830
|
requestRender() {
|
|
4579
4831
|
this.renderLoop.requestRender();
|
|
4580
4832
|
}
|
|
@@ -4593,6 +4845,7 @@ var Viewport = class {
|
|
|
4593
4845
|
return exportImage(this.store, options, this.layerManager);
|
|
4594
4846
|
}
|
|
4595
4847
|
loadState(state) {
|
|
4848
|
+
this.inputHandler.flushPendingHistory();
|
|
4596
4849
|
this.historyRecorder.pause();
|
|
4597
4850
|
this.noteEditor.destroy(this.store);
|
|
4598
4851
|
this.domNodeManager.clearDomNodes();
|
|
@@ -4604,6 +4857,22 @@ var Viewport = class {
|
|
|
4604
4857
|
this.layerManager.setActiveLayer(state.activeLayerId);
|
|
4605
4858
|
}
|
|
4606
4859
|
this.domNodeManager.reattachHtmlContent(this.store);
|
|
4860
|
+
if (this.onHtmlElementMount) {
|
|
4861
|
+
for (const el of this.store.getElementsByType("html")) {
|
|
4862
|
+
if (!this.domNodeManager.hasContent(el.id)) {
|
|
4863
|
+
this.domNodeManager.syncDomNode(el);
|
|
4864
|
+
const node = this.domNodeManager.getNode(el.id);
|
|
4865
|
+
if (node) {
|
|
4866
|
+
this.onHtmlElementMount(el.id, el.domId, node);
|
|
4867
|
+
node.dataset["initialized"] = "true";
|
|
4868
|
+
Object.assign(node.style, {
|
|
4869
|
+
overflow: "hidden",
|
|
4870
|
+
pointerEvents: el.interactive ? "auto" : "none"
|
|
4871
|
+
});
|
|
4872
|
+
}
|
|
4873
|
+
}
|
|
4874
|
+
}
|
|
4875
|
+
}
|
|
4607
4876
|
this.history.clear();
|
|
4608
4877
|
this.historyRecorder.resume();
|
|
4609
4878
|
this.camera.moveTo(state.camera.position.x, state.camera.position.y);
|
|
@@ -4613,6 +4882,7 @@ var Viewport = class {
|
|
|
4613
4882
|
this.loadState(parseState(json));
|
|
4614
4883
|
}
|
|
4615
4884
|
undo() {
|
|
4885
|
+
this.inputHandler.flushPendingHistory();
|
|
4616
4886
|
this.historyRecorder.pause();
|
|
4617
4887
|
const result = this.history.undo(this.store);
|
|
4618
4888
|
this.historyRecorder.resume();
|
|
@@ -4620,6 +4890,7 @@ var Viewport = class {
|
|
|
4620
4890
|
return result;
|
|
4621
4891
|
}
|
|
4622
4892
|
redo() {
|
|
4893
|
+
this.inputHandler.flushPendingHistory();
|
|
4623
4894
|
this.historyRecorder.pause();
|
|
4624
4895
|
const result = this.history.redo(this.store);
|
|
4625
4896
|
this.historyRecorder.resume();
|
|
@@ -4649,6 +4920,19 @@ var Viewport = class {
|
|
|
4649
4920
|
this.requestRender();
|
|
4650
4921
|
return el.id;
|
|
4651
4922
|
}
|
|
4923
|
+
removeLayer(id) {
|
|
4924
|
+
this.historyRecorder.begin();
|
|
4925
|
+
this.layerManager.removeLayer(id);
|
|
4926
|
+
this.historyRecorder.commit();
|
|
4927
|
+
}
|
|
4928
|
+
updateHtmlElement(id, newContent) {
|
|
4929
|
+
const el = this.store.getById(id);
|
|
4930
|
+
if (!el) throw new Error(`Element not found: ${id}`);
|
|
4931
|
+
if (el.type !== "html") throw new Error(`Element ${id} is not an HTML element`);
|
|
4932
|
+
this.domNodeManager.resetHtmlContent(id);
|
|
4933
|
+
this.domNodeManager.storeHtmlContent(id, newContent);
|
|
4934
|
+
this.requestRender();
|
|
4935
|
+
}
|
|
4652
4936
|
addGrid(input) {
|
|
4653
4937
|
const existing = this.store.getElementsByType("grid")[0];
|
|
4654
4938
|
this.historyRecorder.begin();
|
|
@@ -4800,17 +5084,21 @@ var Viewport = class {
|
|
|
4800
5084
|
};
|
|
4801
5085
|
onDrop = (e) => {
|
|
4802
5086
|
e.preventDefault();
|
|
5087
|
+
const rect = this.wrapper.getBoundingClientRect();
|
|
5088
|
+
const screenPos = { x: e.clientX - rect.left, y: e.clientY - rect.top };
|
|
5089
|
+
const worldPos = this.camera.screenToWorld(screenPos);
|
|
5090
|
+
if (this.dropHandler) {
|
|
5091
|
+
this.dropHandler(e, worldPos);
|
|
5092
|
+
return;
|
|
5093
|
+
}
|
|
4803
5094
|
const files = e.dataTransfer?.files;
|
|
4804
5095
|
if (!files) return;
|
|
4805
|
-
const rect = this.wrapper.getBoundingClientRect();
|
|
4806
5096
|
for (const file of files) {
|
|
4807
5097
|
if (!file.type.startsWith("image/")) continue;
|
|
4808
5098
|
const reader = new FileReader();
|
|
4809
5099
|
reader.onload = () => {
|
|
4810
5100
|
const src = reader.result;
|
|
4811
5101
|
if (typeof src !== "string") return;
|
|
4812
|
-
const screenPos = { x: e.clientX - rect.left, y: e.clientY - rect.top };
|
|
4813
|
-
const worldPos = this.camera.screenToWorld(screenPos);
|
|
4814
5102
|
this.addImage(src, worldPos);
|
|
4815
5103
|
};
|
|
4816
5104
|
reader.readAsDataURL(file);
|
|
@@ -4922,26 +5210,6 @@ var Viewport = class {
|
|
|
4922
5210
|
}
|
|
4923
5211
|
};
|
|
4924
5212
|
|
|
4925
|
-
// src/elements/bounds.ts
|
|
4926
|
-
function getElementsBoundingBox(elements) {
|
|
4927
|
-
let minX = Infinity;
|
|
4928
|
-
let minY = Infinity;
|
|
4929
|
-
let maxX = -Infinity;
|
|
4930
|
-
let maxY = -Infinity;
|
|
4931
|
-
let found = false;
|
|
4932
|
-
for (const el of elements) {
|
|
4933
|
-
const b = getElementBounds(el);
|
|
4934
|
-
if (!b) continue;
|
|
4935
|
-
found = true;
|
|
4936
|
-
if (b.x < minX) minX = b.x;
|
|
4937
|
-
if (b.y < minY) minY = b.y;
|
|
4938
|
-
if (b.x + b.w > maxX) maxX = b.x + b.w;
|
|
4939
|
-
if (b.y + b.h > maxY) maxY = b.y + b.h;
|
|
4940
|
-
}
|
|
4941
|
-
if (!found) return null;
|
|
4942
|
-
return { x: minX, y: minY, w: maxX - minX, h: maxY - minY };
|
|
4943
|
-
}
|
|
4944
|
-
|
|
4945
5213
|
// src/tools/hand-tool.ts
|
|
4946
5214
|
var HandTool = class {
|
|
4947
5215
|
name = "hand";
|
|
@@ -5433,23 +5701,7 @@ var SelectTool = class {
|
|
|
5433
5701
|
});
|
|
5434
5702
|
}
|
|
5435
5703
|
}
|
|
5436
|
-
|
|
5437
|
-
for (const id of this._selectedIds) {
|
|
5438
|
-
const el = ctx.store.getById(id);
|
|
5439
|
-
if (el && el.type !== "arrow") movedNonArrowIds.add(id);
|
|
5440
|
-
}
|
|
5441
|
-
if (movedNonArrowIds.size > 0) {
|
|
5442
|
-
const updatedArrows = /* @__PURE__ */ new Set();
|
|
5443
|
-
for (const id of movedNonArrowIds) {
|
|
5444
|
-
const boundArrows = findBoundArrows(id, ctx.store);
|
|
5445
|
-
for (const ba of boundArrows) {
|
|
5446
|
-
if (updatedArrows.has(ba.id)) continue;
|
|
5447
|
-
updatedArrows.add(ba.id);
|
|
5448
|
-
const updates = updateBoundArrow(ba, ctx.store);
|
|
5449
|
-
if (updates) ctx.store.update(ba.id, updates);
|
|
5450
|
-
}
|
|
5451
|
-
}
|
|
5452
|
-
}
|
|
5704
|
+
this.updateArrowsBoundTo(this._selectedIds, ctx);
|
|
5453
5705
|
ctx.requestRender();
|
|
5454
5706
|
return;
|
|
5455
5707
|
}
|
|
@@ -5500,6 +5752,49 @@ var SelectTool = class {
|
|
|
5500
5752
|
}
|
|
5501
5753
|
}
|
|
5502
5754
|
}
|
|
5755
|
+
updateArrowsBoundTo(ids, ctx) {
|
|
5756
|
+
const movedNonArrowIds = /* @__PURE__ */ new Set();
|
|
5757
|
+
for (const id of ids) {
|
|
5758
|
+
const el = ctx.store.getById(id);
|
|
5759
|
+
if (el && el.type !== "arrow") movedNonArrowIds.add(id);
|
|
5760
|
+
}
|
|
5761
|
+
if (movedNonArrowIds.size === 0) return;
|
|
5762
|
+
const updatedArrows = /* @__PURE__ */ new Set();
|
|
5763
|
+
for (const id of movedNonArrowIds) {
|
|
5764
|
+
const boundArrows = findBoundArrows(id, ctx.store);
|
|
5765
|
+
for (const ba of boundArrows) {
|
|
5766
|
+
if (updatedArrows.has(ba.id)) continue;
|
|
5767
|
+
updatedArrows.add(ba.id);
|
|
5768
|
+
const updates = updateBoundArrow(ba, ctx.store);
|
|
5769
|
+
if (updates) ctx.store.update(ba.id, updates);
|
|
5770
|
+
}
|
|
5771
|
+
}
|
|
5772
|
+
}
|
|
5773
|
+
nudgeSelection(dx, dy, ctx) {
|
|
5774
|
+
let moved = false;
|
|
5775
|
+
for (const id of this._selectedIds) {
|
|
5776
|
+
const el = ctx.store.getById(id);
|
|
5777
|
+
if (!el || el.locked) continue;
|
|
5778
|
+
if (el.type === "arrow") {
|
|
5779
|
+
if (el.fromBinding || el.toBinding) continue;
|
|
5780
|
+
ctx.store.update(id, {
|
|
5781
|
+
position: { x: el.position.x + dx, y: el.position.y + dy },
|
|
5782
|
+
from: { x: el.from.x + dx, y: el.from.y + dy },
|
|
5783
|
+
to: { x: el.to.x + dx, y: el.to.y + dy }
|
|
5784
|
+
});
|
|
5785
|
+
} else {
|
|
5786
|
+
ctx.store.update(id, {
|
|
5787
|
+
position: { x: el.position.x + dx, y: el.position.y + dy }
|
|
5788
|
+
});
|
|
5789
|
+
}
|
|
5790
|
+
moved = true;
|
|
5791
|
+
}
|
|
5792
|
+
if (moved) {
|
|
5793
|
+
this.updateArrowsBoundTo(this._selectedIds, ctx);
|
|
5794
|
+
ctx.requestRender();
|
|
5795
|
+
}
|
|
5796
|
+
return moved;
|
|
5797
|
+
}
|
|
5503
5798
|
updateHoverCursor(world, ctx) {
|
|
5504
5799
|
const arrowHit = hitTestArrowHandles(world, this._selectedIds, ctx);
|
|
5505
5800
|
if (arrowHit) {
|
|
@@ -5577,11 +5872,7 @@ var SelectTool = class {
|
|
|
5577
5872
|
position: { x, y },
|
|
5578
5873
|
size: { w, h }
|
|
5579
5874
|
});
|
|
5580
|
-
|
|
5581
|
-
for (const ba of boundArrows) {
|
|
5582
|
-
const updates = updateBoundArrow(ba, ctx.store);
|
|
5583
|
-
if (updates) ctx.store.update(ba.id, updates);
|
|
5584
|
-
}
|
|
5875
|
+
this.updateArrowsBoundTo([this.mode.elementId], ctx);
|
|
5585
5876
|
ctx.requestRender();
|
|
5586
5877
|
}
|
|
5587
5878
|
hitTestResizeHandle(world, ctx) {
|
|
@@ -6627,48 +6918,8 @@ var TemplateTool = class {
|
|
|
6627
6918
|
}
|
|
6628
6919
|
};
|
|
6629
6920
|
|
|
6630
|
-
// src/history/layer-commands.ts
|
|
6631
|
-
var CreateLayerCommand = class {
|
|
6632
|
-
constructor(manager, layer) {
|
|
6633
|
-
this.manager = manager;
|
|
6634
|
-
this.layer = layer;
|
|
6635
|
-
}
|
|
6636
|
-
execute(_store) {
|
|
6637
|
-
this.manager.addLayerDirect(this.layer);
|
|
6638
|
-
}
|
|
6639
|
-
undo(_store) {
|
|
6640
|
-
this.manager.removeLayerDirect(this.layer.id);
|
|
6641
|
-
}
|
|
6642
|
-
};
|
|
6643
|
-
var RemoveLayerCommand = class {
|
|
6644
|
-
constructor(manager, layer) {
|
|
6645
|
-
this.manager = manager;
|
|
6646
|
-
this.layer = layer;
|
|
6647
|
-
}
|
|
6648
|
-
execute(_store) {
|
|
6649
|
-
this.manager.removeLayerDirect(this.layer.id);
|
|
6650
|
-
}
|
|
6651
|
-
undo(_store) {
|
|
6652
|
-
this.manager.addLayerDirect(this.layer);
|
|
6653
|
-
}
|
|
6654
|
-
};
|
|
6655
|
-
var UpdateLayerCommand = class {
|
|
6656
|
-
constructor(manager, layerId, previous, current) {
|
|
6657
|
-
this.manager = manager;
|
|
6658
|
-
this.layerId = layerId;
|
|
6659
|
-
this.previous = previous;
|
|
6660
|
-
this.current = current;
|
|
6661
|
-
}
|
|
6662
|
-
execute(_store) {
|
|
6663
|
-
this.manager.updateLayerDirect(this.layerId, { ...this.current });
|
|
6664
|
-
}
|
|
6665
|
-
undo(_store) {
|
|
6666
|
-
this.manager.updateLayerDirect(this.layerId, { ...this.previous });
|
|
6667
|
-
}
|
|
6668
|
-
};
|
|
6669
|
-
|
|
6670
6921
|
// src/index.ts
|
|
6671
|
-
var VERSION = "0.
|
|
6922
|
+
var VERSION = "0.17.0";
|
|
6672
6923
|
export {
|
|
6673
6924
|
AddElementCommand,
|
|
6674
6925
|
ArrowTool,
|