@elixpo/lixsketch 5.4.7 → 5.5.1
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 +5349 -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 +482 -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,21 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import {
|
|
3
|
+
deselectElement,
|
|
4
|
+
enterEditMode,
|
|
5
|
+
handleTextMouseDown,
|
|
6
|
+
handleTextMouseMove,
|
|
7
|
+
handleTextMouseUp,
|
|
8
|
+
updateCodeToggleForShape
|
|
9
|
+
} from "./chunk-JJCJNLNN.js";
|
|
10
|
+
import "./chunk-LHRTXNVE.js";
|
|
11
|
+
import "./chunk-BZE4CEBG.js";
|
|
12
|
+
import "./chunk-L5OARZJ7.js";
|
|
13
|
+
export {
|
|
14
|
+
deselectElement as deselectTextElement,
|
|
15
|
+
enterEditMode,
|
|
16
|
+
handleTextMouseDown,
|
|
17
|
+
handleTextMouseMove,
|
|
18
|
+
handleTextMouseUp,
|
|
19
|
+
updateCodeToggleForShape
|
|
20
|
+
};
|
|
21
|
+
//# sourceMappingURL=textTool-M7S6F3VC.js.map
|
package/package.json
CHANGED
|
@@ -1,17 +1,26 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@elixpo/lixsketch",
|
|
3
|
-
"version": "5.
|
|
4
|
-
"description": "Open-source SVG whiteboard engine with hand-drawn aesthetics — the core of LixSketch",
|
|
3
|
+
"version": "5.5.1",
|
|
4
|
+
"description": "Open-source SVG whiteboard engine + React canvas component with hand-drawn aesthetics — the core of LixSketch",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.js",
|
|
7
7
|
"exports": {
|
|
8
8
|
".": "./src/index.js",
|
|
9
|
+
"./react": {
|
|
10
|
+
"import": "./dist/react/index.js",
|
|
11
|
+
"default": "./dist/react/index.js"
|
|
12
|
+
},
|
|
13
|
+
"./react/styles": "./dist/react/styles.css",
|
|
9
14
|
"./src/*": "./src/*",
|
|
10
15
|
"./fonts": "./fonts/fonts.css",
|
|
11
16
|
"./fonts/*": "./fonts/*"
|
|
12
17
|
},
|
|
18
|
+
"sideEffects": [
|
|
19
|
+
"**/*.css"
|
|
20
|
+
],
|
|
13
21
|
"files": [
|
|
14
22
|
"src/",
|
|
23
|
+
"dist/",
|
|
15
24
|
"fonts/",
|
|
16
25
|
"README.md"
|
|
17
26
|
],
|
|
@@ -25,7 +34,8 @@
|
|
|
25
34
|
"sketch",
|
|
26
35
|
"excalidraw-alternative",
|
|
27
36
|
"infinite-canvas",
|
|
28
|
-
"framework"
|
|
37
|
+
"framework",
|
|
38
|
+
"react"
|
|
29
39
|
],
|
|
30
40
|
"author": {
|
|
31
41
|
"name": "Ayushman Bhattacharya",
|
|
@@ -43,7 +53,31 @@
|
|
|
43
53
|
"url": "https://github.com/elixpo/sketch.elixpo/issues"
|
|
44
54
|
},
|
|
45
55
|
"dependencies": {
|
|
46
|
-
"
|
|
47
|
-
"perfect-freehand": "^1.2.3"
|
|
56
|
+
"boxicons": "^2.1.4",
|
|
57
|
+
"perfect-freehand": "^1.2.3",
|
|
58
|
+
"roughjs": "^4.6.6"
|
|
59
|
+
},
|
|
60
|
+
"peerDependencies": {
|
|
61
|
+
"react": ">=18.0.0",
|
|
62
|
+
"react-dom": ">=18.0.0",
|
|
63
|
+
"zustand": "^5.0.13"
|
|
64
|
+
},
|
|
65
|
+
"peerDependenciesMeta": {
|
|
66
|
+
"react": {
|
|
67
|
+
"optional": true
|
|
68
|
+
},
|
|
69
|
+
"react-dom": {
|
|
70
|
+
"optional": true
|
|
71
|
+
},
|
|
72
|
+
"zustand": {
|
|
73
|
+
"optional": true
|
|
74
|
+
}
|
|
75
|
+
},
|
|
76
|
+
"devDependencies": {
|
|
77
|
+
"esbuild": "^0.24.0"
|
|
78
|
+
},
|
|
79
|
+
"scripts": {
|
|
80
|
+
"build": "node build.mjs",
|
|
81
|
+
"prepublishOnly": "npm run build"
|
|
48
82
|
}
|
|
49
83
|
}
|
package/src/EngineShortcuts.js
CHANGED
|
@@ -18,31 +18,55 @@
|
|
|
18
18
|
* specific contexts (e.g. when the host's overlay is focused).
|
|
19
19
|
*/
|
|
20
20
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
//
|
|
21
|
+
// NB: tool names are inlined as string literals below (rather than imported
|
|
22
|
+
// from `./index.js`) to avoid a module-init cycle. EngineShortcuts.js and
|
|
23
|
+
// index.js import each other; if SHORTCUT_MAP read TOOLS.PAN at the top
|
|
24
|
+
// level, it would evaluate before index.js had populated TOOLS, throwing
|
|
25
|
+
// "TOOLS is undefined" once esbuild splits this into a chunk.
|
|
26
|
+
//
|
|
27
|
+
// The values still match TOOLS.* exactly. If you change one, change both.
|
|
24
28
|
export const SHORTCUT_MAP = {
|
|
25
|
-
h:
|
|
26
|
-
v:
|
|
27
|
-
1:
|
|
28
|
-
r:
|
|
29
|
-
2:
|
|
30
|
-
o:
|
|
31
|
-
4:
|
|
32
|
-
a:
|
|
33
|
-
5:
|
|
34
|
-
l:
|
|
35
|
-
6:
|
|
36
|
-
p:
|
|
37
|
-
7:
|
|
38
|
-
t:
|
|
39
|
-
8:
|
|
40
|
-
9:
|
|
41
|
-
e:
|
|
42
|
-
0:
|
|
43
|
-
i:
|
|
44
|
-
f:
|
|
45
|
-
k:
|
|
29
|
+
h: 'pan',
|
|
30
|
+
v: 'select',
|
|
31
|
+
1: 'select',
|
|
32
|
+
r: 'rectangle',
|
|
33
|
+
2: 'rectangle',
|
|
34
|
+
o: 'circle',
|
|
35
|
+
4: 'circle',
|
|
36
|
+
a: 'arrow',
|
|
37
|
+
5: 'arrow',
|
|
38
|
+
l: 'line',
|
|
39
|
+
6: 'line',
|
|
40
|
+
p: 'freehand',
|
|
41
|
+
7: 'freehand',
|
|
42
|
+
t: 'text',
|
|
43
|
+
8: 'text',
|
|
44
|
+
9: 'image',
|
|
45
|
+
e: 'eraser',
|
|
46
|
+
0: 'eraser',
|
|
47
|
+
i: 'icon',
|
|
48
|
+
f: 'frame',
|
|
49
|
+
k: 'laser',
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
// Mirror of TOOLS used inside this module's function bodies. Local copy
|
|
53
|
+
// avoids the same module-init cycle while still letting callers compare
|
|
54
|
+
// engine state against named constants instead of magic strings.
|
|
55
|
+
const TOOLS = {
|
|
56
|
+
SELECT: 'select',
|
|
57
|
+
PAN: 'pan',
|
|
58
|
+
RECTANGLE: 'rectangle',
|
|
59
|
+
CIRCLE: 'circle',
|
|
60
|
+
LINE: 'line',
|
|
61
|
+
ARROW: 'arrow',
|
|
62
|
+
FREEHAND: 'freehand',
|
|
63
|
+
TEXT: 'text',
|
|
64
|
+
CODE: 'code',
|
|
65
|
+
ERASER: 'eraser',
|
|
66
|
+
LASER: 'laser',
|
|
67
|
+
IMAGE: 'image',
|
|
68
|
+
FRAME: 'frame',
|
|
69
|
+
ICON: 'icon',
|
|
46
70
|
};
|
|
47
71
|
|
|
48
72
|
function isTypingTarget(target) {
|
|
@@ -165,6 +189,28 @@ export function installEngineShortcuts(engine, options = {}) {
|
|
|
165
189
|
if (window.currentShape) {
|
|
166
190
|
const shape = window.currentShape;
|
|
167
191
|
const shapes = window.shapes;
|
|
192
|
+
const isFrame = shape.shapeName === 'frame';
|
|
193
|
+
const isDiagramFrame = isFrame && !!shape._diagramType;
|
|
194
|
+
|
|
195
|
+
// Issue #24 bug #7: regular frame → orphan children +
|
|
196
|
+
// snapshot for undo (mirrors deleteSelectedShapes).
|
|
197
|
+
let childSnapshot = null;
|
|
198
|
+
if (isFrame && !isDiagramFrame) {
|
|
199
|
+
childSnapshot = [...(shape.containedShapes || [])];
|
|
200
|
+
for (const child of childSnapshot) {
|
|
201
|
+
if (!child || child === shape) continue;
|
|
202
|
+
const el = child.group || child.element;
|
|
203
|
+
if (el) {
|
|
204
|
+
if (shape.clipGroup && el.parentNode === shape.clipGroup) {
|
|
205
|
+
shape.clipGroup.removeChild(el);
|
|
206
|
+
}
|
|
207
|
+
if (window.svg && el.parentNode !== window.svg) window.svg.appendChild(el);
|
|
208
|
+
}
|
|
209
|
+
child.parentFrame = null;
|
|
210
|
+
delete child.isBeingMovedByFrame;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
168
214
|
if (shapes) {
|
|
169
215
|
const idx = shapes.indexOf(shape);
|
|
170
216
|
if (idx !== -1) shapes.splice(idx, 1);
|
|
@@ -175,10 +221,20 @@ export function installEngineShortcuts(engine, options = {}) {
|
|
|
175
221
|
if (shape.parentFrame && typeof shape.parentFrame.removeShapeFromFrame === 'function') {
|
|
176
222
|
shape.parentFrame.removeShapeFromFrame(shape);
|
|
177
223
|
}
|
|
178
|
-
|
|
179
|
-
if (
|
|
224
|
+
|
|
225
|
+
if (isFrame && !isDiagramFrame) {
|
|
226
|
+
shape.containedShapes = [];
|
|
227
|
+
if (shape.group && shape.group.parentNode) shape.group.parentNode.removeChild(shape.group);
|
|
228
|
+
if (shape.clipGroup && shape.clipGroup.parentNode) shape.clipGroup.parentNode.removeChild(shape.clipGroup);
|
|
229
|
+
if (shape.clipPath && shape.clipPath.parentNode) shape.clipPath.parentNode.removeChild(shape.clipPath);
|
|
230
|
+
} else {
|
|
231
|
+
const el = shape.group || shape.element;
|
|
232
|
+
if (el && el.parentNode) el.parentNode.removeChild(el);
|
|
233
|
+
}
|
|
234
|
+
|
|
180
235
|
if (typeof window.pushDeleteAction === 'function') {
|
|
181
|
-
window.pushDeleteAction(shape);
|
|
236
|
+
if (childSnapshot) window.pushDeleteAction(shape, { childSnapshot });
|
|
237
|
+
else window.pushDeleteAction(shape);
|
|
182
238
|
}
|
|
183
239
|
window.currentShape = null;
|
|
184
240
|
if (typeof window.disableAllSideBars === 'function') {
|
package/src/core/AIRenderer.js
CHANGED
|
@@ -316,18 +316,22 @@ export function renderAIDiagram(diagram) {
|
|
|
316
316
|
const ox = vcx - dw / 2 - minX;
|
|
317
317
|
const oy = vcy - dh / 2 - minY;
|
|
318
318
|
|
|
319
|
-
//
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
319
|
+
// Phase 5 (issue #22): no outer wrapper frame. Each generated shape
|
|
320
|
+
// (node, edge, subgraph container) gets the same `groupId` so the whole
|
|
321
|
+
// diagram behaves as one selectable group via Selection.js's existing
|
|
322
|
+
// group-expansion path. Drops the "solid background frame" symptom and
|
|
323
|
+
// makes the rendered content as interactive as user-drawn shapes.
|
|
324
|
+
const groupId = `aidiag-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 7)}`;
|
|
325
|
+
// Kept under the same name `frame` to minimise the diff inside this
|
|
326
|
+
// 600-line function — it's now a thin shim that catches `addShapeToFrame`
|
|
327
|
+
// calls and re-routes them to a groupId assignment. `selectFrame` /
|
|
328
|
+
// `removeSelection` no-op; selection is on the first node below.
|
|
329
|
+
const frame = {
|
|
330
|
+
addShapeToFrame(s) { if (s) s.groupId = groupId; },
|
|
331
|
+
selectFrame() {},
|
|
332
|
+
removeSelection() {},
|
|
333
|
+
shapeName: 'frame',
|
|
334
|
+
};
|
|
331
335
|
|
|
332
336
|
const nodeMap = new Map();
|
|
333
337
|
|
|
@@ -593,12 +597,15 @@ export function renderAIDiagram(diagram) {
|
|
|
593
597
|
}
|
|
594
598
|
}
|
|
595
599
|
|
|
596
|
-
//
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
if (
|
|
600
|
+
// Phase 5: select the first generated node — group expansion in
|
|
601
|
+
// Selection.js will pick up the rest via the shared groupId.
|
|
602
|
+
const first = nodeMap.values().next().value;
|
|
603
|
+
if (first && first.shape) {
|
|
604
|
+
window.currentShape = first.shape;
|
|
605
|
+
if (typeof first.shape.selectShape === 'function') first.shape.selectShape();
|
|
606
|
+
}
|
|
600
607
|
|
|
601
|
-
console.log(`[AIRenderer] Done: ${nodes.length} nodes, ${edges.length} edges, ${subgraphs.length} subgraphs → "${title}"`);
|
|
608
|
+
console.log(`[AIRenderer] Done: ${nodes.length} nodes, ${edges.length} edges, ${subgraphs.length} subgraphs → "${title}" (groupId=${groupId})`);
|
|
602
609
|
return true;
|
|
603
610
|
}
|
|
604
611
|
|
|
@@ -738,7 +745,7 @@ function cross(ax, ay, bx, by, cx, cy) {
|
|
|
738
745
|
* Automatically attach an arrow endpoint to a shape.
|
|
739
746
|
* This makes edges follow nodes when they're moved.
|
|
740
747
|
*/
|
|
741
|
-
function autoAttach(arrow, shape, isStart, contactPoint) {
|
|
748
|
+
export function autoAttach(arrow, shape, isStart, contactPoint) {
|
|
742
749
|
if (!arrow || !shape) return;
|
|
743
750
|
if (typeof arrow.attachToShape !== 'function') return;
|
|
744
751
|
|
|
@@ -1306,6 +1313,11 @@ export function generateFramePreviewSVG(frame, width = 500, height = 350) {
|
|
|
1306
1313
|
// ============================================================
|
|
1307
1314
|
|
|
1308
1315
|
export function initAIRenderer() {
|
|
1316
|
+
// Expose the autoAttach helper so sibling renderers (Mermaid flowchart,
|
|
1317
|
+
// Graph, LixScript) can wire arrow endpoints into shapes without
|
|
1318
|
+
// import-cycling through this large module.
|
|
1319
|
+
window.__autoAttach = autoAttach;
|
|
1320
|
+
|
|
1309
1321
|
// Lazy-load sequence renderer
|
|
1310
1322
|
let _seqParser = null;
|
|
1311
1323
|
let _seqPreview = null;
|
package/src/core/GraphEngine.js
CHANGED
|
@@ -48,39 +48,22 @@ function renderGraphOnCanvas(equations, settings) {
|
|
|
48
48
|
? 'Graph: ' + eqLabels.join(', ')
|
|
49
49
|
: 'Graph';
|
|
50
50
|
|
|
51
|
-
//
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
// Store graph data for re-editing
|
|
59
|
-
frame._graphData = {
|
|
60
|
-
equations: equations.map(eq => ({ expression: eq.expression, color: eq.color })),
|
|
61
|
-
settings: { ...settings },
|
|
62
|
-
};
|
|
63
|
-
frame._frameType = 'graph';
|
|
64
|
-
|
|
65
|
-
window.shapes.push(frame);
|
|
66
|
-
if (window.pushCreateAction) window.pushCreateAction(frame);
|
|
67
|
-
} catch (err) {
|
|
68
|
-
console.error('[GraphEngine] Frame creation failed:', err);
|
|
69
|
-
return false;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
// Parse SVG markup and insert elements into the frame
|
|
51
|
+
// Phase 5 (issue #22): no wrapper frame. The graph is conceptually a
|
|
52
|
+
// single rendering — axes, grid, curves all interlocked — so we don't
|
|
53
|
+
// split it into per-curve shapes. Instead the graph becomes ONE
|
|
54
|
+
// first-class shape on the canvas: a `graphShape` that implements the
|
|
55
|
+
// shape API the engine relies on (contains / selectShape / etc.) so
|
|
56
|
+
// it can be selected, dragged, attached to by arrows, picked up by
|
|
57
|
+
// the rect-drag — exactly like a user-drawn shape.
|
|
73
58
|
try {
|
|
74
59
|
const parser = new DOMParser();
|
|
75
60
|
const doc = parser.parseFromString(svgMarkup, 'image/svg+xml');
|
|
76
61
|
const svgEl = doc.querySelector('svg');
|
|
77
62
|
if (!svgEl) return false;
|
|
78
63
|
|
|
79
|
-
// Create a group to hold all graph elements
|
|
80
64
|
const graphGroup = document.createElementNS(NS, 'g');
|
|
81
65
|
graphGroup.setAttribute('data-type', 'graph-group');
|
|
82
66
|
graphGroup.setAttribute('transform', `translate(${frameX + 20}, ${frameY + 20})`);
|
|
83
|
-
graphGroup.style.pointerEvents = 'none';
|
|
84
67
|
|
|
85
68
|
// Copy defs (clip paths)
|
|
86
69
|
const defs = svgEl.querySelector('defs');
|
|
@@ -90,46 +73,86 @@ function renderGraphOnCanvas(equations, settings) {
|
|
|
90
73
|
window.svg.insertBefore(defsClone, window.svg.firstChild);
|
|
91
74
|
}
|
|
92
75
|
|
|
93
|
-
// Copy all child elements
|
|
94
76
|
while (svgEl.childNodes.length > 0) {
|
|
95
77
|
const child = svgEl.childNodes[0];
|
|
96
|
-
if (child.nodeName === 'defs') {
|
|
97
|
-
svgEl.removeChild(child);
|
|
98
|
-
continue;
|
|
99
|
-
}
|
|
78
|
+
if (child.nodeName === 'defs') { svgEl.removeChild(child); continue; }
|
|
100
79
|
graphGroup.appendChild(child);
|
|
101
80
|
}
|
|
102
|
-
|
|
103
81
|
window.svg.appendChild(graphGroup);
|
|
104
82
|
|
|
105
|
-
// Wrap as a simple shape-like object for the frame
|
|
106
83
|
const graphShape = {
|
|
107
|
-
shapeName: '
|
|
84
|
+
shapeName: 'graph', // first-class shapeName
|
|
85
|
+
shapeID: `graph-${Date.now().toString(36)}-${Math.floor(Math.random() * 10000)}`,
|
|
108
86
|
group: graphGroup,
|
|
109
87
|
element: graphGroup,
|
|
110
88
|
x: frameX + 20,
|
|
111
89
|
y: frameY + 20,
|
|
112
90
|
width: GRAPH_WIDTH,
|
|
113
91
|
height: GRAPH_HEIGHT,
|
|
92
|
+
rotation: 0,
|
|
93
|
+
isSelected: false,
|
|
94
|
+
_selectionRect: null,
|
|
95
|
+
_graphData: {
|
|
96
|
+
equations: equations.map(eq => ({ expression: eq.expression, color: eq.color })),
|
|
97
|
+
settings: { ...settings },
|
|
98
|
+
},
|
|
99
|
+
|
|
100
|
+
// ── Shape API the engine relies on ────────────────────────
|
|
101
|
+
contains(px, py) {
|
|
102
|
+
return px >= this.x && px <= this.x + this.width
|
|
103
|
+
&& py >= this.y && py <= this.y + this.height;
|
|
104
|
+
},
|
|
114
105
|
move(dx, dy) {
|
|
115
|
-
this.x += dx;
|
|
116
|
-
this.y += dy;
|
|
106
|
+
this.x += dx; this.y += dy;
|
|
117
107
|
this.group.setAttribute('transform', `translate(${this.x}, ${this.y})`);
|
|
108
|
+
this._updateSelectionRect();
|
|
109
|
+
},
|
|
110
|
+
selectShape() {
|
|
111
|
+
this.isSelected = true;
|
|
112
|
+
if (this._selectionRect) return;
|
|
113
|
+
const r = document.createElementNS(NS, 'rect');
|
|
114
|
+
r.setAttribute('fill', 'none');
|
|
115
|
+
r.setAttribute('stroke', '#9b7bf7');
|
|
116
|
+
r.setAttribute('stroke-width', '1.5');
|
|
117
|
+
r.setAttribute('stroke-dasharray', '4 3');
|
|
118
|
+
r.setAttribute('pointer-events', 'none');
|
|
119
|
+
window.svg.appendChild(r);
|
|
120
|
+
this._selectionRect = r;
|
|
121
|
+
this._updateSelectionRect();
|
|
122
|
+
},
|
|
123
|
+
removeSelection() {
|
|
124
|
+
this.isSelected = false;
|
|
125
|
+
if (this._selectionRect && this._selectionRect.parentNode) {
|
|
126
|
+
this._selectionRect.parentNode.removeChild(this._selectionRect);
|
|
127
|
+
}
|
|
128
|
+
this._selectionRect = null;
|
|
129
|
+
},
|
|
130
|
+
_updateSelectionRect() {
|
|
131
|
+
if (!this._selectionRect) return;
|
|
132
|
+
const pad = 4;
|
|
133
|
+
this._selectionRect.setAttribute('x', this.x - pad);
|
|
134
|
+
this._selectionRect.setAttribute('y', this.y - pad);
|
|
135
|
+
this._selectionRect.setAttribute('width', this.width + pad * 2);
|
|
136
|
+
this._selectionRect.setAttribute('height', this.height + pad * 2);
|
|
137
|
+
},
|
|
138
|
+
updateAttachedArrows() {
|
|
139
|
+
if (typeof window.updateAttachedArrows === 'function') {
|
|
140
|
+
window.updateAttachedArrows(this);
|
|
141
|
+
}
|
|
118
142
|
},
|
|
119
|
-
updateAttachedArrows() {},
|
|
120
143
|
};
|
|
121
144
|
|
|
122
145
|
window.shapes.push(graphShape);
|
|
123
|
-
if (
|
|
146
|
+
if (window.pushCreateAction) window.pushCreateAction(graphShape);
|
|
147
|
+
|
|
148
|
+
// Auto-select so the user sees something landed.
|
|
149
|
+
window.currentShape = graphShape;
|
|
150
|
+
graphShape.selectShape();
|
|
124
151
|
} catch (err) {
|
|
125
152
|
console.error('[GraphEngine] SVG insertion failed:', err);
|
|
153
|
+
return false;
|
|
126
154
|
}
|
|
127
155
|
|
|
128
|
-
// Select the frame
|
|
129
|
-
window.currentShape = frame;
|
|
130
|
-
if (frame.selectFrame) frame.selectFrame();
|
|
131
|
-
if (window.__sketchStoreApi) window.__sketchStoreApi.setSelectedShapeSidebar('frame');
|
|
132
|
-
|
|
133
156
|
return true;
|
|
134
157
|
}
|
|
135
158
|
|