@fieldnotes/core 0.11.3 → 0.12.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 +114 -11
- package/dist/index.d.cts +9 -1
- package/dist/index.d.ts +9 -1
- package/dist/index.js +114 -11
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -898,6 +898,12 @@ var InputFilter = class _InputFilter {
|
|
|
898
898
|
}
|
|
899
899
|
};
|
|
900
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
|
+
|
|
901
907
|
// src/canvas/input-handler.ts
|
|
902
908
|
var ZOOM_SENSITIVITY = 1e-3;
|
|
903
909
|
var MIDDLE_BUTTON = 1;
|
|
@@ -927,6 +933,8 @@ var InputHandler = class {
|
|
|
927
933
|
inputFilter = new InputFilter();
|
|
928
934
|
deferredDown = null;
|
|
929
935
|
abortController = new AbortController();
|
|
936
|
+
clipboard = [];
|
|
937
|
+
pasteCount = 0;
|
|
930
938
|
setToolManager(toolManager, toolContext) {
|
|
931
939
|
this.toolManager = toolManager;
|
|
932
940
|
this.toolContext = toolContext;
|
|
@@ -1050,6 +1058,14 @@ var InputHandler = class {
|
|
|
1050
1058
|
e.preventDefault();
|
|
1051
1059
|
this.handleRedo();
|
|
1052
1060
|
}
|
|
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
|
+
}
|
|
1053
1069
|
};
|
|
1054
1070
|
onKeyUp = (e) => {
|
|
1055
1071
|
if (e.key === " ") {
|
|
@@ -1106,7 +1122,8 @@ var InputHandler = class {
|
|
|
1106
1122
|
x: e.clientX - rect.left,
|
|
1107
1123
|
y: e.clientY - rect.top,
|
|
1108
1124
|
pressure: e.pressure,
|
|
1109
|
-
pointerType: e.pointerType === "touch" || e.pointerType === "pen" ? e.pointerType : "mouse"
|
|
1125
|
+
pointerType: e.pointerType === "touch" || e.pointerType === "pen" ? e.pointerType : "mouse",
|
|
1126
|
+
shiftKey: e.shiftKey
|
|
1110
1127
|
};
|
|
1111
1128
|
}
|
|
1112
1129
|
dispatchToolDown(e) {
|
|
@@ -1159,6 +1176,72 @@ var InputHandler = class {
|
|
|
1159
1176
|
this.historyRecorder?.resume();
|
|
1160
1177
|
this.toolContext.requestRender();
|
|
1161
1178
|
}
|
|
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
|
+
}
|
|
1162
1245
|
cancelToolIfActive(e) {
|
|
1163
1246
|
if (this.isToolActive) {
|
|
1164
1247
|
this.dispatchToolUp(e);
|
|
@@ -2543,12 +2626,6 @@ var ElementRenderer = class {
|
|
|
2543
2626
|
}
|
|
2544
2627
|
};
|
|
2545
2628
|
|
|
2546
|
-
// src/elements/create-id.ts
|
|
2547
|
-
var counter = 0;
|
|
2548
|
-
function createId(prefix) {
|
|
2549
|
-
return `${prefix}_${Date.now().toString(36)}_${(counter++).toString(36)}`;
|
|
2550
|
-
}
|
|
2551
|
-
|
|
2552
2629
|
// src/elements/element-factory.ts
|
|
2553
2630
|
var DEFAULT_NOTE_FONT_SIZE = 18;
|
|
2554
2631
|
function createStroke(input) {
|
|
@@ -5099,9 +5176,15 @@ var SelectTool = class {
|
|
|
5099
5176
|
lastWorld = { x: 0, y: 0 };
|
|
5100
5177
|
currentWorld = { x: 0, y: 0 };
|
|
5101
5178
|
ctx = null;
|
|
5179
|
+
pendingSingleSelectId = null;
|
|
5180
|
+
hasDragged = false;
|
|
5102
5181
|
get selectedIds() {
|
|
5103
5182
|
return [...this._selectedIds];
|
|
5104
5183
|
}
|
|
5184
|
+
setSelection(ids) {
|
|
5185
|
+
this._selectedIds = ids;
|
|
5186
|
+
this.ctx?.requestRender();
|
|
5187
|
+
}
|
|
5105
5188
|
get isMarqueeActive() {
|
|
5106
5189
|
return this.mode.type === "marquee";
|
|
5107
5190
|
}
|
|
@@ -5150,13 +5233,27 @@ var SelectTool = class {
|
|
|
5150
5233
|
return;
|
|
5151
5234
|
}
|
|
5152
5235
|
}
|
|
5236
|
+
this.pendingSingleSelectId = null;
|
|
5237
|
+
this.hasDragged = false;
|
|
5153
5238
|
const hit = this.hitTest(world, ctx);
|
|
5154
5239
|
if (hit) {
|
|
5155
5240
|
const alreadySelected = this._selectedIds.includes(hit.id);
|
|
5156
|
-
if (
|
|
5157
|
-
|
|
5241
|
+
if (state.shiftKey) {
|
|
5242
|
+
if (alreadySelected) {
|
|
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" };
|
|
5158
5256
|
}
|
|
5159
|
-
this.mode = hit.locked ? { type: "idle" } : { type: "dragging" };
|
|
5160
5257
|
} else {
|
|
5161
5258
|
this._selectedIds = [];
|
|
5162
5259
|
this.mode = { type: "marquee", start: world };
|
|
@@ -5182,6 +5279,7 @@ var SelectTool = class {
|
|
|
5182
5279
|
return;
|
|
5183
5280
|
}
|
|
5184
5281
|
if (this.mode.type === "dragging" && this._selectedIds.length > 0) {
|
|
5282
|
+
this.hasDragged = true;
|
|
5185
5283
|
ctx.setCursor?.("move");
|
|
5186
5284
|
const snapped = this.snap(world, ctx);
|
|
5187
5285
|
const dx = snapped.x - this.lastWorld.x;
|
|
@@ -5250,6 +5348,11 @@ var SelectTool = class {
|
|
|
5250
5348
|
}
|
|
5251
5349
|
ctx.requestRender();
|
|
5252
5350
|
}
|
|
5351
|
+
if (!this.hasDragged && this.pendingSingleSelectId !== null) {
|
|
5352
|
+
this._selectedIds = [this.pendingSingleSelectId];
|
|
5353
|
+
}
|
|
5354
|
+
this.pendingSingleSelectId = null;
|
|
5355
|
+
this.hasDragged = false;
|
|
5253
5356
|
this.mode = { type: "idle" };
|
|
5254
5357
|
ctx.setCursor?.("default");
|
|
5255
5358
|
}
|
|
@@ -6430,7 +6533,7 @@ var UpdateLayerCommand = class {
|
|
|
6430
6533
|
};
|
|
6431
6534
|
|
|
6432
6535
|
// src/index.ts
|
|
6433
|
-
var VERSION = "0.
|
|
6536
|
+
var VERSION = "0.12.0";
|
|
6434
6537
|
// Annotate the CommonJS export names for ESM import in node:
|
|
6435
6538
|
0 && (module.exports = {
|
|
6436
6539
|
AddElementCommand,
|
package/dist/index.d.cts
CHANGED
|
@@ -240,6 +240,7 @@ interface PointerState {
|
|
|
240
240
|
y: number;
|
|
241
241
|
pressure: number;
|
|
242
242
|
pointerType: 'mouse' | 'touch' | 'pen';
|
|
243
|
+
shiftKey: boolean;
|
|
243
244
|
}
|
|
244
245
|
interface Tool {
|
|
245
246
|
readonly name: string;
|
|
@@ -429,6 +430,8 @@ declare class InputHandler {
|
|
|
429
430
|
private readonly inputFilter;
|
|
430
431
|
private deferredDown;
|
|
431
432
|
private readonly abortController;
|
|
433
|
+
private clipboard;
|
|
434
|
+
private pasteCount;
|
|
432
435
|
constructor(element: HTMLElement, camera: Camera, options?: InputHandlerOptions);
|
|
433
436
|
setToolManager(toolManager: ToolManager, toolContext: ToolContext): void;
|
|
434
437
|
destroy(): void;
|
|
@@ -452,6 +455,8 @@ declare class InputHandler {
|
|
|
452
455
|
private deleteSelected;
|
|
453
456
|
private handleUndo;
|
|
454
457
|
private handleRedo;
|
|
458
|
+
private handleCopy;
|
|
459
|
+
private handlePaste;
|
|
455
460
|
private cancelToolIfActive;
|
|
456
461
|
}
|
|
457
462
|
|
|
@@ -900,7 +905,10 @@ declare class SelectTool implements Tool {
|
|
|
900
905
|
private lastWorld;
|
|
901
906
|
private currentWorld;
|
|
902
907
|
private ctx;
|
|
908
|
+
private pendingSingleSelectId;
|
|
909
|
+
private hasDragged;
|
|
903
910
|
get selectedIds(): string[];
|
|
911
|
+
setSelection(ids: string[]): void;
|
|
904
912
|
get isMarqueeActive(): boolean;
|
|
905
913
|
onActivate(ctx: ToolContext): void;
|
|
906
914
|
onDeactivate(ctx: ToolContext): void;
|
|
@@ -1145,6 +1153,6 @@ declare class UpdateLayerCommand implements Command {
|
|
|
1145
1153
|
undo(_store: ElementStore): void;
|
|
1146
1154
|
}
|
|
1147
1155
|
|
|
1148
|
-
declare const VERSION = "0.
|
|
1156
|
+
declare const VERSION = "0.12.0";
|
|
1149
1157
|
|
|
1150
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 FilterAction, type FilteredEvent, type FilteredUpEvent, type FontSizePreset, type GridElement, type GridInfo, HandTool, type HexOrientation, HistoryRecorder, HistoryStack, type HistoryStackOptions, type HtmlElement, type ImageElement, ImageTool, type ImageToolOptions, InputFilter, 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
|
@@ -240,6 +240,7 @@ interface PointerState {
|
|
|
240
240
|
y: number;
|
|
241
241
|
pressure: number;
|
|
242
242
|
pointerType: 'mouse' | 'touch' | 'pen';
|
|
243
|
+
shiftKey: boolean;
|
|
243
244
|
}
|
|
244
245
|
interface Tool {
|
|
245
246
|
readonly name: string;
|
|
@@ -429,6 +430,8 @@ declare class InputHandler {
|
|
|
429
430
|
private readonly inputFilter;
|
|
430
431
|
private deferredDown;
|
|
431
432
|
private readonly abortController;
|
|
433
|
+
private clipboard;
|
|
434
|
+
private pasteCount;
|
|
432
435
|
constructor(element: HTMLElement, camera: Camera, options?: InputHandlerOptions);
|
|
433
436
|
setToolManager(toolManager: ToolManager, toolContext: ToolContext): void;
|
|
434
437
|
destroy(): void;
|
|
@@ -452,6 +455,8 @@ declare class InputHandler {
|
|
|
452
455
|
private deleteSelected;
|
|
453
456
|
private handleUndo;
|
|
454
457
|
private handleRedo;
|
|
458
|
+
private handleCopy;
|
|
459
|
+
private handlePaste;
|
|
455
460
|
private cancelToolIfActive;
|
|
456
461
|
}
|
|
457
462
|
|
|
@@ -900,7 +905,10 @@ declare class SelectTool implements Tool {
|
|
|
900
905
|
private lastWorld;
|
|
901
906
|
private currentWorld;
|
|
902
907
|
private ctx;
|
|
908
|
+
private pendingSingleSelectId;
|
|
909
|
+
private hasDragged;
|
|
903
910
|
get selectedIds(): string[];
|
|
911
|
+
setSelection(ids: string[]): void;
|
|
904
912
|
get isMarqueeActive(): boolean;
|
|
905
913
|
onActivate(ctx: ToolContext): void;
|
|
906
914
|
onDeactivate(ctx: ToolContext): void;
|
|
@@ -1145,6 +1153,6 @@ declare class UpdateLayerCommand implements Command {
|
|
|
1145
1153
|
undo(_store: ElementStore): void;
|
|
1146
1154
|
}
|
|
1147
1155
|
|
|
1148
|
-
declare const VERSION = "0.
|
|
1156
|
+
declare const VERSION = "0.12.0";
|
|
1149
1157
|
|
|
1150
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 FilterAction, type FilteredEvent, type FilteredUpEvent, type FontSizePreset, type GridElement, type GridInfo, HandTool, type HexOrientation, HistoryRecorder, HistoryStack, type HistoryStackOptions, type HtmlElement, type ImageElement, ImageTool, type ImageToolOptions, InputFilter, 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
|
@@ -791,6 +791,12 @@ var InputFilter = class _InputFilter {
|
|
|
791
791
|
}
|
|
792
792
|
};
|
|
793
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
|
+
|
|
794
800
|
// src/canvas/input-handler.ts
|
|
795
801
|
var ZOOM_SENSITIVITY = 1e-3;
|
|
796
802
|
var MIDDLE_BUTTON = 1;
|
|
@@ -820,6 +826,8 @@ var InputHandler = class {
|
|
|
820
826
|
inputFilter = new InputFilter();
|
|
821
827
|
deferredDown = null;
|
|
822
828
|
abortController = new AbortController();
|
|
829
|
+
clipboard = [];
|
|
830
|
+
pasteCount = 0;
|
|
823
831
|
setToolManager(toolManager, toolContext) {
|
|
824
832
|
this.toolManager = toolManager;
|
|
825
833
|
this.toolContext = toolContext;
|
|
@@ -943,6 +951,14 @@ var InputHandler = class {
|
|
|
943
951
|
e.preventDefault();
|
|
944
952
|
this.handleRedo();
|
|
945
953
|
}
|
|
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
|
+
}
|
|
946
962
|
};
|
|
947
963
|
onKeyUp = (e) => {
|
|
948
964
|
if (e.key === " ") {
|
|
@@ -999,7 +1015,8 @@ var InputHandler = class {
|
|
|
999
1015
|
x: e.clientX - rect.left,
|
|
1000
1016
|
y: e.clientY - rect.top,
|
|
1001
1017
|
pressure: e.pressure,
|
|
1002
|
-
pointerType: e.pointerType === "touch" || e.pointerType === "pen" ? e.pointerType : "mouse"
|
|
1018
|
+
pointerType: e.pointerType === "touch" || e.pointerType === "pen" ? e.pointerType : "mouse",
|
|
1019
|
+
shiftKey: e.shiftKey
|
|
1003
1020
|
};
|
|
1004
1021
|
}
|
|
1005
1022
|
dispatchToolDown(e) {
|
|
@@ -1052,6 +1069,72 @@ var InputHandler = class {
|
|
|
1052
1069
|
this.historyRecorder?.resume();
|
|
1053
1070
|
this.toolContext.requestRender();
|
|
1054
1071
|
}
|
|
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
|
+
}
|
|
1055
1138
|
cancelToolIfActive(e) {
|
|
1056
1139
|
if (this.isToolActive) {
|
|
1057
1140
|
this.dispatchToolUp(e);
|
|
@@ -2436,12 +2519,6 @@ var ElementRenderer = class {
|
|
|
2436
2519
|
}
|
|
2437
2520
|
};
|
|
2438
2521
|
|
|
2439
|
-
// src/elements/create-id.ts
|
|
2440
|
-
var counter = 0;
|
|
2441
|
-
function createId(prefix) {
|
|
2442
|
-
return `${prefix}_${Date.now().toString(36)}_${(counter++).toString(36)}`;
|
|
2443
|
-
}
|
|
2444
|
-
|
|
2445
2522
|
// src/elements/element-factory.ts
|
|
2446
2523
|
var DEFAULT_NOTE_FONT_SIZE = 18;
|
|
2447
2524
|
function createStroke(input) {
|
|
@@ -4992,9 +5069,15 @@ var SelectTool = class {
|
|
|
4992
5069
|
lastWorld = { x: 0, y: 0 };
|
|
4993
5070
|
currentWorld = { x: 0, y: 0 };
|
|
4994
5071
|
ctx = null;
|
|
5072
|
+
pendingSingleSelectId = null;
|
|
5073
|
+
hasDragged = false;
|
|
4995
5074
|
get selectedIds() {
|
|
4996
5075
|
return [...this._selectedIds];
|
|
4997
5076
|
}
|
|
5077
|
+
setSelection(ids) {
|
|
5078
|
+
this._selectedIds = ids;
|
|
5079
|
+
this.ctx?.requestRender();
|
|
5080
|
+
}
|
|
4998
5081
|
get isMarqueeActive() {
|
|
4999
5082
|
return this.mode.type === "marquee";
|
|
5000
5083
|
}
|
|
@@ -5043,13 +5126,27 @@ var SelectTool = class {
|
|
|
5043
5126
|
return;
|
|
5044
5127
|
}
|
|
5045
5128
|
}
|
|
5129
|
+
this.pendingSingleSelectId = null;
|
|
5130
|
+
this.hasDragged = false;
|
|
5046
5131
|
const hit = this.hitTest(world, ctx);
|
|
5047
5132
|
if (hit) {
|
|
5048
5133
|
const alreadySelected = this._selectedIds.includes(hit.id);
|
|
5049
|
-
if (
|
|
5050
|
-
|
|
5134
|
+
if (state.shiftKey) {
|
|
5135
|
+
if (alreadySelected) {
|
|
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" };
|
|
5051
5149
|
}
|
|
5052
|
-
this.mode = hit.locked ? { type: "idle" } : { type: "dragging" };
|
|
5053
5150
|
} else {
|
|
5054
5151
|
this._selectedIds = [];
|
|
5055
5152
|
this.mode = { type: "marquee", start: world };
|
|
@@ -5075,6 +5172,7 @@ var SelectTool = class {
|
|
|
5075
5172
|
return;
|
|
5076
5173
|
}
|
|
5077
5174
|
if (this.mode.type === "dragging" && this._selectedIds.length > 0) {
|
|
5175
|
+
this.hasDragged = true;
|
|
5078
5176
|
ctx.setCursor?.("move");
|
|
5079
5177
|
const snapped = this.snap(world, ctx);
|
|
5080
5178
|
const dx = snapped.x - this.lastWorld.x;
|
|
@@ -5143,6 +5241,11 @@ var SelectTool = class {
|
|
|
5143
5241
|
}
|
|
5144
5242
|
ctx.requestRender();
|
|
5145
5243
|
}
|
|
5244
|
+
if (!this.hasDragged && this.pendingSingleSelectId !== null) {
|
|
5245
|
+
this._selectedIds = [this.pendingSingleSelectId];
|
|
5246
|
+
}
|
|
5247
|
+
this.pendingSingleSelectId = null;
|
|
5248
|
+
this.hasDragged = false;
|
|
5146
5249
|
this.mode = { type: "idle" };
|
|
5147
5250
|
ctx.setCursor?.("default");
|
|
5148
5251
|
}
|
|
@@ -6323,7 +6426,7 @@ var UpdateLayerCommand = class {
|
|
|
6323
6426
|
};
|
|
6324
6427
|
|
|
6325
6428
|
// src/index.ts
|
|
6326
|
-
var VERSION = "0.
|
|
6429
|
+
var VERSION = "0.12.0";
|
|
6327
6430
|
export {
|
|
6328
6431
|
AddElementCommand,
|
|
6329
6432
|
ArrowTool,
|