@elixpo/lixsketch 5.4.7 → 5.5.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/react/AIRenderer-M4LMJ66J.js +1105 -0
- package/dist/react/AIRenderer-M4LMJ66J.js.map +7 -0
- package/dist/react/Arrow-BJDAXPMH.js +8 -0
- package/dist/react/Arrow-BJDAXPMH.js.map +7 -0
- package/dist/react/Circle-KPG7TKIX.js +8 -0
- package/dist/react/Circle-KPG7TKIX.js.map +7 -0
- package/dist/react/CodeShape-K4DIZAIV.js +8 -0
- package/dist/react/CodeShape-K4DIZAIV.js.map +7 -0
- package/dist/react/CopyPaste-4CKJRHJ3.js +569 -0
- package/dist/react/CopyPaste-4CKJRHJ3.js.map +7 -0
- package/dist/react/EraserTrail-PA6IQLQN.js +20 -0
- package/dist/react/EraserTrail-PA6IQLQN.js.map +7 -0
- package/dist/react/EventDispatcher-SRFH6LQZ.js +463 -0
- package/dist/react/EventDispatcher-SRFH6LQZ.js.map +7 -0
- package/dist/react/Frame-6UR5XPAX.js +10 -0
- package/dist/react/Frame-6UR5XPAX.js.map +7 -0
- package/dist/react/FreehandStroke-CK24NUT3.js +8 -0
- package/dist/react/FreehandStroke-CK24NUT3.js.map +7 -0
- package/dist/react/GraphEngine-QE5B2PMR.js +340 -0
- package/dist/react/GraphEngine-QE5B2PMR.js.map +7 -0
- package/dist/react/GraphMathParser-2WMTY4IE.js +10 -0
- package/dist/react/GraphMathParser-2WMTY4IE.js.map +7 -0
- package/dist/react/IconShape-KMIA6T2H.js +10 -0
- package/dist/react/IconShape-KMIA6T2H.js.map +7 -0
- package/dist/react/ImageShape-CHHGBXUQ.js +10 -0
- package/dist/react/ImageShape-CHHGBXUQ.js.map +7 -0
- package/dist/react/LayerOrder-XCHF4MSS.js +66 -0
- package/dist/react/LayerOrder-XCHF4MSS.js.map +7 -0
- package/dist/react/Line-2KOQEEGA.js +10 -0
- package/dist/react/Line-2KOQEEGA.js.map +7 -0
- package/dist/react/LixScriptParser-JYWJX375.js +1033 -0
- package/dist/react/LixScriptParser-JYWJX375.js.map +7 -0
- package/dist/react/MermaidFlowchartRenderer-4QBAZ5MB.js +412 -0
- package/dist/react/MermaidFlowchartRenderer-4QBAZ5MB.js.map +7 -0
- package/dist/react/MermaidSequenceParser-UKG2NSZY.js +8 -0
- package/dist/react/MermaidSequenceParser-UKG2NSZY.js.map +7 -0
- package/dist/react/MermaidSequenceRenderer-HPLHY5II.js +387 -0
- package/dist/react/MermaidSequenceRenderer-HPLHY5II.js.map +7 -0
- package/dist/react/Rectangle-6FE7RN6W.js +8 -0
- package/dist/react/Rectangle-6FE7RN6W.js.map +7 -0
- package/dist/react/ResizeCode-WAMDTKSW.js +2 -0
- package/dist/react/ResizeCode-WAMDTKSW.js.map +7 -0
- package/dist/react/ResizeShapes-LKEQTITP.js +250 -0
- package/dist/react/ResizeShapes-LKEQTITP.js.map +7 -0
- package/dist/react/SceneSerializer-4U4B24JM.js +739 -0
- package/dist/react/SceneSerializer-4U4B24JM.js.map +7 -0
- package/dist/react/Selection-VVUHY5YJ.js +34 -0
- package/dist/react/Selection-VVUHY5YJ.js.map +7 -0
- package/dist/react/SketchEngine-YA4RG3KX.js +413 -0
- package/dist/react/SketchEngine-YA4RG3KX.js.map +7 -0
- package/dist/react/TextShape-54ZJ66E3.js +8 -0
- package/dist/react/TextShape-54ZJ66E3.js.map +7 -0
- package/dist/react/UndoRedo-M2JZUBKN.js +30 -0
- package/dist/react/UndoRedo-M2JZUBKN.js.map +7 -0
- package/dist/react/ZoomPan-U3TXC5AJ.js +186 -0
- package/dist/react/ZoomPan-U3TXC5AJ.js.map +7 -0
- package/dist/react/arrowTool-CWEMIRXK.js +17 -0
- package/dist/react/arrowTool-CWEMIRXK.js.map +7 -0
- package/dist/react/boxicons-5JNJQPUP.woff +0 -0
- package/dist/react/boxicons-6NVWQSCQ.eot +0 -0
- package/dist/react/boxicons-AQ5N6WP7.woff2 +0 -0
- package/dist/react/boxicons-GDR4JU3X.ttf +0 -0
- package/dist/react/boxicons-NNFHLMOR.svg +1660 -0
- package/dist/react/chunk-2OQXI7QB.js +564 -0
- package/dist/react/chunk-2OQXI7QB.js.map +7 -0
- package/dist/react/chunk-5OUBTHHO.js +187 -0
- package/dist/react/chunk-5OUBTHHO.js.map +7 -0
- package/dist/react/chunk-6PFXZKL2.js +628 -0
- package/dist/react/chunk-6PFXZKL2.js.map +7 -0
- package/dist/react/chunk-6SFNWGGZ.js +453 -0
- package/dist/react/chunk-6SFNWGGZ.js.map +7 -0
- package/dist/react/chunk-7TZSIR6V.js +210 -0
- package/dist/react/chunk-7TZSIR6V.js.map +7 -0
- package/dist/react/chunk-AJAZC37E.js +662 -0
- package/dist/react/chunk-AJAZC37E.js.map +7 -0
- package/dist/react/chunk-BU4D2WYQ.js +1213 -0
- package/dist/react/chunk-BU4D2WYQ.js.map +7 -0
- package/dist/react/chunk-BZE4CEBG.js +747 -0
- package/dist/react/chunk-BZE4CEBG.js.map +7 -0
- package/dist/react/chunk-CB2RANCB.js +212 -0
- package/dist/react/chunk-CB2RANCB.js.map +7 -0
- package/dist/react/chunk-DNAG7ML6.js +128 -0
- package/dist/react/chunk-DNAG7ML6.js.map +7 -0
- package/dist/react/chunk-HZWLPXFN.js +198 -0
- package/dist/react/chunk-HZWLPXFN.js.map +7 -0
- package/dist/react/chunk-I6HCCIXB.js +572 -0
- package/dist/react/chunk-I6HCCIXB.js.map +7 -0
- package/dist/react/chunk-IZ5OGWGW.js +235 -0
- package/dist/react/chunk-IZ5OGWGW.js.map +7 -0
- package/dist/react/chunk-JJCJNLNN.js +1490 -0
- package/dist/react/chunk-JJCJNLNN.js.map +7 -0
- package/dist/react/chunk-JQ3IRFDP.js +222 -0
- package/dist/react/chunk-JQ3IRFDP.js.map +7 -0
- package/dist/react/chunk-L5OARZJ7.js +1134 -0
- package/dist/react/chunk-L5OARZJ7.js.map +7 -0
- package/dist/react/chunk-LHRTXNVE.js +1600 -0
- package/dist/react/chunk-LHRTXNVE.js.map +7 -0
- package/dist/react/chunk-Q2GA4MBZ.js +1653 -0
- package/dist/react/chunk-Q2GA4MBZ.js.map +7 -0
- package/dist/react/chunk-QNSE5BAY.js +519 -0
- package/dist/react/chunk-QNSE5BAY.js.map +7 -0
- package/dist/react/chunk-QXFBG7OM.js +191 -0
- package/dist/react/chunk-QXFBG7OM.js.map +7 -0
- package/dist/react/chunk-T6ZVV5ZO.js +714 -0
- package/dist/react/chunk-T6ZVV5ZO.js.map +7 -0
- package/dist/react/chunk-URB6MY46.js +974 -0
- package/dist/react/chunk-URB6MY46.js.map +7 -0
- package/dist/react/chunk-VN62KLOC.js +931 -0
- package/dist/react/chunk-VN62KLOC.js.map +7 -0
- package/dist/react/chunk-VQVEPJSA.js +158 -0
- package/dist/react/chunk-VQVEPJSA.js.map +7 -0
- package/dist/react/chunk-XISEAGBV.js +1632 -0
- package/dist/react/chunk-XISEAGBV.js.map +7 -0
- package/dist/react/chunk-YKJUBFHE.js +575 -0
- package/dist/react/chunk-YKJUBFHE.js.map +7 -0
- package/dist/react/circleTool-NUATSEI2.js +14 -0
- package/dist/react/circleTool-NUATSEI2.js.map +7 -0
- package/dist/react/codeTool-MHCB2FNB.js +38 -0
- package/dist/react/codeTool-MHCB2FNB.js.map +7 -0
- package/dist/react/eraserTool-2GS2LQCS.js +103 -0
- package/dist/react/eraserTool-2GS2LQCS.js.map +7 -0
- package/dist/react/frameTool-PWVKKXSP.js +14 -0
- package/dist/react/frameTool-PWVKKXSP.js.map +7 -0
- package/dist/react/freehandTool-SLYGASVP.js +14 -0
- package/dist/react/freehandTool-SLYGASVP.js.map +7 -0
- package/dist/react/iconTool-GPZ7O7NH.js +18 -0
- package/dist/react/iconTool-GPZ7O7NH.js.map +7 -0
- package/dist/react/imageTool-D5R4XGEU.js +15 -0
- package/dist/react/imageTool-D5R4XGEU.js.map +7 -0
- package/dist/react/index.js +5342 -0
- package/dist/react/index.js.map +7 -0
- package/dist/react/laserTool-XVMV63AV.js +239 -0
- package/dist/react/laserTool-XVMV63AV.js.map +7 -0
- package/dist/react/lineTool-WNI5EMZ5.js +14 -0
- package/dist/react/lineTool-WNI5EMZ5.js.map +7 -0
- package/dist/react/lixCode-OJMVUXXI.ttf +0 -0
- package/dist/react/lixDefault-JEAPAUJL.ttf +0 -0
- package/dist/react/lixFancy-BPXYM5CQ.ttf +0 -0
- package/dist/react/lixFont-CPKEUDVM.woff2 +0 -0
- package/dist/react/rectangleTool-U7DZ6ZTA.js +14 -0
- package/dist/react/rectangleTool-U7DZ6ZTA.js.map +7 -0
- package/dist/react/styles.css +6627 -0
- package/dist/react/textTool-M7S6F3VC.js +21 -0
- package/dist/react/textTool-M7S6F3VC.js.map +7 -0
- package/package.json +39 -5
- package/src/EngineShortcuts.js +83 -27
- package/src/core/AIRenderer.js +30 -18
- package/src/core/GraphEngine.js +64 -41
- package/src/core/MermaidFlowchartRenderer.js +153 -88
- package/src/core/MermaidSequenceRenderer.js +168 -93
- package/src/core/SceneSerializer.js +86 -2
- package/src/core/Selection.js +119 -19
- package/src/core/UndoRedo.js +82 -15
- package/src/core/ZoomPan.js +15 -5
- package/src/index.js +14 -1
- package/src/react/LixSketchCanvas.jsx +347 -0
- package/src/react/components/AppMenu.jsx +475 -0
- package/src/react/components/Footer.jsx +85 -0
- package/src/react/components/Toolbar.jsx +140 -0
- package/src/react/components/canvas/CanvasLoadingOverlay.jsx +76 -0
- package/src/react/components/canvas/ContextMenu.jsx +466 -0
- package/src/react/components/canvas/FindBar.jsx +177 -0
- package/src/react/components/canvas/ImageSourcePicker.jsx +133 -0
- package/src/react/components/canvas/MultiSelectActions.jsx +120 -0
- package/src/react/components/canvas/SVGCanvas.jsx +145 -0
- package/src/react/components/canvas/SaveStatusIndicator.jsx +29 -0
- package/src/react/components/modals/CanvasPropertiesModal.jsx +358 -0
- package/src/react/components/modals/CommandPalette.jsx +307 -0
- package/src/react/components/modals/ExportImageModal.jsx +287 -0
- package/src/react/components/modals/GraphModal.jsx +174 -0
- package/src/react/components/modals/HelpModal.jsx +208 -0
- package/src/react/components/modals/LixScriptModal.jsx +130 -0
- package/src/react/components/modals/ShortcutsModal.jsx +125 -0
- package/src/react/components/sidebars/ArrowSidebar.jsx +173 -0
- package/src/react/components/sidebars/CircleSidebar.jsx +134 -0
- package/src/react/components/sidebars/FrameSidebar.jsx +263 -0
- package/src/react/components/sidebars/IconSidebar.jsx +279 -0
- package/src/react/components/sidebars/ImageSidebar.jsx +69 -0
- package/src/react/components/sidebars/LineSidebar.jsx +109 -0
- package/src/react/components/sidebars/PaintbrushSidebar.jsx +119 -0
- package/src/react/components/sidebars/RectangleSidebar.jsx +165 -0
- package/src/react/components/sidebars/ShapeSidebar.jsx +130 -0
- package/src/react/components/sidebars/TextSidebar.jsx +174 -0
- package/src/react/hooks/inertStores.js +58 -0
- package/src/react/hooks/useSketchEngine.js +76 -0
- package/src/react/hooks/useTranslation.js +92 -0
- package/src/react/index.js +41 -0
- package/src/react/store/useSketchStore.js +234 -0
- package/src/react/store/useUIStore.js +196 -0
- package/src/react/styles/arrowSidebar.css +263 -0
- package/src/react/styles/canvasStroke.css +47 -0
- package/src/react/styles/canvasTools.css +769 -0
- package/src/react/styles/circleSidebar.css +206 -0
- package/src/react/styles/fonts/fonts.css +29 -0
- package/src/react/styles/fonts/lixCode.ttf +0 -0
- package/src/react/styles/fonts/lixDefault.ttf +0 -0
- package/src/react/styles/fonts/lixDocs.ttf +0 -0
- package/src/react/styles/fonts/lixFancy.ttf +0 -0
- package/src/react/styles/fonts/lixFont.woff2 +0 -0
- package/src/react/styles/lineSidebar.css +207 -0
- package/src/react/styles/paintbrushSidebar.css +247 -0
- package/src/react/styles/squareSidebar.css +206 -0
- package/src/react/styles/writeText.css +149 -0
- package/src/react/styles.css +175 -0
- package/src/react/toolsEnum.js +20 -0
- package/src/react/utils/toast.js +18 -0
- package/src/shapes/Frame.js +7 -1
- package/src/shapes/Line.js +11 -5
- package/src/tools/arrowTool.js +30 -4
- package/src/tools/circleTool.js +33 -9
- package/src/tools/codeTool.js +5 -3
- package/src/tools/frameTool.js +47 -7
- package/src/tools/freehandTool.js +12 -4
- package/src/tools/iconTool.js +7 -1
- package/src/tools/imageTool.js +7 -1
- package/src/tools/lineTool.js +27 -3
- package/src/tools/rectangleTool.js +45 -8
- package/src/tools/textTool.js +23 -6
|
@@ -0,0 +1,569 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import {
|
|
3
|
+
CodeShape
|
|
4
|
+
} from "./chunk-7TZSIR6V.js";
|
|
5
|
+
import {
|
|
6
|
+
ImageShape
|
|
7
|
+
} from "./chunk-CB2RANCB.js";
|
|
8
|
+
import {
|
|
9
|
+
IconShape
|
|
10
|
+
} from "./chunk-JQ3IRFDP.js";
|
|
11
|
+
import {
|
|
12
|
+
Frame
|
|
13
|
+
} from "./chunk-BU4D2WYQ.js";
|
|
14
|
+
import {
|
|
15
|
+
FreehandStroke
|
|
16
|
+
} from "./chunk-YKJUBFHE.js";
|
|
17
|
+
import {
|
|
18
|
+
compressImage,
|
|
19
|
+
isAllowedImage
|
|
20
|
+
} from "./chunk-DNAG7ML6.js";
|
|
21
|
+
import {
|
|
22
|
+
Rectangle
|
|
23
|
+
} from "./chunk-T6ZVV5ZO.js";
|
|
24
|
+
import {
|
|
25
|
+
Circle
|
|
26
|
+
} from "./chunk-AJAZC37E.js";
|
|
27
|
+
import {
|
|
28
|
+
Arrow
|
|
29
|
+
} from "./chunk-XISEAGBV.js";
|
|
30
|
+
import {
|
|
31
|
+
Line
|
|
32
|
+
} from "./chunk-6PFXZKL2.js";
|
|
33
|
+
import "./chunk-BZE4CEBG.js";
|
|
34
|
+
import {
|
|
35
|
+
pushCreateAction
|
|
36
|
+
} from "./chunk-L5OARZJ7.js";
|
|
37
|
+
import {
|
|
38
|
+
TextShape
|
|
39
|
+
} from "./chunk-QXFBG7OM.js";
|
|
40
|
+
|
|
41
|
+
// src/core/CopyPaste.js
|
|
42
|
+
var clipboard = null;
|
|
43
|
+
var pasteCount = 0;
|
|
44
|
+
var lastMouseSVG = { x: 0, y: 0 };
|
|
45
|
+
function getSVGElement() {
|
|
46
|
+
return document.getElementById("freehand-canvas");
|
|
47
|
+
}
|
|
48
|
+
function cloneOptions(options) {
|
|
49
|
+
return JSON.parse(JSON.stringify(options));
|
|
50
|
+
}
|
|
51
|
+
function serializeShape(shape) {
|
|
52
|
+
switch (shape.shapeName) {
|
|
53
|
+
case "rectangle":
|
|
54
|
+
return {
|
|
55
|
+
type: "rectangle",
|
|
56
|
+
x: shape.x,
|
|
57
|
+
y: shape.y,
|
|
58
|
+
width: shape.width,
|
|
59
|
+
height: shape.height,
|
|
60
|
+
rotation: shape.rotation,
|
|
61
|
+
options: cloneOptions(shape.options)
|
|
62
|
+
};
|
|
63
|
+
case "circle":
|
|
64
|
+
return {
|
|
65
|
+
type: "circle",
|
|
66
|
+
x: shape.x,
|
|
67
|
+
y: shape.y,
|
|
68
|
+
rx: shape.rx,
|
|
69
|
+
ry: shape.ry,
|
|
70
|
+
rotation: shape.rotation,
|
|
71
|
+
options: cloneOptions(shape.options)
|
|
72
|
+
};
|
|
73
|
+
case "line":
|
|
74
|
+
return {
|
|
75
|
+
type: "line",
|
|
76
|
+
startPoint: { x: shape.startPoint.x, y: shape.startPoint.y },
|
|
77
|
+
endPoint: { x: shape.endPoint.x, y: shape.endPoint.y },
|
|
78
|
+
controlPoint: shape.controlPoint ? { x: shape.controlPoint.x, y: shape.controlPoint.y } : null,
|
|
79
|
+
isCurved: shape.isCurved || false,
|
|
80
|
+
options: cloneOptions(shape.options)
|
|
81
|
+
};
|
|
82
|
+
case "arrow":
|
|
83
|
+
return {
|
|
84
|
+
type: "arrow",
|
|
85
|
+
startPoint: { x: shape.startPoint.x, y: shape.startPoint.y },
|
|
86
|
+
endPoint: { x: shape.endPoint.x, y: shape.endPoint.y },
|
|
87
|
+
controlPoint1: shape.controlPoint1 ? { x: shape.controlPoint1.x, y: shape.controlPoint1.y } : null,
|
|
88
|
+
controlPoint2: shape.controlPoint2 ? { x: shape.controlPoint2.x, y: shape.controlPoint2.y } : null,
|
|
89
|
+
options: cloneOptions(shape.options),
|
|
90
|
+
arrowOutlineStyle: shape.arrowOutlineStyle,
|
|
91
|
+
arrowHeadStyle: shape.arrowHeadStyle,
|
|
92
|
+
arrowCurved: shape.arrowCurved,
|
|
93
|
+
arrowCurveAmount: shape.arrowCurveAmount
|
|
94
|
+
};
|
|
95
|
+
case "freehandStroke":
|
|
96
|
+
return {
|
|
97
|
+
type: "freehandStroke",
|
|
98
|
+
points: JSON.parse(JSON.stringify(shape.points)),
|
|
99
|
+
rotation: shape.rotation,
|
|
100
|
+
options: cloneOptions(shape.options)
|
|
101
|
+
};
|
|
102
|
+
case "frame":
|
|
103
|
+
return {
|
|
104
|
+
type: "frame",
|
|
105
|
+
x: shape.x,
|
|
106
|
+
y: shape.y,
|
|
107
|
+
width: shape.width,
|
|
108
|
+
height: shape.height,
|
|
109
|
+
rotation: shape.rotation,
|
|
110
|
+
frameName: shape.frameName,
|
|
111
|
+
options: cloneOptions(shape.options)
|
|
112
|
+
};
|
|
113
|
+
case "text": {
|
|
114
|
+
const group = shape.group;
|
|
115
|
+
const textEl = group.querySelector("text");
|
|
116
|
+
return {
|
|
117
|
+
type: "text",
|
|
118
|
+
x: shape.x,
|
|
119
|
+
y: shape.y,
|
|
120
|
+
rotation: shape.rotation,
|
|
121
|
+
groupHTML: group.cloneNode(true).outerHTML
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
case "code": {
|
|
125
|
+
const group = shape.group;
|
|
126
|
+
return {
|
|
127
|
+
type: "code",
|
|
128
|
+
x: shape.x,
|
|
129
|
+
y: shape.y,
|
|
130
|
+
rotation: shape.rotation,
|
|
131
|
+
groupHTML: group.cloneNode(true).outerHTML
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
case "image": {
|
|
135
|
+
const el = shape.element;
|
|
136
|
+
return {
|
|
137
|
+
type: "image",
|
|
138
|
+
x: shape.x,
|
|
139
|
+
y: shape.y,
|
|
140
|
+
width: shape.width,
|
|
141
|
+
height: shape.height,
|
|
142
|
+
rotation: shape.rotation,
|
|
143
|
+
href: el.getAttribute("href") || el.getAttributeNS("http://www.w3.org/1999/xlink", "href") || ""
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
case "icon": {
|
|
147
|
+
const el = shape.element;
|
|
148
|
+
return {
|
|
149
|
+
type: "icon",
|
|
150
|
+
x: shape.x,
|
|
151
|
+
y: shape.y,
|
|
152
|
+
width: shape.width,
|
|
153
|
+
height: shape.height,
|
|
154
|
+
rotation: shape.rotation,
|
|
155
|
+
elementHTML: el.cloneNode(true).outerHTML,
|
|
156
|
+
viewboxWidth: parseFloat(el.getAttribute("data-viewbox-width")) || 24,
|
|
157
|
+
viewboxHeight: parseFloat(el.getAttribute("data-viewbox-height")) || 24
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
default:
|
|
161
|
+
console.warn("Copy not supported for shape type:", shape.shapeName);
|
|
162
|
+
return null;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
function getShapeCenter(data) {
|
|
166
|
+
switch (data.type) {
|
|
167
|
+
case "rectangle":
|
|
168
|
+
case "frame":
|
|
169
|
+
return { x: data.x + data.width / 2, y: data.y + data.height / 2 };
|
|
170
|
+
case "circle":
|
|
171
|
+
return { x: data.x, y: data.y };
|
|
172
|
+
case "line":
|
|
173
|
+
return {
|
|
174
|
+
x: (data.startPoint.x + data.endPoint.x) / 2,
|
|
175
|
+
y: (data.startPoint.y + data.endPoint.y) / 2
|
|
176
|
+
};
|
|
177
|
+
case "arrow":
|
|
178
|
+
return {
|
|
179
|
+
x: (data.startPoint.x + data.endPoint.x) / 2,
|
|
180
|
+
y: (data.startPoint.y + data.endPoint.y) / 2
|
|
181
|
+
};
|
|
182
|
+
case "freehandStroke": {
|
|
183
|
+
if (!data.points.length) return { x: 0, y: 0 };
|
|
184
|
+
let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;
|
|
185
|
+
data.points.forEach((p) => {
|
|
186
|
+
if (p[0] < minX) minX = p[0];
|
|
187
|
+
if (p[1] < minY) minY = p[1];
|
|
188
|
+
if (p[0] > maxX) maxX = p[0];
|
|
189
|
+
if (p[1] > maxY) maxY = p[1];
|
|
190
|
+
});
|
|
191
|
+
return { x: (minX + maxX) / 2, y: (minY + maxY) / 2 };
|
|
192
|
+
}
|
|
193
|
+
case "text":
|
|
194
|
+
case "code":
|
|
195
|
+
return { x: data.x, y: data.y };
|
|
196
|
+
case "image":
|
|
197
|
+
case "icon":
|
|
198
|
+
return { x: data.x + data.width / 2, y: data.y + data.height / 2 };
|
|
199
|
+
default:
|
|
200
|
+
return { x: 0, y: 0 };
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
function createShapeFromData(data, offsetX, offsetY) {
|
|
204
|
+
const svgEl = getSVGElement();
|
|
205
|
+
if (!svgEl) return null;
|
|
206
|
+
switch (data.type) {
|
|
207
|
+
case "rectangle": {
|
|
208
|
+
const newRect = new Rectangle(
|
|
209
|
+
data.x + offsetX,
|
|
210
|
+
data.y + offsetY,
|
|
211
|
+
data.width,
|
|
212
|
+
data.height,
|
|
213
|
+
cloneOptions(data.options)
|
|
214
|
+
);
|
|
215
|
+
newRect.rotation = data.rotation;
|
|
216
|
+
newRect.draw();
|
|
217
|
+
return newRect;
|
|
218
|
+
}
|
|
219
|
+
case "circle": {
|
|
220
|
+
const newCircle = new Circle(
|
|
221
|
+
data.x + offsetX,
|
|
222
|
+
data.y + offsetY,
|
|
223
|
+
data.rx,
|
|
224
|
+
data.ry,
|
|
225
|
+
cloneOptions(data.options)
|
|
226
|
+
);
|
|
227
|
+
newCircle.rotation = data.rotation;
|
|
228
|
+
newCircle.draw();
|
|
229
|
+
return newCircle;
|
|
230
|
+
}
|
|
231
|
+
case "line": {
|
|
232
|
+
const newLine = new Line(
|
|
233
|
+
{ x: data.startPoint.x + offsetX, y: data.startPoint.y + offsetY },
|
|
234
|
+
{ x: data.endPoint.x + offsetX, y: data.endPoint.y + offsetY },
|
|
235
|
+
cloneOptions(data.options)
|
|
236
|
+
);
|
|
237
|
+
if (data.isCurved && data.controlPoint) {
|
|
238
|
+
newLine.isCurved = true;
|
|
239
|
+
newLine.controlPoint = { x: data.controlPoint.x + offsetX, y: data.controlPoint.y + offsetY };
|
|
240
|
+
}
|
|
241
|
+
newLine.draw();
|
|
242
|
+
return newLine;
|
|
243
|
+
}
|
|
244
|
+
case "arrow": {
|
|
245
|
+
const opts = {
|
|
246
|
+
...cloneOptions(data.options),
|
|
247
|
+
arrowOutlineStyle: data.arrowOutlineStyle,
|
|
248
|
+
arrowHeadStyle: data.arrowHeadStyle,
|
|
249
|
+
arrowCurved: data.arrowCurved,
|
|
250
|
+
arrowCurveAmount: data.arrowCurveAmount,
|
|
251
|
+
controlPoint1: data.controlPoint1 ? { x: data.controlPoint1.x + offsetX, y: data.controlPoint1.y + offsetY } : null,
|
|
252
|
+
controlPoint2: data.controlPoint2 ? { x: data.controlPoint2.x + offsetX, y: data.controlPoint2.y + offsetY } : null
|
|
253
|
+
};
|
|
254
|
+
const newArrow = new Arrow(
|
|
255
|
+
{ x: data.startPoint.x + offsetX, y: data.startPoint.y + offsetY },
|
|
256
|
+
{ x: data.endPoint.x + offsetX, y: data.endPoint.y + offsetY },
|
|
257
|
+
opts
|
|
258
|
+
);
|
|
259
|
+
return newArrow;
|
|
260
|
+
}
|
|
261
|
+
case "freehandStroke": {
|
|
262
|
+
const offsetPoints = data.points.map((p) => [
|
|
263
|
+
p[0] + offsetX,
|
|
264
|
+
p[1] + offsetY,
|
|
265
|
+
p[2] || 0.5
|
|
266
|
+
]);
|
|
267
|
+
const newStroke = new FreehandStroke(offsetPoints, cloneOptions(data.options));
|
|
268
|
+
newStroke.rotation = data.rotation;
|
|
269
|
+
newStroke.draw();
|
|
270
|
+
return newStroke;
|
|
271
|
+
}
|
|
272
|
+
case "frame": {
|
|
273
|
+
const newFrame = new Frame(
|
|
274
|
+
data.x + offsetX,
|
|
275
|
+
data.y + offsetY,
|
|
276
|
+
data.width,
|
|
277
|
+
data.height,
|
|
278
|
+
{ ...cloneOptions(data.options), frameName: data.frameName, rotation: data.rotation }
|
|
279
|
+
);
|
|
280
|
+
newFrame.rotation = data.rotation;
|
|
281
|
+
return newFrame;
|
|
282
|
+
}
|
|
283
|
+
case "text": {
|
|
284
|
+
const tempDiv = document.createElement("div");
|
|
285
|
+
tempDiv.innerHTML = data.groupHTML;
|
|
286
|
+
const clonedGroup = tempDiv.firstElementChild;
|
|
287
|
+
if (!clonedGroup) return null;
|
|
288
|
+
const newID = `text-${String(Date.now()).slice(0, 8)}-${Math.floor(Math.random() * 1e4)}`;
|
|
289
|
+
clonedGroup.setAttribute("id", newID);
|
|
290
|
+
const textChild = clonedGroup.querySelector("text");
|
|
291
|
+
if (textChild) textChild.setAttribute("id", `${newID}-text`);
|
|
292
|
+
const newX = data.x + offsetX;
|
|
293
|
+
const newY = data.y + offsetY;
|
|
294
|
+
const rotation = data.rotation || 0;
|
|
295
|
+
if (textChild && rotation) {
|
|
296
|
+
try {
|
|
297
|
+
const bbox = { x: 0, y: 0, width: 100, height: 30 };
|
|
298
|
+
clonedGroup.setAttribute("transform", `translate(${newX}, ${newY}) rotate(${rotation}, ${bbox.width / 2}, ${bbox.height / 2})`);
|
|
299
|
+
} catch (e) {
|
|
300
|
+
clonedGroup.setAttribute("transform", `translate(${newX}, ${newY})`);
|
|
301
|
+
}
|
|
302
|
+
} else {
|
|
303
|
+
clonedGroup.setAttribute("transform", `translate(${newX}, ${newY})`);
|
|
304
|
+
}
|
|
305
|
+
clonedGroup.setAttribute("data-x", newX);
|
|
306
|
+
clonedGroup.setAttribute("data-y", newY);
|
|
307
|
+
svgEl.appendChild(clonedGroup);
|
|
308
|
+
const textShape = new TextShape(clonedGroup);
|
|
309
|
+
return textShape;
|
|
310
|
+
}
|
|
311
|
+
case "code": {
|
|
312
|
+
const tempDiv = document.createElement("div");
|
|
313
|
+
tempDiv.innerHTML = data.groupHTML;
|
|
314
|
+
const clonedGroup = tempDiv.firstElementChild;
|
|
315
|
+
if (!clonedGroup) return null;
|
|
316
|
+
const newID = `code-${String(Date.now()).slice(0, 8)}-${Math.floor(Math.random() * 1e4)}`;
|
|
317
|
+
clonedGroup.setAttribute("id", newID);
|
|
318
|
+
const codeChild = clonedGroup.querySelector("text");
|
|
319
|
+
if (codeChild) codeChild.setAttribute("id", `${newID}-code`);
|
|
320
|
+
const newX = data.x + offsetX;
|
|
321
|
+
const newY = data.y + offsetY;
|
|
322
|
+
const rotation = data.rotation || 0;
|
|
323
|
+
if (rotation) {
|
|
324
|
+
clonedGroup.setAttribute("transform", `translate(${newX}, ${newY}) rotate(${rotation}, 0, 0)`);
|
|
325
|
+
} else {
|
|
326
|
+
clonedGroup.setAttribute("transform", `translate(${newX}, ${newY})`);
|
|
327
|
+
}
|
|
328
|
+
clonedGroup.setAttribute("data-x", newX);
|
|
329
|
+
clonedGroup.setAttribute("data-y", newY);
|
|
330
|
+
svgEl.appendChild(clonedGroup);
|
|
331
|
+
const codeShape = new CodeShape(clonedGroup);
|
|
332
|
+
return codeShape;
|
|
333
|
+
}
|
|
334
|
+
case "image": {
|
|
335
|
+
const imgEl = document.createElementNS("http://www.w3.org/2000/svg", "image");
|
|
336
|
+
const newX = data.x + offsetX;
|
|
337
|
+
const newY = data.y + offsetY;
|
|
338
|
+
imgEl.setAttribute("x", newX);
|
|
339
|
+
imgEl.setAttribute("y", newY);
|
|
340
|
+
imgEl.setAttribute("width", data.width);
|
|
341
|
+
imgEl.setAttribute("height", data.height);
|
|
342
|
+
imgEl.setAttribute("href", data.href);
|
|
343
|
+
imgEl.setAttribute("data-shape-x", newX);
|
|
344
|
+
imgEl.setAttribute("data-shape-y", newY);
|
|
345
|
+
imgEl.setAttribute("data-shape-width", data.width);
|
|
346
|
+
imgEl.setAttribute("data-shape-height", data.height);
|
|
347
|
+
imgEl.setAttribute("preserveAspectRatio", "none");
|
|
348
|
+
imgEl.setAttribute("style", "cursor: pointer;");
|
|
349
|
+
svgEl.appendChild(imgEl);
|
|
350
|
+
const imageShape = new ImageShape(imgEl);
|
|
351
|
+
imageShape.rotation = data.rotation;
|
|
352
|
+
return imageShape;
|
|
353
|
+
}
|
|
354
|
+
case "icon": {
|
|
355
|
+
const tempDiv = document.createElement("div");
|
|
356
|
+
tempDiv.innerHTML = data.elementHTML;
|
|
357
|
+
const clonedEl = tempDiv.firstElementChild;
|
|
358
|
+
if (!clonedEl) return null;
|
|
359
|
+
const newX = data.x + offsetX;
|
|
360
|
+
const newY = data.y + offsetY;
|
|
361
|
+
const newID = `icon-${String(Date.now()).slice(0, 8)}-${Math.floor(Math.random() * 1e4)}`;
|
|
362
|
+
clonedEl.setAttribute("id", newID);
|
|
363
|
+
clonedEl.setAttribute("x", newX);
|
|
364
|
+
clonedEl.setAttribute("y", newY);
|
|
365
|
+
clonedEl.setAttribute("data-shape-x", newX);
|
|
366
|
+
clonedEl.setAttribute("data-shape-y", newY);
|
|
367
|
+
clonedEl.setAttribute("data-shape-width", data.width);
|
|
368
|
+
clonedEl.setAttribute("data-shape-height", data.height);
|
|
369
|
+
clonedEl.setAttribute("data-shape-rotation", data.rotation);
|
|
370
|
+
clonedEl.setAttribute("data-viewbox-width", data.viewboxWidth);
|
|
371
|
+
clonedEl.setAttribute("data-viewbox-height", data.viewboxHeight);
|
|
372
|
+
const scale = data.width / Math.max(data.viewboxWidth, data.viewboxHeight);
|
|
373
|
+
const localCenterX = data.width / 2 / scale;
|
|
374
|
+
const localCenterY = data.height / 2 / scale;
|
|
375
|
+
clonedEl.setAttribute("transform", `translate(${newX}, ${newY}) scale(${scale}) rotate(${data.rotation}, ${localCenterX}, ${localCenterY})`);
|
|
376
|
+
svgEl.appendChild(clonedEl);
|
|
377
|
+
const iconShape = new IconShape(clonedEl);
|
|
378
|
+
return iconShape;
|
|
379
|
+
}
|
|
380
|
+
default:
|
|
381
|
+
return null;
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
function copySelected() {
|
|
385
|
+
const shapesToCopy = [];
|
|
386
|
+
if (window.multiSelection && window.multiSelection.selectedShapes && window.multiSelection.selectedShapes.size > 0) {
|
|
387
|
+
window.multiSelection.selectedShapes.forEach((shape) => {
|
|
388
|
+
const data = serializeShape(shape);
|
|
389
|
+
if (data) shapesToCopy.push(data);
|
|
390
|
+
});
|
|
391
|
+
} else if (typeof currentShape !== "undefined" && currentShape && currentShape.isSelected) {
|
|
392
|
+
const data = serializeShape(currentShape);
|
|
393
|
+
if (data) shapesToCopy.push(data);
|
|
394
|
+
}
|
|
395
|
+
if (shapesToCopy.length === 0) return false;
|
|
396
|
+
let totalX = 0, totalY = 0;
|
|
397
|
+
shapesToCopy.forEach((d) => {
|
|
398
|
+
const c = getShapeCenter(d);
|
|
399
|
+
totalX += c.x;
|
|
400
|
+
totalY += c.y;
|
|
401
|
+
});
|
|
402
|
+
const centerX = totalX / shapesToCopy.length;
|
|
403
|
+
const centerY = totalY / shapesToCopy.length;
|
|
404
|
+
clipboard = {
|
|
405
|
+
shapes: shapesToCopy,
|
|
406
|
+
centerX,
|
|
407
|
+
centerY
|
|
408
|
+
};
|
|
409
|
+
pasteCount = 0;
|
|
410
|
+
return true;
|
|
411
|
+
}
|
|
412
|
+
function pasteClipboard() {
|
|
413
|
+
if (!clipboard || clipboard.shapes.length === 0) return false;
|
|
414
|
+
pasteCount++;
|
|
415
|
+
const baseOffset = 20 * pasteCount;
|
|
416
|
+
const targetX = lastMouseSVG.x;
|
|
417
|
+
const targetY = lastMouseSVG.y;
|
|
418
|
+
const groupOffsetX = targetX - clipboard.centerX + baseOffset;
|
|
419
|
+
const groupOffsetY = targetY - clipboard.centerY + baseOffset;
|
|
420
|
+
if (typeof shapes !== "undefined" && Array.isArray(shapes)) {
|
|
421
|
+
shapes.forEach((s) => {
|
|
422
|
+
if (s.isSelected && typeof s.removeSelection === "function") {
|
|
423
|
+
s.removeSelection();
|
|
424
|
+
s.isSelected = false;
|
|
425
|
+
}
|
|
426
|
+
});
|
|
427
|
+
}
|
|
428
|
+
if (window.multiSelection) {
|
|
429
|
+
window.multiSelection.clearSelection();
|
|
430
|
+
}
|
|
431
|
+
if (typeof currentShape !== "undefined") {
|
|
432
|
+
currentShape = null;
|
|
433
|
+
}
|
|
434
|
+
if (typeof disableAllSideBars === "function") {
|
|
435
|
+
disableAllSideBars();
|
|
436
|
+
}
|
|
437
|
+
const pastedShapes = [];
|
|
438
|
+
clipboard.shapes.forEach((data) => {
|
|
439
|
+
const newShape = createShapeFromData(data, groupOffsetX, groupOffsetY);
|
|
440
|
+
if (newShape) {
|
|
441
|
+
if (typeof shapes !== "undefined" && Array.isArray(shapes)) {
|
|
442
|
+
shapes.push(newShape);
|
|
443
|
+
}
|
|
444
|
+
pushCreateAction(newShape);
|
|
445
|
+
pastedShapes.push(newShape);
|
|
446
|
+
}
|
|
447
|
+
});
|
|
448
|
+
if (pastedShapes.length === 1) {
|
|
449
|
+
const s = pastedShapes[0];
|
|
450
|
+
s.isSelected = true;
|
|
451
|
+
currentShape = s;
|
|
452
|
+
if (typeof s.addAnchors === "function") {
|
|
453
|
+
s.addAnchors();
|
|
454
|
+
} else if (typeof s.selectShape === "function") {
|
|
455
|
+
s.selectShape();
|
|
456
|
+
}
|
|
457
|
+
} else if (pastedShapes.length > 1 && window.multiSelection) {
|
|
458
|
+
pastedShapes.forEach((s) => {
|
|
459
|
+
window.multiSelection.addShape(s);
|
|
460
|
+
});
|
|
461
|
+
window.multiSelection.updateControls();
|
|
462
|
+
}
|
|
463
|
+
return true;
|
|
464
|
+
}
|
|
465
|
+
function handleCopyPasteKeydown(e) {
|
|
466
|
+
const tag = (e.target.tagName || "").toLowerCase();
|
|
467
|
+
if (tag === "input" || tag === "textarea" || e.target.isContentEditable) return;
|
|
468
|
+
if ((e.ctrlKey || e.metaKey) && e.key.toLowerCase() === "c") {
|
|
469
|
+
if (copySelected()) {
|
|
470
|
+
e.preventDefault();
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
if ((e.ctrlKey || e.metaKey) && e.key.toLowerCase() === "v") {
|
|
474
|
+
if (pasteClipboard()) {
|
|
475
|
+
e.preventDefault();
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
function handleMouseMoveForPaste(e) {
|
|
480
|
+
const svgEl = getSVGElement();
|
|
481
|
+
if (!svgEl) return;
|
|
482
|
+
const viewBox = svgEl.viewBox.baseVal;
|
|
483
|
+
const rect = svgEl.getBoundingClientRect();
|
|
484
|
+
const mouseX = e.clientX - rect.left;
|
|
485
|
+
const mouseY = e.clientY - rect.top;
|
|
486
|
+
lastMouseSVG.x = viewBox.x + mouseX / rect.width * viewBox.width;
|
|
487
|
+
lastMouseSVG.y = viewBox.y + mouseY / rect.height * viewBox.height;
|
|
488
|
+
}
|
|
489
|
+
function handlePasteEvent(e) {
|
|
490
|
+
const tag = (e.target.tagName || "").toLowerCase();
|
|
491
|
+
if (tag === "input" || tag === "textarea" || e.target.isContentEditable) return;
|
|
492
|
+
const items = e.clipboardData?.items;
|
|
493
|
+
if (!items) return;
|
|
494
|
+
for (const item of items) {
|
|
495
|
+
if (item.type.startsWith("image/")) {
|
|
496
|
+
e.preventDefault();
|
|
497
|
+
const blob = item.getAsFile();
|
|
498
|
+
if (!blob) return;
|
|
499
|
+
if (!isAllowedImage(blob)) {
|
|
500
|
+
console.warn("[CopyPaste] Rejected pasted image type:", blob.type);
|
|
501
|
+
return;
|
|
502
|
+
}
|
|
503
|
+
const reader = new FileReader();
|
|
504
|
+
reader.onload = async (ev) => {
|
|
505
|
+
const rawDataUrl = ev.target.result;
|
|
506
|
+
const isSvg = (blob.type || "").toLowerCase() === "image/svg+xml";
|
|
507
|
+
let placedDataUrl = rawDataUrl;
|
|
508
|
+
if (!isSvg) {
|
|
509
|
+
try {
|
|
510
|
+
const compressed = await compressImage(rawDataUrl);
|
|
511
|
+
if (compressed?.dataUrl) placedDataUrl = compressed.dataUrl;
|
|
512
|
+
} catch (err) {
|
|
513
|
+
console.warn("[CopyPaste] Pre-placement compression failed, using raw:", err);
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
placeImageFromDataUrl(placedDataUrl);
|
|
517
|
+
};
|
|
518
|
+
reader.readAsDataURL(blob);
|
|
519
|
+
return;
|
|
520
|
+
}
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
function placeImageFromDataUrl(dataUrl) {
|
|
524
|
+
const svgEl = getSVGElement();
|
|
525
|
+
if (!svgEl || !window.ImageShape) return;
|
|
526
|
+
const img = new Image();
|
|
527
|
+
img.onload = () => {
|
|
528
|
+
const aspectRatio = img.height / img.width;
|
|
529
|
+
const displayW = Math.min(400, img.width);
|
|
530
|
+
const displayH = displayW * aspectRatio;
|
|
531
|
+
const vb = svgEl.viewBox.baseVal;
|
|
532
|
+
const cx = vb.x + vb.width / 2;
|
|
533
|
+
const cy = vb.y + vb.height / 2;
|
|
534
|
+
const imgEl = document.createElementNS("http://www.w3.org/2000/svg", "image");
|
|
535
|
+
imgEl.setAttribute("href", dataUrl);
|
|
536
|
+
imgEl.setAttribute("x", cx - displayW / 2);
|
|
537
|
+
imgEl.setAttribute("y", cy - displayH / 2);
|
|
538
|
+
imgEl.setAttribute("width", displayW);
|
|
539
|
+
imgEl.setAttribute("height", displayH);
|
|
540
|
+
imgEl.setAttribute("data-shape-x", cx - displayW / 2);
|
|
541
|
+
imgEl.setAttribute("data-shape-y", cy - displayH / 2);
|
|
542
|
+
imgEl.setAttribute("data-shape-width", displayW);
|
|
543
|
+
imgEl.setAttribute("data-shape-height", displayH);
|
|
544
|
+
imgEl.setAttribute("type", "image");
|
|
545
|
+
imgEl.setAttribute("preserveAspectRatio", "none");
|
|
546
|
+
svgEl.appendChild(imgEl);
|
|
547
|
+
const imageShape = new ImageShape(imgEl);
|
|
548
|
+
if (window.shapes) window.shapes.push(imageShape);
|
|
549
|
+
if (window.pushCreateAction) window.pushCreateAction(imageShape);
|
|
550
|
+
if (window.uploadImageToCloudinary) {
|
|
551
|
+
window.uploadImageToCloudinary(imageShape);
|
|
552
|
+
}
|
|
553
|
+
console.log("[CopyPaste] Pasted image from clipboard");
|
|
554
|
+
};
|
|
555
|
+
img.src = dataUrl;
|
|
556
|
+
}
|
|
557
|
+
function initCopyPaste() {
|
|
558
|
+
document.addEventListener("keydown", handleCopyPasteKeydown);
|
|
559
|
+
document.addEventListener("pointermove", handleMouseMoveForPaste);
|
|
560
|
+
document.addEventListener("paste", handlePasteEvent);
|
|
561
|
+
window.copySelected = copySelected;
|
|
562
|
+
window.pasteClipboard = pasteClipboard;
|
|
563
|
+
}
|
|
564
|
+
export {
|
|
565
|
+
copySelected,
|
|
566
|
+
initCopyPaste,
|
|
567
|
+
pasteClipboard
|
|
568
|
+
};
|
|
569
|
+
//# sourceMappingURL=CopyPaste-4CKJRHJ3.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/core/CopyPaste.js"],
|
|
4
|
+
"sourcesContent": ["/* eslint-disable */\n// Centralized Copy/Paste system for ALL shape types\n// Supports single and multi-selection copy/paste\n// Pastes at mouse pointer position with offset to prevent stacking\n\nimport { pushCreateAction } from './UndoRedo.js';\nimport { Rectangle } from '../shapes/Rectangle.js';\nimport { Circle } from '../shapes/Circle.js';\nimport { Line } from '../shapes/Line.js';\nimport { Arrow } from '../shapes/Arrow.js';\nimport { FreehandStroke } from '../shapes/FreehandStroke.js';\nimport { Frame } from '../shapes/Frame.js';\nimport { TextShape } from '../shapes/TextShape.js';\nimport { CodeShape } from '../shapes/CodeShape.js';\nimport { ImageShape } from '../shapes/ImageShape.js';\nimport { isAllowedImage, isAllowedImageDataUrl } from '../utils/allowedImageTypes.js';\nimport { compressImage } from '../utils/imageCompressor.js';\nimport { IconShape } from '../shapes/IconShape.js';\n\n// Clipboard storage\nlet clipboard = null; // { shapes: [...clonedData], centerX, centerY }\nlet pasteCount = 0; // Increments per paste to offset repeated pastes\n\n// Last known mouse position in SVG coordinates\nlet lastMouseSVG = { x: 0, y: 0 };\n\nfunction getSVGElement() {\n return document.getElementById('freehand-canvas');\n}\n\nfunction getSVGCoordsFromMouse(e) {\n const svgEl = getSVGElement();\n if (!svgEl) return { x: 0, y: 0 };\n const viewBox = svgEl.viewBox.baseVal;\n const rect = svgEl.getBoundingClientRect();\n const mouseX = e.clientX - rect.left;\n const mouseY = e.clientY - rect.top;\n const svgX = viewBox.x + (mouseX / rect.width) * viewBox.width;\n const svgY = viewBox.y + (mouseY / rect.height) * viewBox.height;\n return { x: svgX, y: svgY };\n}\n\nfunction cloneOptions(options) {\n return JSON.parse(JSON.stringify(options));\n}\n\n// ============================================================\n// SERIALIZE: Extract copyable data from a shape\n// ============================================================\nfunction serializeShape(shape) {\n switch (shape.shapeName) {\n case 'rectangle':\n return {\n type: 'rectangle',\n x: shape.x,\n y: shape.y,\n width: shape.width,\n height: shape.height,\n rotation: shape.rotation,\n options: cloneOptions(shape.options)\n };\n\n case 'circle':\n return {\n type: 'circle',\n x: shape.x,\n y: shape.y,\n rx: shape.rx,\n ry: shape.ry,\n rotation: shape.rotation,\n options: cloneOptions(shape.options)\n };\n\n case 'line':\n return {\n type: 'line',\n startPoint: { x: shape.startPoint.x, y: shape.startPoint.y },\n endPoint: { x: shape.endPoint.x, y: shape.endPoint.y },\n controlPoint: shape.controlPoint ? { x: shape.controlPoint.x, y: shape.controlPoint.y } : null,\n isCurved: shape.isCurved || false,\n options: cloneOptions(shape.options)\n };\n\n case 'arrow':\n return {\n type: 'arrow',\n startPoint: { x: shape.startPoint.x, y: shape.startPoint.y },\n endPoint: { x: shape.endPoint.x, y: shape.endPoint.y },\n controlPoint1: shape.controlPoint1 ? { x: shape.controlPoint1.x, y: shape.controlPoint1.y } : null,\n controlPoint2: shape.controlPoint2 ? { x: shape.controlPoint2.x, y: shape.controlPoint2.y } : null,\n options: cloneOptions(shape.options),\n arrowOutlineStyle: shape.arrowOutlineStyle,\n arrowHeadStyle: shape.arrowHeadStyle,\n arrowCurved: shape.arrowCurved,\n arrowCurveAmount: shape.arrowCurveAmount\n };\n\n case 'freehandStroke':\n return {\n type: 'freehandStroke',\n points: JSON.parse(JSON.stringify(shape.points)),\n rotation: shape.rotation,\n options: cloneOptions(shape.options)\n };\n\n case 'frame':\n return {\n type: 'frame',\n x: shape.x,\n y: shape.y,\n width: shape.width,\n height: shape.height,\n rotation: shape.rotation,\n frameName: shape.frameName,\n options: cloneOptions(shape.options)\n };\n\n case 'text': {\n const group = shape.group;\n const textEl = group.querySelector('text');\n return {\n type: 'text',\n x: shape.x,\n y: shape.y,\n rotation: shape.rotation,\n groupHTML: group.cloneNode(true).outerHTML\n };\n }\n\n case 'code': {\n const group = shape.group;\n return {\n type: 'code',\n x: shape.x,\n y: shape.y,\n rotation: shape.rotation,\n groupHTML: group.cloneNode(true).outerHTML\n };\n }\n\n case 'image': {\n const el = shape.element;\n return {\n type: 'image',\n x: shape.x,\n y: shape.y,\n width: shape.width,\n height: shape.height,\n rotation: shape.rotation,\n href: el.getAttribute('href') || el.getAttributeNS('http://www.w3.org/1999/xlink', 'href') || ''\n };\n }\n\n case 'icon': {\n const el = shape.element;\n return {\n type: 'icon',\n x: shape.x,\n y: shape.y,\n width: shape.width,\n height: shape.height,\n rotation: shape.rotation,\n elementHTML: el.cloneNode(true).outerHTML,\n viewboxWidth: parseFloat(el.getAttribute('data-viewbox-width')) || 24,\n viewboxHeight: parseFloat(el.getAttribute('data-viewbox-height')) || 24\n };\n }\n\n default:\n console.warn('Copy not supported for shape type:', shape.shapeName);\n return null;\n }\n}\n\n// ============================================================\n// Get bounding center of a serialized shape\n// ============================================================\nfunction getShapeCenter(data) {\n switch (data.type) {\n case 'rectangle':\n case 'frame':\n return { x: data.x + data.width / 2, y: data.y + data.height / 2 };\n case 'circle':\n return { x: data.x, y: data.y };\n case 'line':\n return {\n x: (data.startPoint.x + data.endPoint.x) / 2,\n y: (data.startPoint.y + data.endPoint.y) / 2\n };\n case 'arrow':\n return {\n x: (data.startPoint.x + data.endPoint.x) / 2,\n y: (data.startPoint.y + data.endPoint.y) / 2\n };\n case 'freehandStroke': {\n if (!data.points.length) return { x: 0, y: 0 };\n let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;\n data.points.forEach(p => {\n if (p[0] < minX) minX = p[0];\n if (p[1] < minY) minY = p[1];\n if (p[0] > maxX) maxX = p[0];\n if (p[1] > maxY) maxY = p[1];\n });\n return { x: (minX + maxX) / 2, y: (minY + maxY) / 2 };\n }\n case 'text':\n case 'code':\n return { x: data.x, y: data.y };\n case 'image':\n case 'icon':\n return { x: data.x + data.width / 2, y: data.y + data.height / 2 };\n default:\n return { x: 0, y: 0 };\n }\n}\n\n// ============================================================\n// DESERIALIZE: Create a new shape from copied data at offset\n// ============================================================\nfunction createShapeFromData(data, offsetX, offsetY) {\n const svgEl = getSVGElement();\n if (!svgEl) return null;\n\n switch (data.type) {\n case 'rectangle': {\n const newRect = new Rectangle(\n data.x + offsetX,\n data.y + offsetY,\n data.width,\n data.height,\n cloneOptions(data.options)\n );\n newRect.rotation = data.rotation;\n newRect.draw();\n return newRect;\n }\n\n case 'circle': {\n const newCircle = new Circle(\n data.x + offsetX,\n data.y + offsetY,\n data.rx,\n data.ry,\n cloneOptions(data.options)\n );\n newCircle.rotation = data.rotation;\n newCircle.draw();\n return newCircle;\n }\n\n case 'line': {\n const newLine = new Line(\n { x: data.startPoint.x + offsetX, y: data.startPoint.y + offsetY },\n { x: data.endPoint.x + offsetX, y: data.endPoint.y + offsetY },\n cloneOptions(data.options)\n );\n if (data.isCurved && data.controlPoint) {\n newLine.isCurved = true;\n newLine.controlPoint = { x: data.controlPoint.x + offsetX, y: data.controlPoint.y + offsetY };\n }\n newLine.draw();\n return newLine;\n }\n\n case 'arrow': {\n const opts = {\n ...cloneOptions(data.options),\n arrowOutlineStyle: data.arrowOutlineStyle,\n arrowHeadStyle: data.arrowHeadStyle,\n arrowCurved: data.arrowCurved,\n arrowCurveAmount: data.arrowCurveAmount,\n controlPoint1: data.controlPoint1 ? { x: data.controlPoint1.x + offsetX, y: data.controlPoint1.y + offsetY } : null,\n controlPoint2: data.controlPoint2 ? { x: data.controlPoint2.x + offsetX, y: data.controlPoint2.y + offsetY } : null\n };\n const newArrow = new Arrow(\n { x: data.startPoint.x + offsetX, y: data.startPoint.y + offsetY },\n { x: data.endPoint.x + offsetX, y: data.endPoint.y + offsetY },\n opts\n );\n return newArrow;\n }\n\n case 'freehandStroke': {\n const offsetPoints = data.points.map(p => [\n p[0] + offsetX,\n p[1] + offsetY,\n p[2] || 0.5\n ]);\n const newStroke = new FreehandStroke(offsetPoints, cloneOptions(data.options));\n newStroke.rotation = data.rotation;\n newStroke.draw();\n return newStroke;\n }\n\n case 'frame': {\n const newFrame = new Frame(\n data.x + offsetX,\n data.y + offsetY,\n data.width,\n data.height,\n { ...cloneOptions(data.options), frameName: data.frameName, rotation: data.rotation }\n );\n newFrame.rotation = data.rotation;\n return newFrame;\n }\n\n case 'text': {\n // Parse the cloned HTML and insert into SVG\n const tempDiv = document.createElement('div');\n tempDiv.innerHTML = data.groupHTML;\n const clonedGroup = tempDiv.firstElementChild;\n if (!clonedGroup) return null;\n\n // Generate new unique ID\n const newID = `text-${String(Date.now()).slice(0, 8)}-${Math.floor(Math.random() * 10000)}`;\n clonedGroup.setAttribute('id', newID);\n const textChild = clonedGroup.querySelector('text');\n if (textChild) textChild.setAttribute('id', `${newID}-text`);\n\n // Update position\n const newX = data.x + offsetX;\n const newY = data.y + offsetY;\n const rotation = data.rotation || 0;\n if (textChild && rotation) {\n try {\n const bbox = { x: 0, y: 0, width: 100, height: 30 }; // approximate until appended\n clonedGroup.setAttribute('transform', `translate(${newX}, ${newY}) rotate(${rotation}, ${bbox.width / 2}, ${bbox.height / 2})`);\n } catch (e) {\n clonedGroup.setAttribute('transform', `translate(${newX}, ${newY})`);\n }\n } else {\n clonedGroup.setAttribute('transform', `translate(${newX}, ${newY})`);\n }\n clonedGroup.setAttribute('data-x', newX);\n clonedGroup.setAttribute('data-y', newY);\n\n svgEl.appendChild(clonedGroup);\n\n const textShape = new TextShape(clonedGroup);\n return textShape;\n }\n\n case 'code': {\n const tempDiv = document.createElement('div');\n tempDiv.innerHTML = data.groupHTML;\n const clonedGroup = tempDiv.firstElementChild;\n if (!clonedGroup) return null;\n\n const newID = `code-${String(Date.now()).slice(0, 8)}-${Math.floor(Math.random() * 10000)}`;\n clonedGroup.setAttribute('id', newID);\n const codeChild = clonedGroup.querySelector('text');\n if (codeChild) codeChild.setAttribute('id', `${newID}-code`);\n\n const newX = data.x + offsetX;\n const newY = data.y + offsetY;\n const rotation = data.rotation || 0;\n if (rotation) {\n clonedGroup.setAttribute('transform', `translate(${newX}, ${newY}) rotate(${rotation}, 0, 0)`);\n } else {\n clonedGroup.setAttribute('transform', `translate(${newX}, ${newY})`);\n }\n clonedGroup.setAttribute('data-x', newX);\n clonedGroup.setAttribute('data-y', newY);\n\n svgEl.appendChild(clonedGroup);\n\n const codeShape = new CodeShape(clonedGroup);\n return codeShape;\n }\n\n case 'image': {\n const imgEl = document.createElementNS('http://www.w3.org/2000/svg', 'image');\n const newX = data.x + offsetX;\n const newY = data.y + offsetY;\n imgEl.setAttribute('x', newX);\n imgEl.setAttribute('y', newY);\n imgEl.setAttribute('width', data.width);\n imgEl.setAttribute('height', data.height);\n imgEl.setAttribute('href', data.href);\n imgEl.setAttribute('data-shape-x', newX);\n imgEl.setAttribute('data-shape-y', newY);\n imgEl.setAttribute('data-shape-width', data.width);\n imgEl.setAttribute('data-shape-height', data.height);\n imgEl.setAttribute('preserveAspectRatio', 'none');\n imgEl.setAttribute('style', 'cursor: pointer;');\n\n // ImageShape constructor moves element into a group and appends to svg\n svgEl.appendChild(imgEl);\n const imageShape = new ImageShape(imgEl);\n imageShape.rotation = data.rotation;\n return imageShape;\n }\n\n case 'icon': {\n // Parse the cloned icon element HTML\n const tempDiv = document.createElement('div');\n tempDiv.innerHTML = data.elementHTML;\n const clonedEl = tempDiv.firstElementChild;\n if (!clonedEl) return null;\n\n const newX = data.x + offsetX;\n const newY = data.y + offsetY;\n const newID = `icon-${String(Date.now()).slice(0, 8)}-${Math.floor(Math.random() * 10000)}`;\n clonedEl.setAttribute('id', newID);\n clonedEl.setAttribute('x', newX);\n clonedEl.setAttribute('y', newY);\n clonedEl.setAttribute('data-shape-x', newX);\n clonedEl.setAttribute('data-shape-y', newY);\n clonedEl.setAttribute('data-shape-width', data.width);\n clonedEl.setAttribute('data-shape-height', data.height);\n clonedEl.setAttribute('data-shape-rotation', data.rotation);\n clonedEl.setAttribute('data-viewbox-width', data.viewboxWidth);\n clonedEl.setAttribute('data-viewbox-height', data.viewboxHeight);\n\n // Recalculate transform\n const scale = data.width / Math.max(data.viewboxWidth, data.viewboxHeight);\n const localCenterX = data.width / 2 / scale;\n const localCenterY = data.height / 2 / scale;\n clonedEl.setAttribute('transform', `translate(${newX}, ${newY}) scale(${scale}) rotate(${data.rotation}, ${localCenterX}, ${localCenterY})`);\n\n svgEl.appendChild(clonedEl);\n\n const iconShape = new IconShape(clonedEl);\n return iconShape;\n }\n\n default:\n return null;\n }\n}\n\n// ============================================================\n// COPY: Serialize currently selected shapes\n// ============================================================\nfunction copySelected() {\n const shapesToCopy = [];\n\n // Check multi-selection first\n if (window.multiSelection && window.multiSelection.selectedShapes && window.multiSelection.selectedShapes.size > 0) {\n window.multiSelection.selectedShapes.forEach(shape => {\n const data = serializeShape(shape);\n if (data) shapesToCopy.push(data);\n });\n }\n // Fall back to single currentShape\n else if (typeof currentShape !== 'undefined' && currentShape && currentShape.isSelected) {\n const data = serializeShape(currentShape);\n if (data) shapesToCopy.push(data);\n }\n\n if (shapesToCopy.length === 0) return false;\n\n // Calculate center of all copied shapes\n let totalX = 0, totalY = 0;\n shapesToCopy.forEach(d => {\n const c = getShapeCenter(d);\n totalX += c.x;\n totalY += c.y;\n });\n const centerX = totalX / shapesToCopy.length;\n const centerY = totalY / shapesToCopy.length;\n\n clipboard = {\n shapes: shapesToCopy,\n centerX,\n centerY\n };\n pasteCount = 0;\n\n return true;\n}\n\n// ============================================================\n// PASTE: Create new shapes from clipboard at mouse position\n// ============================================================\nfunction pasteClipboard() {\n if (!clipboard || clipboard.shapes.length === 0) return false;\n\n pasteCount++;\n const baseOffset = 20 * pasteCount;\n\n // Calculate paste position: center the group on the mouse pointer\n const targetX = lastMouseSVG.x;\n const targetY = lastMouseSVG.y;\n const groupOffsetX = targetX - clipboard.centerX + baseOffset;\n const groupOffsetY = targetY - clipboard.centerY + baseOffset;\n\n // Deselect all currently selected shapes\n if (typeof shapes !== 'undefined' && Array.isArray(shapes)) {\n shapes.forEach(s => {\n if (s.isSelected && typeof s.removeSelection === 'function') {\n s.removeSelection();\n s.isSelected = false;\n }\n });\n }\n if (window.multiSelection) {\n window.multiSelection.clearSelection();\n }\n if (typeof currentShape !== 'undefined') {\n currentShape = null;\n }\n if (typeof disableAllSideBars === 'function') {\n disableAllSideBars();\n }\n\n const pastedShapes = [];\n\n clipboard.shapes.forEach(data => {\n const newShape = createShapeFromData(data, groupOffsetX, groupOffsetY);\n if (newShape) {\n if (typeof shapes !== 'undefined' && Array.isArray(shapes)) {\n shapes.push(newShape);\n }\n pushCreateAction(newShape);\n pastedShapes.push(newShape);\n }\n });\n\n // Select the pasted shapes\n if (pastedShapes.length === 1) {\n const s = pastedShapes[0];\n s.isSelected = true;\n currentShape = s;\n if (typeof s.addAnchors === 'function') {\n s.addAnchors();\n } else if (typeof s.selectShape === 'function') {\n s.selectShape();\n }\n } else if (pastedShapes.length > 1 && window.multiSelection) {\n pastedShapes.forEach(s => {\n window.multiSelection.addShape(s);\n });\n window.multiSelection.updateControls();\n }\n\n return true;\n}\n\n// ============================================================\n// KEYBOARD HANDLER: Ctrl+C / Ctrl+V\n// ============================================================\nfunction handleCopyPasteKeydown(e) {\n // Don't intercept if user is typing in an input/textarea/contenteditable\n const tag = (e.target.tagName || '').toLowerCase();\n if (tag === 'input' || tag === 'textarea' || e.target.isContentEditable) return;\n\n if ((e.ctrlKey || e.metaKey) && e.key.toLowerCase() === 'c') {\n if (copySelected()) {\n e.preventDefault();\n }\n }\n\n if ((e.ctrlKey || e.metaKey) && e.key.toLowerCase() === 'v') {\n if (pasteClipboard()) {\n e.preventDefault();\n }\n }\n}\n\n// Track mouse position for paste placement\nfunction handleMouseMoveForPaste(e) {\n const svgEl = getSVGElement();\n if (!svgEl) return;\n const viewBox = svgEl.viewBox.baseVal;\n const rect = svgEl.getBoundingClientRect();\n const mouseX = e.clientX - rect.left;\n const mouseY = e.clientY - rect.top;\n lastMouseSVG.x = viewBox.x + (mouseX / rect.width) * viewBox.width;\n lastMouseSVG.y = viewBox.y + (mouseY / rect.height) * viewBox.height;\n}\n\n// ============================================================\n// PASTE IMAGE FROM CLIPBOARD (external images, screenshots)\n// ============================================================\nfunction handlePasteEvent(e) {\n // Don't intercept if user is typing\n const tag = (e.target.tagName || '').toLowerCase();\n if (tag === 'input' || tag === 'textarea' || e.target.isContentEditable) return;\n\n const items = e.clipboardData?.items;\n if (!items) return;\n\n for (const item of items) {\n if (item.type.startsWith('image/')) {\n e.preventDefault();\n const blob = item.getAsFile();\n if (!blob) return;\n\n // Validate against the canonical allowlist \u2014 clipboard sources\n // can include animated GIFs / HEIC / TIFF / arbitrary mime types.\n if (!isAllowedImage(blob)) {\n console.warn('[CopyPaste] Rejected pasted image type:', blob.type);\n return;\n }\n\n const reader = new FileReader();\n reader.onload = async (ev) => {\n const rawDataUrl = ev.target.result;\n const isSvg = (blob.type || '').toLowerCase() === 'image/svg+xml';\n let placedDataUrl = rawDataUrl;\n if (!isSvg) {\n try {\n const compressed = await compressImage(rawDataUrl);\n if (compressed?.dataUrl) placedDataUrl = compressed.dataUrl;\n } catch (err) {\n console.warn('[CopyPaste] Pre-placement compression failed, using raw:', err);\n }\n }\n placeImageFromDataUrl(placedDataUrl);\n };\n reader.readAsDataURL(blob);\n return; // only handle first image\n }\n }\n}\n\nfunction placeImageFromDataUrl(dataUrl) {\n const svgEl = getSVGElement();\n if (!svgEl || !window.ImageShape) return;\n\n const img = new Image();\n img.onload = () => {\n const aspectRatio = img.height / img.width;\n const displayW = Math.min(400, img.width);\n const displayH = displayW * aspectRatio;\n\n // Place at center of current viewport\n const vb = svgEl.viewBox.baseVal;\n const cx = vb.x + vb.width / 2;\n const cy = vb.y + vb.height / 2;\n\n const imgEl = document.createElementNS('http://www.w3.org/2000/svg', 'image');\n imgEl.setAttribute('href', dataUrl);\n imgEl.setAttribute('x', cx - displayW / 2);\n imgEl.setAttribute('y', cy - displayH / 2);\n imgEl.setAttribute('width', displayW);\n imgEl.setAttribute('height', displayH);\n imgEl.setAttribute('data-shape-x', cx - displayW / 2);\n imgEl.setAttribute('data-shape-y', cy - displayH / 2);\n imgEl.setAttribute('data-shape-width', displayW);\n imgEl.setAttribute('data-shape-height', displayH);\n imgEl.setAttribute('type', 'image');\n imgEl.setAttribute('preserveAspectRatio', 'none');\n\n svgEl.appendChild(imgEl);\n const imageShape = new ImageShape(imgEl);\n if (window.shapes) window.shapes.push(imageShape);\n if (window.pushCreateAction) window.pushCreateAction(imageShape);\n\n // Compress and upload to Cloudinary\n if (window.uploadImageToCloudinary) {\n window.uploadImageToCloudinary(imageShape);\n }\n\n console.log('[CopyPaste] Pasted image from clipboard');\n };\n img.src = dataUrl;\n}\n\n// ============================================================\n// INIT: Set up event listeners\n// ============================================================\nfunction initCopyPaste() {\n document.addEventListener('keydown', handleCopyPasteKeydown);\n document.addEventListener('pointermove', handleMouseMoveForPaste);\n document.addEventListener('paste', handlePasteEvent);\n\n // Expose for context menu\n window.copySelected = copySelected;\n window.pasteClipboard = pasteClipboard;\n}\n\nexport { initCopyPaste, copySelected, pasteClipboard };\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import {
|
|
3
|
+
createEraserTrail,
|
|
4
|
+
fadeOutEraserTrail,
|
|
5
|
+
forceCleanupEraserTrail,
|
|
6
|
+
getIsErasing,
|
|
7
|
+
getTargetedElements,
|
|
8
|
+
setIsErasing,
|
|
9
|
+
updateEraserTrail
|
|
10
|
+
} from "./chunk-5OUBTHHO.js";
|
|
11
|
+
export {
|
|
12
|
+
createEraserTrail,
|
|
13
|
+
fadeOutEraserTrail,
|
|
14
|
+
forceCleanupEraserTrail,
|
|
15
|
+
getIsErasing,
|
|
16
|
+
getTargetedElements,
|
|
17
|
+
setIsErasing,
|
|
18
|
+
updateEraserTrail
|
|
19
|
+
};
|
|
20
|
+
//# sourceMappingURL=EraserTrail-PA6IQLQN.js.map
|