@elixpo/lixsketch 5.5.11 → 5.5.13
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-PWWLWI6U.js → AIRenderer-ATIKGFB4.js} +90 -8
- package/dist/react/{AIRenderer-PWWLWI6U.js.map → AIRenderer-ATIKGFB4.js.map} +2 -2
- package/dist/react/{CopyPaste-SA72NDFN.js → CopyPaste-VUM5WRDX.js} +2 -2
- package/dist/react/FreehandStroke-JKTCTOKU.js +8 -0
- package/dist/react/{GraphEngine-IHRVGUGG.js → GraphEngine-KQXHNTZQ.js} +39 -1
- package/dist/react/{GraphEngine-IHRVGUGG.js.map → GraphEngine-KQXHNTZQ.js.map} +2 -2
- package/dist/react/{MermaidStructuredRenderer-GGOOGON5.js → MermaidStructuredRenderer-26WGA6YD.js} +152 -25
- package/dist/react/MermaidStructuredRenderer-26WGA6YD.js.map +7 -0
- package/dist/react/{SceneSerializer-ZPHV6IUP.js → SceneSerializer-3RWFYSLY.js} +2 -2
- package/dist/react/{SketchEngine-NPF2XN6Z.js → SketchEngine-WW5LIHNT.js} +6 -6
- package/dist/react/{chunk-YKJUBFHE.js → chunk-ABZEV54U.js} +23 -2
- package/dist/react/chunk-ABZEV54U.js.map +7 -0
- package/dist/react/index.js +55 -47
- package/dist/react/index.js.map +2 -2
- package/dist/react/styles.css +10 -3
- package/package.json +1 -1
- package/src/core/AIRenderer.js +104 -6
- package/src/core/GraphEngine.js +45 -0
- package/src/core/MermaidStructuredRenderer.js +162 -22
- package/src/react/LixSketchCanvas.jsx +4 -0
- package/src/react/components/AppMenu.jsx +2 -2
- package/src/react/components/Toolbar.jsx +1 -1
- package/src/react/components/canvas/FindBar.jsx +1 -1
- package/src/react/components/modals/CanvasPropertiesModal.jsx +1 -1
- package/src/react/components/modals/CommandPalette.jsx +3 -3
- package/src/react/components/sidebars/ArrowSidebar.jsx +6 -6
- package/src/react/components/sidebars/CircleSidebar.jsx +3 -3
- package/src/react/components/sidebars/FrameSidebar.jsx +2 -2
- package/src/react/components/sidebars/IconSidebar.jsx +2 -2
- package/src/react/components/sidebars/LineSidebar.jsx +4 -4
- package/src/react/components/sidebars/PaintbrushSidebar.jsx +5 -5
- package/src/react/components/sidebars/RectangleSidebar.jsx +4 -4
- package/src/react/components/sidebars/ShapeSidebar.jsx +1 -1
- package/src/react/components/sidebars/TextSidebar.jsx +5 -5
- package/src/react/store/useSketchStore.js +7 -2
- package/src/react/store/useUIStore.js +3 -4
- package/src/react/styles.css +12 -3
- package/src/shapes/FreehandStroke.js +28 -3
- package/dist/react/FreehandStroke-CK24NUT3.js +0 -8
- package/dist/react/MermaidStructuredRenderer-GGOOGON5.js.map +0 -7
- package/dist/react/chunk-YKJUBFHE.js.map +0 -7
- /package/dist/react/{CopyPaste-SA72NDFN.js.map → CopyPaste-VUM5WRDX.js.map} +0 -0
- /package/dist/react/{FreehandStroke-CK24NUT3.js.map → FreehandStroke-JKTCTOKU.js.map} +0 -0
- /package/dist/react/{SceneSerializer-ZPHV6IUP.js.map → SceneSerializer-3RWFYSLY.js.map} +0 -0
- /package/dist/react/{SketchEngine-NPF2XN6Z.js.map → SketchEngine-WW5LIHNT.js.map} +0 -0
|
@@ -89,7 +89,7 @@ export default function CircleSidebar() {
|
|
|
89
89
|
<div className="flex items-center gap-1">
|
|
90
90
|
{[1, 2, 4, 7].map((w) => (
|
|
91
91
|
<button key={w} onClick={() => updateThickness(w)}
|
|
92
|
-
className={`w-9 h-8 flex items-center justify-center rounded-lg transition-all duration-100 ${thickness === w ? 'bg-[#
|
|
92
|
+
className={`w-9 h-8 flex items-center justify-center rounded-lg transition-all duration-100 ${thickness === w ? 'bg-[#7667a8]/20 text-[#7667a8]' : 'text-text-muted hover:bg-white/[0.06]'}`}
|
|
93
93
|
>
|
|
94
94
|
<div className="w-5 rounded-full bg-current" style={{ height: Math.max(1, w) }} />
|
|
95
95
|
</button>
|
|
@@ -104,7 +104,7 @@ export default function CircleSidebar() {
|
|
|
104
104
|
<div className="flex items-center gap-1">
|
|
105
105
|
{[{ v: 'solid', d: '' }, { v: 'dashed', d: '6 4' }, { v: 'dotted', d: '2 3' }].map((s) => (
|
|
106
106
|
<button key={s.v} onClick={() => updateStyle(s.v)}
|
|
107
|
-
className={`w-11 h-8 flex items-center justify-center rounded-lg transition-all duration-100 ${lineStyle === s.v ? 'bg-[#
|
|
107
|
+
className={`w-11 h-8 flex items-center justify-center rounded-lg transition-all duration-100 ${lineStyle === s.v ? 'bg-[#7667a8]/20' : 'hover:bg-white/[0.06]'}`}
|
|
108
108
|
>
|
|
109
109
|
<svg width="28" height="4" viewBox="0 0 28 4"><line x1="0" y1="2" x2="28" y2="2" stroke="#fff" strokeWidth="2" strokeDasharray={s.d} strokeLinecap="round" /></svg>
|
|
110
110
|
</button>
|
|
@@ -119,7 +119,7 @@ export default function CircleSidebar() {
|
|
|
119
119
|
<div className="flex flex-col gap-0.5">
|
|
120
120
|
{FILLS.map((f) => (
|
|
121
121
|
<button key={f.value} onClick={() => updateFill(f.value)}
|
|
122
|
-
className={`flex items-center gap-2 px-2.5 py-1.5 rounded-lg text-xs transition-all duration-100 ${fillStyle === f.value ? 'bg-[#
|
|
122
|
+
className={`flex items-center gap-2 px-2.5 py-1.5 rounded-lg text-xs transition-all duration-100 ${fillStyle === f.value ? 'bg-[#7667a8] text-white' : 'text-text-secondary hover:bg-white/[0.06]'}`}
|
|
123
123
|
>
|
|
124
124
|
<span className="w-1.5 h-1.5 rounded-full bg-current" />
|
|
125
125
|
{t(f.label)}
|
|
@@ -16,7 +16,7 @@ const FILL_STYLES = [
|
|
|
16
16
|
|
|
17
17
|
const FILL_COLORS = [
|
|
18
18
|
'#1e1e28',
|
|
19
|
-
'#
|
|
19
|
+
'#15111f',
|
|
20
20
|
'#1a1a2e',
|
|
21
21
|
'#0d1117',
|
|
22
22
|
'#2d2d3a',
|
|
@@ -101,7 +101,7 @@ export default function FrameSidebar() {
|
|
|
101
101
|
type="text"
|
|
102
102
|
value={frameName}
|
|
103
103
|
onChange={updateName}
|
|
104
|
-
className="w-32 px-2.5 py-1.5 bg-white/[0.05] border border-white/[0.1] rounded-lg text-white text-xs outline-none focus:border-[#
|
|
104
|
+
className="w-32 px-2.5 py-1.5 bg-white/[0.05] border border-white/[0.1] rounded-lg text-white text-xs outline-none focus:border-[#7667a8]/50 transition-all duration-150 font-[lixFont]"
|
|
105
105
|
spellCheck={false}
|
|
106
106
|
/>
|
|
107
107
|
</ToolbarButton>
|
|
@@ -65,14 +65,14 @@ function IconCell({ icon, onClick }) {
|
|
|
65
65
|
>
|
|
66
66
|
{normalizedSvg ? (
|
|
67
67
|
<div
|
|
68
|
-
style={{ width: '24px', height: '24px', overflow: 'visible', flexShrink: 0, pointerEvents: 'none', filter: 'brightness(0) invert(1)' }}
|
|
68
|
+
style={{ width: '24px', height: '24px', overflow: 'visible', flexShrink: 0, pointerEvents: 'none', filter: 'var(--lix-icon-filter, brightness(0) invert(1))' }}
|
|
69
69
|
dangerouslySetInnerHTML={{ __html: normalizedSvg }}
|
|
70
70
|
/>
|
|
71
71
|
) : (
|
|
72
72
|
<img
|
|
73
73
|
src={`/icons/${encodeURIComponent(icon.filename)}`}
|
|
74
74
|
alt=""
|
|
75
|
-
style={{ width: '24px', height: '24px', pointerEvents: 'none', filter: 'invert(1)' }}
|
|
75
|
+
style={{ width: '24px', height: '24px', pointerEvents: 'none', filter: 'var(--lix-icon-filter, brightness(0) invert(1))' }}
|
|
76
76
|
loading="lazy"
|
|
77
77
|
/>
|
|
78
78
|
)}
|
|
@@ -12,7 +12,7 @@ function ColorGrid({ colors, selected, onSelect }) {
|
|
|
12
12
|
<div className="grid grid-cols-4 gap-1.5">
|
|
13
13
|
{colors.map((c) => (
|
|
14
14
|
<button key={c} onClick={() => onSelect(c)}
|
|
15
|
-
className={`w-7 h-7 rounded-md border-[1.5px] transition-all duration-100 ${selected === c ? 'border-[#
|
|
15
|
+
className={`w-7 h-7 rounded-md border-[1.5px] transition-all duration-100 ${selected === c ? 'border-[#7667a8] scale-110' : 'border-white/[0.08] hover:border-white/20'}`}
|
|
16
16
|
style={{ backgroundColor: c }}
|
|
17
17
|
/>
|
|
18
18
|
))}
|
|
@@ -52,7 +52,7 @@ export default function LineSidebar() {
|
|
|
52
52
|
<div className="flex items-center gap-1">
|
|
53
53
|
{[1, 2, 4, 7].map((w) => (
|
|
54
54
|
<button key={w} onClick={() => updateThickness(w)}
|
|
55
|
-
className={`w-9 h-8 flex items-center justify-center rounded-lg transition-all duration-100 ${thickness === w ? 'bg-[#
|
|
55
|
+
className={`w-9 h-8 flex items-center justify-center rounded-lg transition-all duration-100 ${thickness === w ? 'bg-[#7667a8]/20 text-[#7667a8]' : 'text-text-muted hover:bg-white/[0.06]'}`}
|
|
56
56
|
>
|
|
57
57
|
<div className="w-5 rounded-full bg-current" style={{ height: Math.max(1, w) }} />
|
|
58
58
|
</button>
|
|
@@ -67,7 +67,7 @@ export default function LineSidebar() {
|
|
|
67
67
|
<div className="flex items-center gap-1">
|
|
68
68
|
{[{ v: 'solid', d: '' }, { v: 'dashed', d: '6 4' }, { v: 'dotted', d: '2 3' }].map((s) => (
|
|
69
69
|
<button key={s.v} onClick={() => updateStyle(s.v)}
|
|
70
|
-
className={`w-11 h-8 flex items-center justify-center rounded-lg transition-all duration-100 ${lineStyle === s.v ? 'bg-[#
|
|
70
|
+
className={`w-11 h-8 flex items-center justify-center rounded-lg transition-all duration-100 ${lineStyle === s.v ? 'bg-[#7667a8]/20' : 'hover:bg-white/[0.06]'}`}
|
|
71
71
|
>
|
|
72
72
|
<svg width="28" height="4" viewBox="0 0 28 4"><line x1="0" y1="2" x2="28" y2="2" stroke="#fff" strokeWidth="2" strokeDasharray={s.d} strokeLinecap="round" /></svg>
|
|
73
73
|
</button>
|
|
@@ -82,7 +82,7 @@ export default function LineSidebar() {
|
|
|
82
82
|
<div className="flex items-center gap-1">
|
|
83
83
|
{[{ v: 0, l: '0' }, { v: 2, l: '2' }, { v: 4, l: '4' }].map((s) => (
|
|
84
84
|
<button key={s.v} onClick={() => updateSloppiness(s.v)}
|
|
85
|
-
className={`w-8 h-8 flex items-center justify-center rounded-lg text-xs transition-all duration-100 ${sloppiness === s.v ? 'bg-[#
|
|
85
|
+
className={`w-8 h-8 flex items-center justify-center rounded-lg text-xs transition-all duration-100 ${sloppiness === s.v ? 'bg-[#7667a8]/20 text-accent-blue' : 'text-text-muted hover:bg-white/6'}`}
|
|
86
86
|
>{s.l}</button>
|
|
87
87
|
))}
|
|
88
88
|
</div>
|
|
@@ -15,7 +15,7 @@ function ColorGrid({ colors, selected, onSelect }) {
|
|
|
15
15
|
<div className="grid grid-cols-4 gap-1.5">
|
|
16
16
|
{colors.map((c) => (
|
|
17
17
|
<button key={c} onClick={() => onSelect(c)}
|
|
18
|
-
className={`w-7 h-7 rounded-md border-[1.5px] transition-all duration-100 ${selected === c ? 'border-[#
|
|
18
|
+
className={`w-7 h-7 rounded-md border-[1.5px] transition-all duration-100 ${selected === c ? 'border-[#7667a8] scale-110' : 'border-white/[0.08] hover:border-white/20'}`}
|
|
19
19
|
style={{ backgroundColor: c }}
|
|
20
20
|
/>
|
|
21
21
|
))}
|
|
@@ -56,7 +56,7 @@ export default function PaintbrushSidebar() {
|
|
|
56
56
|
<div className="flex items-center gap-1">
|
|
57
57
|
{[1, 2, 4, 7].map((w) => (
|
|
58
58
|
<button key={w} onClick={() => updateThickness(w)}
|
|
59
|
-
className={`w-9 h-8 flex items-center justify-center rounded-lg transition-all duration-100 ${thickness === w ? 'bg-[#
|
|
59
|
+
className={`w-9 h-8 flex items-center justify-center rounded-lg transition-all duration-100 ${thickness === w ? 'bg-[#7667a8]/20 text-[#7667a8]' : 'text-text-muted hover:bg-white/[0.06]'}`}
|
|
60
60
|
>
|
|
61
61
|
<div className="w-5 rounded-full bg-current" style={{ height: Math.max(1, w) }} />
|
|
62
62
|
</button>
|
|
@@ -75,7 +75,7 @@ export default function PaintbrushSidebar() {
|
|
|
75
75
|
{ v: 'brush', i: 'bxs-brush', l: 'Brush' },
|
|
76
76
|
].map((t) => (
|
|
77
77
|
<button key={t.v} onClick={() => updateTaper(t.v)}
|
|
78
|
-
className={`flex items-center gap-2 px-2.5 py-1.5 rounded-lg text-xs transition-all duration-100 ${taper === t.v ? 'bg-[#
|
|
78
|
+
className={`flex items-center gap-2 px-2.5 py-1.5 rounded-lg text-xs transition-all duration-100 ${taper === t.v ? 'bg-[#7667a8] text-white' : 'text-text-secondary hover:bg-white/[0.06]'}`}
|
|
79
79
|
>
|
|
80
80
|
<i className={`bx ${t.i} text-sm`} /> {t.l}
|
|
81
81
|
</button>
|
|
@@ -94,7 +94,7 @@ export default function PaintbrushSidebar() {
|
|
|
94
94
|
{ v: 'rough', i: 'bxs-bolt', l: 'Rough' },
|
|
95
95
|
].map((r) => (
|
|
96
96
|
<button key={r.v} onClick={() => updateRoughness(r.v)}
|
|
97
|
-
className={`flex items-center gap-2 px-2.5 py-1.5 rounded-lg text-xs transition-all duration-100 ${roughness === r.v ? 'bg-[#
|
|
97
|
+
className={`flex items-center gap-2 px-2.5 py-1.5 rounded-lg text-xs transition-all duration-100 ${roughness === r.v ? 'bg-[#7667a8] text-white' : 'text-text-secondary hover:bg-white/[0.06]'}`}
|
|
98
98
|
>
|
|
99
99
|
<i className={`bx ${r.i} text-sm`} /> {r.l}
|
|
100
100
|
</button>
|
|
@@ -109,7 +109,7 @@ export default function PaintbrushSidebar() {
|
|
|
109
109
|
<input
|
|
110
110
|
type="range" min="0" max="1" step="0.05" value={opacity}
|
|
111
111
|
onChange={(e) => updateOpacity(parseFloat(e.target.value))}
|
|
112
|
-
className="w-28 h-1 bg-white/10 rounded-full appearance-none cursor-pointer accent-[#
|
|
112
|
+
className="w-28 h-1 bg-white/10 rounded-full appearance-none cursor-pointer accent-[#7667a8]"
|
|
113
113
|
/>
|
|
114
114
|
</ToolbarButton>
|
|
115
115
|
<Divider />
|
|
@@ -26,7 +26,7 @@ function ColorGrid({ colors, selected, onSelect }) {
|
|
|
26
26
|
key={c}
|
|
27
27
|
onClick={() => onSelect(c)}
|
|
28
28
|
className={`w-7 h-7 rounded-md border-[1.5px] transition-all duration-100 ${
|
|
29
|
-
selected === c ? 'border-[#
|
|
29
|
+
selected === c ? 'border-[#7667a8] scale-110' : 'border-white/[0.08] hover:border-white/20'
|
|
30
30
|
}`}
|
|
31
31
|
style={!isTrans ? { backgroundColor: c } : undefined}
|
|
32
32
|
>
|
|
@@ -102,7 +102,7 @@ export default function RectangleSidebar() {
|
|
|
102
102
|
key={w}
|
|
103
103
|
onClick={() => updateThickness(w)}
|
|
104
104
|
className={`w-9 h-8 flex items-center justify-center rounded-lg transition-all duration-100 ${
|
|
105
|
-
thickness === w ? 'bg-[#
|
|
105
|
+
thickness === w ? 'bg-[#7667a8]/20 text-[#7667a8]' : 'text-text-muted hover:bg-white/[0.06]'
|
|
106
106
|
}`}
|
|
107
107
|
>
|
|
108
108
|
<div className="w-5 rounded-full bg-current" style={{ height: Math.max(1, w) }} />
|
|
@@ -126,7 +126,7 @@ export default function RectangleSidebar() {
|
|
|
126
126
|
key={s.v}
|
|
127
127
|
onClick={() => updateStyle(s.v)}
|
|
128
128
|
className={`w-11 h-8 flex items-center justify-center rounded-lg transition-all duration-100 ${
|
|
129
|
-
lineStyle === s.v ? 'bg-[#
|
|
129
|
+
lineStyle === s.v ? 'bg-[#7667a8]/20' : 'hover:bg-white/[0.06]'
|
|
130
130
|
}`}
|
|
131
131
|
>
|
|
132
132
|
<svg width="28" height="4" viewBox="0 0 28 4">
|
|
@@ -148,7 +148,7 @@ export default function RectangleSidebar() {
|
|
|
148
148
|
key={f.value}
|
|
149
149
|
onClick={() => updateFill(f.value)}
|
|
150
150
|
className={`flex items-center gap-2 px-2.5 py-1.5 rounded-lg text-xs transition-all duration-100 ${
|
|
151
|
-
fillStyle === f.value ? 'bg-[#
|
|
151
|
+
fillStyle === f.value ? 'bg-[#7667a8] text-white' : 'text-text-secondary hover:bg-white/[0.06]'
|
|
152
152
|
}`}
|
|
153
153
|
>
|
|
154
154
|
<span className="w-1.5 h-1.5 rounded-full bg-current" />
|
|
@@ -28,7 +28,7 @@ export function ToolbarButton({ icon, preview, children, tooltip }) {
|
|
|
28
28
|
title={tooltip}
|
|
29
29
|
className={`h-9 flex items-center gap-1.5 px-3 rounded-lg transition-all duration-100 ${
|
|
30
30
|
open
|
|
31
|
-
? 'bg-
|
|
31
|
+
? 'bg-accent-blue/20 text-accent-blue'
|
|
32
32
|
: 'text-text-muted hover:text-text-primary hover:bg-surface-hover'
|
|
33
33
|
}`}
|
|
34
34
|
>
|
|
@@ -87,7 +87,7 @@ export default function TextSidebar() {
|
|
|
87
87
|
<div className="grid grid-cols-4 gap-1.5">
|
|
88
88
|
{TEXT_COLORS.map((c) => (
|
|
89
89
|
<button key={c} onClick={() => updateColor(c)}
|
|
90
|
-
className={`w-7 h-7 rounded-md border-[1.5px] transition-all duration-100 ${textColor === c ? 'border-[#
|
|
90
|
+
className={`w-7 h-7 rounded-md border-[1.5px] transition-all duration-100 ${textColor === c ? 'border-[#7667a8] scale-110' : 'border-white/[0.08] hover:border-white/20'}`}
|
|
91
91
|
style={{ backgroundColor: c }}
|
|
92
92
|
/>
|
|
93
93
|
))}
|
|
@@ -104,7 +104,7 @@ export default function TextSidebar() {
|
|
|
104
104
|
<div className="flex flex-col gap-0.5">
|
|
105
105
|
{FONTS.map((f) => (
|
|
106
106
|
<button key={f.value} onClick={() => updateFont(f.value)}
|
|
107
|
-
className={`flex items-center px-2.5 py-1.5 rounded-lg text-xs transition-all duration-100 ${font === f.value ? 'bg-[#
|
|
107
|
+
className={`flex items-center px-2.5 py-1.5 rounded-lg text-xs transition-all duration-100 ${font === f.value ? 'bg-[#7667a8] text-white' : 'text-text-secondary hover:bg-white/[0.06]'}`}
|
|
108
108
|
style={{ fontFamily: f.value }}
|
|
109
109
|
>
|
|
110
110
|
{f.label}
|
|
@@ -123,7 +123,7 @@ export default function TextSidebar() {
|
|
|
123
123
|
<div className="flex items-center gap-1">
|
|
124
124
|
{['S', 'M', 'L', 'XL'].map((s) => (
|
|
125
125
|
<button key={s} onClick={() => updateSize(s)}
|
|
126
|
-
className={`w-8 h-8 flex items-center justify-center rounded-lg text-xs transition-all duration-100 ${fontSize === s ? 'bg-[#
|
|
126
|
+
className={`w-8 h-8 flex items-center justify-center rounded-lg text-xs transition-all duration-100 ${fontSize === s ? 'bg-[#7667a8]/20 text-[#7667a8]' : 'text-text-muted hover:bg-white/[0.06]'}`}
|
|
127
127
|
>{s}</button>
|
|
128
128
|
))}
|
|
129
129
|
</div>
|
|
@@ -136,7 +136,7 @@ export default function TextSidebar() {
|
|
|
136
136
|
<p className="text-xs text-text-muted uppercase tracking-wider mb-2">{t('sidebar.code')}</p>
|
|
137
137
|
<div className="flex flex-col gap-2">
|
|
138
138
|
<button onClick={toggleCodeMode}
|
|
139
|
-
className={`flex items-center gap-2 px-2.5 py-1.5 rounded-lg text-xs transition-all duration-100 ${codeMode ? 'bg-[#
|
|
139
|
+
className={`flex items-center gap-2 px-2.5 py-1.5 rounded-lg text-xs transition-all duration-100 ${codeMode ? 'bg-[#7667a8] text-white' : 'text-text-secondary hover:bg-white/[0.06]'}`}
|
|
140
140
|
>
|
|
141
141
|
<div className={`w-6 h-3 rounded-full transition-all duration-150 relative ${codeMode ? 'bg-white/30' : 'bg-white/10'}`}>
|
|
142
142
|
<div className={`absolute top-0.5 w-2 h-2 rounded-full bg-white transition-all duration-150 ${codeMode ? 'left-3.5' : 'left-0.5'}`} />
|
|
@@ -147,7 +147,7 @@ export default function TextSidebar() {
|
|
|
147
147
|
<div className="flex flex-wrap gap-1 max-w-[180px]">
|
|
148
148
|
{LANGUAGES.map((lang) => (
|
|
149
149
|
<button key={lang} onClick={() => updateLanguage(lang)}
|
|
150
|
-
className={`px-1.5 py-0.5 rounded text-[9px] transition-all duration-100 ${language === lang ? 'bg-[#
|
|
150
|
+
className={`px-1.5 py-0.5 rounded text-[9px] transition-all duration-100 ${language === lang ? 'bg-[#7667a8]/20 text-[#7667a8]' : 'text-text-dim hover:bg-white/[0.06] hover:text-text-secondary'}`}
|
|
151
151
|
>{lang}</button>
|
|
152
152
|
))}
|
|
153
153
|
</div>
|
|
@@ -177,8 +177,13 @@ const useSketchStore = create((set, get) => ({
|
|
|
177
177
|
setPanStart: (p) => set({ panStart: p }),
|
|
178
178
|
|
|
179
179
|
// --- Canvas background ---
|
|
180
|
-
canvasBackground: 'var(--lixsketch-bg, #
|
|
181
|
-
setCanvasBackground: (color) =>
|
|
180
|
+
canvasBackground: 'var(--lixsketch-bg, #15111f)',
|
|
181
|
+
setCanvasBackground: (color) => {
|
|
182
|
+
set({ canvasBackground: color })
|
|
183
|
+
if (typeof window !== 'undefined') {
|
|
184
|
+
requestAnimationFrame(() => window.__adaptCanvasContrast?.(color))
|
|
185
|
+
}
|
|
186
|
+
},
|
|
182
187
|
|
|
183
188
|
// --- Grid ---
|
|
184
189
|
gridEnabled: false,
|
|
@@ -59,10 +59,10 @@ function applyTheme(theme) {
|
|
|
59
59
|
? (window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light')
|
|
60
60
|
: theme
|
|
61
61
|
body.classList.remove('theme-dark', 'theme-light')
|
|
62
|
-
|
|
62
|
+
body.classList.add(`theme-${resolved}`)
|
|
63
63
|
|
|
64
64
|
const svgEl = window.svg
|
|
65
|
-
if (svgEl) svgEl.style.background = resolved === 'light' ? '#
|
|
65
|
+
if (svgEl) svgEl.style.background = resolved === 'light' ? '#fbf9fd' : '#15111f'
|
|
66
66
|
}
|
|
67
67
|
|
|
68
68
|
const useUIStore = create((set, get) => ({
|
|
@@ -157,8 +157,7 @@ const useUIStore = create((set, get) => ({
|
|
|
157
157
|
setCanvasLoading: (loading, message) => set({ canvasLoading: loading, canvasLoadingMessage: message || 'Loading canvas...' }),
|
|
158
158
|
|
|
159
159
|
// --- Theme ---
|
|
160
|
-
|
|
161
|
-
theme: 'light',
|
|
160
|
+
theme: 'dark',
|
|
162
161
|
setTheme: (newTheme) => {
|
|
163
162
|
const prev = get().theme
|
|
164
163
|
const resolve = (t) => t === 'system'
|
package/src/react/styles.css
CHANGED
|
@@ -22,16 +22,25 @@
|
|
|
22
22
|
@import './styles/writeText.css';
|
|
23
23
|
|
|
24
24
|
.lixsketch-canvas-root {
|
|
25
|
+
--lix-icon-filter: brightness(0) invert(1);
|
|
25
26
|
position: relative;
|
|
26
27
|
width: 100%;
|
|
27
28
|
height: 100%;
|
|
28
|
-
background: var(--lixsketch-bg, #
|
|
29
|
-
color: var(--lixsketch-fg, #
|
|
29
|
+
background: var(--lixsketch-bg, #15111f);
|
|
30
|
+
color: var(--lixsketch-fg, #f5effb);
|
|
30
31
|
font-family: var(--lixsketch-font, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif);
|
|
31
32
|
overflow: hidden;
|
|
32
33
|
isolation: isolate;
|
|
33
34
|
}
|
|
34
35
|
|
|
36
|
+
.theme-light .lixsketch-canvas-root {
|
|
37
|
+
--lix-icon-filter: none;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
.theme-dark .lixsketch-canvas-root {
|
|
41
|
+
--lix-icon-filter: brightness(0) invert(1);
|
|
42
|
+
}
|
|
43
|
+
|
|
35
44
|
.lixsketch-canvas-svg {
|
|
36
45
|
position: absolute;
|
|
37
46
|
inset: 0;
|
|
@@ -50,7 +59,7 @@
|
|
|
50
59
|
display: flex;
|
|
51
60
|
align-items: center;
|
|
52
61
|
justify-content: center;
|
|
53
|
-
background: var(--lixsketch-bg, #
|
|
62
|
+
background: var(--lixsketch-bg, #15111f);
|
|
54
63
|
z-index: 50;
|
|
55
64
|
}
|
|
56
65
|
|
|
@@ -186,6 +186,11 @@ class FreehandStroke {
|
|
|
186
186
|
getPathData() {
|
|
187
187
|
if (this.points.length < 2) return '';
|
|
188
188
|
|
|
189
|
+
if (this.options.closedFill) {
|
|
190
|
+
const [first, ...rest] = this.points;
|
|
191
|
+
return [`M ${first[0]} ${first[1]}`, ...rest.map(point => `L ${point[0]} ${point[1]}`), 'Z'].join(' ');
|
|
192
|
+
}
|
|
193
|
+
|
|
189
194
|
const isRough = this.options.roughness === "rough";
|
|
190
195
|
const isMedium = this.options.roughness === "medium";
|
|
191
196
|
|
|
@@ -292,14 +297,20 @@ class FreehandStroke {
|
|
|
292
297
|
this.selectionOutline = null;
|
|
293
298
|
}
|
|
294
299
|
|
|
295
|
-
//
|
|
296
|
-
//
|
|
300
|
+
// Normal freehand paths use the filled outline from perfect-freehand.
|
|
301
|
+
// Closed-fill paths (pie sectors, polygons) use their actual polygon
|
|
302
|
+
// geometry with a separate outline, preserving sharp radial edges.
|
|
297
303
|
const path = document.createElementNS('http://www.w3.org/2000/svg', 'path');
|
|
298
304
|
const pathData = this.getPathData();
|
|
299
305
|
path.setAttribute('d', pathData);
|
|
300
306
|
path.setAttribute('fill', this.options.stroke);
|
|
301
307
|
path.setAttribute('fill-opacity', this.options.strokeOpacity);
|
|
302
|
-
path.setAttribute('stroke', 'none');
|
|
308
|
+
path.setAttribute('stroke', this.options.closedFill ? (this.options.outlineStroke || 'none') : 'none');
|
|
309
|
+
if (this.options.closedFill) {
|
|
310
|
+
path.setAttribute('stroke-width', this.options.outlineWidth || this.options.strokeWidth || 1);
|
|
311
|
+
path.setAttribute('stroke-linejoin', 'round');
|
|
312
|
+
path.setAttribute('vector-effect', 'non-scaling-stroke');
|
|
313
|
+
}
|
|
303
314
|
|
|
304
315
|
// Overlay a dashed/dotted centerline if needed
|
|
305
316
|
if (this.options.strokeStyle === "dashed" || this.options.strokeStyle === "dotted") {
|
|
@@ -425,6 +436,20 @@ class FreehandStroke {
|
|
|
425
436
|
const rotatedX = dx * Math.cos(angleRad) - dy * Math.sin(angleRad) + centerX;
|
|
426
437
|
const rotatedY = dx * Math.sin(angleRad) + dy * Math.cos(angleRad) + centerY;
|
|
427
438
|
|
|
439
|
+
if (this.options.closedFill && this.points.length >= 3) {
|
|
440
|
+
const localX = rotatedX - ox;
|
|
441
|
+
const localY = rotatedY - oy;
|
|
442
|
+
let inside = false;
|
|
443
|
+
for (let i = 0, j = this.points.length - 1; i < this.points.length; j = i++) {
|
|
444
|
+
const xi = this.points[i][0], yi = this.points[i][1];
|
|
445
|
+
const xj = this.points[j][0], yj = this.points[j][1];
|
|
446
|
+
const crosses = ((yi > localY) !== (yj > localY))
|
|
447
|
+
&& (localX < (xj - xi) * (localY - yi) / ((yj - yi) || Number.EPSILON) + xi);
|
|
448
|
+
if (crosses) inside = !inside;
|
|
449
|
+
}
|
|
450
|
+
return inside;
|
|
451
|
+
}
|
|
452
|
+
|
|
428
453
|
return rotatedX >= bbX &&
|
|
429
454
|
rotatedX <= bbX + this.boundingBox.width &&
|
|
430
455
|
rotatedY >= bbY &&
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../src/core/MermaidStructuredRenderer.js"],
|
|
4
|
-
"sourcesContent": ["/* eslint-disable */\n/**\n * Native renderers for Mermaid ER and chart diagrams.\n *\n * Preview is SVG, while canvas placement deliberately creates ordinary\n * LixSketch shapes. That keeps entities, attributes, relationships, bars,\n * points, and legend items independently selectable and editable.\n */\n\nconst NS = 'http://www.w3.org/2000/svg';\nconst PALETTE = [\n { fill: '#dfeee4', stroke: '#5f836c' },\n { fill: '#f4e3d4', stroke: '#a97852' },\n { fill: '#e9e1ef', stroke: '#7e6b91' },\n { fill: '#f3edc9', stroke: '#9a8745' },\n { fill: '#dcebed', stroke: '#5d7f82' },\n { fill: '#f1dedc', stroke: '#9a6863' },\n];\n\nfunction escapeXml(value) {\n return String(value ?? '')\n .replace(/&/g, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/\"/g, '"');\n}\n\nfunction isDark() {\n return typeof document !== 'undefined' && document.body?.classList.contains('theme-dark');\n}\n\nfunction theme() {\n return isDark()\n ? { bg: '#20232a', text: '#f0eee8', line: '#aaa89f', frame: '#77766f', panel: '#292d34' }\n : { bg: '#fbfaf6', text: '#343832', line: '#6e746c', frame: '#b9b7ac', panel: '#f5f2ea' };\n}\n\nfunction sourceLines(src) {\n return src.split('\\n').map(line => line.trim()).filter(line => line && !line.startsWith('%%'));\n}\n\nexport function detectStructuredMermaid(src) {\n const header = sourceLines(src)[0]?.toLowerCase() || '';\n if (header === 'erdiagram') return 'er';\n if (/^pie(?:\\s|$)/.test(header) || /^xychart(?:-beta)?(?:\\s|$)/.test(header)) return 'chart';\n return null;\n}\n\n// ---------------------------------------------------------------------\n// Entity relationship diagrams\n// ---------------------------------------------------------------------\n\nexport function parseERDiagram(src) {\n const lines = sourceLines(src);\n if (lines[0]?.toLowerCase() !== 'erdiagram') return null;\n\n const entityMap = new Map();\n const relationships = [];\n let current = null;\n\n const ensureEntity = (name) => {\n if (!entityMap.has(name)) entityMap.set(name, { name, attributes: [] });\n return entityMap.get(name);\n };\n\n for (let index = 1; index < lines.length; index++) {\n const line = lines[index];\n const entityStart = line.match(/^([\\w-]+)\\s*\\{$/);\n if (entityStart) {\n current = ensureEntity(entityStart[1]);\n continue;\n }\n if (line === '}') {\n current = null;\n continue;\n }\n if (current) {\n const attribute = line.match(/^(\\S+)\\s+(\\S+)(?:\\s+(.+))?$/);\n if (attribute) {\n current.attributes.push({\n type: attribute[1],\n name: attribute[2],\n key: attribute[3] || '',\n });\n }\n continue;\n }\n\n // CUSTOMER ||--o{ ORDER : places\n const relation = line.match(/^([\\w-]+)\\s+([|o}{.]+)(?:--|\\.\\.)([|o}{.]+)\\s+([\\w-]+)\\s*:\\s*(.+)$/);\n if (relation) {\n ensureEntity(relation[1]);\n ensureEntity(relation[4]);\n relationships.push({\n from: relation[1],\n fromCardinality: relation[2],\n toCardinality: relation[3],\n to: relation[4],\n label: relation[5],\n });\n }\n }\n\n if (entityMap.size === 0) return null;\n return { type: 'erDiagram', title: 'Entity relationship diagram', entities: [...entityMap.values()], relationships };\n}\n\nfunction layoutER(diagram) {\n const width = 230;\n const headerHeight = 44;\n const rowHeight = 30;\n const columns = Math.max(1, Math.ceil(Math.sqrt(diagram.entities.length)));\n return diagram.entities.map((entity, index) => ({\n ...entity,\n x: 60 + (index % columns) * 330,\n y: 55 + Math.floor(index / columns) * 270,\n width,\n headerHeight,\n rowHeight,\n height: headerHeight + Math.max(1, entity.attributes.length) * rowHeight,\n color: PALETTE[index % PALETTE.length],\n }));\n}\n\nexport function renderERPreviewSVG(diagram) {\n if (!diagram?.entities?.length) return '';\n const TK = theme();\n const entities = layoutER(diagram);\n const byName = new Map(entities.map(entity => [entity.name, entity]));\n const maxX = Math.max(...entities.map(entity => entity.x + entity.width)) + 60;\n const maxY = Math.max(...entities.map(entity => entity.y + entity.height)) + 55;\n let content = `<rect width=\"${maxX}\" height=\"${maxY}\" rx=\"10\" fill=\"${TK.bg}\"/>`;\n content += `<defs><marker id=\"er-arrow\" markerWidth=\"9\" markerHeight=\"7\" refX=\"8\" refY=\"3.5\" orient=\"auto\"><path d=\"M1 1 L8 3.5 L1 6\" fill=\"none\" stroke=\"${TK.line}\" stroke-width=\"1.4\"/></marker></defs>`;\n\n for (const relation of diagram.relationships) {\n const from = byName.get(relation.from);\n const to = byName.get(relation.to);\n if (!from || !to) continue;\n const x1 = from.x + from.width / 2;\n const y1 = from.y + from.height / 2;\n const x2 = to.x + to.width / 2;\n const y2 = to.y + to.height / 2;\n const mx = (x1 + x2) / 2;\n const my = (y1 + y2) / 2;\n content += `<line x1=\"${x1}\" y1=\"${y1}\" x2=\"${x2}\" y2=\"${y2}\" stroke=\"${TK.line}\" stroke-width=\"1.6\" marker-end=\"url(#er-arrow)\"/>`;\n content += `<text x=\"${mx}\" y=\"${my - 8}\" text-anchor=\"middle\" fill=\"${TK.text}\" font-size=\"12\" font-family=\"lixFont\">${escapeXml(`${relation.fromCardinality} ${relation.label} ${relation.toCardinality}`)}</text>`;\n }\n\n for (const entity of entities) {\n content += `<g><rect x=\"${entity.x}\" y=\"${entity.y}\" width=\"${entity.width}\" height=\"${entity.height}\" rx=\"8\" fill=\"${TK.panel}\" stroke=\"${entity.color.stroke}\" stroke-width=\"1.5\"/>`;\n content += `<rect x=\"${entity.x}\" y=\"${entity.y}\" width=\"${entity.width}\" height=\"${entity.headerHeight}\" rx=\"8\" fill=\"${entity.color.fill}\" stroke=\"${entity.color.stroke}\" stroke-width=\"1.5\"/>`;\n content += `<text x=\"${entity.x + entity.width / 2}\" y=\"${entity.y + 27}\" text-anchor=\"middle\" fill=\"#343832\" font-size=\"14\" font-weight=\"600\" font-family=\"lixFont\">${escapeXml(entity.name)}</text>`;\n const attributes = entity.attributes.length ? entity.attributes : [{ type: '', name: 'No attributes', key: '' }];\n attributes.forEach((attribute, row) => {\n const y = entity.y + entity.headerHeight + row * entity.rowHeight;\n content += `<line x1=\"${entity.x}\" y1=\"${y}\" x2=\"${entity.x + entity.width}\" y2=\"${y}\" stroke=\"${TK.frame}\" stroke-width=\"0.8\"/>`;\n content += `<text x=\"${entity.x + 10}\" y=\"${y + 20}\" fill=\"${TK.text}\" font-size=\"11\" font-family=\"lixCode\">${escapeXml([attribute.type, attribute.name, attribute.key].filter(Boolean).join(' '))}</text>`;\n });\n content += '</g>';\n }\n return `<svg xmlns=\"${NS}\" width=\"600\" height=\"450\" viewBox=\"0 0 ${maxX} ${maxY}\">${content}</svg>`;\n}\n\n// ---------------------------------------------------------------------\n// Pie and XY charts\n// ---------------------------------------------------------------------\n\nfunction numberList(value) {\n return value.replace(/^\\[|\\]$/g, '').split(',').map(item => Number(item.trim())).filter(Number.isFinite);\n}\n\nexport function parseChartDiagram(src) {\n const lines = sourceLines(src);\n const header = lines[0]?.toLowerCase() || '';\n if (/^pie(?:\\s|$)/.test(header)) {\n let title = lines[0].replace(/^pie(?:\\s+showData)?\\s*/i, '').replace(/^title\\s+/i, '').trim() || 'Pie chart';\n const values = [];\n for (let index = 1; index < lines.length; index++) {\n const titleMatch = lines[index].match(/^title\\s+(.+)$/i);\n if (titleMatch) { title = titleMatch[1]; continue; }\n const item = lines[index].match(/^\"?(.+?)\"?\\s*:\\s*(-?\\d+(?:\\.\\d+)?)$/);\n if (item) values.push({ label: item[1], value: Number(item[2]) });\n }\n return values.length ? { type: 'chart', kind: 'pie', title, categories: values.map(v => v.label), series: [{ name: title, values: values.map(v => v.value) }] } : null;\n }\n if (!/^xychart(?:-beta)?(?:\\s|$)/.test(header)) return null;\n let title = 'Chart';\n let categories = [];\n const series = [];\n for (let index = 1; index < lines.length; index++) {\n const titleMatch = lines[index].match(/^title\\s+\"?(.+?)\"?$/i);\n const axisMatch = lines[index].match(/^x-axis(?:\\s+\".*?\")?\\s+(\\[.+\\])/i);\n const seriesMatch = lines[index].match(/^(bar|line)(?:\\s+\"?([^\"\\[]+)\"?)?\\s+(\\[.+\\])$/i);\n if (titleMatch) title = titleMatch[1];\n else if (axisMatch) categories = axisMatch[1].replace(/^\\[|\\]$/g, '').split(',').map(v => v.trim().replace(/^\"|\"$/g, ''));\n else if (seriesMatch) series.push({ kind: seriesMatch[1].toLowerCase(), name: seriesMatch[2]?.trim() || seriesMatch[1], values: numberList(seriesMatch[3]) });\n }\n const maxItems = Math.max(0, ...series.map(item => item.values.length));\n if (!categories.length) categories = Array.from({ length: maxItems }, (_, index) => String(index + 1));\n return series.length ? { type: 'chart', kind: 'xy', title, categories, series } : null;\n}\n\nexport function renderChartPreviewSVG(chart) {\n if (!chart?.series?.length) return '';\n const TK = theme();\n const width = 720;\n const height = 450;\n const left = 70;\n const top = 60;\n const plotWidth = 580;\n const plotHeight = 300;\n const values = chart.series.flatMap(series => series.values);\n const maximum = Math.max(1, ...values.map(Math.abs));\n const categoryCount = Math.max(1, chart.categories.length);\n const slot = plotWidth / categoryCount;\n let content = `<rect width=\"${width}\" height=\"${height}\" rx=\"10\" fill=\"${TK.bg}\"/><text x=\"${width / 2}\" y=\"32\" text-anchor=\"middle\" fill=\"${TK.text}\" font-size=\"18\" font-family=\"lixFont\">${escapeXml(chart.title)}</text>`;\n content += `<line x1=\"${left}\" y1=\"${top}\" x2=\"${left}\" y2=\"${top + plotHeight}\" stroke=\"${TK.line}\"/><line x1=\"${left}\" y1=\"${top + plotHeight}\" x2=\"${left + plotWidth}\" y2=\"${top + plotHeight}\" stroke=\"${TK.line}\"/>`;\n\n chart.categories.forEach((category, index) => {\n content += `<text x=\"${left + slot * (index + .5)}\" y=\"${top + plotHeight + 24}\" text-anchor=\"middle\" fill=\"${TK.text}\" font-size=\"11\" font-family=\"lixFont\">${escapeXml(category)}</text>`;\n });\n\n chart.series.forEach((series, seriesIndex) => {\n const color = PALETTE[seriesIndex % PALETTE.length];\n if (series.kind === 'line') {\n const points = series.values.map((value, index) => `${left + slot * (index + .5)},${top + plotHeight - Math.abs(value) / maximum * plotHeight}`).join(' ');\n content += `<polyline points=\"${points}\" fill=\"none\" stroke=\"${color.stroke}\" stroke-width=\"3\"/>`;\n series.values.forEach((value, index) => content += `<circle cx=\"${left + slot * (index + .5)}\" cy=\"${top + plotHeight - Math.abs(value) / maximum * plotHeight}\" r=\"5\" fill=\"${color.fill}\" stroke=\"${color.stroke}\" stroke-width=\"2\"/>`);\n } else {\n const barWidth = Math.max(12, slot * .7 / chart.series.length);\n series.values.forEach((value, index) => {\n const barHeight = Math.abs(value) / maximum * plotHeight;\n const x = left + slot * index + slot * .15 + seriesIndex * barWidth;\n content += `<rect x=\"${x}\" y=\"${top + plotHeight - barHeight}\" width=\"${barWidth}\" height=\"${barHeight}\" rx=\"4\" fill=\"${color.fill}\" stroke=\"${color.stroke}\" stroke-width=\"1.5\"/><text x=\"${x + barWidth / 2}\" y=\"${top + plotHeight - barHeight - 7}\" text-anchor=\"middle\" fill=\"${TK.text}\" font-size=\"10\" font-family=\"lixFont\">${value}</text>`;\n });\n }\n });\n return `<svg xmlns=\"${NS}\" width=\"600\" height=\"450\" viewBox=\"0 0 ${width} ${height}\">${content}</svg>`;\n}\n\n// ---------------------------------------------------------------------\n// Native canvas placement helpers\n// ---------------------------------------------------------------------\n\nfunction push(shape, frame) {\n if (!shape) return null;\n window.shapes.push(shape);\n if (window.pushCreateAction) window.pushCreateAction(shape);\n if (frame?.addShapeToFrame) frame.addShapeToFrame(shape);\n return shape;\n}\n\nfunction canvasOrigin(width, height) {\n const vb = window.currentViewBox || { x: 0, y: 0, width: window.innerWidth, height: window.innerHeight };\n return { x: vb.x + vb.width / 2 - width / 2, y: vb.y + vb.height / 2 - height / 2 };\n}\n\nfunction createFrame(x, y, width, height, name, type) {\n const TK = theme();\n const frame = new window.Frame(x - 45, y - 45, width + 90, height + 90, {\n stroke: TK.frame, strokeWidth: 1, fill: 'transparent', opacity: .75, frameName: name,\n });\n frame._diagramType = type;\n push(frame);\n return frame;\n}\n\nexport function renderEROnCanvas(diagram) {\n if (!diagram?.entities?.length || !window.Rectangle || !window.Arrow || !window.Frame) return false;\n const TK = theme();\n const entities = layoutER(diagram);\n const width = Math.max(...entities.map(entity => entity.x + entity.width)) + 40;\n const height = Math.max(...entities.map(entity => entity.y + entity.height)) + 40;\n const origin = canvasOrigin(width, height);\n const frame = createFrame(origin.x, origin.y, width, height, diagram.title, 'mermaid-er');\n const entityShapes = new Map();\n let first = null;\n\n for (const entity of entities) {\n const x = origin.x + entity.x;\n const y = origin.y + entity.y;\n const header = push(new window.Rectangle(x, y, entity.width, entity.headerHeight, {\n stroke: entity.color.stroke, strokeWidth: 1.5, fill: entity.color.fill, fillStyle: 'solid', roughness: 1,\n label: entity.name, labelColor: '#343832', labelFontSize: 15,\n }), frame);\n if (!first) first = header;\n entityShapes.set(entity.name, { shape: header, x, y, width: entity.width, height: entity.headerHeight });\n const attributes = entity.attributes.length ? entity.attributes : [{ type: '', name: 'No attributes', key: '' }];\n attributes.forEach((attribute, row) => push(new window.Rectangle(\n x, y + entity.headerHeight + row * entity.rowHeight, entity.width, entity.rowHeight,\n { stroke: TK.frame, strokeWidth: 1, fill: TK.panel, fillStyle: 'solid', roughness: .4,\n label: [attribute.type, attribute.name, attribute.key].filter(Boolean).join(' '), labelColor: TK.text, labelFontSize: 11 }\n ), frame));\n }\n\n for (const relation of diagram.relationships) {\n const from = entityShapes.get(relation.from);\n const to = entityShapes.get(relation.to);\n if (!from || !to) continue;\n const start = { x: from.x + from.width / 2, y: from.y + from.height / 2 };\n const end = { x: to.x + to.width / 2, y: to.y + to.height / 2 };\n const arrow = push(new window.Arrow(start, end, {\n stroke: TK.line, strokeWidth: 1.5, roughness: 1,\n label: `${relation.fromCardinality} ${relation.label} ${relation.toCardinality}`, labelColor: TK.text,\n }), frame);\n if (arrow && window.__autoAttach) {\n window.__autoAttach(arrow, from.shape, true, start);\n window.__autoAttach(arrow, to.shape, false, end);\n }\n }\n if (first?.selectShape) { window.currentShape = first; first.selectShape(); }\n return true;\n}\n\nexport function renderChartOnCanvas(chart) {\n if (!chart?.series?.length || !window.Rectangle || !window.Circle || !window.Line || !window.Frame) return false;\n const TK = theme();\n const width = 720;\n const height = 450;\n const origin = canvasOrigin(width, height);\n const frame = createFrame(origin.x, origin.y, width, height, chart.title, 'mermaid-chart');\n const left = origin.x + 70;\n const top = origin.y + 65;\n const plotWidth = 580;\n const plotHeight = 300;\n const values = chart.series.flatMap(series => series.values);\n const maximum = Math.max(1, ...values.map(Math.abs));\n const slot = plotWidth / Math.max(1, chart.categories.length);\n let first = null;\n\n push(new window.Line({ x: left, y: top }, { x: left, y: top + plotHeight }, { stroke: TK.line, strokeWidth: 1.5, roughness: 0 }), frame);\n push(new window.Line({ x: left, y: top + plotHeight }, { x: left + plotWidth, y: top + plotHeight }, { stroke: TK.line, strokeWidth: 1.5, roughness: 0 }), frame);\n\n chart.series.forEach((series, seriesIndex) => {\n const color = PALETTE[seriesIndex % PALETTE.length];\n if (series.kind === 'line') {\n let previous = null;\n series.values.forEach((value, index) => {\n const point = { x: left + slot * (index + .5), y: top + plotHeight - Math.abs(value) / maximum * plotHeight };\n const dot = push(new window.Circle(point.x, point.y, 8, 8, {\n stroke: color.stroke, strokeWidth: 2, fill: color.fill, fillStyle: 'solid', roughness: .5,\n label: String(value), labelColor: TK.text, labelFontSize: 9,\n }), frame);\n if (!first) first = dot;\n if (previous) push(new window.Line(previous, point, { stroke: color.stroke, strokeWidth: 3, roughness: .5 }), frame);\n previous = point;\n });\n } else {\n const barWidth = Math.max(18, slot * .7 / chart.series.length);\n series.values.forEach((value, index) => {\n const barHeight = Math.max(8, Math.abs(value) / maximum * plotHeight);\n const x = left + slot * index + slot * .15 + seriesIndex * barWidth;\n const bar = push(new window.Rectangle(x, top + plotHeight - barHeight, barWidth, barHeight, {\n stroke: color.stroke, strokeWidth: 1.5, fill: color.fill, fillStyle: 'solid', roughness: .7,\n label: `${chart.categories[index] || index + 1}\\n${value}`, labelColor: '#343832', labelFontSize: 11,\n }), frame);\n if (!first) first = bar;\n });\n }\n });\n if (first?.selectShape) { window.currentShape = first; first.selectShape(); }\n return true;\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": ["title"]
|
|
7
|
-
}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../src/shapes/FreehandStroke.js"],
|
|
4
|
-
"sourcesContent": ["/* eslint-disable */\nimport { getStroke } from \"perfect-freehand\";\n// FreehandStroke shape class - extracted from canvasStroke.js\n// Depends on globals: svg, shapes, currentShape, currentZoom, currentViewBox\n\nfunction getSvgCoordinates(event) {\n const rect = svg.getBoundingClientRect();\n const scaleX = currentViewBox.width / rect.width;\n const scaleY = currentViewBox.height / rect.height;\n\n const svgX = currentViewBox.x + (event.clientX - rect.left) * scaleX;\n const svgY = currentViewBox.y + (event.clientY - rect.top) * scaleY;\n\n return { x: svgX, y: svgY };\n}\n\nfunction getSvgPathFromStroke(stroke) {\n if (!stroke.length) return '';\n \n // Use more sophisticated curve fitting\n const pathData = [];\n pathData.push('M', stroke[0][0], stroke[0][1]);\n \n for (let i = 1; i < stroke.length - 1; i++) {\n const curr = stroke[i];\n const next = stroke[i + 1];\n \n // Calculate control points for smoother curves\n const cpX = curr[0] + (next[0] - curr[0]) * 0.5;\n const cpY = curr[1] + (next[1] - curr[1]) * 0.5;\n \n pathData.push('Q', curr[0], curr[1], cpX, cpY);\n }\n \n // Add final point\n if (stroke.length > 1) {\n const lastPoint = stroke[stroke.length - 1];\n pathData.push('L', lastPoint[0], lastPoint[1]);\n }\n \n return pathData.join(' ');\n}\n\nclass FreehandStroke {\n constructor(points = [], options = {}) {\n this.points = points;\n this.rawPoints = []; \n this.options = {\n stroke: \"#fff\",\n strokeWidth: 3,\n fill: \"none\",\n strokeLinecap: \"round\",\n strokeLinejoin: \"round\",\n strokeOpacity: 1,\n thinning: 0.5,\n roughness: 0,\n strokeStyle: \"solid\",\n ...options\n };\n this.element = null;\n this.isSelected = false;\n this.rotation = 0;\n this.group = document.createElementNS('http://www.w3.org/2000/svg', 'g');\n this.anchors = [];\n this.rotationAnchor = null;\n this.rotationLine = null;\n this.selectionPadding = 8;\n this.selectionOutline = null;\n this.boundingBox = { x: 0, y: 0, width: 0, height: 0 };\n this.shapeName = \"freehandStroke\";\n this._moveOffsetX = 0;\n this._moveOffsetY = 0;\n\n // Frame attachment properties\n this.parentFrame = null;\n \n svg.appendChild(this.group);\n this.draw();\n }\n\n // Add position and dimension properties for frame compatibility\n // Getters include pending move offset so callers see the visual position\n get x() {\n return this.boundingBox.x + (this._moveOffsetX || 0);\n }\n\n set x(value) {\n const dx = value - this.boundingBox.x - (this._moveOffsetX || 0);\n this.points = this.points.map(point => [point[0] + dx, point[1], point[2] || 0.5]);\n this.boundingBox.x = value - (this._moveOffsetX || 0);\n }\n\n get y() {\n return this.boundingBox.y + (this._moveOffsetY || 0);\n }\n\n set y(value) {\n const dy = value - this.boundingBox.y - (this._moveOffsetY || 0);\n this.points = this.points.map(point => [point[0], point[1] + dy, point[2] || 0.5]);\n this.boundingBox.y = value - (this._moveOffsetY || 0);\n }\n \n get width() {\n return this.boundingBox.width;\n }\n \n set width(value) {\n if (this.boundingBox.width === 0) return;\n const scaleX = value / this.boundingBox.width;\n const centerX = this.boundingBox.x + this.boundingBox.width / 2;\n this.points = this.points.map(point => [\n centerX + (point[0] - centerX) * scaleX,\n point[1],\n point[2] || 0.5\n ]);\n this.boundingBox.width = value;\n }\n \n get height() {\n return this.boundingBox.height;\n }\n \n set height(value) {\n if (this.boundingBox.height === 0) return;\n const scaleY = value / this.boundingBox.height;\n const centerY = this.boundingBox.y + this.boundingBox.height / 2;\n this.points = this.points.map(point => [\n point[0],\n centerY + (point[1] - centerY) * scaleY,\n point[2] || 0.5\n ]);\n this.boundingBox.height = value;\n }\n\n // Enhanced smoothing algorithm\n smoothPoints(points, factor = 0.8) {\n if (points.length < 3) return points;\n \n const smoothed = [points[0]]; // Keep first point\n \n for (let i = 1; i < points.length - 1; i++) {\n const prev = points[i - 1];\n const curr = points[i];\n const next = points[i + 1];\n \n // Apply weighted average smoothing\n const smoothedX = curr[0] * (1 - factor) + (prev[0] + next[0]) * factor * 0.5;\n const smoothedY = curr[1] * (1 - factor) + (prev[1] + next[1]) * factor * 0.5;\n const pressure = curr[2] || 0.5;\n \n smoothed.push([smoothedX, smoothedY, pressure]);\n }\n \n smoothed.push(points[points.length - 1]); // Keep last point\n return smoothed;\n }\n\n // Interpolate points for smoother curves\n interpolatePoints(points, steps = 2) {\n if (points.length < 2) return points;\n \n const interpolated = [points[0]];\n \n for (let i = 0; i < points.length - 1; i++) {\n const curr = points[i];\n const next = points[i + 1];\n \n for (let j = 1; j <= steps; j++) {\n const t = j / (steps + 1);\n const x = curr[0] + (next[0] - curr[0]) * t;\n const y = curr[1] + (next[1] - curr[1]) * t;\n const pressure = curr[2] + (next[2] - curr[2]) * t;\n interpolated.push([x, y, pressure]);\n }\n \n if (i < points.length - 2) {\n interpolated.push(next);\n }\n }\n \n interpolated.push(points[points.length - 1]);\n return interpolated;\n }\n\n // Enhanced path generation with better curve fitting\n getPathData() {\n if (this.points.length < 2) return '';\n\n const isRough = this.options.roughness === \"rough\";\n const isMedium = this.options.roughness === \"medium\";\n\n // Roughness: jitter points before smoothing\n let pts = this.points;\n if (isRough || isMedium) {\n const jitter = isRough ? 3.5 : 1.5;\n pts = pts.map((p, i) => {\n if (i === 0 || i === pts.length - 1) return p;\n return [\n p[0] + (Math.random() - 0.5) * jitter,\n p[1] + (Math.random() - 0.5) * jitter,\n p[2] || 0.5\n ];\n });\n }\n\n let smoothedPoints = this.interpolatePoints(pts, 1);\n if (!isRough) {\n smoothedPoints = this.smoothPoints(smoothedPoints, 0.6);\n smoothedPoints = this.smoothPoints(smoothedPoints, 0.4);\n }\n\n const thinning = this.options.thinning !== undefined ? this.options.thinning : 0;\n const smoothing = isRough ? 0.3 : isMedium ? 0.6 : 0.9;\n const streamline = isRough ? 0.1 : isMedium ? 0.25 : 0.4;\n\n const stroke = getStroke(smoothedPoints, {\n size: this.options.strokeWidth,\n thinning: thinning,\n smoothing: smoothing,\n streamline: streamline,\n easing: (t) => Math.sin(t * Math.PI * 0.5),\n start: {\n taper: thinning > 0 ? this.options.strokeWidth * 2 : 0,\n easing: (t) => t * t,\n cap: thinning === 0\n },\n end: {\n taper: thinning > 0 ? this.options.strokeWidth * 2 : 0,\n easing: (t) => --t * t * t + 1,\n cap: thinning === 0\n },\n simulatePressure: thinning > 0\n });\n\n return getSvgPathFromStroke(stroke);\n }\n\n // Simple centerline path used for dashed/dotted overlays\n getCenterlinePathData() {\n if (this.points.length < 2) return '';\n const d = [`M ${this.points[0][0]} ${this.points[0][1]}`];\n for (let i = 1; i < this.points.length - 1; i++) {\n const curr = this.points[i];\n const next = this.points[i + 1];\n const cpX = curr[0] + (next[0] - curr[0]) * 0.5;\n const cpY = curr[1] + (next[1] - curr[1]) * 0.5;\n d.push(`Q ${curr[0]} ${curr[1]} ${cpX} ${cpY}`);\n }\n const last = this.points[this.points.length - 1];\n d.push(`L ${last[0]} ${last[1]}`);\n return d.join(' ');\n }\n\n // Calculate the bounding box of the stroke\n calculateBoundingBox() {\n if (this.points.length === 0) {\n return { x: 0, y: 0, width: 0, height: 0 };\n }\n \n let minX = Infinity, minY = Infinity;\n let maxX = -Infinity, maxY = -Infinity;\n \n this.points.forEach(point => {\n minX = Math.min(minX, point[0]);\n minY = Math.min(minY, point[1]);\n maxX = Math.max(maxX, point[0]);\n maxY = Math.max(maxY, point[1]);\n });\n \n // Ensure we have valid dimensions\n if (minX === Infinity || minY === Infinity) {\n return { x: 0, y: 0, width: 0, height: 0 };\n }\n \n // Add padding for stroke width\n const padding = this.options.strokeWidth / 2;\n return {\n x: minX - padding,\n y: minY - padding,\n width: Math.max(0, (maxX - minX) + padding * 2),\n height: Math.max(0, (maxY - minY) + padding * 2)\n };\n }\n\n draw() {\n while (this.group.firstChild) {\n this.group.removeChild(this.group.firstChild);\n }\n\n if (this.selectionOutline && this.selectionOutline.parentNode === this.group) {\n this.group.removeChild(this.selectionOutline);\n this.selectionOutline = null;\n }\n\n // Create the path element\n // perfect-freehand returns a filled outline \u2014 use fill, not stroke\n const path = document.createElementNS('http://www.w3.org/2000/svg', 'path');\n const pathData = this.getPathData();\n path.setAttribute('d', pathData);\n path.setAttribute('fill', this.options.stroke);\n path.setAttribute('fill-opacity', this.options.strokeOpacity);\n path.setAttribute('stroke', 'none');\n\n // Overlay a dashed/dotted centerline if needed\n if (this.options.strokeStyle === \"dashed\" || this.options.strokeStyle === \"dotted\") {\n const dashArray = this.options.strokeStyle === \"dashed\"\n ? `${this.options.strokeWidth * 3} ${this.options.strokeWidth * 2}`\n : `${this.options.strokeWidth * 0.5} ${this.options.strokeWidth * 2}`;\n const overlay = document.createElementNS('http://www.w3.org/2000/svg', 'path');\n overlay.setAttribute('d', this.getCenterlinePathData());\n overlay.setAttribute('fill', 'none');\n overlay.setAttribute('stroke', this.options.stroke);\n overlay.setAttribute('stroke-width', this.options.strokeWidth);\n overlay.setAttribute('stroke-linecap', 'round');\n overlay.setAttribute('stroke-linejoin', 'round');\n overlay.setAttribute('stroke-dasharray', dashArray);\n overlay.setAttribute('stroke-opacity', this.options.strokeOpacity);\n this.group.appendChild(overlay);\n }\n\n this.element = path;\n this.group.appendChild(path);\n\n // Calculate and store bounding box\n this.boundingBox = this.calculateBoundingBox();\n\n // Apply rotation\n const centerX = this.boundingBox.x + this.boundingBox.width / 2;\n const centerY = this.boundingBox.y + this.boundingBox.height / 2;\n\n // Ensure centerX and centerY are valid numbers\n if (!isNaN(centerX) && !isNaN(centerY)) {\n this.group.setAttribute('transform', `rotate(${this.rotation} ${centerX} ${centerY})`);\n }\n\n if (this.isSelected) {\n this.addAnchors();\n }\n }\n\n move(dx, dy) {\n // Accumulate offset for transform-based movement (avoids full path rebuild)\n this._moveOffsetX = (this._moveOffsetX || 0) + dx;\n this._moveOffsetY = (this._moveOffsetY || 0) + dy;\n const centerX = this.boundingBox.x + this.boundingBox.width / 2;\n const centerY = this.boundingBox.y + this.boundingBox.height / 2;\n const rot = this.rotation ? `rotate(${this.rotation} ${centerX} ${centerY})` : '';\n this.group.setAttribute('transform', `translate(${this._moveOffsetX}, ${this._moveOffsetY}) ${rot}`);\n }\n\n // Call after drag ends to bake the offset into actual point coordinates\n finalizeMove() {\n if (this._moveOffsetX || this._moveOffsetY) {\n const ox = this._moveOffsetX || 0;\n const oy = this._moveOffsetY || 0;\n this.points = this.points.map(point => [point[0] + ox, point[1] + oy, point[2] || 0.5]);\n this._moveOffsetX = 0;\n this._moveOffsetY = 0;\n this.draw();\n }\n }\n\n updateAttachedArrows() {\n if (typeof window.__updateArrowsForShape === 'function') {\n window.__updateArrowsForShape(this);\n }\n }\n\n selectStroke() {\n this.isSelected = true;\n this.draw();\n // Show sidebar and update it with current stroke properties\n disableAllSideBars();\n paintBrushSideBar.classList.remove(\"hidden\");\n if (window.__showSidebarForShape) window.__showSidebarForShape('freehandStroke');\n this.updateSidebar();\n }\n\n deselectStroke() {\n this.isSelected = false;\n this.anchors = [];\n this.rotationAnchor = null;\n this.draw();\n }\n\n removeSelection() {\n this.anchors.forEach(anchor => {\n if (anchor.parentNode === this.group) {\n this.group.removeChild(anchor);\n }\n });\n if (this.rotationAnchor && this.rotationAnchor.parentNode === this.group) {\n this.group.removeChild(this.rotationAnchor);\n }\n if (this.rotationLine && this.rotationLine.parentNode === this.group) {\n this.group.removeChild(this.rotationLine);\n }\n if (this.selectionOutline && this.selectionOutline.parentNode === this.group) {\n this.group.removeChild(this.selectionOutline);\n }\n this.anchors = [];\n this.rotationAnchor = null;\n this.rotationLine = null;\n this.selectionOutline = null;\n this.isSelected = false;\n }\n\n // No-op: React sidebar handles UI updates via Zustand store\n updateSidebar() {}\n\n contains(x, y) {\n // Account for pending move offset (during drag, points aren't updated yet)\n const ox = this._moveOffsetX || 0;\n const oy = this._moveOffsetY || 0;\n const bbX = this.boundingBox.x + ox;\n const bbY = this.boundingBox.y + oy;\n const centerX = bbX + this.boundingBox.width / 2;\n const centerY = bbY + this.boundingBox.height / 2;\n\n // Adjust for rotation\n const dx = x - centerX;\n const dy = y - centerY;\n\n const angleRad = -this.rotation * Math.PI / 180;\n const rotatedX = dx * Math.cos(angleRad) - dy * Math.sin(angleRad) + centerX;\n const rotatedY = dx * Math.sin(angleRad) + dy * Math.cos(angleRad) + centerY;\n\n return rotatedX >= bbX &&\n rotatedX <= bbX + this.boundingBox.width &&\n rotatedY >= bbY &&\n rotatedY <= bbY + this.boundingBox.height;\n }\n\n isNearAnchor(x, y) {\n if (!this.isSelected) return null;\n const buffer = 10;\n const anchorSize = 10 / currentZoom;\n\n // Account for pending move offset\n const ox = this._moveOffsetX || 0;\n const oy = this._moveOffsetY || 0;\n\n // Transform the input coordinates to account for rotation\n const centerX = this.boundingBox.x + ox + this.boundingBox.width / 2;\n const centerY = this.boundingBox.y + oy + this.boundingBox.height / 2;\n\n // Rotate the mouse coordinates to the shape's local coordinate system\n const angleRad = -this.rotation * Math.PI / 180;\n const dx = x - centerX;\n const dy = y - centerY;\n const localX = dx * Math.cos(angleRad) - dy * Math.sin(angleRad) + centerX;\n const localY = dx * Math.sin(angleRad) + dy * Math.cos(angleRad) + centerY;\n\n // Check resize anchors in local space\n const expandedX = this.boundingBox.x + ox - this.selectionPadding;\n const expandedY = this.boundingBox.y + oy - this.selectionPadding;\n const expandedWidth = this.boundingBox.width + 2 * this.selectionPadding;\n const expandedHeight = this.boundingBox.height + 2 * this.selectionPadding;\n \n const anchorPositions = [\n { x: expandedX, y: expandedY }, // top-left\n { x: expandedX + expandedWidth, y: expandedY }, // top-right\n { x: expandedX, y: expandedY + expandedHeight }, // bottom-left\n { x: expandedX + expandedWidth, y: expandedY + expandedHeight }, // bottom-right\n { x: expandedX + expandedWidth / 2, y: expandedY }, // top-center\n { x: expandedX + expandedWidth / 2, y: expandedY + expandedHeight }, // bottom-center\n { x: expandedX, y: expandedY + expandedHeight / 2 }, // left-center\n { x: expandedX + expandedWidth, y: expandedY + expandedHeight / 2 } // right-center\n ];\n\n for (let i = 0; i < anchorPositions.length; i++) {\n const anchor = anchorPositions[i];\n const distance = Math.sqrt(Math.pow(localX - anchor.x, 2) + Math.pow(localY - anchor.y, 2));\n if (distance <= anchorSize / 2 + buffer) {\n return { type: 'resize', index: i };\n }\n }\n \n // Check rotation anchor (this one stays in world coordinates)\n if (this.rotationAnchor) {\n const rotationX = parseFloat(this.rotationAnchor.getAttribute('cx'));\n const rotationY = parseFloat(this.rotationAnchor.getAttribute('cy'));\n const distance = Math.sqrt(Math.pow(x - rotationX, 2) + Math.pow(y - rotationY, 2));\n if (distance <= anchorSize / 2 + buffer) {\n return { type: 'rotate' };\n }\n }\n \n return null;\n}\n\n rotate(angle) {\n this.rotation = angle;\n // If anchors exist, update their cursors for the new rotation\n if (this.isSelected && this.anchors.length > 0) {\n const cursors = ['nw-resize', 'ne-resize', 'sw-resize', 'se-resize', 'n-resize', 's-resize', 'w-resize', 'e-resize'];\n this.anchors.forEach((anchor, i) => {\n if (anchor) {\n const originalCursor = cursors[i];\n const rotatedCursor = this.getRotatedCursor(originalCursor, this.rotation);\n anchor.style.cursor = rotatedCursor;\n }\n });\n }\n}\n\n addAnchors() {\n const anchorSize = 10 / currentZoom;\n const anchorStrokeWidth = 2 / currentZoom;\n \n const expandedX = this.boundingBox.x - this.selectionPadding;\n const expandedY = this.boundingBox.y - this.selectionPadding;\n const expandedWidth = this.boundingBox.width + 2 * this.selectionPadding;\n const expandedHeight = this.boundingBox.height + 2 * this.selectionPadding;\n \n const positions = [\n { x: expandedX, y: expandedY, cursor: 'nw-resize' }, // top-left\n { x: expandedX + expandedWidth, y: expandedY, cursor: 'ne-resize' }, // top-right\n { x: expandedX, y: expandedY + expandedHeight, cursor: 'sw-resize' }, // bottom-left\n { x: expandedX + expandedWidth, y: expandedY + expandedHeight, cursor: 'se-resize' }, // bottom-right\n { x: expandedX + expandedWidth / 2, y: expandedY, cursor: 'n-resize' }, // top-center\n { x: expandedX + expandedWidth / 2, y: expandedY + expandedHeight, cursor: 's-resize' }, // bottom-center\n { x: expandedX, y: expandedY + expandedHeight / 2, cursor: 'w-resize' }, // left-center\n { x: expandedX + expandedWidth, y: expandedY + expandedHeight / 2, cursor: 'e-resize' } // right-center\n ];\n \n // Create resize anchors\n positions.forEach((pos, i) => {\n const anchor = document.createElementNS('http://www.w3.org/2000/svg', 'rect');\n anchor.setAttribute('x', pos.x - anchorSize / 2);\n anchor.setAttribute('y', pos.y - anchorSize / 2);\n anchor.setAttribute('width', anchorSize);\n anchor.setAttribute('height', anchorSize);\n anchor.setAttribute('class', 'anchor');\n anchor.setAttribute('data-index', i);\n anchor.setAttribute('fill', '#121212');\n anchor.setAttribute('stroke', '#5B57D1');\n anchor.setAttribute('stroke-width', anchorStrokeWidth);\n anchor.setAttribute('vector-effect', 'non-scaling-stroke');\n\n // Set proper cursor for each anchor direction, accounting for rotation\n const rotatedCursor = this.getRotatedCursor(pos.cursor, this.rotation);\n anchor.style.cursor = rotatedCursor;\n anchor.style.pointerEvents = 'all';\n \n this.group.appendChild(anchor);\n this.anchors[i] = anchor;\n });\n\n // Create rotation anchor\n const rotationAnchorDistance = 30 / currentZoom;\n const rotationX = expandedX + expandedWidth / 2;\n const rotationY = expandedY - rotationAnchorDistance;\n \n const rotationAnchor = document.createElementNS('http://www.w3.org/2000/svg', 'circle');\n rotationAnchor.setAttribute('cx', rotationX);\n rotationAnchor.setAttribute('cy', rotationY);\n rotationAnchor.setAttribute('r', anchorSize / 2);\n rotationAnchor.setAttribute('fill', '#121212');\n rotationAnchor.setAttribute('stroke', '#5B57D1');\n rotationAnchor.setAttribute('stroke-width', anchorStrokeWidth);\n rotationAnchor.setAttribute('vector-effect', 'non-scaling-stroke');\n rotationAnchor.setAttribute('class', 'rotation-anchor');\n rotationAnchor.style.cursor = 'grab';\n rotationAnchor.style.pointerEvents = 'all';\n \n this.group.appendChild(rotationAnchor);\n this.rotationAnchor = rotationAnchor;\n\n // Create selection outline\n const outlinePoints = [\n [expandedX, expandedY],\n [expandedX + expandedWidth, expandedY],\n [expandedX + expandedWidth, expandedY + expandedHeight],\n [expandedX, expandedY + expandedHeight],\n [expandedX, expandedY]\n ];\n \n const outline = document.createElementNS('http://www.w3.org/2000/svg', 'polyline');\n outline.setAttribute('points', outlinePoints.map(p => p.join(',')).join(' '));\n outline.setAttribute('fill', 'none');\n outline.setAttribute('stroke', '#5B57D1');\n outline.setAttribute('stroke-width', 1.5);\n outline.setAttribute('vector-effect', 'non-scaling-stroke');\n outline.setAttribute('stroke-dasharray', '4 2');\n outline.setAttribute('style', 'pointer-events: none;');\n this.group.appendChild(outline);\n this.selectionOutline = outline;\n\n // Add line from rotation anchor to shape\n const rotationLine = document.createElementNS('http://www.w3.org/2000/svg', 'line');\n rotationLine.setAttribute('x1', rotationX);\n rotationLine.setAttribute('y1', rotationY);\n rotationLine.setAttribute('x2', expandedX + expandedWidth / 2);\n rotationLine.setAttribute('y2', expandedY);\n rotationLine.setAttribute('stroke', '#5B57D1');\n rotationLine.setAttribute('stroke-width', 1);\n rotationLine.setAttribute('vector-effect', 'non-scaling-stroke');\n rotationLine.setAttribute('stroke-dasharray', '2 2');\n rotationLine.setAttribute('style', 'pointer-events: none;');\n this.group.appendChild(rotationLine);\n this.rotationLine = rotationLine;\n\n // Show sidebar when anchors are added (when shape is selected)\n disableAllSideBars();\n paintBrushSideBar.classList.remove(\"hidden\");\n if (window.__showSidebarForShape) window.__showSidebarForShape('freehandStroke');\n this.updateSidebar();\n}\n\ngetRotatedCursor(direction, angle) {\n // Normalize angle to 0-360\n const normalizedAngle = ((angle % 360) + 360) % 360;\n \n // Map of cursor directions\n const cursors = ['n-resize', 'ne-resize', 'e-resize', 'se-resize', 's-resize', 'sw-resize', 'w-resize', 'nw-resize'];\n const directionMap = {\n 'n-resize': 0,\n 'ne-resize': 1,\n 'e-resize': 2,\n 'se-resize': 3,\n 's-resize': 4,\n 'sw-resize': 5,\n 'w-resize': 6,\n 'nw-resize': 7\n };\n \n if (!(direction in directionMap)) return direction;\n \n // Calculate how many 45-degree increments to rotate\n const rotationSteps = Math.round(normalizedAngle / 45);\n const currentIndex = directionMap[direction];\n const newIndex = (currentIndex + rotationSteps) % 8;\n \n return cursors[newIndex];\n}\n\n updatePosition(anchorIndex, newX, newY) {\n const centerX = this.boundingBox.x + this.boundingBox.width / 2;\n const centerY = this.boundingBox.y + this.boundingBox.height / 2;\n \n // Transform new coordinates to local space (accounting for rotation)\n const angleRad = -this.rotation * Math.PI / 180;\n const dx = newX - centerX;\n const dy = newY - centerY;\n const localX = dx * Math.cos(angleRad) - dy * Math.sin(angleRad) + centerX;\n const localY = dx * Math.sin(angleRad) + dy * Math.cos(angleRad) + centerY;\n \n // Calculate scale factors based on anchor movement in local space\n const expandedX = this.boundingBox.x - this.selectionPadding;\n const expandedY = this.boundingBox.y - this.selectionPadding;\n const expandedWidth = this.boundingBox.width + 2 * this.selectionPadding;\n const expandedHeight = this.boundingBox.height + 2 * this.selectionPadding;\n \n let scaleX = 1, scaleY = 1;\n switch(anchorIndex) {\n case 0: // top-left\n scaleX = (centerX - localX) / (centerX - expandedX);\n scaleY = (centerY - localY) / (centerY - expandedY);\n break;\n case 1: // top-right\n scaleX = (localX - centerX) / (expandedX + expandedWidth - centerX);\n scaleY = (centerY - localY) / (centerY - expandedY);\n break;\n case 2: // bottom-left\n scaleX = (centerX - localX) / (centerX - expandedX);\n scaleY = (localY - centerY) / (expandedY + expandedHeight - centerY);\n break;\n case 3: // bottom-right\n scaleX = (localX - centerX) / (expandedX + expandedWidth - centerX);\n scaleY = (localY - centerY) / (expandedY + expandedHeight - centerY);\n break;\n case 4: // top-center\n scaleY = (centerY - localY) / (centerY - expandedY);\n break;\n case 5: // bottom-center\n scaleY = (localY - centerY) / (expandedY + expandedHeight - centerY);\n break;\n case 6: // left-center\n scaleX = (centerX - localX) / (centerX - expandedX);\n break;\n case 7: // right-center\n scaleX = (localX - centerX) / (expandedX + expandedWidth - centerX);\n break;\n }\n \n // Prevent negative scaling\n scaleX = Math.max(0.1, Math.abs(scaleX));\n scaleY = Math.max(0.1, Math.abs(scaleY));\n \n // Apply scaling to all points relative to center\n this.points = this.points.map(point => {\n const relX = point[0] - centerX;\n const relY = point[1] - centerY;\n return [\n centerX + relX * scaleX,\n centerY + relY * scaleY,\n point[2] || 0.5\n ];\n });\n \n this.draw();\n}\n}\n\nexport { FreehandStroke };\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": []
|
|
7
|
-
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|