@snowcone-app/canvas 0.27.0 → 0.28.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ERROR_CONTRACT.md +13 -0
- package/dist/{CanvasRenderer-yszzrDfo.js → CanvasRenderer-B_3GISlW.js} +1124 -1068
- package/dist/CanvasRenderer-B_3GISlW.js.map +1 -0
- package/dist/{CanvasStateV1-BTbCD_xC.js → CanvasStateV1-kL09wsAn.js} +3 -3
- package/dist/{CanvasStateV1-BTbCD_xC.js.map → CanvasStateV1-kL09wsAn.js.map} +1 -1
- package/dist/ContextualToolbars-C69oYLdw.js +5771 -0
- package/dist/ContextualToolbars-C69oYLdw.js.map +1 -0
- package/dist/{EditorCanvasImpl-Ui8Ceb-h.js → EditorCanvasImpl-CrI9C_xM.js} +8 -8
- package/dist/{EditorCanvasImpl-Ui8Ceb-h.js.map → EditorCanvasImpl-CrI9C_xM.js.map} +1 -1
- package/dist/{ExportManager-BTcyj4cf.js → ExportManager-J2xK86uq.js} +12 -16
- package/dist/ExportManager-J2xK86uq.js.map +1 -0
- package/dist/{FontAnalyzer-EF3gLPr8.js → FontAnalyzer-PE6nysqE.js} +658 -639
- package/dist/FontAnalyzer-PE6nysqE.js.map +1 -0
- package/dist/{ImagePanel-CIk6z41z.js → ImagePanel-CmQCxBGm.js} +6 -6
- package/dist/{ImagePanel-CIk6z41z.js.map → ImagePanel-CmQCxBGm.js.map} +1 -1
- package/dist/{SnowconeCanvas-DuWALOAt.js → SnowconeCanvas-CQiFVR0X.js} +10 -10
- package/dist/{SnowconeCanvas-DuWALOAt.js.map → SnowconeCanvas-CQiFVR0X.js.map} +1 -1
- package/dist/{UnifiedFontService-CHVYDBDW.js → UnifiedFontService-BJzoqfBF.js} +755 -713
- package/dist/UnifiedFontService-BJzoqfBF.js.map +1 -0
- package/dist/advanced.mjs +14 -14
- package/dist/components/MultiSelectionToolbar.d.ts +18 -0
- package/dist/components/ui/toolbar-button.d.ts +2 -0
- package/dist/core/GestureConstraints.d.ts +92 -0
- package/dist/core/InteractionStateMachine.d.ts +16 -2
- package/dist/core/ResizeHandler.d.ts +4 -1
- package/dist/core/ResizePipeline.d.ts +3 -0
- package/dist/{custom-icons-CcLMyybv.js → custom-icons-BWiUGqD6.js} +2 -2
- package/dist/{custom-icons-CcLMyybv.js.map → custom-icons-BWiUGqD6.js.map} +1 -1
- package/dist/{design-builder-cZY958Rw.js → design-builder-bquxIHct.js} +2 -2
- package/dist/{design-builder-cZY958Rw.js.map → design-builder-bquxIHct.js.map} +1 -1
- package/dist/{editorErrors-BhrZ_nwj.js → editorErrors-8uDRMhow.js} +2 -2
- package/dist/editorErrors-8uDRMhow.js.map +1 -0
- package/dist/{embed-CJswRZte.js → embed-L3oRIgsj.js} +10 -10
- package/dist/{embed-CJswRZte.js.map → embed-L3oRIgsj.js.map} +1 -1
- package/dist/embed.mjs +6 -6
- package/dist/errors/editorError.d.ts +7 -1
- package/dist/{guards-DIX8aXWM.js → guards-BlbhM5MX.js} +2 -2
- package/dist/{guards-DIX8aXWM.js.map → guards-BlbhM5MX.js.map} +1 -1
- package/dist/hooks/index.d.ts +2 -0
- package/dist/hooks/useAlignDistribute.d.ts +19 -0
- package/dist/index.mjs +8 -8
- package/dist/internals.mjs +5 -5
- package/dist/{template-fields-BXl29sgh.js → template-fields-ai7vnW8g.js} +6 -6
- package/dist/{template-fields-BXl29sgh.js.map → template-fields-ai7vnW8g.js.map} +1 -1
- package/dist/testing.mjs +4 -4
- package/dist/{usePieceGuideBundle-DE21DQGZ.js → usePieceGuideBundle-CMe5br2a.js} +2 -2
- package/dist/{usePieceGuideBundle-DE21DQGZ.js.map → usePieceGuideBundle-CMe5br2a.js.map} +1 -1
- package/dist/utils/alignDistribute.d.ts +41 -0
- package/dist/{validation-DGXAQmUC.js → validation-B8kIYutI.js} +2592 -2562
- package/dist/validation-B8kIYutI.js.map +1 -0
- package/dist/workers/export-worker.bundle.string.d.ts +1 -1
- package/example/package.json +1 -1
- package/package.json +1 -1
- package/dist/CanvasRenderer-yszzrDfo.js.map +0 -1
- package/dist/ContextualToolbars-BHjYsril.js +0 -5556
- package/dist/ContextualToolbars-BHjYsril.js.map +0 -1
- package/dist/ExportManager-BTcyj4cf.js.map +0 -1
- package/dist/FontAnalyzer-EF3gLPr8.js.map +0 -1
- package/dist/UnifiedFontService-CHVYDBDW.js.map +0 -1
- package/dist/editorErrors-BhrZ_nwj.js.map +0 -1
- package/dist/validation-DGXAQmUC.js.map +0 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { X as te, Y as ee, ar as
|
|
2
|
-
import { T as Bt, a as Te, u as
|
|
3
|
-
import { i as Lt, a as Re } from "./guards-
|
|
4
|
-
const
|
|
1
|
+
import { X as te, Y as ee, ar as et, Z as zt, aE as ne, aC as se, av as Vt, aB as oe, au as dt, aF as ie, aG as Ft, aH as ae, aI as re, c as $t, aJ as le, aK as he, aL as ce, aM as de, a4 as jt, a0 as qt, a6 as gt, a1 as Ut, a2 as Ht, a5 as fe, a8 as ge, aN as Ot, aO as ue, aP as pe, aQ as ye, I as be, aR as Se, aS as me, aT as tt } from "./FontAnalyzer-PE6nysqE.js";
|
|
2
|
+
import { T as Bt, a as Te, u as we, K as ve, z as kt, L as Yt, M as Me, N as xe, O as Ce } from "./ExportManager-J2xK86uq.js";
|
|
3
|
+
import { i as Lt, a as Re } from "./guards-BlbhM5MX.js";
|
|
4
|
+
const rt = {
|
|
5
5
|
// Canvas-specific
|
|
6
6
|
canvas: {
|
|
7
7
|
snapThreshold: 8,
|
|
@@ -15,30 +15,30 @@ const it = {
|
|
|
15
15
|
spacingLabelFontSize: 11,
|
|
16
16
|
spacingLabelFontFamily: "-apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif"
|
|
17
17
|
}
|
|
18
|
-
}, ke = 2,
|
|
19
|
-
function Gt(
|
|
20
|
-
return ke /
|
|
18
|
+
}, ke = 2, xt = 6, Pe = 16, Ae = 5, Ee = 5, Zt = 0.5;
|
|
19
|
+
function Gt(v) {
|
|
20
|
+
return ke / v;
|
|
21
21
|
}
|
|
22
|
-
function
|
|
23
|
-
return
|
|
22
|
+
function Ne(v) {
|
|
23
|
+
return xt / v;
|
|
24
24
|
}
|
|
25
|
-
function Ie(
|
|
26
|
-
return Pe /
|
|
25
|
+
function Ie(v) {
|
|
26
|
+
return Pe / v;
|
|
27
27
|
}
|
|
28
|
-
function
|
|
29
|
-
return [Ae /
|
|
28
|
+
function Ke(v) {
|
|
29
|
+
return [Ae / v, Ee / v];
|
|
30
30
|
}
|
|
31
|
-
function He(
|
|
32
|
-
|
|
33
|
-
const n = Zt /
|
|
34
|
-
|
|
31
|
+
function He(v, t, e, s) {
|
|
32
|
+
v.save();
|
|
33
|
+
const n = Zt / s;
|
|
34
|
+
v.translate(t, e), v.scale(n, n), v.strokeStyle = "#000", v.lineWidth = 1.5, v.lineCap = "round", v.lineJoin = "round", v.translate(-12, -12), v.beginPath(), v.moveTo(21, 12), v.arc(12, 12, 9, 0, -Math.PI / 2, !0), v.bezierCurveTo(3.5, 4.5, 4, 6, 3, 8), v.stroke(), v.beginPath(), v.moveTo(3, 3), v.lineTo(3, 8), v.lineTo(8, 8), v.stroke(), v.beginPath(), v.moveTo(3, 12), v.arc(12, 12, 9, Math.PI, Math.PI / 2, !0), v.bezierCurveTo(20.5, 19.5, 20, 18, 21, 16), v.stroke(), v.beginPath(), v.moveTo(16, 16), v.lineTo(21, 16), v.lineTo(21, 21), v.stroke(), v.restore();
|
|
35
35
|
}
|
|
36
|
-
function
|
|
37
|
-
const i = Ie(
|
|
38
|
-
|
|
36
|
+
function $e(v, t, e, s = 1, n = "#3b82f6", o = !1) {
|
|
37
|
+
const i = Ie(s);
|
|
38
|
+
v.save(), v.fillStyle = "#fff", v.strokeStyle = n, v.lineWidth = o ? Gt(s) * 1.25 : Gt(s), v.beginPath(), v.arc(t, e, i, 0, Math.PI * 2), v.fill(), v.stroke(), He(v, t, e, s), v.restore();
|
|
39
39
|
}
|
|
40
|
-
const Xt =
|
|
41
|
-
class
|
|
40
|
+
const Xt = xt * 2;
|
|
41
|
+
class je {
|
|
42
42
|
constructor() {
|
|
43
43
|
this.resizeHandles = [], this.rotationHandle = null, this.elementRotation = 0, this.rotationAnchor = { x: 0, y: 0 };
|
|
44
44
|
}
|
|
@@ -48,18 +48,18 @@ class Ge {
|
|
|
48
48
|
* @param zoom - Current zoom level (used to maintain consistent rotation handle distance in screen space)
|
|
49
49
|
*/
|
|
50
50
|
update(t, e = 1) {
|
|
51
|
-
const n = "isCropping" in t && t.isCropping ? t.getBoundingBox() : t.getVisualBoundingBox(),
|
|
52
|
-
this.elementRotation = t.rotation, this.rotationAnchor =
|
|
53
|
-
const a =
|
|
51
|
+
const n = "isCropping" in t && t.isCropping ? t.getBoundingBox() : t.getVisualBoundingBox(), o = t.getRotationAnchor(), i = t.getEnabledAnchors();
|
|
52
|
+
this.elementRotation = t.rotation, this.rotationAnchor = o;
|
|
53
|
+
const a = rt.canvas.selectionPadding, r = {
|
|
54
54
|
x: n.x - a,
|
|
55
55
|
y: n.y - a,
|
|
56
56
|
width: n.width + a * 2,
|
|
57
57
|
height: n.height + a * 2
|
|
58
|
-
}, l = te(r, t.rotation,
|
|
58
|
+
}, l = te(r, t.rotation, o), h = Math.abs(t.rotation % 360) > 0.1;
|
|
59
59
|
this.resizeHandles = l.filter((c) => !(!i.includes(c.anchor) || h && c.anchor.includes("middle"))), this.rotationHandle = ee(
|
|
60
60
|
r,
|
|
61
61
|
t.rotation,
|
|
62
|
-
|
|
62
|
+
o,
|
|
63
63
|
e
|
|
64
64
|
);
|
|
65
65
|
}
|
|
@@ -67,67 +67,67 @@ class Ge {
|
|
|
67
67
|
* Render all handles
|
|
68
68
|
* @param renderRotationInCanvas - If false, skip canvas rendering of rotation handle (for React-based rendering)
|
|
69
69
|
*/
|
|
70
|
-
render(t, e = !0,
|
|
70
|
+
render(t, e = !0, s = 0, n = !1, o = !1, i = null, a = !1, r = null, l = 1, h = !0) {
|
|
71
71
|
this.resizeHandles.forEach((c) => {
|
|
72
72
|
if (a && r && c.anchor !== r.anchor)
|
|
73
73
|
return;
|
|
74
|
-
const d = !!(i && i.anchor === c.anchor),
|
|
75
|
-
this.renderResizeHandle(t, c, d,
|
|
76
|
-
}), h && e && this.rotationHandle && !n && !a && this.renderRotationHandle(t, this.rotationHandle,
|
|
74
|
+
const d = !!(i && i.anchor === c.anchor), f = !!(a && r && r.anchor === c.anchor);
|
|
75
|
+
this.renderResizeHandle(t, c, d, f, l);
|
|
76
|
+
}), h && e && this.rotationHandle && !n && !a && this.renderRotationHandle(t, this.rotationHandle, o, l), h && e && this.rotationHandle && n && this.renderRotationTooltip(t, this.rotationHandle, s, l);
|
|
77
77
|
}
|
|
78
78
|
/**
|
|
79
79
|
* Render a single resize handle
|
|
80
80
|
* Corner handles are circles, side handles are rounded rectangles
|
|
81
81
|
*/
|
|
82
|
-
renderResizeHandle(t, e,
|
|
82
|
+
renderResizeHandle(t, e, s = !1, n = !1, o = 1) {
|
|
83
83
|
t.save();
|
|
84
|
-
const i = e.x *
|
|
84
|
+
const i = e.x * o, a = e.y * o;
|
|
85
85
|
if (e.anchor.includes("middle")) {
|
|
86
86
|
const l = e.anchor === "middle-top" || e.anchor === "middle-bottom";
|
|
87
87
|
t.translate(i, a), t.rotate(-this.elementRotation * Math.PI / 180), l && t.rotate(Math.PI / 2), t.translate(-i, -a);
|
|
88
|
-
const h = Xt * 0.6, c = Xt * 1.4, d = h / 2,
|
|
89
|
-
t.fillStyle = "#fff", t.strokeStyle =
|
|
88
|
+
const h = Xt * 0.6, c = Xt * 1.4, d = h / 2, f = i - h / 2, p = a - c / 2;
|
|
89
|
+
t.fillStyle = "#fff", t.strokeStyle = et(t.canvas), t.lineWidth = s || n ? 2.5 : 2, t.beginPath(), t.roundRect(f, p, h, c, d), t.fill(), t.stroke();
|
|
90
90
|
} else
|
|
91
|
-
t.fillStyle = "#fff", t.strokeStyle =
|
|
91
|
+
t.fillStyle = "#fff", t.strokeStyle = et(t.canvas), t.lineWidth = s || n ? 2.5 : 2, t.beginPath(), t.arc(i, a, xt, 0, Math.PI * 2), t.fill(), t.stroke();
|
|
92
92
|
t.restore();
|
|
93
93
|
}
|
|
94
94
|
/**
|
|
95
95
|
* Render the rotation handle (with refresh-ccw icon)
|
|
96
96
|
* Works in screen space (positions multiplied by zoom, fixed pixel sizes)
|
|
97
97
|
*/
|
|
98
|
-
renderRotationHandle(t, e,
|
|
98
|
+
renderRotationHandle(t, e, s = !1, n = 1) {
|
|
99
99
|
t.save();
|
|
100
|
-
const
|
|
101
|
-
t.fillStyle = "#fff", t.strokeStyle =
|
|
100
|
+
const o = e.x * n, i = e.y * n, a = xt * 2.67;
|
|
101
|
+
t.fillStyle = "#fff", t.strokeStyle = et(t.canvas), t.lineWidth = s ? 2.5 : 2, t.beginPath(), t.arc(o, i, a, 0, Math.PI * 2), t.fill(), t.stroke();
|
|
102
102
|
const r = Zt;
|
|
103
|
-
t.translate(
|
|
103
|
+
t.translate(o, i), t.scale(r, r), t.strokeStyle = "#000", t.lineWidth = 1.5, t.lineCap = "round", t.lineJoin = "round", t.translate(-12, -12), t.beginPath(), t.moveTo(21, 12), t.arc(12, 12, 9, 0, -Math.PI / 2, !0), t.bezierCurveTo(3.5, 4.5, 4, 6, 3, 8), t.stroke(), t.beginPath(), t.moveTo(3, 3), t.lineTo(3, 8), t.lineTo(8, 8), t.stroke(), t.beginPath(), t.moveTo(3, 12), t.arc(12, 12, 9, Math.PI, Math.PI / 2, !0), t.bezierCurveTo(20.5, 19.5, 20, 18, 21, 16), t.stroke(), t.beginPath(), t.moveTo(16, 16), t.lineTo(21, 16), t.lineTo(21, 21), t.stroke(), t.restore();
|
|
104
104
|
}
|
|
105
105
|
/**
|
|
106
106
|
* Render rotation tooltip (angle display while rotating)
|
|
107
107
|
*/
|
|
108
|
-
renderRotationTooltip(t, e,
|
|
108
|
+
renderRotationTooltip(t, e, s, n = 1) {
|
|
109
109
|
t.save();
|
|
110
|
-
const
|
|
111
|
-
t.shadowColor = "rgba(0,0,0,0.3)", t.shadowBlur = 3, t.shadowOffsetY = 1, t.fillStyle = "#333", t.beginPath(), t.roundRect(r - i / 2, l, i, a, 3), t.fill(), t.shadowColor = "transparent", t.shadowBlur = 0, t.shadowOffsetY = 0, t.fillStyle = "#fff", t.font = "12px Arial", t.textAlign = "center", t.textBaseline = "middle", t.fillText(
|
|
110
|
+
const o = `${Math.round(s)}°`, i = o.length * 8 + 12, a = 22, r = e.x * n, l = e.y * n - 35;
|
|
111
|
+
t.shadowColor = "rgba(0,0,0,0.3)", t.shadowBlur = 3, t.shadowOffsetY = 1, t.fillStyle = "#333", t.beginPath(), t.roundRect(r - i / 2, l, i, a, 3), t.fill(), t.shadowColor = "transparent", t.shadowBlur = 0, t.shadowOffsetY = 0, t.fillStyle = "#fff", t.font = "12px Arial", t.textAlign = "center", t.textBaseline = "middle", t.fillText(o, r, l + a / 2), t.restore();
|
|
112
112
|
}
|
|
113
113
|
/**
|
|
114
114
|
* Test if a point hits any resize handle
|
|
115
115
|
* @param zoom - Current zoom level (radius scales inversely with zoom)
|
|
116
116
|
*/
|
|
117
|
-
hitTestResize(t, e,
|
|
118
|
-
const n = se /
|
|
119
|
-
for (const
|
|
120
|
-
if (zt(t, e,
|
|
121
|
-
return
|
|
117
|
+
hitTestResize(t, e, s = 1) {
|
|
118
|
+
const n = se / s;
|
|
119
|
+
for (const o of this.resizeHandles)
|
|
120
|
+
if (zt(t, e, o.x, o.y, n))
|
|
121
|
+
return o;
|
|
122
122
|
return null;
|
|
123
123
|
}
|
|
124
124
|
/**
|
|
125
125
|
* Test if a point hits the rotation handle
|
|
126
126
|
* @param zoom - Current zoom level (radius scales inversely with zoom)
|
|
127
127
|
*/
|
|
128
|
-
hitTestRotation(t, e,
|
|
128
|
+
hitTestRotation(t, e, s = 1) {
|
|
129
129
|
if (!this.rotationHandle) return !1;
|
|
130
|
-
const n = (
|
|
130
|
+
const n = (xt * 2.67 + 2) / s;
|
|
131
131
|
return zt(t, e, this.rotationHandle.x, this.rotationHandle.y, n);
|
|
132
132
|
}
|
|
133
133
|
/**
|
|
@@ -142,86 +142,127 @@ class Ge {
|
|
|
142
142
|
* @param rotation - Element rotation in degrees
|
|
143
143
|
*/
|
|
144
144
|
getCursor(t, e) {
|
|
145
|
-
const
|
|
145
|
+
const s = t.anchor.includes("middle") ? "edge" : "corner";
|
|
146
146
|
return ne(
|
|
147
147
|
t.x,
|
|
148
148
|
t.y,
|
|
149
149
|
this.rotationAnchor.x,
|
|
150
150
|
this.rotationAnchor.y,
|
|
151
|
-
|
|
151
|
+
s,
|
|
152
152
|
e,
|
|
153
153
|
t.anchor
|
|
154
154
|
);
|
|
155
155
|
}
|
|
156
156
|
}
|
|
157
|
-
|
|
157
|
+
const Be = 15;
|
|
158
|
+
function Le(v, t) {
|
|
159
|
+
return Math.abs(v) >= Math.abs(t) ? "x" : "y";
|
|
160
|
+
}
|
|
161
|
+
function We(v, t, e) {
|
|
162
|
+
return e != null && e.shift ? Le(v, t) === "x" ? { dx: v, dy: 0, lockedAxis: "y" } : { dx: 0, dy: t, lockedAxis: "x" } : { dx: v, dy: t, lockedAxis: null };
|
|
163
|
+
}
|
|
164
|
+
function De(v, t = Be) {
|
|
165
|
+
let s = (Math.round(v / t) * t % 360 + 360) % 360;
|
|
166
|
+
return s > 180 && (s -= 360), s === 0 ? 0 : s;
|
|
167
|
+
}
|
|
168
|
+
function _e({
|
|
169
|
+
anchor: v,
|
|
170
|
+
startVisualWidth: t,
|
|
171
|
+
startVisualHeight: e,
|
|
172
|
+
newVisualWidth: s,
|
|
173
|
+
newVisualHeight: n
|
|
174
|
+
}) {
|
|
175
|
+
const o = t !== 0 ? t : 1, i = e !== 0 ? e : 1, a = s / o, r = n / i;
|
|
176
|
+
let l;
|
|
177
|
+
return v === "middle-left" || v === "middle-right" ? l = a : v === "middle-top" || v === "middle-bottom" ? l = r : l = Math.abs(a - 1) >= Math.abs(r - 1) ? a : r, {
|
|
178
|
+
scale: l,
|
|
179
|
+
newVisualWidth: t * l,
|
|
180
|
+
newVisualHeight: e * l
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
class ze {
|
|
158
184
|
/**
|
|
159
185
|
* Calculate new dimensions and position for a resize operation
|
|
160
186
|
*/
|
|
161
187
|
static calculateResize({
|
|
162
188
|
element: t,
|
|
163
189
|
handle: e,
|
|
164
|
-
dx:
|
|
190
|
+
dx: s,
|
|
165
191
|
dy: n,
|
|
166
|
-
startData:
|
|
167
|
-
snapSystem: i
|
|
192
|
+
startData: o,
|
|
193
|
+
snapSystem: i,
|
|
194
|
+
modifiers: a
|
|
168
195
|
}) {
|
|
169
|
-
var
|
|
170
|
-
const
|
|
171
|
-
let
|
|
172
|
-
e.anchor.includes("right") ?
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
196
|
+
var O, D, Q, E, j;
|
|
197
|
+
const l = new Vt(t).worldDeltaToLocal(s, n), h = l.dx, c = l.dy, d = o.visualWidth ?? o.width ?? 0, f = o.visualHeight ?? o.height ?? 0, p = o.width ?? 0, b = o.height ?? 0;
|
|
198
|
+
let g = d, u = f;
|
|
199
|
+
e.anchor.includes("right") ? g = d + h : e.anchor.includes("left") && (g = d - h), e.anchor !== "middle-left" && e.anchor !== "middle-right" && (e.anchor.includes("bottom") ? u = f + c : e.anchor.includes("top") && (u = f - c));
|
|
200
|
+
const y = (a == null ? void 0 : a.shift) === !0;
|
|
201
|
+
let S = null;
|
|
202
|
+
if (y) {
|
|
203
|
+
const _ = _e({
|
|
204
|
+
anchor: e.anchor,
|
|
205
|
+
startVisualWidth: d,
|
|
206
|
+
startVisualHeight: f,
|
|
207
|
+
newVisualWidth: g,
|
|
208
|
+
newVisualHeight: u
|
|
209
|
+
});
|
|
210
|
+
S = _.scale, g = _.newVisualWidth, u = _.newVisualHeight;
|
|
211
|
+
}
|
|
212
|
+
let m, w;
|
|
213
|
+
if (S !== null)
|
|
214
|
+
m = p * S, w = b * S;
|
|
215
|
+
else if (e.anchor === "middle-left" || e.anchor === "middle-right") {
|
|
216
|
+
const _ = g - d;
|
|
217
|
+
m = p + _, w = b;
|
|
177
218
|
} else if (e.anchor === "middle-top" || e.anchor === "middle-bottom") {
|
|
178
|
-
const
|
|
179
|
-
|
|
219
|
+
const _ = u - f;
|
|
220
|
+
m = p, w = b + _;
|
|
180
221
|
} else {
|
|
181
|
-
const
|
|
182
|
-
|
|
222
|
+
const _ = g / d, $ = u / f;
|
|
223
|
+
m = p * _, w = b * $;
|
|
183
224
|
}
|
|
184
|
-
const
|
|
185
|
-
let
|
|
225
|
+
const T = g, C = u;
|
|
226
|
+
let R = !1;
|
|
186
227
|
if (i && t.transformType === "image") {
|
|
187
|
-
const
|
|
188
|
-
if (
|
|
189
|
-
const
|
|
190
|
-
if (!!
|
|
191
|
-
const
|
|
192
|
-
(
|
|
228
|
+
const _ = e.anchor ?? "", $ = _ === "top-left" || _ === "top-right" || _ === "bottom-left" || _ === "bottom-right", Y = _.startsWith("crop-");
|
|
229
|
+
if ($ && !Y) {
|
|
230
|
+
const k = (O = i.activeSnaps) == null ? void 0 : O.x, H = (D = i.activeSnaps) == null ? void 0 : D.y;
|
|
231
|
+
if (!!k || !!H) {
|
|
232
|
+
const I = [k, H].find(
|
|
233
|
+
(z) => typeof z == "object" && z !== null && "frozenWidth" in z
|
|
193
234
|
);
|
|
194
|
-
if (
|
|
195
|
-
const
|
|
196
|
-
let
|
|
197
|
-
|
|
198
|
-
const
|
|
199
|
-
|
|
235
|
+
if (I) {
|
|
236
|
+
const z = t, G = o.transformData, st = I.frozenWidth ?? ((Q = z.transformData) == null ? void 0 : Q.width) ?? p, lt = z.imageAspectRatio || (G != null && G.width && (G != null && G.height) ? G.width / G.height : null);
|
|
237
|
+
let U = I.frozenHeight;
|
|
238
|
+
U == null && (lt && lt !== 0 ? U = st / lt : (E = z.transformData) != null && E.height ? U = z.transformData.height : U = b);
|
|
239
|
+
const F = p !== 0 ? st / p : 1, nt = b !== 0 ? U / b : 1;
|
|
240
|
+
g = d * F, u = f * nt, m = st, w = U, R = !0;
|
|
200
241
|
}
|
|
201
242
|
}
|
|
202
243
|
}
|
|
203
244
|
}
|
|
204
|
-
|
|
205
|
-
const
|
|
206
|
-
if (!e.anchor.includes("middle") && ((
|
|
207
|
-
const
|
|
208
|
-
|
|
245
|
+
m = Math.max(50, m), w = Math.max(40, w);
|
|
246
|
+
const x = t.clone(), P = x.resize(e.anchor, m, w, o);
|
|
247
|
+
if (!e.anchor.includes("middle") && ((j = x.stroke) != null && j.enabled) && o.strokeWidth !== void 0 && o.strokeWidth > 0) {
|
|
248
|
+
const _ = o.width ?? 1, $ = o.height ?? 1, Y = Math.sqrt(m / _ * (w / $)), k = Math.max(1, Math.round(o.strokeWidth * Y * 10) / 10);
|
|
249
|
+
x.stroke = { ...x.stroke, width: k };
|
|
209
250
|
}
|
|
210
|
-
const
|
|
211
|
-
if (
|
|
212
|
-
const
|
|
251
|
+
const A = R || P === !1, B = e.anchor.includes("top") || e.anchor.includes("bottom"), L = "isCropping" in x && x.isCropping, W = "isGroup" in x && x.isGroup;
|
|
252
|
+
if (B && !L && !W) {
|
|
253
|
+
const _ = t.getRotationAnchor(), $ = this._calculateFixedCornerOffset({
|
|
213
254
|
element: t,
|
|
214
|
-
updatedElement:
|
|
255
|
+
updatedElement: x,
|
|
215
256
|
handle: e,
|
|
216
|
-
rotationAnchor:
|
|
257
|
+
rotationAnchor: _
|
|
217
258
|
});
|
|
218
|
-
|
|
259
|
+
x.x += $.x, x.y += $.y;
|
|
219
260
|
}
|
|
220
261
|
return {
|
|
221
|
-
element:
|
|
222
|
-
isFrozen:
|
|
262
|
+
element: x,
|
|
263
|
+
isFrozen: A,
|
|
223
264
|
// For snap system to detect break-free: dimensions before freeze was applied
|
|
224
|
-
unfrozenDimensions:
|
|
265
|
+
unfrozenDimensions: R ? { width: T, height: C } : void 0
|
|
225
266
|
};
|
|
226
267
|
}
|
|
227
268
|
/**
|
|
@@ -232,27 +273,27 @@ class Be {
|
|
|
232
273
|
static _calculateFixedCornerOffset({
|
|
233
274
|
element: t,
|
|
234
275
|
updatedElement: e,
|
|
235
|
-
handle:
|
|
276
|
+
handle: s,
|
|
236
277
|
rotationAnchor: n
|
|
237
278
|
}) {
|
|
238
|
-
const
|
|
279
|
+
const o = new Vt(t), { cos: i, sin: a } = o.getRenderingCosSin(), r = t.getVisualBoundingBox(), l = e.getVisualBoundingBox(), h = n, c = e.getRotationAnchor(), d = this._getFixedLocalCoords(s.anchor, r.width, r.height), f = d.x, p = d.y, b = r.x - h.x, g = r.y - h.y, u = b + f, y = g + p, S = u * i - y * a, m = u * a + y * i, w = h.x + S, T = h.y + m, C = this._getFixedLocalCoords(s.anchor, l.width, l.height), R = C.x, x = C.y, P = l.x - c.x, M = l.y - c.y, A = P + R, B = M + x, L = A * i - B * a, W = A * a + B * i, O = c.x + L, D = c.y + W;
|
|
239
280
|
return {
|
|
240
|
-
x:
|
|
241
|
-
y:
|
|
281
|
+
x: w - O,
|
|
282
|
+
y: T - D
|
|
242
283
|
};
|
|
243
284
|
}
|
|
244
285
|
/**
|
|
245
286
|
* Get local coordinates of the fixed point for a given handle
|
|
246
287
|
* @private
|
|
247
288
|
*/
|
|
248
|
-
static _getFixedLocalCoords(t, e,
|
|
289
|
+
static _getFixedLocalCoords(t, e, s) {
|
|
249
290
|
const n = { x: 0, y: 0 };
|
|
250
291
|
switch (t) {
|
|
251
292
|
case "top-left":
|
|
252
|
-
n.x = e, n.y =
|
|
293
|
+
n.x = e, n.y = s;
|
|
253
294
|
break;
|
|
254
295
|
case "top-right":
|
|
255
|
-
n.x = 0, n.y =
|
|
296
|
+
n.x = 0, n.y = s;
|
|
256
297
|
break;
|
|
257
298
|
case "bottom-left":
|
|
258
299
|
n.x = e, n.y = 0;
|
|
@@ -261,13 +302,13 @@ class Be {
|
|
|
261
302
|
n.x = 0, n.y = 0;
|
|
262
303
|
break;
|
|
263
304
|
case "middle-left":
|
|
264
|
-
n.x = e, n.y =
|
|
305
|
+
n.x = e, n.y = s / 2;
|
|
265
306
|
break;
|
|
266
307
|
case "middle-right":
|
|
267
|
-
n.x = 0, n.y =
|
|
308
|
+
n.x = 0, n.y = s / 2;
|
|
268
309
|
break;
|
|
269
310
|
case "middle-top":
|
|
270
|
-
n.x = e / 2, n.y =
|
|
311
|
+
n.x = e / 2, n.y = s;
|
|
271
312
|
break;
|
|
272
313
|
case "middle-bottom":
|
|
273
314
|
n.x = e / 2, n.y = 0;
|
|
@@ -276,7 +317,7 @@ class Be {
|
|
|
276
317
|
return n;
|
|
277
318
|
}
|
|
278
319
|
}
|
|
279
|
-
class
|
|
320
|
+
class Ve {
|
|
280
321
|
constructor() {
|
|
281
322
|
this.hooks = {
|
|
282
323
|
beforeResize: [],
|
|
@@ -300,8 +341,8 @@ class Le {
|
|
|
300
341
|
*/
|
|
301
342
|
removeHook(t, e) {
|
|
302
343
|
if (!this.hooks[t]) return;
|
|
303
|
-
const
|
|
304
|
-
|
|
344
|
+
const s = this.hooks[t].indexOf(e);
|
|
345
|
+
s !== -1 && this.hooks[t].splice(s, 1);
|
|
305
346
|
}
|
|
306
347
|
/**
|
|
307
348
|
* Clear all hooks at a stage
|
|
@@ -321,9 +362,9 @@ class Le {
|
|
|
321
362
|
* Run hooks at a specific stage
|
|
322
363
|
*/
|
|
323
364
|
runHooks(t, e) {
|
|
324
|
-
return this.hooks[t] ? this.hooks[t].reduce((
|
|
325
|
-
const
|
|
326
|
-
return
|
|
365
|
+
return this.hooks[t] ? this.hooks[t].reduce((s, n) => {
|
|
366
|
+
const o = n(s);
|
|
367
|
+
return o !== void 0 ? o : s;
|
|
327
368
|
}, e) : e;
|
|
328
369
|
}
|
|
329
370
|
/**
|
|
@@ -331,23 +372,24 @@ class Le {
|
|
|
331
372
|
*/
|
|
332
373
|
executeResize(t) {
|
|
333
374
|
const e = this.runHooks("beforeResize", t);
|
|
334
|
-
let
|
|
375
|
+
let s = ze.calculateResize({
|
|
335
376
|
...e,
|
|
336
|
-
snapSystem: t.snapSystem
|
|
377
|
+
snapSystem: t.snapSystem,
|
|
378
|
+
modifiers: t.modifiers
|
|
337
379
|
});
|
|
338
|
-
return
|
|
380
|
+
return s.handle = t.handle, s.startData = t.startData, s = this.runHooks("afterResize", s), s;
|
|
339
381
|
}
|
|
340
382
|
/**
|
|
341
383
|
* Execute position update with hooks
|
|
342
384
|
* Used for drag operations
|
|
343
385
|
*/
|
|
344
386
|
executePositionUpdate(t, e) {
|
|
345
|
-
const
|
|
346
|
-
return this.runHooks("afterPositionUpdate",
|
|
387
|
+
const s = this.runHooks("beforePositionUpdate", { position: t, element: e });
|
|
388
|
+
return this.runHooks("afterPositionUpdate", s).position;
|
|
347
389
|
}
|
|
348
390
|
}
|
|
349
|
-
const
|
|
350
|
-
class
|
|
391
|
+
const qe = new Ve();
|
|
392
|
+
class Ue {
|
|
351
393
|
constructor(t = null) {
|
|
352
394
|
this.state = "IDLE", this.context = {
|
|
353
395
|
mode: null,
|
|
@@ -391,14 +433,14 @@ class Ne {
|
|
|
391
433
|
/**
|
|
392
434
|
* Start drag operation
|
|
393
435
|
*/
|
|
394
|
-
startDrag(t, e,
|
|
436
|
+
startDrag(t, e, s, n = null) {
|
|
395
437
|
this.state = "DRAGGING";
|
|
396
|
-
const
|
|
397
|
-
let i =
|
|
438
|
+
const o = t.getTransformStartData();
|
|
439
|
+
let i = o;
|
|
398
440
|
if (n === "crop-image-drag" && t.transformData) {
|
|
399
441
|
const a = t.transformData;
|
|
400
442
|
i = {
|
|
401
|
-
...
|
|
443
|
+
...o,
|
|
402
444
|
cropX: a.cropX,
|
|
403
445
|
cropY: a.cropY,
|
|
404
446
|
cropWidth: a.cropWidth,
|
|
@@ -410,7 +452,7 @@ class Ne {
|
|
|
410
452
|
dragMode: n,
|
|
411
453
|
// 'crop-image-drag' for moving image within crop, null for normal drag
|
|
412
454
|
startX: e,
|
|
413
|
-
startY:
|
|
455
|
+
startY: s,
|
|
414
456
|
startData: i,
|
|
415
457
|
activeHandle: null,
|
|
416
458
|
element: t
|
|
@@ -431,27 +473,34 @@ class Ne {
|
|
|
431
473
|
/**
|
|
432
474
|
* Update drag operation
|
|
433
475
|
* Returns updated position { x, y }
|
|
434
|
-
|
|
435
|
-
|
|
476
|
+
*
|
|
477
|
+
* `modifiers.shift` axis-locks the drag to the dominant axis
|
|
478
|
+
* (re-evaluated each move). Alignment snapping still runs on the
|
|
479
|
+
* free axis; on the locked axis the position is clamped back to the
|
|
480
|
+
* gesture-start value AFTER snapping, so a snap can never move the
|
|
481
|
+
* element off the locked axis. Read modifiers from the CURRENT
|
|
482
|
+
* pointer event — users press/release Shift mid-gesture.
|
|
483
|
+
*/
|
|
484
|
+
updateDrag(t, e, s = null, n) {
|
|
436
485
|
if (this.state !== "DRAGGING")
|
|
437
486
|
throw new Error("Cannot update drag: not in DRAGGING state");
|
|
438
|
-
const
|
|
439
|
-
let
|
|
487
|
+
const o = t - this.context.startX, i = e - this.context.startY, { dx: a, dy: r, lockedAxis: l } = We(o, i, n), h = this.context.startData;
|
|
488
|
+
let c = h.x + a, d = h.y + r;
|
|
440
489
|
if (this.snapHandler && this.snapHandler.snapPosition && this.context.element) {
|
|
441
|
-
const
|
|
442
|
-
|
|
490
|
+
const f = this.snapHandler.snapPosition({ x: c, y: d }, this.context.element, s);
|
|
491
|
+
c = f.x, d = f.y;
|
|
443
492
|
}
|
|
444
|
-
return { x:
|
|
493
|
+
return l === "x" ? c = h.x : l === "y" && (d = h.y), { x: c, y: d };
|
|
445
494
|
}
|
|
446
495
|
/**
|
|
447
496
|
* Start resize operation
|
|
448
497
|
*/
|
|
449
|
-
startResize(t, e,
|
|
498
|
+
startResize(t, e, s, n, o, i) {
|
|
450
499
|
this.state = "RESIZING";
|
|
451
500
|
const a = t.getTransformStartData(), r = t.clone();
|
|
452
501
|
(e.anchor === "top-left" || e.anchor === "top-right" || e.anchor === "bottom-left" || e.anchor === "bottom-right") && a.lineCount !== void 0 && r.transformType === "custom" && (r._lockedLineCount = a.lineCount), this.context = {
|
|
453
502
|
mode: "resize",
|
|
454
|
-
startX:
|
|
503
|
+
startX: s,
|
|
455
504
|
startY: n,
|
|
456
505
|
startData: {
|
|
457
506
|
...a,
|
|
@@ -459,8 +508,8 @@ class Ne {
|
|
|
459
508
|
visualY: i.y,
|
|
460
509
|
visualWidth: i.width,
|
|
461
510
|
visualHeight: i.height,
|
|
462
|
-
bboxX:
|
|
463
|
-
bboxY:
|
|
511
|
+
bboxX: o.x,
|
|
512
|
+
bboxY: o.y
|
|
464
513
|
},
|
|
465
514
|
activeHandle: e,
|
|
466
515
|
element: r
|
|
@@ -474,8 +523,8 @@ class Ne {
|
|
|
474
523
|
updateResize(t, e) {
|
|
475
524
|
if (this.state !== "RESIZING")
|
|
476
525
|
throw new Error("Cannot update resize: not in RESIZING state");
|
|
477
|
-
const
|
|
478
|
-
return { dx:
|
|
526
|
+
const s = t - this.context.startX, n = e - this.context.startY;
|
|
527
|
+
return { dx: s, dy: n };
|
|
479
528
|
}
|
|
480
529
|
/**
|
|
481
530
|
* Adjust the resize start position to account for snap corrections
|
|
@@ -507,16 +556,16 @@ class Ne {
|
|
|
507
556
|
* Reset resize start data to current element state (for unfreezing)
|
|
508
557
|
* This updates startData to use the current element dimensions, preventing jumps
|
|
509
558
|
*/
|
|
510
|
-
resetResizeStartData(t, e,
|
|
559
|
+
resetResizeStartData(t, e, s) {
|
|
511
560
|
if (this.state !== "RESIZING")
|
|
512
561
|
return;
|
|
513
|
-
const n = t.getBoundingBox(),
|
|
514
|
-
this.context.startX = e, this.context.startY =
|
|
562
|
+
const n = t.getBoundingBox(), o = t.getVisualBoundingBox(), i = t.getTransformStartData();
|
|
563
|
+
this.context.startX = e, this.context.startY = s, this.context.startData = {
|
|
515
564
|
...i,
|
|
516
|
-
visualX:
|
|
517
|
-
visualY:
|
|
518
|
-
visualWidth:
|
|
519
|
-
visualHeight:
|
|
565
|
+
visualX: o.x,
|
|
566
|
+
visualY: o.y,
|
|
567
|
+
visualWidth: o.width,
|
|
568
|
+
visualHeight: o.height,
|
|
520
569
|
bboxX: n.x,
|
|
521
570
|
bboxY: n.y
|
|
522
571
|
};
|
|
@@ -524,14 +573,14 @@ class Ne {
|
|
|
524
573
|
/**
|
|
525
574
|
* Start rotation operation
|
|
526
575
|
*/
|
|
527
|
-
startRotate(t, e,
|
|
576
|
+
startRotate(t, e, s, n, o) {
|
|
528
577
|
this.state = "ROTATING", this.context = {
|
|
529
578
|
mode: "rotate",
|
|
530
579
|
startX: e,
|
|
531
|
-
startY:
|
|
580
|
+
startY: s,
|
|
532
581
|
startData: {
|
|
533
582
|
startAngle: n,
|
|
534
|
-
currentRotation:
|
|
583
|
+
currentRotation: o,
|
|
535
584
|
elementData: t.getTransformStartData()
|
|
536
585
|
},
|
|
537
586
|
activeHandle: null,
|
|
@@ -541,13 +590,19 @@ class Ne {
|
|
|
541
590
|
/**
|
|
542
591
|
* Update rotation operation
|
|
543
592
|
* Returns updated rotation angle in degrees
|
|
593
|
+
*
|
|
594
|
+
* `modifiers.shift` snaps the result to 15° increments in stored
|
|
595
|
+
* (user-facing, sign-flipped — gotcha #15) degrees. The shift snap
|
|
596
|
+
* REPLACES the snapHandler's rotation snap while held: the 15° grid
|
|
597
|
+
* is a superset of the usual 0/90/180 magnets and must win
|
|
598
|
+
* deterministically. Read modifiers from the CURRENT pointer event.
|
|
544
599
|
*/
|
|
545
|
-
updateRotate(t, e,
|
|
600
|
+
updateRotate(t, e, s, n, o) {
|
|
546
601
|
if (this.state !== "ROTATING")
|
|
547
602
|
throw new Error("Cannot update rotate: not in ROTATING state");
|
|
548
|
-
const
|
|
549
|
-
let
|
|
550
|
-
return
|
|
603
|
+
const i = this.context.startData, r = (oe(s, n, t, e) - i.startAngle) * 180 / Math.PI;
|
|
604
|
+
let l = i.currentRotation - r;
|
|
605
|
+
return l = (l % 360 + 360) % 360, l > 180 && (l -= 360), o != null && o.shift ? De(l) : this.snapHandler && this.snapHandler.snapRotation && this.context.element ? this.snapHandler.snapRotation(l, this.context.element) : l;
|
|
551
606
|
}
|
|
552
607
|
/**
|
|
553
608
|
* Get rotation context
|
|
@@ -569,12 +624,12 @@ class Ne {
|
|
|
569
624
|
* frame. PinchHandler consumes both via `getPinchContext()` to
|
|
570
625
|
* produce the next element.
|
|
571
626
|
*/
|
|
572
|
-
startPinch(t, e,
|
|
627
|
+
startPinch(t, e, s) {
|
|
573
628
|
this.state = "PINCHING";
|
|
574
629
|
const n = {
|
|
575
|
-
x: (e.x +
|
|
576
|
-
y: (e.y +
|
|
577
|
-
},
|
|
630
|
+
x: (e.x + s.x) / 2,
|
|
631
|
+
y: (e.y + s.y) / 2
|
|
632
|
+
}, o = s.x - e.x, i = s.y - e.y, a = Math.hypot(o, i), r = Math.atan2(i, o), l = {
|
|
578
633
|
elementData: t.getTransformStartData(),
|
|
579
634
|
startCentroid: n,
|
|
580
635
|
startDistance: a,
|
|
@@ -605,14 +660,14 @@ class Ne {
|
|
|
605
660
|
updatePinch(t, e) {
|
|
606
661
|
if (this.state !== "PINCHING")
|
|
607
662
|
throw new Error("Cannot update pinch: not in PINCHING state");
|
|
608
|
-
const
|
|
663
|
+
const s = this.context.startData, n = {
|
|
609
664
|
x: (t.x + e.x) / 2,
|
|
610
665
|
y: (t.y + e.y) / 2
|
|
611
|
-
},
|
|
666
|
+
}, o = e.x - t.x, i = e.y - t.y, a = Math.hypot(o, i), r = Math.atan2(i, o), l = Math.max(s.startDistance, 1e-4), h = a / l, c = Math.max(h, 0.05), d = r - s.startAngle;
|
|
612
667
|
return {
|
|
613
668
|
scale: c,
|
|
614
669
|
rotationDelta: d,
|
|
615
|
-
startCentroid:
|
|
670
|
+
startCentroid: s.startCentroid,
|
|
616
671
|
currentCentroid: n
|
|
617
672
|
};
|
|
618
673
|
}
|
|
@@ -681,7 +736,7 @@ class bt {
|
|
|
681
736
|
* - 1 rotation anchor (may be same as center)
|
|
682
737
|
*/
|
|
683
738
|
static getSnapAnchors(t) {
|
|
684
|
-
const e = t.getVisualBoundingBox(),
|
|
739
|
+
const e = t.getVisualBoundingBox(), s = {
|
|
685
740
|
// Corners
|
|
686
741
|
topLeft: { x: e.x, y: e.y },
|
|
687
742
|
topRight: { x: e.x + e.width, y: e.y },
|
|
@@ -698,17 +753,17 @@ class bt {
|
|
|
698
753
|
rotation: this.resolve(t)
|
|
699
754
|
};
|
|
700
755
|
if (t.rotation !== 0) {
|
|
701
|
-
const n =
|
|
702
|
-
Object.keys(
|
|
756
|
+
const n = s.rotation, o = dt.toRadiansInverse(t.rotation);
|
|
757
|
+
Object.keys(s).forEach((i) => {
|
|
703
758
|
if (i === "rotation") return;
|
|
704
|
-
const a =
|
|
705
|
-
|
|
759
|
+
const a = s[i], r = a.x - n.x, l = a.y - n.y, h = r * Math.cos(o) - l * Math.sin(o), c = r * Math.sin(o) + l * Math.cos(o);
|
|
760
|
+
s[i] = {
|
|
706
761
|
x: n.x + h,
|
|
707
762
|
y: n.y + c
|
|
708
763
|
};
|
|
709
764
|
});
|
|
710
765
|
}
|
|
711
|
-
return
|
|
766
|
+
return s;
|
|
712
767
|
}
|
|
713
768
|
/**
|
|
714
769
|
* Get edge lines for an element (for edge-to-edge snapping)
|
|
@@ -762,11 +817,11 @@ class bt {
|
|
|
762
817
|
* (different from center of visual bbox)
|
|
763
818
|
*/
|
|
764
819
|
static hasCustomRotationAnchor(t) {
|
|
765
|
-
const e = t.getVisualBoundingBox(),
|
|
820
|
+
const e = t.getVisualBoundingBox(), s = {
|
|
766
821
|
x: e.x + e.width / 2,
|
|
767
822
|
y: e.y + e.height / 2
|
|
768
|
-
}, n = this.resolve(t),
|
|
769
|
-
return Math.abs(n.x -
|
|
823
|
+
}, n = this.resolve(t), o = 1e-3;
|
|
824
|
+
return Math.abs(n.x - s.x) > o || Math.abs(n.y - s.y) > o;
|
|
770
825
|
}
|
|
771
826
|
}
|
|
772
827
|
class Nt {
|
|
@@ -780,8 +835,8 @@ class Nt {
|
|
|
780
835
|
/** Insert a point into the grid */
|
|
781
836
|
insert(t) {
|
|
782
837
|
const e = this.getCellKey(t.x, t.y);
|
|
783
|
-
let
|
|
784
|
-
|
|
838
|
+
let s = this.cells.get(e);
|
|
839
|
+
s || (s = /* @__PURE__ */ new Set(), this.cells.set(e, s)), s.add(t);
|
|
785
840
|
let n = this.idIndex.get(t.id);
|
|
786
841
|
n || (n = /* @__PURE__ */ new Set(), this.idIndex.set(t.id, n)), n.add(e);
|
|
787
842
|
}
|
|
@@ -789,12 +844,12 @@ class Nt {
|
|
|
789
844
|
removeById(t) {
|
|
790
845
|
const e = this.idIndex.get(t);
|
|
791
846
|
if (e) {
|
|
792
|
-
for (const
|
|
793
|
-
const n = this.cells.get(
|
|
847
|
+
for (const s of e) {
|
|
848
|
+
const n = this.cells.get(s);
|
|
794
849
|
if (n) {
|
|
795
|
-
for (const
|
|
796
|
-
|
|
797
|
-
n.size === 0 && this.cells.delete(
|
|
850
|
+
for (const o of n)
|
|
851
|
+
o.id === t && n.delete(o);
|
|
852
|
+
n.size === 0 && this.cells.delete(s);
|
|
798
853
|
}
|
|
799
854
|
}
|
|
800
855
|
this.idIndex.delete(t);
|
|
@@ -807,19 +862,19 @@ class Nt {
|
|
|
807
862
|
* [x - radius, x + radius] x [y - radius, y + radius].
|
|
808
863
|
* Each candidate is then distance-checked against the radius.
|
|
809
864
|
*/
|
|
810
|
-
queryNear(t, e,
|
|
811
|
-
const
|
|
865
|
+
queryNear(t, e, s, n) {
|
|
866
|
+
const o = [], i = Math.floor((t - s) / this.cellSize), a = Math.floor((t + s) / this.cellSize), r = Math.floor((e - s) / this.cellSize), l = Math.floor((e + s) / this.cellSize);
|
|
812
867
|
for (let h = i; h <= a; h++)
|
|
813
868
|
for (let c = r; c <= l; c++) {
|
|
814
|
-
const d = `${h},${c}`,
|
|
815
|
-
if (
|
|
816
|
-
for (const p of
|
|
869
|
+
const d = `${h},${c}`, f = this.cells.get(d);
|
|
870
|
+
if (f)
|
|
871
|
+
for (const p of f) {
|
|
817
872
|
if (n !== void 0 && p.id === n) continue;
|
|
818
873
|
const b = p.x - t, g = p.y - e;
|
|
819
|
-
b * b + g * g <=
|
|
874
|
+
b * b + g * g <= s * s && o.push(p);
|
|
820
875
|
}
|
|
821
876
|
}
|
|
822
|
-
return
|
|
877
|
+
return o;
|
|
823
878
|
}
|
|
824
879
|
/**
|
|
825
880
|
* Query all items whose coordinate on `axis` is within `radius` of the
|
|
@@ -833,26 +888,26 @@ class Nt {
|
|
|
833
888
|
*
|
|
834
889
|
* Scans all cells in the band along the target axis.
|
|
835
890
|
*/
|
|
836
|
-
queryNearAxis(t, e,
|
|
837
|
-
const
|
|
891
|
+
queryNearAxis(t, e, s, n) {
|
|
892
|
+
const o = [];
|
|
838
893
|
if (t === "x") {
|
|
839
|
-
const i = Math.floor((e -
|
|
894
|
+
const i = Math.floor((e - s) / this.cellSize), a = Math.floor((e + s) / this.cellSize);
|
|
840
895
|
for (const [r, l] of this.cells) {
|
|
841
896
|
const h = r.indexOf(","), c = parseInt(r.substring(0, h), 10);
|
|
842
897
|
if (!(c < i || c > a))
|
|
843
898
|
for (const d of l)
|
|
844
|
-
n !== void 0 && d.id === n || Math.abs(d.x - e) <=
|
|
899
|
+
n !== void 0 && d.id === n || Math.abs(d.x - e) <= s && o.push(d);
|
|
845
900
|
}
|
|
846
901
|
} else {
|
|
847
|
-
const i = Math.floor((e -
|
|
902
|
+
const i = Math.floor((e - s) / this.cellSize), a = Math.floor((e + s) / this.cellSize);
|
|
848
903
|
for (const [r, l] of this.cells) {
|
|
849
904
|
const h = r.indexOf(","), c = parseInt(r.substring(h + 1), 10);
|
|
850
905
|
if (!(c < i || c > a))
|
|
851
906
|
for (const d of l)
|
|
852
|
-
n !== void 0 && d.id === n || Math.abs(d.y - e) <=
|
|
907
|
+
n !== void 0 && d.id === n || Math.abs(d.y - e) <= s && o.push(d);
|
|
853
908
|
}
|
|
854
909
|
}
|
|
855
|
-
return
|
|
910
|
+
return o;
|
|
856
911
|
}
|
|
857
912
|
/** Rebuild from a full list of items (clears existing data first) */
|
|
858
913
|
rebuild(t) {
|
|
@@ -865,27 +920,27 @@ class Nt {
|
|
|
865
920
|
return `${Math.floor(t / this.cellSize)},${Math.floor(e / this.cellSize)}`;
|
|
866
921
|
}
|
|
867
922
|
}
|
|
868
|
-
function
|
|
869
|
-
const t =
|
|
923
|
+
function ct(v) {
|
|
924
|
+
const t = v.transformData;
|
|
870
925
|
if (t && "width" in t && typeof t.width == "number")
|
|
871
926
|
return t.width;
|
|
872
927
|
}
|
|
873
|
-
function St(
|
|
874
|
-
const t =
|
|
928
|
+
function St(v) {
|
|
929
|
+
const t = v.transformData;
|
|
875
930
|
if (t && "height" in t && typeof t.height == "number")
|
|
876
931
|
return t.height;
|
|
877
932
|
}
|
|
878
|
-
function
|
|
879
|
-
const e =
|
|
933
|
+
function vt(v, t) {
|
|
934
|
+
const e = v.transformData;
|
|
880
935
|
return e && "width" in e ? (e.width = t, !0) : !1;
|
|
881
936
|
}
|
|
882
|
-
function Pt(
|
|
883
|
-
const e =
|
|
937
|
+
function Pt(v, t) {
|
|
938
|
+
const e = v.transformData;
|
|
884
939
|
return e && "height" in e ? (e.height = t, !0) : !1;
|
|
885
940
|
}
|
|
886
|
-
class
|
|
941
|
+
class Ze {
|
|
887
942
|
constructor(t = {}) {
|
|
888
|
-
this._extraSnapRects = [], this.snapThreshold = t.snapThreshold ||
|
|
943
|
+
this._extraSnapRects = [], this.snapThreshold = t.snapThreshold || rt.canvas.snapThreshold, this.enabled = t.enabled !== !1, this.showGuides = t.showGuides !== !1, this.guides = [], this.activeSnaps = {
|
|
889
944
|
x: null,
|
|
890
945
|
// { snapTo: number, anchorKey: string, frozenFontSize: number, frozenWidth: number, frozenPosition: {x, y}, isPositionBasedSnap: boolean }
|
|
891
946
|
y: null
|
|
@@ -941,31 +996,31 @@ class Ke {
|
|
|
941
996
|
_populateSpatialGrid(t) {
|
|
942
997
|
this._spatialGrid.clear(), this._anchorMetadata.clear();
|
|
943
998
|
for (const e of t) {
|
|
944
|
-
const
|
|
945
|
-
for (const [n,
|
|
999
|
+
const s = bt.getSnapAnchors(e);
|
|
1000
|
+
for (const [n, o] of Object.entries(s)) {
|
|
946
1001
|
const i = `${e.id}:${n}`, a = {
|
|
947
|
-
x:
|
|
948
|
-
y:
|
|
1002
|
+
x: o.x,
|
|
1003
|
+
y: o.y,
|
|
949
1004
|
id: i
|
|
950
1005
|
};
|
|
951
1006
|
this._spatialGrid.insert(a), this._anchorMetadata.set(i, {
|
|
952
1007
|
elementId: e.id,
|
|
953
1008
|
anchorKey: n,
|
|
954
|
-
point:
|
|
1009
|
+
point: o
|
|
955
1010
|
});
|
|
956
1011
|
}
|
|
957
1012
|
}
|
|
958
1013
|
for (const e of this._extraSnapRects) {
|
|
959
|
-
const
|
|
1014
|
+
const s = e.x + e.width / 2, n = e.y + e.height / 2, o = e.x + e.width, i = e.y + e.height, a = {
|
|
960
1015
|
topLeft: { x: e.x, y: e.y },
|
|
961
|
-
topRight: { x:
|
|
1016
|
+
topRight: { x: o, y: e.y },
|
|
962
1017
|
bottomLeft: { x: e.x, y: i },
|
|
963
|
-
bottomRight: { x:
|
|
964
|
-
topCenter: { x:
|
|
965
|
-
rightCenter: { x:
|
|
966
|
-
bottomCenter: { x:
|
|
1018
|
+
bottomRight: { x: o, y: i },
|
|
1019
|
+
topCenter: { x: s, y: e.y },
|
|
1020
|
+
rightCenter: { x: o, y: n },
|
|
1021
|
+
bottomCenter: { x: s, y: i },
|
|
967
1022
|
leftCenter: { x: e.x, y: n },
|
|
968
|
-
center: { x:
|
|
1023
|
+
center: { x: s, y: n }
|
|
969
1024
|
// No `rotation` anchor — extras are un-rotated by definition.
|
|
970
1025
|
}, r = `__snap-rect:${e.id}`;
|
|
971
1026
|
for (const [l, h] of Object.entries(a)) {
|
|
@@ -985,93 +1040,93 @@ class Ke {
|
|
|
985
1040
|
/**
|
|
986
1041
|
* Snap a position during drag operation
|
|
987
1042
|
*/
|
|
988
|
-
snapPosition(t, e,
|
|
989
|
-
if (!this.enabled || !
|
|
1043
|
+
snapPosition(t, e, s) {
|
|
1044
|
+
if (!this.enabled || !s)
|
|
990
1045
|
return this.clearGuides(), t;
|
|
991
1046
|
const n = e.clone();
|
|
992
1047
|
n.x = t.x, n.y = t.y;
|
|
993
|
-
const
|
|
1048
|
+
const o = bt.getSnapAnchors(n), i = s.filter((y) => y.id !== e.id);
|
|
994
1049
|
this._populateSpatialGrid(i);
|
|
995
1050
|
let a = null, r = null, l = 1 / 0, h = 1 / 0;
|
|
996
|
-
const c = [], d = [],
|
|
997
|
-
for (const [y,
|
|
998
|
-
const
|
|
999
|
-
for (const
|
|
1000
|
-
const C = this._anchorMetadata.get(
|
|
1051
|
+
const c = [], d = [], f = [];
|
|
1052
|
+
for (const [y, S] of Object.entries(o)) {
|
|
1053
|
+
const m = this._spatialGrid.queryNearAxis("x", S.x, this.snapThreshold);
|
|
1054
|
+
for (const T of m) {
|
|
1055
|
+
const C = this._anchorMetadata.get(T.id);
|
|
1001
1056
|
if (!C) continue;
|
|
1002
|
-
const R = C.point, x = C.anchorKey, P = Math.abs(
|
|
1057
|
+
const R = C.point, x = C.anchorKey, P = Math.abs(S.x - R.x);
|
|
1003
1058
|
if (P < this.snapThreshold) {
|
|
1004
|
-
const
|
|
1059
|
+
const M = {
|
|
1005
1060
|
snapTo: R.x,
|
|
1006
|
-
offset:
|
|
1061
|
+
offset: S.x - t.x,
|
|
1007
1062
|
// How far anchor is from element position
|
|
1008
1063
|
distance: P,
|
|
1009
1064
|
guide: {
|
|
1010
1065
|
type: "vertical",
|
|
1011
1066
|
x: R.x,
|
|
1012
|
-
y1: Math.min(
|
|
1013
|
-
y2: Math.max(
|
|
1067
|
+
y1: Math.min(S.y, R.y) - 50,
|
|
1068
|
+
y2: Math.max(S.y, R.y) + 50,
|
|
1014
1069
|
movingKey: y,
|
|
1015
1070
|
otherKey: x
|
|
1016
1071
|
}
|
|
1017
1072
|
};
|
|
1018
|
-
c.push(
|
|
1073
|
+
c.push(M), P < l && (l = P, a = M);
|
|
1019
1074
|
}
|
|
1020
1075
|
}
|
|
1021
|
-
const
|
|
1022
|
-
for (const
|
|
1023
|
-
const C = this._anchorMetadata.get(
|
|
1076
|
+
const w = this._spatialGrid.queryNearAxis("y", S.y, this.snapThreshold);
|
|
1077
|
+
for (const T of w) {
|
|
1078
|
+
const C = this._anchorMetadata.get(T.id);
|
|
1024
1079
|
if (!C) continue;
|
|
1025
|
-
const R = C.point, x = C.anchorKey, P = Math.abs(
|
|
1080
|
+
const R = C.point, x = C.anchorKey, P = Math.abs(S.y - R.y);
|
|
1026
1081
|
if (P < this.snapThreshold) {
|
|
1027
|
-
const
|
|
1082
|
+
const M = {
|
|
1028
1083
|
snapTo: R.y,
|
|
1029
|
-
offset:
|
|
1084
|
+
offset: S.y - t.y,
|
|
1030
1085
|
distance: P,
|
|
1031
1086
|
guide: {
|
|
1032
1087
|
type: "horizontal",
|
|
1033
1088
|
y: R.y,
|
|
1034
|
-
x1: Math.min(
|
|
1035
|
-
x2: Math.max(
|
|
1089
|
+
x1: Math.min(S.x, R.x) - 50,
|
|
1090
|
+
x2: Math.max(S.x, R.x) + 50,
|
|
1036
1091
|
movingKey: y,
|
|
1037
1092
|
otherKey: x
|
|
1038
1093
|
}
|
|
1039
1094
|
};
|
|
1040
|
-
d.push(
|
|
1095
|
+
d.push(M), P < h && (h = P, r = M);
|
|
1041
1096
|
}
|
|
1042
1097
|
}
|
|
1043
1098
|
}
|
|
1044
1099
|
let p = t.x, b = t.y;
|
|
1045
1100
|
a && (p = a.snapTo - a.offset), r && (b = r.snapTo - r.offset);
|
|
1046
|
-
const g = /* @__PURE__ */ new Map(),
|
|
1101
|
+
const g = /* @__PURE__ */ new Map(), u = /* @__PURE__ */ new Map();
|
|
1047
1102
|
for (const y of c) {
|
|
1048
|
-
const
|
|
1049
|
-
(!
|
|
1103
|
+
const S = g.get(y.snapTo);
|
|
1104
|
+
(!S || y.distance < S.distance) && g.set(y.snapTo, y);
|
|
1050
1105
|
}
|
|
1051
1106
|
for (const y of d) {
|
|
1052
|
-
const
|
|
1053
|
-
(!
|
|
1107
|
+
const S = u.get(y.snapTo);
|
|
1108
|
+
(!S || y.distance < S.distance) && u.set(y.snapTo, y);
|
|
1054
1109
|
}
|
|
1055
1110
|
for (const y of g.values())
|
|
1056
|
-
|
|
1057
|
-
for (const y of
|
|
1058
|
-
|
|
1059
|
-
return this.guides =
|
|
1111
|
+
f.push(y.guide);
|
|
1112
|
+
for (const y of u.values())
|
|
1113
|
+
f.push(y.guide);
|
|
1114
|
+
return this.guides = f, { x: p, y: b };
|
|
1060
1115
|
}
|
|
1061
1116
|
/**
|
|
1062
1117
|
* Calculate what the frozen font size should be at the snap point
|
|
1063
1118
|
* This ensures consistent font size regardless of which side of threshold you enter from
|
|
1064
1119
|
*/
|
|
1065
|
-
_calculateFrozenFontSizeAtSnap(t, e,
|
|
1066
|
-
if (!
|
|
1120
|
+
_calculateFrozenFontSizeAtSnap(t, e, s, n, o) {
|
|
1121
|
+
if (!o) return t.fontSize ?? 0;
|
|
1067
1122
|
const i = n != null && n.anchor ? String(n.anchor) : "";
|
|
1068
1123
|
if (!(n && (i.includes("top") || i.includes("bottom"))))
|
|
1069
|
-
return
|
|
1070
|
-
const r =
|
|
1124
|
+
return o.fontSize ?? 0;
|
|
1125
|
+
const r = ct(t) ?? t.width ?? o.width;
|
|
1071
1126
|
let l = r;
|
|
1072
1127
|
i.includes("right") && e !== 0 ? l = r + e : i.includes("left") && e !== 0 && (l = r - e);
|
|
1073
|
-
const h = l /
|
|
1074
|
-
return (
|
|
1128
|
+
const h = l / o.width;
|
|
1129
|
+
return (o.fontSize ?? 0) * h;
|
|
1075
1130
|
}
|
|
1076
1131
|
/**
|
|
1077
1132
|
* Check if this will be a position-based snap (vs dimension-based)
|
|
@@ -1098,17 +1153,17 @@ class Ke {
|
|
|
1098
1153
|
* Uses the spatial grid (pre-populated via _populateSpatialGrid) for
|
|
1099
1154
|
* O(1) amortized lookup instead of scanning all other elements.
|
|
1100
1155
|
*/
|
|
1101
|
-
_findXSnaps(t, e,
|
|
1102
|
-
const
|
|
1103
|
-
for (const a of
|
|
1156
|
+
_findXSnaps(t, e, s, n) {
|
|
1157
|
+
const o = [], i = new Set(n);
|
|
1158
|
+
for (const a of s) {
|
|
1104
1159
|
const r = t[a];
|
|
1105
1160
|
if (!r) continue;
|
|
1106
1161
|
const l = this._spatialGrid.queryNearAxis("x", r.x, this.snapThreshold);
|
|
1107
1162
|
for (const h of l) {
|
|
1108
1163
|
const c = this._anchorMetadata.get(h.id);
|
|
1109
1164
|
if (!c || !i.has(c.anchorKey)) continue;
|
|
1110
|
-
const d = c.point,
|
|
1111
|
-
p < this.snapThreshold &&
|
|
1165
|
+
const d = c.point, f = c.anchorKey, p = Math.abs(r.x - d.x);
|
|
1166
|
+
p < this.snapThreshold && o.push({
|
|
1112
1167
|
distance: p,
|
|
1113
1168
|
snapTo: d.x,
|
|
1114
1169
|
currentValue: r.x,
|
|
@@ -1118,29 +1173,29 @@ class Ke {
|
|
|
1118
1173
|
y1: Math.min(r.y, d.y) - 50,
|
|
1119
1174
|
y2: Math.max(r.y, d.y) + 50,
|
|
1120
1175
|
movingKey: a,
|
|
1121
|
-
otherKey:
|
|
1176
|
+
otherKey: f
|
|
1122
1177
|
}
|
|
1123
1178
|
});
|
|
1124
1179
|
}
|
|
1125
1180
|
}
|
|
1126
|
-
return
|
|
1181
|
+
return o;
|
|
1127
1182
|
}
|
|
1128
1183
|
/**
|
|
1129
1184
|
* Find all Y-axis snaps within threshold.
|
|
1130
1185
|
* Uses the spatial grid (pre-populated via _populateSpatialGrid) for
|
|
1131
1186
|
* O(1) amortized lookup instead of scanning all other elements.
|
|
1132
1187
|
*/
|
|
1133
|
-
_findYSnaps(t, e,
|
|
1134
|
-
const
|
|
1135
|
-
for (const a of
|
|
1188
|
+
_findYSnaps(t, e, s, n) {
|
|
1189
|
+
const o = [], i = new Set(n);
|
|
1190
|
+
for (const a of s) {
|
|
1136
1191
|
const r = t[a];
|
|
1137
1192
|
if (!r) continue;
|
|
1138
1193
|
const l = this._spatialGrid.queryNearAxis("y", r.y, this.snapThreshold);
|
|
1139
1194
|
for (const h of l) {
|
|
1140
1195
|
const c = this._anchorMetadata.get(h.id);
|
|
1141
1196
|
if (!c || !i.has(c.anchorKey)) continue;
|
|
1142
|
-
const d = c.point,
|
|
1143
|
-
p < this.snapThreshold &&
|
|
1197
|
+
const d = c.point, f = c.anchorKey, p = Math.abs(r.y - d.y);
|
|
1198
|
+
p < this.snapThreshold && o.push({
|
|
1144
1199
|
distance: p,
|
|
1145
1200
|
snapTo: d.y,
|
|
1146
1201
|
currentValue: r.y,
|
|
@@ -1150,44 +1205,44 @@ class Ke {
|
|
|
1150
1205
|
x1: Math.min(r.x, d.x) - 50,
|
|
1151
1206
|
x2: Math.max(r.x, d.x) + 50,
|
|
1152
1207
|
movingKey: a,
|
|
1153
|
-
otherKey:
|
|
1208
|
+
otherKey: f
|
|
1154
1209
|
}
|
|
1155
1210
|
});
|
|
1156
1211
|
}
|
|
1157
1212
|
}
|
|
1158
|
-
return
|
|
1213
|
+
return o;
|
|
1159
1214
|
}
|
|
1160
1215
|
/**
|
|
1161
1216
|
* Sort snaps by distance and prioritize based on handle anchor
|
|
1162
1217
|
*/
|
|
1163
|
-
_prioritizeSnaps(t, e,
|
|
1218
|
+
_prioritizeSnaps(t, e, s) {
|
|
1164
1219
|
if (!e || !e.anchor) {
|
|
1165
|
-
t.sort((n,
|
|
1220
|
+
t.sort((n, o) => n.distance - o.distance);
|
|
1166
1221
|
return;
|
|
1167
1222
|
}
|
|
1168
|
-
|
|
1169
|
-
const i = n.guide.movingKey.includes("left") ? -1e3 : 0, a =
|
|
1170
|
-
return n.distance + i - (
|
|
1171
|
-
}) : e.anchor.includes("right") ? t.sort((n,
|
|
1172
|
-
const i = n.guide.movingKey.includes("right") ? -1e3 : 0, a =
|
|
1173
|
-
return n.distance + i - (
|
|
1174
|
-
}) : t.sort((n,
|
|
1175
|
-
const i = n.guide.movingKey.includes("top") ? -1e3 : 0, a =
|
|
1176
|
-
return n.distance + i - (
|
|
1177
|
-
}) : e.anchor.includes("bottom") ? t.sort((n,
|
|
1178
|
-
const i = n.guide.movingKey.includes("bottom") ? -1e3 : 0, a =
|
|
1179
|
-
return n.distance + i - (
|
|
1180
|
-
}) : t.sort((n,
|
|
1223
|
+
s === "x" ? e.anchor.includes("left") ? t.sort((n, o) => {
|
|
1224
|
+
const i = n.guide.movingKey.includes("left") ? -1e3 : 0, a = o.guide.movingKey.includes("left") ? -1e3 : 0;
|
|
1225
|
+
return n.distance + i - (o.distance + a);
|
|
1226
|
+
}) : e.anchor.includes("right") ? t.sort((n, o) => {
|
|
1227
|
+
const i = n.guide.movingKey.includes("right") ? -1e3 : 0, a = o.guide.movingKey.includes("right") ? -1e3 : 0;
|
|
1228
|
+
return n.distance + i - (o.distance + a);
|
|
1229
|
+
}) : t.sort((n, o) => n.distance - o.distance) : s === "y" && (e.anchor.includes("top") ? t.sort((n, o) => {
|
|
1230
|
+
const i = n.guide.movingKey.includes("top") ? -1e3 : 0, a = o.guide.movingKey.includes("top") ? -1e3 : 0;
|
|
1231
|
+
return n.distance + i - (o.distance + a);
|
|
1232
|
+
}) : e.anchor.includes("bottom") ? t.sort((n, o) => {
|
|
1233
|
+
const i = n.guide.movingKey.includes("bottom") ? -1e3 : 0, a = o.guide.movingKey.includes("bottom") ? -1e3 : 0;
|
|
1234
|
+
return n.distance + i - (o.distance + a);
|
|
1235
|
+
}) : t.sort((n, o) => n.distance - o.distance));
|
|
1181
1236
|
}
|
|
1182
1237
|
/**
|
|
1183
1238
|
* Create a guide visualization for an active snap
|
|
1184
1239
|
*/
|
|
1185
|
-
_createGuideForSnap(t, e,
|
|
1186
|
-
const i =
|
|
1240
|
+
_createGuideForSnap(t, e, s, n, o) {
|
|
1241
|
+
const i = s[e];
|
|
1187
1242
|
if (!i) return null;
|
|
1188
|
-
if (
|
|
1243
|
+
if (o === "x") {
|
|
1189
1244
|
let a = 1 / 0, r = -1 / 0;
|
|
1190
|
-
for (const l of Object.values(
|
|
1245
|
+
for (const l of Object.values(s))
|
|
1191
1246
|
Math.abs(l.x - t.snapTo) < 5 && (a = Math.min(a, l.y), r = Math.max(r, l.y));
|
|
1192
1247
|
for (const l of n) {
|
|
1193
1248
|
const h = bt.getSnapAnchors(l);
|
|
@@ -1207,9 +1262,9 @@ class Ke {
|
|
|
1207
1262
|
otherKey: "snap"
|
|
1208
1263
|
}
|
|
1209
1264
|
};
|
|
1210
|
-
} else if (
|
|
1265
|
+
} else if (o === "y") {
|
|
1211
1266
|
let a = 1 / 0, r = -1 / 0;
|
|
1212
|
-
for (const l of Object.values(
|
|
1267
|
+
for (const l of Object.values(s))
|
|
1213
1268
|
Math.abs(l.y - t.snapTo) < 5 && (a = Math.min(a, l.x), r = Math.max(r, l.x));
|
|
1214
1269
|
for (const l of n) {
|
|
1215
1270
|
const h = bt.getSnapAnchors(l);
|
|
@@ -1238,9 +1293,9 @@ class Ke {
|
|
|
1238
1293
|
* Adjust threshold to compensate for this velocity difference
|
|
1239
1294
|
*/
|
|
1240
1295
|
_getAdjustedStickyThreshold(t, e) {
|
|
1241
|
-
const
|
|
1242
|
-
let
|
|
1243
|
-
return t === "x" ? n > 1 && (
|
|
1296
|
+
const s = e.getVisualBoundingBox(), n = s.width / s.height;
|
|
1297
|
+
let o = this.stickyThreshold;
|
|
1298
|
+
return t === "x" ? n > 1 && (o = this.stickyThreshold / Math.sqrt(n)) : t === "y" && n < 1 && (o = this.stickyThreshold * Math.sqrt(n)), o;
|
|
1244
1299
|
}
|
|
1245
1300
|
/**
|
|
1246
1301
|
* Calculate what dimensions should be when edge reaches snap point
|
|
@@ -1258,30 +1313,30 @@ class Ke {
|
|
|
1258
1313
|
* @param handle - The resize handle being dragged
|
|
1259
1314
|
* @returns {Object} { frozenWidth, frozenHeight } - Dimensions at snap point
|
|
1260
1315
|
*/
|
|
1261
|
-
_calculateFrozenDimensionsAtSnap(t, e,
|
|
1262
|
-
const i =
|
|
1316
|
+
_calculateFrozenDimensionsAtSnap(t, e, s, n, o) {
|
|
1317
|
+
const i = ct(t) ?? t.width ?? 0, a = St(t) ?? t.height ?? 0;
|
|
1263
1318
|
let r = i, l = a;
|
|
1264
1319
|
const h = t.transformType === "image", c = h ? t.imageAspectRatio || (i && a ? i / a : null) : null, d = n.toLowerCase();
|
|
1265
|
-
return e === "x" ? d.includes("right") ? (r = i +
|
|
1320
|
+
return e === "x" ? d.includes("right") ? (r = i + s, h && c && (l = r / c)) : d.includes("left") && (r = i - s, h && c && (l = r / c)) : e === "y" && (d.includes("bottom") ? (l = a + s, h && c && (r = l * c)) : d.includes("top") && (l = a - s, h && c && (r = l * c))), { frozenWidth: r, frozenHeight: l };
|
|
1266
1321
|
}
|
|
1267
1322
|
/**
|
|
1268
1323
|
* Process sticky snapping for a single axis
|
|
1269
1324
|
* @returns {Object} { snapDelta, bestSnap }
|
|
1270
1325
|
*/
|
|
1271
|
-
_processStickySnap(t, e,
|
|
1326
|
+
_processStickySnap(t, e, s, n, o, i, a) {
|
|
1272
1327
|
const r = this.activeSnaps[t];
|
|
1273
1328
|
let l = 0, h = null;
|
|
1274
1329
|
if (r) {
|
|
1275
1330
|
const c = e[r.anchorKey];
|
|
1276
1331
|
if (c) {
|
|
1277
|
-
const d = t === "x" ? c.x : c.y,
|
|
1278
|
-
if (
|
|
1332
|
+
const d = t === "x" ? c.x : c.y, f = Math.abs(d - r.snapTo), p = this._getAdjustedStickyThreshold(t, n);
|
|
1333
|
+
if (f < p) {
|
|
1279
1334
|
if (l = r.snapTo - d, !(t === "y" && r.isPositionBasedSnap)) {
|
|
1280
1335
|
const g = this._calculateFrozenFontSizeAtSnap(
|
|
1281
1336
|
n,
|
|
1282
1337
|
t === "x" ? l : 0,
|
|
1283
1338
|
t === "y" ? l : 0,
|
|
1284
|
-
|
|
1339
|
+
o,
|
|
1285
1340
|
i
|
|
1286
1341
|
);
|
|
1287
1342
|
g !== r.frozenFontSize && (r.frozenFontSize = g);
|
|
@@ -1289,47 +1344,47 @@ class Ke {
|
|
|
1289
1344
|
h = this._createGuideForSnap(r, r.anchorKey, e, a, t);
|
|
1290
1345
|
} else {
|
|
1291
1346
|
const b = r;
|
|
1292
|
-
if (this.activeSnaps[t] = null,
|
|
1293
|
-
h =
|
|
1294
|
-
const g = b && b.anchorKey === h.guide.movingKey && Math.abs(b.snapTo - h.snapTo) < 1,
|
|
1347
|
+
if (this.activeSnaps[t] = null, s.length > 0 && s[0].distance < this.snapThreshold) {
|
|
1348
|
+
h = s[0], l = h.snapTo - h.currentValue;
|
|
1349
|
+
const g = b && b.anchorKey === h.guide.movingKey && Math.abs(b.snapTo - h.snapTo) < 1, u = g ? b.frozenFontSize : this._calculateFrozenFontSizeAtSnap(
|
|
1295
1350
|
n,
|
|
1296
1351
|
t === "x" ? l : 0,
|
|
1297
1352
|
t === "y" ? l : 0,
|
|
1298
|
-
|
|
1353
|
+
o,
|
|
1299
1354
|
i
|
|
1300
1355
|
), y = this._isPositionBasedSnap(n, t);
|
|
1301
|
-
let
|
|
1302
|
-
g ?
|
|
1356
|
+
let S;
|
|
1357
|
+
g ? S = b.frozenPosition : y ? S = {
|
|
1303
1358
|
x: t === "x" ? n.x + l : n.x,
|
|
1304
1359
|
y: t === "y" ? n.y + l : n.y
|
|
1305
|
-
} :
|
|
1306
|
-
const
|
|
1360
|
+
} : S = { x: n.x, y: n.y };
|
|
1361
|
+
const m = this._calculateFrozenDimensionsAtSnap(
|
|
1307
1362
|
n,
|
|
1308
1363
|
t,
|
|
1309
1364
|
l,
|
|
1310
1365
|
h.guide.movingKey,
|
|
1311
|
-
|
|
1366
|
+
o
|
|
1312
1367
|
);
|
|
1313
1368
|
this.activeSnaps[t] = {
|
|
1314
1369
|
snapTo: h.snapTo,
|
|
1315
1370
|
anchorKey: h.guide.movingKey,
|
|
1316
|
-
frozenFontSize:
|
|
1317
|
-
frozenWidth:
|
|
1318
|
-
frozenHeight:
|
|
1319
|
-
frozenPosition:
|
|
1371
|
+
frozenFontSize: u,
|
|
1372
|
+
frozenWidth: m.frozenWidth,
|
|
1373
|
+
frozenHeight: m.frozenHeight,
|
|
1374
|
+
frozenPosition: S,
|
|
1320
1375
|
isPositionBasedSnap: y
|
|
1321
1376
|
};
|
|
1322
1377
|
}
|
|
1323
1378
|
}
|
|
1324
1379
|
} else
|
|
1325
1380
|
this.activeSnaps[t] = null;
|
|
1326
|
-
} else if (
|
|
1327
|
-
h =
|
|
1328
|
-
const c = this.activeSnaps[t], d = c && c.anchorKey === h.guide.movingKey && Math.abs(c.snapTo - h.snapTo) < 1,
|
|
1381
|
+
} else if (s.length > 0 && s[0].distance < this.snapThreshold) {
|
|
1382
|
+
h = s[0], l = h.snapTo - h.currentValue;
|
|
1383
|
+
const c = this.activeSnaps[t], d = c && c.anchorKey === h.guide.movingKey && Math.abs(c.snapTo - h.snapTo) < 1, f = d ? c.frozenFontSize : this._calculateFrozenFontSizeAtSnap(
|
|
1329
1384
|
n,
|
|
1330
1385
|
t === "x" ? l : 0,
|
|
1331
1386
|
t === "y" ? l : 0,
|
|
1332
|
-
|
|
1387
|
+
o,
|
|
1333
1388
|
i
|
|
1334
1389
|
), p = this._isPositionBasedSnap(n, t);
|
|
1335
1390
|
let b;
|
|
@@ -1342,12 +1397,12 @@ class Ke {
|
|
|
1342
1397
|
t,
|
|
1343
1398
|
l,
|
|
1344
1399
|
h.guide.movingKey,
|
|
1345
|
-
|
|
1400
|
+
o
|
|
1346
1401
|
);
|
|
1347
1402
|
this.activeSnaps[t] = {
|
|
1348
1403
|
snapTo: h.snapTo,
|
|
1349
1404
|
anchorKey: h.guide.movingKey,
|
|
1350
|
-
frozenFontSize:
|
|
1405
|
+
frozenFontSize: f,
|
|
1351
1406
|
frozenWidth: g.frozenWidth,
|
|
1352
1407
|
frozenHeight: g.frozenHeight,
|
|
1353
1408
|
frozenPosition: b,
|
|
@@ -1359,16 +1414,16 @@ class Ke {
|
|
|
1359
1414
|
/**
|
|
1360
1415
|
* Adjust element for right edge resize
|
|
1361
1416
|
*/
|
|
1362
|
-
_adjustElementForRightResize(t, e,
|
|
1363
|
-
const n = t.getVisualBoundingBox(),
|
|
1364
|
-
if (!
|
|
1365
|
-
const i =
|
|
1366
|
-
i !== void 0 ?
|
|
1417
|
+
_adjustElementForRightResize(t, e, s) {
|
|
1418
|
+
const n = t.getVisualBoundingBox(), o = t.transformType === "image";
|
|
1419
|
+
if (!o) {
|
|
1420
|
+
const i = ct(t);
|
|
1421
|
+
i !== void 0 ? vt(t, i + e) : t.width !== void 0 && (t.width += e);
|
|
1367
1422
|
}
|
|
1368
|
-
if (
|
|
1369
|
-
const i =
|
|
1423
|
+
if (s.anchor === "middle-right") {
|
|
1424
|
+
const i = dt.toRadiansInverse(t.rotation), a = Math.cos(i), r = Math.sin(i);
|
|
1370
1425
|
t.x += e / 2 * a, t.y += e / 2 * r;
|
|
1371
|
-
} else if (!
|
|
1426
|
+
} else if (!o) {
|
|
1372
1427
|
const a = t.getVisualBoundingBox().x - n.x;
|
|
1373
1428
|
a !== 0 && (t.x -= a);
|
|
1374
1429
|
}
|
|
@@ -1376,16 +1431,16 @@ class Ke {
|
|
|
1376
1431
|
/**
|
|
1377
1432
|
* Adjust element for left edge resize
|
|
1378
1433
|
*/
|
|
1379
|
-
_adjustElementForLeftResize(t, e,
|
|
1380
|
-
const n = t.getVisualBoundingBox(),
|
|
1381
|
-
if (!
|
|
1382
|
-
const i =
|
|
1383
|
-
i !== void 0 ?
|
|
1434
|
+
_adjustElementForLeftResize(t, e, s) {
|
|
1435
|
+
const n = t.getVisualBoundingBox(), o = t.transformType === "image";
|
|
1436
|
+
if (!o) {
|
|
1437
|
+
const i = ct(t);
|
|
1438
|
+
i !== void 0 ? vt(t, i - e) : t.width !== void 0 && (t.width -= e);
|
|
1384
1439
|
}
|
|
1385
|
-
if (
|
|
1386
|
-
const i =
|
|
1440
|
+
if (s.anchor === "middle-left") {
|
|
1441
|
+
const i = dt.toRadiansInverse(t.rotation), a = Math.cos(i), r = Math.sin(i);
|
|
1387
1442
|
t.x += e / 2 * a, t.y += e / 2 * r;
|
|
1388
|
-
} else if (t.x += e, !
|
|
1443
|
+
} else if (t.x += e, !o) {
|
|
1389
1444
|
const i = t.getVisualBoundingBox(), a = i.x + i.width - (n.x + n.width);
|
|
1390
1445
|
a !== 0 && (t.x -= a);
|
|
1391
1446
|
}
|
|
@@ -1393,36 +1448,36 @@ class Ke {
|
|
|
1393
1448
|
/**
|
|
1394
1449
|
* Adjust element for bottom edge resize
|
|
1395
1450
|
*/
|
|
1396
|
-
_adjustElementForBottomResize(t, e,
|
|
1397
|
-
const n = t.getVisualBoundingBox(),
|
|
1398
|
-
if (!
|
|
1451
|
+
_adjustElementForBottomResize(t, e, s) {
|
|
1452
|
+
const n = t.getVisualBoundingBox(), o = t.transformType === "image";
|
|
1453
|
+
if (!o) {
|
|
1399
1454
|
const r = St(t);
|
|
1400
1455
|
r !== void 0 ? Pt(t, r + e) : t.height !== void 0 && (t.height += e);
|
|
1401
1456
|
}
|
|
1402
1457
|
const i = t.getVisualBoundingBox(), a = Math.abs(i.height - n.height) > 0.01;
|
|
1403
|
-
if (
|
|
1404
|
-
const r =
|
|
1458
|
+
if (s.anchor === "middle-bottom") {
|
|
1459
|
+
const r = dt.toRadiansInverse(t.rotation), l = Math.cos(r), h = Math.sin(r);
|
|
1405
1460
|
t.x -= e / 2 * h, t.y += e / 2 * l;
|
|
1406
|
-
} else if (!
|
|
1461
|
+
} else if (!o && a) {
|
|
1407
1462
|
const r = i.y - n.y;
|
|
1408
1463
|
r !== 0 && (t.y -= r);
|
|
1409
|
-
} else
|
|
1464
|
+
} else o || (t.y += e);
|
|
1410
1465
|
}
|
|
1411
1466
|
/**
|
|
1412
1467
|
* Adjust element for top edge resize
|
|
1413
1468
|
*/
|
|
1414
|
-
_adjustElementForTopResize(t, e,
|
|
1415
|
-
const n = t.getVisualBoundingBox(),
|
|
1416
|
-
if (!
|
|
1469
|
+
_adjustElementForTopResize(t, e, s) {
|
|
1470
|
+
const n = t.getVisualBoundingBox(), o = t.transformType === "image";
|
|
1471
|
+
if (!o) {
|
|
1417
1472
|
const r = St(t);
|
|
1418
1473
|
r !== void 0 ? Pt(t, r - e) : t.height !== void 0 && (t.height -= e);
|
|
1419
1474
|
}
|
|
1420
1475
|
const i = t.getVisualBoundingBox(), a = Math.abs(i.height - n.height) > 0.01;
|
|
1421
|
-
if (
|
|
1422
|
-
const r =
|
|
1476
|
+
if (s.anchor === "middle-top") {
|
|
1477
|
+
const r = dt.toRadiansInverse(t.rotation), l = Math.cos(r), h = Math.sin(r);
|
|
1423
1478
|
t.x -= e / 2 * h, t.y += e / 2 * l;
|
|
1424
1479
|
} else {
|
|
1425
|
-
const r = !
|
|
1480
|
+
const r = !o && a;
|
|
1426
1481
|
if (t.y += e, r) {
|
|
1427
1482
|
const l = t.getVisualBoundingBox(), h = l.y + l.height - (n.y + n.height);
|
|
1428
1483
|
h !== 0 && (t.y -= h);
|
|
@@ -1437,64 +1492,64 @@ class Ke {
|
|
|
1437
1492
|
* @param {object} startData - Original data from when resize started (for font size preservation)
|
|
1438
1493
|
* @returns {object} Modified resize result with adjusted element
|
|
1439
1494
|
*/
|
|
1440
|
-
snapDimensions(t, e,
|
|
1441
|
-
var
|
|
1495
|
+
snapDimensions(t, e, s = null) {
|
|
1496
|
+
var T, C, R, x, P;
|
|
1442
1497
|
if (!this.enabled || !e)
|
|
1443
1498
|
return this.clearGuides(), t;
|
|
1444
|
-
const { element: n } = t,
|
|
1499
|
+
const { element: n } = t, o = t.handle;
|
|
1445
1500
|
let i;
|
|
1446
1501
|
const a = n.transformType === "image", r = this.activeSnaps.x !== null || this.activeSnaps.y !== null;
|
|
1447
1502
|
if (a && r && t.isFrozen && t.unfrozenDimensions) {
|
|
1448
|
-
const
|
|
1449
|
-
if (
|
|
1450
|
-
const A = n.getVisualBoundingBox(), B = A.width, L = A.height, W = (
|
|
1451
|
-
|
|
1503
|
+
const M = n.clone();
|
|
1504
|
+
if (M.transformData) {
|
|
1505
|
+
const A = n.getVisualBoundingBox(), B = A.width, L = A.height, W = (s == null ? void 0 : s.width) ?? n.width ?? 0, O = (s == null ? void 0 : s.height) ?? n.height ?? 0, D = (s == null ? void 0 : s.visualWidth) ?? B, Q = (s == null ? void 0 : s.visualHeight) ?? L, E = t.unfrozenDimensions.width / D, j = t.unfrozenDimensions.height / Q;
|
|
1506
|
+
vt(M, W * E), Pt(M, O * j);
|
|
1452
1507
|
}
|
|
1453
|
-
i = bt.getSnapAnchors(
|
|
1508
|
+
i = bt.getSnapAnchors(M);
|
|
1454
1509
|
} else
|
|
1455
1510
|
i = bt.getSnapAnchors(n);
|
|
1456
|
-
const l = e.filter((
|
|
1511
|
+
const l = e.filter((M) => M.id !== n.id);
|
|
1457
1512
|
if (l.length === 0)
|
|
1458
1513
|
return this.clearGuides(), t;
|
|
1459
1514
|
this._populateSpatialGrid(l);
|
|
1460
|
-
const h = this._getSnapKeysForHandle(
|
|
1461
|
-
this._prioritizeSnaps(d,
|
|
1462
|
-
const p = this._processStickySnap("x", i, d, n,
|
|
1463
|
-
y &&
|
|
1464
|
-
const
|
|
1465
|
-
if (a &&
|
|
1515
|
+
const h = this._getSnapKeysForHandle(o), c = this._getTargetSnapKeys(), d = this._findXSnaps(i, l, h, c), f = this._findYSnaps(i, l, h, c);
|
|
1516
|
+
this._prioritizeSnaps(d, o, "x"), this._prioritizeSnaps(f, o, "y");
|
|
1517
|
+
const p = this._processStickySnap("x", i, d, n, o, s, l), b = this._processStickySnap("y", i, f, n, o, s, l), g = p.snapDelta, u = b.snapDelta, y = p.bestSnap, S = b.bestSnap, m = [];
|
|
1518
|
+
y && m.push(y.guide), S && m.push(S.guide), this.guides = m, m.length > 0;
|
|
1519
|
+
const w = o && (o.anchor === "top-left" || o.anchor === "top-right" || o.anchor === "bottom-left" || o.anchor === "bottom-right");
|
|
1520
|
+
if (a && w && (g !== 0 || u !== 0))
|
|
1466
1521
|
return t;
|
|
1467
|
-
if (g !== 0 ||
|
|
1468
|
-
const
|
|
1522
|
+
if (g !== 0 || u !== 0) {
|
|
1523
|
+
const M = n.clone(), A = this.activeSnaps.x || this.activeSnaps.y, B = (A == null ? void 0 : A.frozenFontSize) ?? n.fontSize ?? 0, L = (A == null ? void 0 : A.frozenWidth) ?? ct(n) ?? n.width ?? 0, W = (A == null ? void 0 : A.frozenHeight) ?? St(n) ?? n.height ?? 0, O = (A == null ? void 0 : A.frozenPosition) ?? { x: n.x, y: n.y }, D = M.isCropping && !String(o.anchor).startsWith("crop-");
|
|
1469
1524
|
if (!D)
|
|
1470
|
-
if (
|
|
1525
|
+
if (o && o.anchor) {
|
|
1471
1526
|
if (g !== 0) {
|
|
1472
|
-
const k = (
|
|
1473
|
-
|
|
1527
|
+
const k = (T = this.activeSnaps.x) == null ? void 0 : T.anchorKey, H = k == null ? void 0 : k.toLowerCase();
|
|
1528
|
+
H && H.includes("right") ? this._adjustElementForRightResize(M, g, o) : H && H.includes("left") ? this._adjustElementForLeftResize(M, g, o) : M.x += g;
|
|
1474
1529
|
}
|
|
1475
|
-
if (
|
|
1476
|
-
const k = (C = this.activeSnaps.y) == null ? void 0 : C.anchorKey,
|
|
1477
|
-
|
|
1530
|
+
if (u !== 0) {
|
|
1531
|
+
const k = (C = this.activeSnaps.y) == null ? void 0 : C.anchorKey, H = k == null ? void 0 : k.toLowerCase();
|
|
1532
|
+
H && H.includes("bottom") ? this._adjustElementForBottomResize(M, u, o) : H && H.includes("top") ? this._adjustElementForTopResize(M, u, o) : M.y += u;
|
|
1478
1533
|
}
|
|
1479
1534
|
} else
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
const
|
|
1483
|
-
if (
|
|
1484
|
-
if (
|
|
1535
|
+
M.x += g, M.y += u;
|
|
1536
|
+
M.fontSize !== void 0 && (M.fontSize = B);
|
|
1537
|
+
const Q = M.transformType === "image", E = this.activeSnaps.x !== null || this.activeSnaps.y !== null;
|
|
1538
|
+
if (Q && E) {
|
|
1539
|
+
if (ct(M) !== void 0) {
|
|
1485
1540
|
const k = this.activeSnaps.x || this.activeSnaps.y;
|
|
1486
|
-
let
|
|
1487
|
-
k && (
|
|
1488
|
-
const
|
|
1489
|
-
|
|
1541
|
+
let H = L, X = W;
|
|
1542
|
+
k && (H = k.frozenWidth ?? H, X = k.frozenHeight ?? X);
|
|
1543
|
+
const I = ct(n), z = St(n), G = M.imageAspectRatio || (I && z ? I / z : null);
|
|
1544
|
+
G && G !== 0 && (X = H / G), vt(M, H), Pt(M, X), k && (k.frozenWidth = H, k.frozenHeight = X);
|
|
1490
1545
|
}
|
|
1491
1546
|
} else
|
|
1492
|
-
(((R = this.activeSnaps.y) == null ? void 0 : R.isPositionBasedSnap) || !1) && (
|
|
1493
|
-
const
|
|
1494
|
-
return (g === 0 ||
|
|
1547
|
+
(((R = this.activeSnaps.y) == null ? void 0 : R.isPositionBasedSnap) || !1) && (ct(M) !== void 0 ? vt(M, L) : M.width !== void 0 && (M.width = L));
|
|
1548
|
+
const j = o && (o.anchor === "middle-left" || o.anchor === "middle-right"), _ = o && (o.anchor === "middle-top" || o.anchor === "middle-bottom"), $ = ((x = this.activeSnaps.x) == null ? void 0 : x.isPositionBasedSnap) || !1, Y = ((P = this.activeSnaps.y) == null ? void 0 : P.isPositionBasedSnap) || !1;
|
|
1549
|
+
return (g === 0 || $) && !j && !_ && !D && (M.x = O.x), (u === 0 || Y) && !_ && !j && !D && (M.y = O.y), {
|
|
1495
1550
|
...t,
|
|
1496
|
-
element:
|
|
1497
|
-
snapAdjustment: { dx: g, dy:
|
|
1551
|
+
element: M,
|
|
1552
|
+
snapAdjustment: { dx: g, dy: u },
|
|
1498
1553
|
// Flag to indicate we're in sticky snap mode (used to freeze font size)
|
|
1499
1554
|
isInStickySnap: !0
|
|
1500
1555
|
};
|
|
@@ -1504,16 +1559,16 @@ class Ke {
|
|
|
1504
1559
|
/**
|
|
1505
1560
|
* Snap rotation (for future implementation)
|
|
1506
1561
|
*/
|
|
1507
|
-
snapRotation(t, e,
|
|
1562
|
+
snapRotation(t, e, s) {
|
|
1508
1563
|
if (!this.enabled) return t;
|
|
1509
|
-
const n = [0, 45, 90, 135, 180, 225, 270, 315, 360],
|
|
1564
|
+
const n = [0, 45, 90, 135, 180, 225, 270, 315, 360], o = 5;
|
|
1510
1565
|
for (const i of n)
|
|
1511
|
-
if (ie(t, i,
|
|
1566
|
+
if (ie(t, i, o))
|
|
1512
1567
|
return i;
|
|
1513
1568
|
return t;
|
|
1514
1569
|
}
|
|
1515
1570
|
}
|
|
1516
|
-
class
|
|
1571
|
+
class Je {
|
|
1517
1572
|
constructor(t = {}) {
|
|
1518
1573
|
this.lastSnapTarget = null, this.detectionThreshold = t.detectionThreshold || 100, this.minDistance = t.minDistance || 10, this.enabled = t.enabled !== !1, this.showLabels = t.showLabels !== !1, this.indicators = [];
|
|
1519
1574
|
}
|
|
@@ -1545,109 +1600,109 @@ class $e {
|
|
|
1545
1600
|
* Snap position to match consistent spacing patterns
|
|
1546
1601
|
* Returns adjusted position if spacing snap is detected, otherwise returns original position
|
|
1547
1602
|
*/
|
|
1548
|
-
snapToSpacing(t, e,
|
|
1549
|
-
if (!this.enabled || !
|
|
1603
|
+
snapToSpacing(t, e, s) {
|
|
1604
|
+
if (!this.enabled || !s)
|
|
1550
1605
|
return t;
|
|
1551
|
-
const n = Ft,
|
|
1552
|
-
if (
|
|
1606
|
+
const n = Ft, o = s.filter((g) => g.id !== e.id);
|
|
1607
|
+
if (o.length === 0)
|
|
1553
1608
|
return t;
|
|
1554
1609
|
const i = e.clone();
|
|
1555
1610
|
i.x = t.x, i.y = t.y;
|
|
1556
1611
|
const a = i.getVisualBoundingBox(), r = a.x - t.x, l = a.y - t.y;
|
|
1557
|
-
let h = t.x, c = t.y, d = !1,
|
|
1558
|
-
const p =
|
|
1559
|
-
const
|
|
1560
|
-
return !(a.x + a.width <
|
|
1612
|
+
let h = t.x, c = t.y, d = !1, f = !1;
|
|
1613
|
+
const p = o.filter((g) => {
|
|
1614
|
+
const u = g.getVisualBoundingBox();
|
|
1615
|
+
return !(a.x + a.width < u.x || a.x > u.x + u.width);
|
|
1561
1616
|
});
|
|
1562
|
-
if (p.sort((g,
|
|
1563
|
-
const y = g.getVisualBoundingBox(),
|
|
1564
|
-
return y.y -
|
|
1617
|
+
if (p.sort((g, u) => {
|
|
1618
|
+
const y = g.getVisualBoundingBox(), S = u.getVisualBoundingBox();
|
|
1619
|
+
return y.y - S.y;
|
|
1565
1620
|
}), p.length >= 1) {
|
|
1566
|
-
let g = null,
|
|
1567
|
-
for (const
|
|
1568
|
-
const
|
|
1569
|
-
|
|
1621
|
+
let g = null, u = null;
|
|
1622
|
+
for (const m of p) {
|
|
1623
|
+
const w = m.getVisualBoundingBox();
|
|
1624
|
+
w.y + w.height <= a.y ? (!g || w.y > g.getVisualBoundingBox().y) && (g = m) : w.y >= a.y + a.height && (!u || w.y < u.getVisualBoundingBox().y) && (u = m);
|
|
1570
1625
|
}
|
|
1571
1626
|
const y = [];
|
|
1572
|
-
for (let
|
|
1573
|
-
const
|
|
1627
|
+
for (let m = 0; m < p.length - 1; m++) {
|
|
1628
|
+
const w = p[m].getVisualBoundingBox(), C = p[m + 1].getVisualBoundingBox().y - (w.y + w.height);
|
|
1574
1629
|
y.push(C);
|
|
1575
1630
|
}
|
|
1576
|
-
let
|
|
1631
|
+
let S = null;
|
|
1577
1632
|
if (g) {
|
|
1578
|
-
const
|
|
1579
|
-
for (const
|
|
1580
|
-
if (Math.abs(
|
|
1581
|
-
|
|
1633
|
+
const m = g.getVisualBoundingBox(), w = a.y - (m.y + m.height);
|
|
1634
|
+
for (const T of y)
|
|
1635
|
+
if (Math.abs(w - T) <= n) {
|
|
1636
|
+
S = T;
|
|
1582
1637
|
break;
|
|
1583
1638
|
}
|
|
1584
1639
|
}
|
|
1585
|
-
if (!
|
|
1586
|
-
const
|
|
1587
|
-
for (const
|
|
1588
|
-
if (Math.abs(
|
|
1589
|
-
|
|
1640
|
+
if (!S && u) {
|
|
1641
|
+
const w = u.getVisualBoundingBox().y - (a.y + a.height);
|
|
1642
|
+
for (const T of y)
|
|
1643
|
+
if (Math.abs(w - T) <= n) {
|
|
1644
|
+
S = T;
|
|
1590
1645
|
break;
|
|
1591
1646
|
}
|
|
1592
1647
|
}
|
|
1593
|
-
if (
|
|
1648
|
+
if (S !== null && S > 0) {
|
|
1594
1649
|
if (g) {
|
|
1595
|
-
const
|
|
1596
|
-
Math.abs(
|
|
1650
|
+
const m = g.getVisualBoundingBox(), w = a.y - (m.y + m.height);
|
|
1651
|
+
Math.abs(w - S) <= n && (c = m.y + m.height + S - l, f = !0);
|
|
1597
1652
|
}
|
|
1598
|
-
if (!
|
|
1599
|
-
const
|
|
1600
|
-
Math.abs(
|
|
1653
|
+
if (!f && u) {
|
|
1654
|
+
const m = u.getVisualBoundingBox(), w = m.y - (a.y + a.height);
|
|
1655
|
+
Math.abs(w - S) <= n && (c = m.y - a.height - S - l, f = !0);
|
|
1601
1656
|
}
|
|
1602
1657
|
}
|
|
1603
1658
|
}
|
|
1604
|
-
const b =
|
|
1605
|
-
const
|
|
1606
|
-
return !(a.y + a.height <
|
|
1659
|
+
const b = o.filter((g) => {
|
|
1660
|
+
const u = g.getVisualBoundingBox();
|
|
1661
|
+
return !(a.y + a.height < u.y || a.y > u.y + u.height);
|
|
1607
1662
|
});
|
|
1608
|
-
if (b.sort((g,
|
|
1609
|
-
const y = g.getVisualBoundingBox(),
|
|
1610
|
-
return y.x -
|
|
1663
|
+
if (b.sort((g, u) => {
|
|
1664
|
+
const y = g.getVisualBoundingBox(), S = u.getVisualBoundingBox();
|
|
1665
|
+
return y.x - S.x;
|
|
1611
1666
|
}), b.length >= 1) {
|
|
1612
|
-
let g = null,
|
|
1613
|
-
for (const
|
|
1614
|
-
const
|
|
1615
|
-
|
|
1667
|
+
let g = null, u = null;
|
|
1668
|
+
for (const m of b) {
|
|
1669
|
+
const w = m.getVisualBoundingBox();
|
|
1670
|
+
w.x + w.width <= a.x ? (!g || w.x > g.getVisualBoundingBox().x) && (g = m) : w.x >= a.x + a.width && (!u || w.x < u.getVisualBoundingBox().x) && (u = m);
|
|
1616
1671
|
}
|
|
1617
1672
|
const y = [];
|
|
1618
|
-
for (let
|
|
1619
|
-
const
|
|
1673
|
+
for (let m = 0; m < b.length - 1; m++) {
|
|
1674
|
+
const w = b[m].getVisualBoundingBox(), C = b[m + 1].getVisualBoundingBox().x - (w.x + w.width);
|
|
1620
1675
|
y.push(C);
|
|
1621
1676
|
}
|
|
1622
|
-
let
|
|
1677
|
+
let S = null;
|
|
1623
1678
|
if (g) {
|
|
1624
|
-
const
|
|
1625
|
-
for (const
|
|
1626
|
-
if (Math.abs(
|
|
1627
|
-
|
|
1679
|
+
const m = g.getVisualBoundingBox(), w = a.x - (m.x + m.width);
|
|
1680
|
+
for (const T of y)
|
|
1681
|
+
if (Math.abs(w - T) <= n) {
|
|
1682
|
+
S = T;
|
|
1628
1683
|
break;
|
|
1629
1684
|
}
|
|
1630
1685
|
}
|
|
1631
|
-
if (!
|
|
1632
|
-
const
|
|
1633
|
-
for (const
|
|
1634
|
-
if (Math.abs(
|
|
1635
|
-
|
|
1686
|
+
if (!S && u) {
|
|
1687
|
+
const w = u.getVisualBoundingBox().x - (a.x + a.width);
|
|
1688
|
+
for (const T of y)
|
|
1689
|
+
if (Math.abs(w - T) <= n) {
|
|
1690
|
+
S = T;
|
|
1636
1691
|
break;
|
|
1637
1692
|
}
|
|
1638
1693
|
}
|
|
1639
|
-
if (
|
|
1694
|
+
if (S !== null && S > 0) {
|
|
1640
1695
|
if (g) {
|
|
1641
|
-
const
|
|
1642
|
-
Math.abs(
|
|
1696
|
+
const m = g.getVisualBoundingBox(), w = a.x - (m.x + m.width);
|
|
1697
|
+
Math.abs(w - S) <= n && (h = m.x + m.width + S - r, d = !0);
|
|
1643
1698
|
}
|
|
1644
|
-
if (!d &&
|
|
1645
|
-
const
|
|
1646
|
-
Math.abs(
|
|
1699
|
+
if (!d && u) {
|
|
1700
|
+
const m = u.getVisualBoundingBox(), w = m.x - (a.x + a.width);
|
|
1701
|
+
Math.abs(w - S) <= n && (h = m.x - a.width - S - r, d = !0);
|
|
1647
1702
|
}
|
|
1648
1703
|
}
|
|
1649
1704
|
}
|
|
1650
|
-
return this.lastSnapTarget = d ||
|
|
1705
|
+
return this.lastSnapTarget = d || f ? { x: h, y: c } : null, { x: h, y: c };
|
|
1651
1706
|
}
|
|
1652
1707
|
/**
|
|
1653
1708
|
* Detect spacing between a moving element and other elements
|
|
@@ -1655,31 +1710,31 @@ class $e {
|
|
|
1655
1710
|
* Also detects consistent spacing patterns (e.g., evenly spaced rows/columns)
|
|
1656
1711
|
* @param showAllMeasurements - When true (Alt key held), shows all spacing measurements, not just to moving element
|
|
1657
1712
|
*/
|
|
1658
|
-
detectSpacing(t, e,
|
|
1713
|
+
detectSpacing(t, e, s = !1) {
|
|
1659
1714
|
if (!this.enabled || !e)
|
|
1660
1715
|
return this.clearIndicators(), [];
|
|
1661
1716
|
const n = e.filter((c) => c.id !== t.id);
|
|
1662
1717
|
if (n.length === 0)
|
|
1663
1718
|
return this.clearIndicators(), [];
|
|
1664
|
-
const
|
|
1719
|
+
const o = t.getVisualBoundingBox(), i = [], a = [], r = [], l = [];
|
|
1665
1720
|
for (const c of n) {
|
|
1666
|
-
const d = c.getVisualBoundingBox(),
|
|
1667
|
-
|
|
1721
|
+
const d = c.getVisualBoundingBox(), f = o.x - (d.x + d.width), p = d.x - (o.x + o.width), b = o.y - (d.y + d.height), g = d.y - (o.y + o.height), u = !(o.y + o.height < d.y || o.y > d.y + d.height), y = !(o.x + o.width < d.x || o.x > d.x + d.width);
|
|
1722
|
+
f >= this.minDistance && f < this.detectionThreshold && u && i.push({ element: c, distance: f }), p >= this.minDistance && p < this.detectionThreshold && u && a.push({ element: c, distance: p }), b >= this.minDistance && b < this.detectionThreshold && y && r.push({ element: c, distance: b }), g >= this.minDistance && g < this.detectionThreshold && y && l.push({ element: c, distance: g });
|
|
1668
1723
|
}
|
|
1669
1724
|
i.sort((c, d) => c.distance - d.distance), a.sort((c, d) => c.distance - d.distance), r.sort((c, d) => c.distance - d.distance), l.sort((c, d) => c.distance - d.distance);
|
|
1670
1725
|
const h = [];
|
|
1671
|
-
if (
|
|
1726
|
+
if (s) {
|
|
1672
1727
|
const c = this.detectAllMeasurements(t, e);
|
|
1673
1728
|
h.push(...c);
|
|
1674
1729
|
} else {
|
|
1675
1730
|
if (i.length > 0) {
|
|
1676
|
-
const c = this.detectConsistentSpacing(t,
|
|
1731
|
+
const c = this.detectConsistentSpacing(t, o, i, "left", n);
|
|
1677
1732
|
h.push(...c);
|
|
1678
1733
|
}
|
|
1679
1734
|
if (a.length > 0) {
|
|
1680
1735
|
const c = this.detectConsistentSpacing(
|
|
1681
1736
|
t,
|
|
1682
|
-
|
|
1737
|
+
o,
|
|
1683
1738
|
a,
|
|
1684
1739
|
"right",
|
|
1685
1740
|
n
|
|
@@ -1687,13 +1742,13 @@ class $e {
|
|
|
1687
1742
|
h.push(...c);
|
|
1688
1743
|
}
|
|
1689
1744
|
if (r.length > 0) {
|
|
1690
|
-
const c = this.detectConsistentSpacing(t,
|
|
1745
|
+
const c = this.detectConsistentSpacing(t, o, r, "top", n);
|
|
1691
1746
|
h.push(...c);
|
|
1692
1747
|
}
|
|
1693
1748
|
if (l.length > 0) {
|
|
1694
1749
|
const c = this.detectConsistentSpacing(
|
|
1695
1750
|
t,
|
|
1696
|
-
|
|
1751
|
+
o,
|
|
1697
1752
|
l,
|
|
1698
1753
|
"bottom",
|
|
1699
1754
|
n
|
|
@@ -1708,9 +1763,9 @@ class $e {
|
|
|
1708
1763
|
* Shows measurements from the hovered element to other elements within detection threshold
|
|
1709
1764
|
*/
|
|
1710
1765
|
detectAllMeasurements(t, e) {
|
|
1711
|
-
const
|
|
1766
|
+
const s = [], n = t.getVisualBoundingBox(), o = e.filter((l) => l.id !== t.id), i = this.detectionThreshold * 3;
|
|
1712
1767
|
let a = 0, r = 0;
|
|
1713
|
-
for (const l of
|
|
1768
|
+
for (const l of o) {
|
|
1714
1769
|
const h = l.getVisualBoundingBox();
|
|
1715
1770
|
if (Math.min(
|
|
1716
1771
|
Math.abs(n.x - (h.x + h.width)),
|
|
@@ -1723,9 +1778,9 @@ class $e {
|
|
|
1723
1778
|
// bottom
|
|
1724
1779
|
) > i)
|
|
1725
1780
|
continue;
|
|
1726
|
-
let d = 0,
|
|
1781
|
+
let d = 0, f = !1, p = 0, b = 0, g = 0;
|
|
1727
1782
|
const y = -30 * (a % 2 === 0 ? 1 : -1);
|
|
1728
|
-
h.x >= n.x + n.width ? (d = h.x - (n.x + n.width), d >= this.minDistance && (
|
|
1783
|
+
h.x >= n.x + n.width ? (d = h.x - (n.x + n.width), d >= this.minDistance && (f = !0, p = n.x + n.width, b = h.x, g = (n.y + n.height / 2 + h.y + h.height / 2) / 2 + y)) : n.x >= h.x + h.width && (d = n.x - (h.x + h.width), d >= this.minDistance && (f = !0, p = h.x + h.width, b = n.x, g = (n.y + n.height / 2 + h.y + h.height / 2) / 2 + y)), f && (s.push({
|
|
1729
1784
|
type: "horizontal",
|
|
1730
1785
|
distance: Math.round(d),
|
|
1731
1786
|
x1: p,
|
|
@@ -1735,106 +1790,106 @@ class $e {
|
|
|
1735
1790
|
labelY: g,
|
|
1736
1791
|
isAltHover: !0
|
|
1737
1792
|
}), a++);
|
|
1738
|
-
let
|
|
1793
|
+
let S = 0, m = !1, w = 0, T = 0, C = 0;
|
|
1739
1794
|
const x = 30 * (r % 2 === 0 ? 1 : -1);
|
|
1740
|
-
h.y >= n.y + n.height ? (
|
|
1795
|
+
h.y >= n.y + n.height ? (S = h.y - (n.y + n.height), S >= this.minDistance && (m = !0, w = (n.x + n.width / 2 + h.x + h.width / 2) / 2 + x, T = n.y + n.height, C = h.y)) : n.y >= h.y + h.height && (S = n.y - (h.y + h.height), S >= this.minDistance && (m = !0, w = (n.x + n.width / 2 + h.x + h.width / 2) / 2 + x, T = h.y + h.height, C = n.y)), m && (s.push({
|
|
1741
1796
|
type: "vertical",
|
|
1742
|
-
distance: Math.round(
|
|
1743
|
-
x:
|
|
1744
|
-
y1:
|
|
1797
|
+
distance: Math.round(S),
|
|
1798
|
+
x: w,
|
|
1799
|
+
y1: T,
|
|
1745
1800
|
y2: C,
|
|
1746
|
-
labelX:
|
|
1747
|
-
labelY: (
|
|
1801
|
+
labelX: w,
|
|
1802
|
+
labelY: (T + C) / 2,
|
|
1748
1803
|
isAltHover: !0
|
|
1749
1804
|
}), r++);
|
|
1750
1805
|
}
|
|
1751
|
-
return
|
|
1806
|
+
return s;
|
|
1752
1807
|
}
|
|
1753
1808
|
/**
|
|
1754
1809
|
* Detect consistent spacing patterns (e.g., evenly spaced rows/columns)
|
|
1755
1810
|
* and create indicators for all matching spacings
|
|
1756
1811
|
*/
|
|
1757
|
-
detectConsistentSpacing(t, e,
|
|
1758
|
-
const i = [], r =
|
|
1812
|
+
detectConsistentSpacing(t, e, s, n, o) {
|
|
1813
|
+
const i = [], r = s[0], l = r.distance, h = r.element.getVisualBoundingBox(), c = this.checkIfWouldSnap(e, l, n, o);
|
|
1759
1814
|
if (this.addIndicatorForDirection(i, e, h, l, n, c), n === "left" || n === "right") {
|
|
1760
|
-
const d =
|
|
1761
|
-
if (
|
|
1762
|
-
const p =
|
|
1815
|
+
const d = o.filter((f) => {
|
|
1816
|
+
if (f.id === t.id) return !1;
|
|
1817
|
+
const p = f.getVisualBoundingBox();
|
|
1763
1818
|
return !(e.y + e.height < p.y || e.y > p.y + p.height);
|
|
1764
1819
|
});
|
|
1765
|
-
if (d.sort((
|
|
1766
|
-
const b =
|
|
1820
|
+
if (d.sort((f, p) => {
|
|
1821
|
+
const b = f.getVisualBoundingBox(), g = p.getVisualBoundingBox();
|
|
1767
1822
|
return b.x - g.x;
|
|
1768
1823
|
}), n === "left")
|
|
1769
|
-
for (let
|
|
1770
|
-
const p = d[
|
|
1824
|
+
for (let f = 0; f < d.length - 1; f++) {
|
|
1825
|
+
const p = d[f], b = d[f + 1], g = p.getVisualBoundingBox(), u = b.getVisualBoundingBox(), y = u.x - (g.x + g.width);
|
|
1771
1826
|
if (Math.abs(y - l) <= 16 && y >= this.minDistance) {
|
|
1772
|
-
const
|
|
1827
|
+
const S = Math.max(g.y, u.y), m = Math.min(g.y + g.height, u.y + u.height), w = (S + m) / 2;
|
|
1773
1828
|
i.push({
|
|
1774
1829
|
type: "horizontal",
|
|
1775
1830
|
distance: Math.round(y),
|
|
1776
1831
|
x1: g.x + g.width,
|
|
1777
|
-
x2:
|
|
1778
|
-
y:
|
|
1779
|
-
labelX: (g.x + g.width +
|
|
1780
|
-
labelY:
|
|
1832
|
+
x2: u.x,
|
|
1833
|
+
y: w,
|
|
1834
|
+
labelX: (g.x + g.width + u.x) / 2,
|
|
1835
|
+
labelY: w
|
|
1781
1836
|
});
|
|
1782
1837
|
}
|
|
1783
1838
|
}
|
|
1784
1839
|
else
|
|
1785
|
-
for (let
|
|
1786
|
-
const p = d[
|
|
1840
|
+
for (let f = 0; f < d.length - 1; f++) {
|
|
1841
|
+
const p = d[f], b = d[f + 1], g = p.getVisualBoundingBox(), u = b.getVisualBoundingBox(), y = u.x - (g.x + g.width);
|
|
1787
1842
|
if (Math.abs(y - l) <= 16 && y >= this.minDistance) {
|
|
1788
|
-
const
|
|
1843
|
+
const S = Math.max(g.y, u.y), m = Math.min(g.y + g.height, u.y + u.height), w = (S + m) / 2;
|
|
1789
1844
|
i.push({
|
|
1790
1845
|
type: "horizontal",
|
|
1791
1846
|
distance: Math.round(y),
|
|
1792
1847
|
x1: g.x + g.width,
|
|
1793
|
-
x2:
|
|
1794
|
-
y:
|
|
1795
|
-
labelX: (g.x + g.width +
|
|
1796
|
-
labelY:
|
|
1848
|
+
x2: u.x,
|
|
1849
|
+
y: w,
|
|
1850
|
+
labelX: (g.x + g.width + u.x) / 2,
|
|
1851
|
+
labelY: w
|
|
1797
1852
|
});
|
|
1798
1853
|
}
|
|
1799
1854
|
}
|
|
1800
1855
|
} else {
|
|
1801
|
-
const d =
|
|
1802
|
-
if (
|
|
1803
|
-
const p =
|
|
1856
|
+
const d = o.filter((f) => {
|
|
1857
|
+
if (f.id === t.id) return !1;
|
|
1858
|
+
const p = f.getVisualBoundingBox();
|
|
1804
1859
|
return !(e.x + e.width < p.x || e.x > p.x + p.width);
|
|
1805
1860
|
});
|
|
1806
|
-
if (d.sort((
|
|
1807
|
-
const b =
|
|
1861
|
+
if (d.sort((f, p) => {
|
|
1862
|
+
const b = f.getVisualBoundingBox(), g = p.getVisualBoundingBox();
|
|
1808
1863
|
return b.y - g.y;
|
|
1809
1864
|
}), n === "top")
|
|
1810
|
-
for (let
|
|
1811
|
-
const p = d[
|
|
1865
|
+
for (let f = 0; f < d.length - 1; f++) {
|
|
1866
|
+
const p = d[f], b = d[f + 1], g = p.getVisualBoundingBox(), u = b.getVisualBoundingBox(), y = u.y - (g.y + g.height);
|
|
1812
1867
|
if (Math.abs(y - l) <= 16 && y >= this.minDistance) {
|
|
1813
|
-
const
|
|
1868
|
+
const S = Math.max(g.x, u.x), m = Math.min(g.x + g.width, u.x + u.width), w = (S + m) / 2;
|
|
1814
1869
|
i.push({
|
|
1815
1870
|
type: "vertical",
|
|
1816
1871
|
distance: Math.round(y),
|
|
1817
|
-
x:
|
|
1872
|
+
x: w,
|
|
1818
1873
|
y1: g.y + g.height,
|
|
1819
|
-
y2:
|
|
1820
|
-
labelX:
|
|
1821
|
-
labelY: (g.y + g.height +
|
|
1874
|
+
y2: u.y,
|
|
1875
|
+
labelX: w,
|
|
1876
|
+
labelY: (g.y + g.height + u.y) / 2
|
|
1822
1877
|
});
|
|
1823
1878
|
}
|
|
1824
1879
|
}
|
|
1825
1880
|
else
|
|
1826
|
-
for (let
|
|
1827
|
-
const p = d[
|
|
1881
|
+
for (let f = 0; f < d.length - 1; f++) {
|
|
1882
|
+
const p = d[f], b = d[f + 1], g = p.getVisualBoundingBox(), u = b.getVisualBoundingBox(), y = u.y - (g.y + g.height);
|
|
1828
1883
|
if (Math.abs(y - l) <= 16 && y >= this.minDistance) {
|
|
1829
|
-
const
|
|
1884
|
+
const S = Math.max(g.x, u.x), m = Math.min(g.x + g.width, u.x + u.width), w = (S + m) / 2;
|
|
1830
1885
|
i.push({
|
|
1831
1886
|
type: "vertical",
|
|
1832
1887
|
distance: Math.round(y),
|
|
1833
|
-
x:
|
|
1888
|
+
x: w,
|
|
1834
1889
|
y1: g.y + g.height,
|
|
1835
|
-
y2:
|
|
1836
|
-
labelX:
|
|
1837
|
-
labelY: (g.y + g.height +
|
|
1890
|
+
y2: u.y,
|
|
1891
|
+
labelX: w,
|
|
1892
|
+
labelY: (g.y + g.height + u.y) / 2
|
|
1838
1893
|
});
|
|
1839
1894
|
}
|
|
1840
1895
|
}
|
|
@@ -1844,9 +1899,9 @@ class $e {
|
|
|
1844
1899
|
/**
|
|
1845
1900
|
* Check if spacing would snap to a pattern
|
|
1846
1901
|
*/
|
|
1847
|
-
checkIfWouldSnap(t, e,
|
|
1848
|
-
const
|
|
1849
|
-
if (
|
|
1902
|
+
checkIfWouldSnap(t, e, s, n) {
|
|
1903
|
+
const o = Ft;
|
|
1904
|
+
if (s === "top" || s === "bottom") {
|
|
1850
1905
|
const i = n.filter((a) => {
|
|
1851
1906
|
const r = a.getVisualBoundingBox();
|
|
1852
1907
|
return !(t.x + t.width < r.x || t.x > r.x + r.width);
|
|
@@ -1863,7 +1918,7 @@ class $e {
|
|
|
1863
1918
|
}
|
|
1864
1919
|
if (a.length > 0) {
|
|
1865
1920
|
const r = a.reduce((c, d) => c + d, 0) / a.length;
|
|
1866
|
-
return Math.abs(e - r) <=
|
|
1921
|
+
return Math.abs(e - r) <= o;
|
|
1867
1922
|
}
|
|
1868
1923
|
}
|
|
1869
1924
|
return !1;
|
|
@@ -1884,7 +1939,7 @@ class $e {
|
|
|
1884
1939
|
}
|
|
1885
1940
|
if (a.length > 0) {
|
|
1886
1941
|
const r = a.reduce((c, d) => c + d, 0) / a.length;
|
|
1887
|
-
return Math.abs(e - r) <=
|
|
1942
|
+
return Math.abs(e - r) <= o;
|
|
1888
1943
|
}
|
|
1889
1944
|
}
|
|
1890
1945
|
return !1;
|
|
@@ -1893,59 +1948,59 @@ class $e {
|
|
|
1893
1948
|
/**
|
|
1894
1949
|
* Helper method to add a spacing indicator in a specific direction
|
|
1895
1950
|
*/
|
|
1896
|
-
addIndicatorForDirection(t, e,
|
|
1897
|
-
if (
|
|
1898
|
-
const a = Math.max(e.y,
|
|
1951
|
+
addIndicatorForDirection(t, e, s, n, o, i = !1) {
|
|
1952
|
+
if (o === "left") {
|
|
1953
|
+
const a = Math.max(e.y, s.y), r = Math.min(e.y + e.height, s.y + s.height), l = (a + r) / 2;
|
|
1899
1954
|
t.push({
|
|
1900
1955
|
type: "horizontal",
|
|
1901
1956
|
distance: Math.round(n),
|
|
1902
|
-
x1:
|
|
1957
|
+
x1: s.x + s.width,
|
|
1903
1958
|
x2: e.x,
|
|
1904
1959
|
y: l,
|
|
1905
|
-
labelX: (
|
|
1960
|
+
labelX: (s.x + s.width + e.x) / 2,
|
|
1906
1961
|
labelY: l,
|
|
1907
1962
|
isSnapTarget: i
|
|
1908
1963
|
});
|
|
1909
|
-
} else if (
|
|
1910
|
-
const a = Math.max(e.y,
|
|
1964
|
+
} else if (o === "right") {
|
|
1965
|
+
const a = Math.max(e.y, s.y), r = Math.min(e.y + e.height, s.y + s.height), l = (a + r) / 2;
|
|
1911
1966
|
t.push({
|
|
1912
1967
|
type: "horizontal",
|
|
1913
1968
|
distance: Math.round(n),
|
|
1914
1969
|
x1: e.x + e.width,
|
|
1915
|
-
x2:
|
|
1970
|
+
x2: s.x,
|
|
1916
1971
|
y: l,
|
|
1917
|
-
labelX: (e.x + e.width +
|
|
1972
|
+
labelX: (e.x + e.width + s.x) / 2,
|
|
1918
1973
|
labelY: l,
|
|
1919
1974
|
isSnapTarget: i
|
|
1920
1975
|
});
|
|
1921
|
-
} else if (
|
|
1922
|
-
const a = Math.max(e.x,
|
|
1976
|
+
} else if (o === "top") {
|
|
1977
|
+
const a = Math.max(e.x, s.x), r = Math.min(e.x + e.width, s.x + s.width), l = (a + r) / 2;
|
|
1923
1978
|
t.push({
|
|
1924
1979
|
type: "vertical",
|
|
1925
1980
|
distance: Math.round(n),
|
|
1926
1981
|
x: l,
|
|
1927
|
-
y1:
|
|
1982
|
+
y1: s.y + s.height,
|
|
1928
1983
|
y2: e.y,
|
|
1929
1984
|
labelX: l,
|
|
1930
|
-
labelY: (
|
|
1985
|
+
labelY: (s.y + s.height + e.y) / 2,
|
|
1931
1986
|
isSnapTarget: i
|
|
1932
1987
|
});
|
|
1933
|
-
} else if (
|
|
1934
|
-
const a = Math.max(e.x,
|
|
1988
|
+
} else if (o === "bottom") {
|
|
1989
|
+
const a = Math.max(e.x, s.x), r = Math.min(e.x + e.width, s.x + s.width), l = (a + r) / 2;
|
|
1935
1990
|
t.push({
|
|
1936
1991
|
type: "vertical",
|
|
1937
1992
|
distance: Math.round(n),
|
|
1938
1993
|
x: l,
|
|
1939
1994
|
y1: e.y + e.height,
|
|
1940
|
-
y2:
|
|
1995
|
+
y2: s.y,
|
|
1941
1996
|
labelX: l,
|
|
1942
|
-
labelY: (e.y + e.height +
|
|
1997
|
+
labelY: (e.y + e.height + s.y) / 2,
|
|
1943
1998
|
isSnapTarget: i
|
|
1944
1999
|
});
|
|
1945
2000
|
}
|
|
1946
2001
|
}
|
|
1947
2002
|
}
|
|
1948
|
-
const Wt = $t("ArtboardRenderer"),
|
|
2003
|
+
const Wt = $t("ArtboardRenderer"), Fe = {
|
|
1949
2004
|
showLabel: !0,
|
|
1950
2005
|
showBorder: !0,
|
|
1951
2006
|
borderColor: "",
|
|
@@ -1965,13 +2020,13 @@ const Wt = $t("ArtboardRenderer"), We = {
|
|
|
1965
2020
|
};
|
|
1966
2021
|
class Jt {
|
|
1967
2022
|
constructor(t = {}) {
|
|
1968
|
-
this.options = { ...
|
|
2023
|
+
this.options = { ...Fe, ...t };
|
|
1969
2024
|
}
|
|
1970
2025
|
/**
|
|
1971
2026
|
* Render an artboard
|
|
1972
2027
|
*/
|
|
1973
|
-
render(t, e,
|
|
1974
|
-
t.save(), this.renderBackground(t, e), this.options.showBorder && this.renderBorder(t, e,
|
|
2028
|
+
render(t, e, s = !1) {
|
|
2029
|
+
t.save(), this.renderBackground(t, e), this.options.showBorder && this.renderBorder(t, e, s), this.options.showLabel && this.renderLabel(t, e, s), t.restore();
|
|
1975
2030
|
}
|
|
1976
2031
|
/**
|
|
1977
2032
|
* Render artboard background
|
|
@@ -1987,69 +2042,69 @@ class Jt {
|
|
|
1987
2042
|
* Renders preset color as base layer, then texture on top
|
|
1988
2043
|
*/
|
|
1989
2044
|
renderTextureBackground(t, e) {
|
|
1990
|
-
const
|
|
1991
|
-
if (t.fillStyle = n, t.fillRect(e.x, e.y, e.width, e.height), !
|
|
1992
|
-
Bt.loadTexture(e.backgroundTexture).catch((
|
|
1993
|
-
Wt.error("Failed to load texture:",
|
|
2045
|
+
const s = Bt.getTexture(e.backgroundTexture), n = Bt.getTexturePresetColor(e.backgroundTexture);
|
|
2046
|
+
if (t.fillStyle = n, t.fillRect(e.x, e.y, e.width, e.height), !s || !s.complete) {
|
|
2047
|
+
Bt.loadTexture(e.backgroundTexture).catch((o) => {
|
|
2048
|
+
Wt.error("Failed to load texture:", o);
|
|
1994
2049
|
});
|
|
1995
2050
|
return;
|
|
1996
2051
|
}
|
|
1997
|
-
t.save(), t.beginPath(), t.rect(e.x, e.y, e.width, e.height), t.clip(), t.drawImage(
|
|
2052
|
+
t.save(), t.beginPath(), t.rect(e.x, e.y, e.width, e.height), t.clip(), t.drawImage(s, e.x, e.y, e.width, e.height), t.restore();
|
|
1998
2053
|
}
|
|
1999
2054
|
/**
|
|
2000
2055
|
* Render a checkerboard pattern for transparent backgrounds
|
|
2001
2056
|
*/
|
|
2002
|
-
renderCheckerboard(t, e,
|
|
2057
|
+
renderCheckerboard(t, e, s, n, o) {
|
|
2003
2058
|
const a = "#ffffff", r = "#d0d0d0";
|
|
2004
|
-
t.save(), t.beginPath(), t.rect(e,
|
|
2005
|
-
for (let l = 0; l < Math.ceil(
|
|
2059
|
+
t.save(), t.beginPath(), t.rect(e, s, n, o), t.clip(), t.fillStyle = a, t.fillRect(e, s, n, o), t.fillStyle = r;
|
|
2060
|
+
for (let l = 0; l < Math.ceil(o / 16); l++)
|
|
2006
2061
|
for (let h = 0; h < Math.ceil(n / 16); h++)
|
|
2007
|
-
(l + h) % 2 === 1 && t.fillRect(e + h * 16,
|
|
2062
|
+
(l + h) % 2 === 1 && t.fillRect(e + h * 16, s + l * 16, 16, 16);
|
|
2008
2063
|
t.restore();
|
|
2009
2064
|
}
|
|
2010
2065
|
/**
|
|
2011
2066
|
* Render artboard border (respects clipShape and borderRadius option)
|
|
2012
2067
|
*/
|
|
2013
|
-
renderBorder(t, e,
|
|
2014
|
-
const { x: n, y:
|
|
2015
|
-
if (t.strokeStyle =
|
|
2068
|
+
renderBorder(t, e, s) {
|
|
2069
|
+
const { x: n, y: o, width: i, height: a, clipShape: r } = e, l = this.options.borderColor || ae(), h = this.options.selectedBorderColor || et();
|
|
2070
|
+
if (t.strokeStyle = s ? h : l, t.lineWidth = s ? this.options.selectedBorderWidth : this.options.borderWidth, t.beginPath(), !r || r === "rectangle")
|
|
2016
2071
|
if (this.options.borderRadius > 0) {
|
|
2017
2072
|
const c = Math.min(this.options.borderRadius, Math.min(i, a) / 2);
|
|
2018
|
-
this.roundedRect(t, n,
|
|
2073
|
+
this.roundedRect(t, n, o, i, a, c);
|
|
2019
2074
|
} else
|
|
2020
|
-
t.rect(n,
|
|
2075
|
+
t.rect(n, o, i, a);
|
|
2021
2076
|
else if (r === "circle") {
|
|
2022
|
-
const c = n + i / 2, d =
|
|
2023
|
-
t.arc(c, d,
|
|
2077
|
+
const c = n + i / 2, d = o + a / 2, f = Math.min(i, a) / 2;
|
|
2078
|
+
t.arc(c, d, f, 0, Math.PI * 2);
|
|
2024
2079
|
} else if (typeof r == "object" && r.type === "rounded") {
|
|
2025
2080
|
const c = Math.min(r.radius, Math.min(i, a) / 2);
|
|
2026
|
-
this.roundedRect(t, n,
|
|
2081
|
+
this.roundedRect(t, n, o, i, a, c);
|
|
2027
2082
|
} else if (typeof r == "object" && r.type === "path")
|
|
2028
2083
|
try {
|
|
2029
2084
|
const c = new Path2D(r.d);
|
|
2030
|
-
t.save(), t.translate(n,
|
|
2085
|
+
t.save(), t.translate(n, o), t.stroke(c), t.restore();
|
|
2031
2086
|
return;
|
|
2032
2087
|
} catch (c) {
|
|
2033
|
-
Wt.warn("Invalid SVG path for border, falling back to rectangle:", c), t.rect(n,
|
|
2088
|
+
Wt.warn("Invalid SVG path for border, falling back to rectangle:", c), t.rect(n, o, i, a);
|
|
2034
2089
|
}
|
|
2035
2090
|
t.stroke();
|
|
2036
2091
|
}
|
|
2037
2092
|
/**
|
|
2038
2093
|
* Render artboard label (name + dimensions)
|
|
2039
2094
|
*/
|
|
2040
|
-
renderLabel(t, e,
|
|
2041
|
-
const n = this.options.labelFontSize,
|
|
2095
|
+
renderLabel(t, e, s) {
|
|
2096
|
+
const n = this.options.labelFontSize, o = this.options.labelPadding, i = `${e.name} (${Math.round(e.width)} × ${Math.round(e.height)})`, a = e.x, r = e.y - o;
|
|
2042
2097
|
t.font = `${n}px -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif`;
|
|
2043
|
-
const l = this.options.selectedBorderColor ||
|
|
2044
|
-
t.fillStyle =
|
|
2098
|
+
const l = this.options.selectedBorderColor || et(), h = this.options.labelColor || re();
|
|
2099
|
+
t.fillStyle = s ? l : h, t.textAlign = "left", t.textBaseline = "bottom", t.fillText(i, a, r);
|
|
2045
2100
|
}
|
|
2046
2101
|
/**
|
|
2047
2102
|
* Render multiple artboards
|
|
2048
2103
|
*/
|
|
2049
|
-
renderMultiple(t, e,
|
|
2104
|
+
renderMultiple(t, e, s) {
|
|
2050
2105
|
e.forEach((n) => {
|
|
2051
|
-
const
|
|
2052
|
-
this.render(t, n,
|
|
2106
|
+
const o = n.id === s;
|
|
2107
|
+
this.render(t, n, o);
|
|
2053
2108
|
});
|
|
2054
2109
|
}
|
|
2055
2110
|
/**
|
|
@@ -2065,26 +2120,26 @@ class Jt {
|
|
|
2065
2120
|
* If borderRadius option is set and no special clipShape, uses rounded rectangle
|
|
2066
2121
|
*/
|
|
2067
2122
|
applyClipPath(t, e) {
|
|
2068
|
-
const { x:
|
|
2123
|
+
const { x: s, y: n, width: o, height: i, clipShape: a } = e;
|
|
2069
2124
|
if (this.options.borderRadius > 0, t.beginPath(), !a || a === "rectangle")
|
|
2070
2125
|
if (this.options.borderRadius > 0) {
|
|
2071
|
-
const r = Math.min(this.options.borderRadius, Math.min(
|
|
2072
|
-
this.roundedRect(t,
|
|
2126
|
+
const r = Math.min(this.options.borderRadius, Math.min(o, i) / 2);
|
|
2127
|
+
this.roundedRect(t, s, n, o, i, r);
|
|
2073
2128
|
} else
|
|
2074
|
-
t.rect(
|
|
2129
|
+
t.rect(s, n, o, i);
|
|
2075
2130
|
else if (a === "circle") {
|
|
2076
|
-
const r =
|
|
2131
|
+
const r = s + o / 2, l = n + i / 2, h = Math.min(o, i) / 2;
|
|
2077
2132
|
t.arc(r, l, h, 0, Math.PI * 2);
|
|
2078
2133
|
} else if (typeof a == "object" && a.type === "rounded") {
|
|
2079
|
-
const r = Math.min(a.radius, Math.min(
|
|
2080
|
-
this.roundedRect(t,
|
|
2134
|
+
const r = Math.min(a.radius, Math.min(o, i) / 2);
|
|
2135
|
+
this.roundedRect(t, s, n, o, i, r);
|
|
2081
2136
|
} else if (typeof a == "object" && a.type === "path")
|
|
2082
2137
|
try {
|
|
2083
2138
|
const r = new Path2D(a.d);
|
|
2084
|
-
t.translate(
|
|
2139
|
+
t.translate(s, n), t.clip(r), t.translate(-s, -n);
|
|
2085
2140
|
return;
|
|
2086
2141
|
} catch (r) {
|
|
2087
|
-
Wt.warn("Invalid SVG path, falling back to rectangle:", r), t.rect(
|
|
2142
|
+
Wt.warn("Invalid SVG path, falling back to rectangle:", r), t.rect(s, n, o, i);
|
|
2088
2143
|
}
|
|
2089
2144
|
t.clip();
|
|
2090
2145
|
}
|
|
@@ -2092,8 +2147,8 @@ class Jt {
|
|
|
2092
2147
|
* Draw a rounded rectangle path
|
|
2093
2148
|
* Helper method for rounded clip shapes
|
|
2094
2149
|
*/
|
|
2095
|
-
roundedRect(t, e,
|
|
2096
|
-
typeof t.roundRect == "function" ? t.roundRect(e,
|
|
2150
|
+
roundedRect(t, e, s, n, o, i) {
|
|
2151
|
+
typeof t.roundRect == "function" ? t.roundRect(e, s, n, o, i) : (t.moveTo(e + i, s), t.lineTo(e + n - i, s), t.arcTo(e + n, s, e + n, s + i, i), t.lineTo(e + n, s + o - i), t.arcTo(e + n, s + o, e + n - i, s + o, i), t.lineTo(e + i, s + o), t.arcTo(e, s + o, e, s + o - i, i), t.lineTo(e, s + i), t.arcTo(e, s, e + i, s, i));
|
|
2097
2152
|
}
|
|
2098
2153
|
/**
|
|
2099
2154
|
* Restore after clipping
|
|
@@ -2104,21 +2159,21 @@ class Jt {
|
|
|
2104
2159
|
/**
|
|
2105
2160
|
* Render artboard outline (for dragging/resizing preview)
|
|
2106
2161
|
*/
|
|
2107
|
-
renderOutline(t, e,
|
|
2108
|
-
t.save(), t.setLineDash([5, 5]), t.strokeStyle = i ? "#0066cc" : "#999", t.lineWidth = 1, t.strokeRect(e,
|
|
2162
|
+
renderOutline(t, e, s, n, o, i = !1) {
|
|
2163
|
+
t.save(), t.setLineDash([5, 5]), t.strokeStyle = i ? "#0066cc" : "#999", t.lineWidth = 1, t.strokeRect(e, s, n, o), t.restore();
|
|
2109
2164
|
}
|
|
2110
2165
|
/**
|
|
2111
2166
|
* Render resize handles for artboard
|
|
2112
2167
|
*/
|
|
2113
2168
|
renderResizeHandles(t, e) {
|
|
2114
|
-
const { x: n, y:
|
|
2115
|
-
{ x: n, y:
|
|
2169
|
+
const { x: n, y: o, width: i, height: a } = e, r = [
|
|
2170
|
+
{ x: n, y: o },
|
|
2116
2171
|
// top-left
|
|
2117
|
-
{ x: n + i, y:
|
|
2172
|
+
{ x: n + i, y: o },
|
|
2118
2173
|
// top-right
|
|
2119
|
-
{ x: n, y:
|
|
2174
|
+
{ x: n, y: o + a },
|
|
2120
2175
|
// bottom-left
|
|
2121
|
-
{ x: n + i, y:
|
|
2176
|
+
{ x: n + i, y: o + a }
|
|
2122
2177
|
// bottom-right
|
|
2123
2178
|
];
|
|
2124
2179
|
t.save(), r.forEach((l) => {
|
|
@@ -2160,11 +2215,11 @@ class mt {
|
|
|
2160
2215
|
/**
|
|
2161
2216
|
* Render selection box layer
|
|
2162
2217
|
*/
|
|
2163
|
-
static renderSelectionLayer(t, e,
|
|
2164
|
-
if (!e || e.visible === !1 ||
|
|
2218
|
+
static renderSelectionLayer(t, e, s, n = 1) {
|
|
2219
|
+
if (!e || e.visible === !1 || s && s.getMode() === "drag" || "isGroup" in e && e.isGroup) return;
|
|
2165
2220
|
const i = e.getVisualBoundingBox(), a = e.getRotationAnchor();
|
|
2166
|
-
t.save(), t.strokeStyle =
|
|
2167
|
-
const r =
|
|
2221
|
+
t.save(), t.strokeStyle = et(t.canvas), t.lineWidth = 2, t.translate(a.x * n, a.y * n), t.rotate(dt.toRadians(e.rotation)), t.translate(-a.x * n, -a.y * n);
|
|
2222
|
+
const r = rt.canvas.selectionPadding;
|
|
2168
2223
|
t.strokeRect(
|
|
2169
2224
|
(i.x - r) * n,
|
|
2170
2225
|
(i.y - r) * n,
|
|
@@ -2176,9 +2231,9 @@ class mt {
|
|
|
2176
2231
|
* Render position and size info below the selected element
|
|
2177
2232
|
* Only shows dimensions (width x height) while resizing
|
|
2178
2233
|
*/
|
|
2179
|
-
static renderPositionSizeInfo(t, e,
|
|
2180
|
-
if (!e || !(
|
|
2181
|
-
const i = e.getVisualBoundingBox(), a = Math.round(i.width), r = Math.round(i.height), l = `${a} × ${r}`, h =
|
|
2234
|
+
static renderPositionSizeInfo(t, e, s, n, o = 1) {
|
|
2235
|
+
if (!e || !(s != null && s.rotationHandle) || (n == null ? void 0 : n.getMode()) !== "resize") return;
|
|
2236
|
+
const i = e.getVisualBoundingBox(), a = Math.round(i.width), r = Math.round(i.height), l = `${a} × ${r}`, h = s.rotationHandle, c = h.x * o, d = h.y * o - 20;
|
|
2182
2237
|
t.save(), t.font = "10px system-ui, -apple-system, sans-serif";
|
|
2183
2238
|
const p = t.measureText(l).width + 12, b = 18;
|
|
2184
2239
|
t.shadowColor = le(t.canvas), t.shadowBlur = 4, t.shadowOffsetY = 1, t.fillStyle = he(t.canvas), t.beginPath(), t.roundRect(
|
|
@@ -2193,17 +2248,17 @@ class mt {
|
|
|
2193
2248
|
/**
|
|
2194
2249
|
* Render transform handles layer
|
|
2195
2250
|
*/
|
|
2196
|
-
static renderHandlesLayer(t, e,
|
|
2251
|
+
static renderHandlesLayer(t, e, s, n, o, i, a, r = 1, l = !0) {
|
|
2197
2252
|
if (!e || e.visible === !1 || a.getMode() === "drag") return;
|
|
2198
|
-
const c = i.type === "rotation-handle", d = i.type === "resize-handle" ? i.data : null,
|
|
2199
|
-
|
|
2253
|
+
const c = i.type === "rotation-handle", d = i.type === "resize-handle" ? i.data : null, f = a.getMode() === "resize", p = f ? a.getActiveHandle() : null;
|
|
2254
|
+
s.render(
|
|
2200
2255
|
t,
|
|
2201
2256
|
l,
|
|
2202
2257
|
n,
|
|
2203
|
-
|
|
2258
|
+
o,
|
|
2204
2259
|
c,
|
|
2205
2260
|
d,
|
|
2206
|
-
|
|
2261
|
+
f,
|
|
2207
2262
|
p,
|
|
2208
2263
|
r,
|
|
2209
2264
|
!0
|
|
@@ -2216,8 +2271,8 @@ class _t {
|
|
|
2216
2271
|
* Render hover highlights layer with fade-in animation
|
|
2217
2272
|
* Outlines the actual element shape instead of a rectangular border
|
|
2218
2273
|
*/
|
|
2219
|
-
static renderHoverLayer(t, e,
|
|
2220
|
-
if (e.type !== "element" || !e.data || e.data.id ===
|
|
2274
|
+
static renderHoverLayer(t, e, s, n = !1, o = 1, i) {
|
|
2275
|
+
if (e.type !== "element" || !e.data || e.data.id === s) return;
|
|
2221
2276
|
const a = e.data;
|
|
2222
2277
|
t.save();
|
|
2223
2278
|
const r = 150, l = 0.5;
|
|
@@ -2226,82 +2281,82 @@ class _t {
|
|
|
2226
2281
|
const c = performance.now() - e.startTime;
|
|
2227
2282
|
h = Math.min(c / r, 1) * l;
|
|
2228
2283
|
}
|
|
2229
|
-
t.strokeStyle = de(t.canvas), t.globalAlpha = h, t.lineWidth = 3, this.renderElementOutline(t, a,
|
|
2284
|
+
t.strokeStyle = de(t.canvas), t.globalAlpha = h, t.lineWidth = 3, this.renderElementOutline(t, a, o, i), t.restore();
|
|
2230
2285
|
}
|
|
2231
2286
|
/**
|
|
2232
2287
|
* Render outline for a specific element type
|
|
2233
2288
|
*/
|
|
2234
|
-
static renderElementOutline(t, e,
|
|
2235
|
-
const
|
|
2236
|
-
t.translate(
|
|
2289
|
+
static renderElementOutline(t, e, s = 1, n) {
|
|
2290
|
+
const o = e.getRotationAnchor();
|
|
2291
|
+
t.translate(o.x * s, o.y * s), t.rotate(dt.toRadians(e.rotation)), t.translate(-o.x * s, -o.y * s), e.transformType === "shape" ? this.renderShapeOutline(t, e, s) : e.transformType === "image" ? this.renderImageOutline(t, e, s) : e.transformType === "group" ? this.renderGroupOutline(t, e, s) : this.renderTextOutline(t, e, s, n);
|
|
2237
2292
|
}
|
|
2238
2293
|
/**
|
|
2239
2294
|
* Render outline for shape elements (star, rectangle, circle, etc.)
|
|
2240
2295
|
* Creates a ring effect with a gap between the element and the stroke
|
|
2241
2296
|
*/
|
|
2242
|
-
static renderShapeOutline(t, e,
|
|
2243
|
-
const n = e.transformData,
|
|
2244
|
-
switch (t.save(), t.translate(e.x *
|
|
2297
|
+
static renderShapeOutline(t, e, s) {
|
|
2298
|
+
const n = e.transformData, o = n.width * s, i = n.height * s, a = 2, l = a + a / 2;
|
|
2299
|
+
switch (t.save(), t.translate(e.x * s, e.y * s), t.beginPath(), n.shapeType) {
|
|
2245
2300
|
case "rectangle": {
|
|
2246
|
-
const h = n.borderRadius || 0, c = -(
|
|
2301
|
+
const h = n.borderRadius || 0, c = -(o + l * 2) / 2, d = -(i + l * 2) / 2, f = o + l * 2, p = i + l * 2;
|
|
2247
2302
|
if (h > 0) {
|
|
2248
|
-
const b = Math.min(h / 100 * Math.min(
|
|
2249
|
-
t.roundRect(c, d,
|
|
2303
|
+
const b = Math.min(h / 100 * Math.min(f, p), f / 2, p / 2);
|
|
2304
|
+
t.roundRect(c, d, f, p, b);
|
|
2250
2305
|
} else
|
|
2251
|
-
t.rect(c, d,
|
|
2306
|
+
t.rect(c, d, f, p);
|
|
2252
2307
|
break;
|
|
2253
2308
|
}
|
|
2254
2309
|
case "circle": {
|
|
2255
|
-
const h = Math.min(
|
|
2310
|
+
const h = Math.min(o, i) / 2 + l;
|
|
2256
2311
|
t.arc(0, 0, h, 0, Math.PI * 2);
|
|
2257
2312
|
break;
|
|
2258
2313
|
}
|
|
2259
2314
|
case "ellipse": {
|
|
2260
|
-
const h = (n.radiusX ??
|
|
2315
|
+
const h = (n.radiusX ?? o / 2) + l, c = (n.radiusY ?? i / 2) + l;
|
|
2261
2316
|
t.ellipse(0, 0, h, c, 0, 0, Math.PI * 2);
|
|
2262
2317
|
break;
|
|
2263
2318
|
}
|
|
2264
2319
|
case "triangle": {
|
|
2265
|
-
const h =
|
|
2320
|
+
const h = o / 2, c = i / 2, d = [
|
|
2266
2321
|
{ x: 0, y: -c },
|
|
2267
2322
|
// top
|
|
2268
2323
|
{ x: h, y: c },
|
|
2269
2324
|
// bottom-right
|
|
2270
2325
|
{ x: -h, y: c }
|
|
2271
2326
|
// bottom-left
|
|
2272
|
-
],
|
|
2273
|
-
const
|
|
2274
|
-
return { x:
|
|
2327
|
+
], f = d.map((b, g) => {
|
|
2328
|
+
const u = d[(g + 1) % 3], y = u.x - b.x, S = u.y - b.y, m = Math.sqrt(y * y + S * S);
|
|
2329
|
+
return { x: S / m, y: -y / m };
|
|
2275
2330
|
}), p = d.map((b, g) => {
|
|
2276
|
-
const
|
|
2331
|
+
const u = f[(g + 2) % 3], y = f[g], S = u.x + y.x, m = u.y + y.y, w = Math.sqrt(S * S + m * m), T = (S * u.x + m * u.y) / w, C = l / T;
|
|
2277
2332
|
return {
|
|
2278
|
-
x: b.x +
|
|
2279
|
-
y: b.y +
|
|
2333
|
+
x: b.x + S / w * C,
|
|
2334
|
+
y: b.y + m / w * C
|
|
2280
2335
|
};
|
|
2281
2336
|
});
|
|
2282
2337
|
t.moveTo(p[0].x, p[0].y), t.lineTo(p[1].x, p[1].y), t.lineTo(p[2].x, p[2].y), t.closePath();
|
|
2283
2338
|
break;
|
|
2284
2339
|
}
|
|
2285
2340
|
case "star": {
|
|
2286
|
-
const h = n.points ?? 5, c = n.innerRadius ?? 0.4, d = Math.min(
|
|
2341
|
+
const h = n.points ?? 5, c = n.innerRadius ?? 0.4, d = Math.min(o, i) / 2 + l, f = d * c;
|
|
2287
2342
|
for (let p = 0; p < h * 2; p++) {
|
|
2288
|
-
const b = p * Math.PI / h - Math.PI / 2, g = p % 2 === 0 ? d :
|
|
2289
|
-
p === 0 ? t.moveTo(
|
|
2343
|
+
const b = p * Math.PI / h - Math.PI / 2, g = p % 2 === 0 ? d : f, u = g * Math.cos(b), y = g * Math.sin(b);
|
|
2344
|
+
p === 0 ? t.moveTo(u, y) : t.lineTo(u, y);
|
|
2290
2345
|
}
|
|
2291
2346
|
t.closePath();
|
|
2292
2347
|
break;
|
|
2293
2348
|
}
|
|
2294
2349
|
case "polygon": {
|
|
2295
|
-
const h = n.sides ?? 5, c = Math.min(
|
|
2350
|
+
const h = n.sides ?? 5, c = Math.min(o, i) / 2 + l;
|
|
2296
2351
|
for (let d = 0; d < h; d++) {
|
|
2297
|
-
const
|
|
2352
|
+
const f = d * 2 * Math.PI / h - Math.PI / 2, p = c * Math.cos(f), b = c * Math.sin(f);
|
|
2298
2353
|
d === 0 ? t.moveTo(p, b) : t.lineTo(p, b);
|
|
2299
2354
|
}
|
|
2300
2355
|
t.closePath();
|
|
2301
2356
|
break;
|
|
2302
2357
|
}
|
|
2303
2358
|
case "line": {
|
|
2304
|
-
const h =
|
|
2359
|
+
const h = o / 2 + l;
|
|
2305
2360
|
t.moveTo(-h, 0), t.lineTo(h, 0);
|
|
2306
2361
|
break;
|
|
2307
2362
|
}
|
|
@@ -2312,24 +2367,24 @@ class _t {
|
|
|
2312
2367
|
* Render outline for image elements
|
|
2313
2368
|
* Creates a ring effect with a gap between the element and the stroke
|
|
2314
2369
|
*/
|
|
2315
|
-
static renderImageOutline(t, e,
|
|
2370
|
+
static renderImageOutline(t, e, s) {
|
|
2316
2371
|
var b;
|
|
2317
|
-
const n = e.getVisualBoundingBox(),
|
|
2318
|
-
t.save(), t.translate(e.x *
|
|
2319
|
-
const c = -(
|
|
2372
|
+
const n = e.getVisualBoundingBox(), o = n.width * s, i = n.height * s, a = ((b = e.transformData) == null ? void 0 : b.borderRadius) || 0, r = 2, h = r + r / 2;
|
|
2373
|
+
t.save(), t.translate(e.x * s, e.y * s);
|
|
2374
|
+
const c = -(o + h * 2) / 2, d = -(i + h * 2) / 2, f = o + h * 2, p = i + h * 2;
|
|
2320
2375
|
if (t.beginPath(), a > 0) {
|
|
2321
|
-
const g = Math.min(a / 100 * Math.min(
|
|
2322
|
-
t.roundRect(c, d,
|
|
2376
|
+
const g = Math.min(a / 100 * Math.min(f, p), f / 2, p / 2);
|
|
2377
|
+
t.roundRect(c, d, f, p, g);
|
|
2323
2378
|
} else
|
|
2324
|
-
t.rect(c, d,
|
|
2379
|
+
t.rect(c, d, f, p);
|
|
2325
2380
|
t.stroke(), t.restore();
|
|
2326
2381
|
}
|
|
2327
2382
|
/**
|
|
2328
2383
|
* Render outline for group elements
|
|
2329
2384
|
* Creates a ring effect with a gap between the element and the stroke
|
|
2330
2385
|
*/
|
|
2331
|
-
static renderGroupOutline(t, e,
|
|
2332
|
-
const n = e.getVisualBoundingBox(),
|
|
2386
|
+
static renderGroupOutline(t, e, s) {
|
|
2387
|
+
const n = e.getVisualBoundingBox(), o = 2, a = o + o / 2, r = n.x * s - a, l = n.y * s - a, h = n.width * s + a * 2, c = n.height * s + a * 2;
|
|
2333
2388
|
t.save(), t.setLineDash([5, 5]), t.beginPath(), t.roundRect(r, l, h, c, 8), t.stroke(), t.restore();
|
|
2334
2389
|
}
|
|
2335
2390
|
/**
|
|
@@ -2337,9 +2392,9 @@ class _t {
|
|
|
2337
2392
|
* Creates a ring effect with a gap between text and stroke (ring behind text fill)
|
|
2338
2393
|
* Supports all transform types: custom, circle, wave, arch, etc.
|
|
2339
2394
|
*/
|
|
2340
|
-
static renderTextOutline(t, e,
|
|
2341
|
-
const
|
|
2342
|
-
|
|
2395
|
+
static renderTextOutline(t, e, s, n) {
|
|
2396
|
+
const o = e.transformType;
|
|
2397
|
+
o === "circle" || o === "wave" || o === "arch" || o === "lean" || o === "ascend" || o === "flag" ? this.renderTransformHoverRingEffect(t, e, s) : this.renderHoverRingEffect(t, e, s);
|
|
2343
2398
|
}
|
|
2344
2399
|
/**
|
|
2345
2400
|
* HOVER RING EFFECT for straight/custom text
|
|
@@ -2352,11 +2407,11 @@ class _t {
|
|
|
2352
2407
|
* - Element stroke (StrokeRenderer.ts - only when stroke.enabled = true)
|
|
2353
2408
|
* - Selection box (dashed rectangle in element.render())
|
|
2354
2409
|
*/
|
|
2355
|
-
static renderHoverRingEffect(t, e,
|
|
2356
|
-
t.save(), t.translate(e.x *
|
|
2357
|
-
const n = e.fontSize,
|
|
2358
|
-
|
|
2359
|
-
const p =
|
|
2410
|
+
static renderHoverRingEffect(t, e, s) {
|
|
2411
|
+
t.save(), t.translate(e.x * s, e.y * s), s !== 1 && t.scale(s, s);
|
|
2412
|
+
const n = e.fontSize, o = e.fontFamily, i = e.bold || !1, a = e.italic || !1, r = e.textAlign || "center", l = jt(n, o, i, a), h = n * 1.2, c = 4 / s, d = 4 / s, f = document.createElement("canvas");
|
|
2413
|
+
f.width = t.canvas.width, f.height = t.canvas.height;
|
|
2414
|
+
const p = f.getContext("2d");
|
|
2360
2415
|
if (!p) {
|
|
2361
2416
|
t.restore();
|
|
2362
2417
|
return;
|
|
@@ -2364,86 +2419,86 @@ class _t {
|
|
|
2364
2419
|
p.setTransform(t.getTransform()), p.textBaseline = "alphabetic", p.lineJoin = "round";
|
|
2365
2420
|
const b = e.getRichText ? e.getRichText() : null;
|
|
2366
2421
|
if (b) {
|
|
2367
|
-
const g = qt(b),
|
|
2368
|
-
g.forEach((
|
|
2422
|
+
const g = qt(b), u = [], y = [];
|
|
2423
|
+
g.forEach((w) => {
|
|
2369
2424
|
if (e.transformType === "custom" && e.transformData) {
|
|
2370
|
-
const
|
|
2425
|
+
const T = e.transformData.width - gt * 2, C = Ut(w, T, {
|
|
2371
2426
|
fontSize: n,
|
|
2372
|
-
fontFamily:
|
|
2427
|
+
fontFamily: o,
|
|
2373
2428
|
bold: i,
|
|
2374
2429
|
italic: a
|
|
2375
2430
|
});
|
|
2376
2431
|
C.forEach((R, x) => {
|
|
2377
|
-
|
|
2432
|
+
u.push(R), y.push({
|
|
2378
2433
|
isParagraphStart: x === 0,
|
|
2379
2434
|
isParagraphEnd: x === C.length - 1
|
|
2380
2435
|
});
|
|
2381
2436
|
});
|
|
2382
2437
|
} else
|
|
2383
|
-
|
|
2438
|
+
u.push(w), y.push({
|
|
2384
2439
|
isParagraphStart: !0,
|
|
2385
2440
|
isParagraphEnd: !0
|
|
2386
2441
|
});
|
|
2387
2442
|
});
|
|
2388
|
-
let
|
|
2389
|
-
|
|
2390
|
-
const
|
|
2391
|
-
|
|
2392
|
-
var D,
|
|
2393
|
-
const C = y[
|
|
2443
|
+
let S;
|
|
2444
|
+
u.length === 0 ? S = 0 : u.length === 1 ? S = l.height : S = (u.length - 1) * h + l.height;
|
|
2445
|
+
const m = -S / 2;
|
|
2446
|
+
u.forEach((w, T) => {
|
|
2447
|
+
var D, Q;
|
|
2448
|
+
const C = y[T].isParagraphStart, R = y[T].isParagraphEnd;
|
|
2394
2449
|
let x = 0;
|
|
2395
|
-
const P =
|
|
2450
|
+
const P = w.map((E) => E.text).join(""), M = ((D = P.match(/^ +/)) == null ? void 0 : D[0].length) || 0, A = ((Q = P.match(/ +$/)) == null ? void 0 : Q[0].length) || 0;
|
|
2396
2451
|
let B = 0;
|
|
2397
|
-
|
|
2398
|
-
const
|
|
2452
|
+
w.forEach((E) => {
|
|
2453
|
+
const j = E.style.fontSize !== void 0 ? E.style.fontSize : n, _ = E.style.fontFamily !== void 0 ? E.style.fontFamily : o, $ = E.style.bold !== void 0 ? E.style.bold : i, Y = E.style.italic !== void 0 ? E.style.italic : a;
|
|
2399
2454
|
let k = E.text;
|
|
2400
|
-
const
|
|
2401
|
-
if (!C &&
|
|
2402
|
-
const
|
|
2403
|
-
k = k.substring(
|
|
2455
|
+
const H = B, X = B + E.text.length;
|
|
2456
|
+
if (!C && M > 0 && H < M) {
|
|
2457
|
+
const I = Math.min(M - H, E.text.length);
|
|
2458
|
+
k = k.substring(I);
|
|
2404
2459
|
}
|
|
2405
2460
|
if (!R && A > 0) {
|
|
2406
|
-
const
|
|
2407
|
-
if (
|
|
2408
|
-
const
|
|
2409
|
-
k = k.substring(0,
|
|
2461
|
+
const I = P.length - A;
|
|
2462
|
+
if (X > I) {
|
|
2463
|
+
const z = !C && H < M ? Math.min(M - H, E.text.length) : 0, G = Math.max(0, I - H - z);
|
|
2464
|
+
k = k.substring(0, G);
|
|
2410
2465
|
}
|
|
2411
2466
|
}
|
|
2412
|
-
k.length > 0 && (t.save(), t.font = Ht(
|
|
2467
|
+
k.length > 0 && (t.save(), t.font = Ht(j, _, $, Y), x += t.measureText(k).width, t.restore()), B += E.text.length;
|
|
2413
2468
|
});
|
|
2414
|
-
const L = e.transformType === "custom" && e.transformData ? e.transformData.width -
|
|
2469
|
+
const L = e.transformType === "custom" && e.transformData ? e.transformData.width - gt * 2 : void 0;
|
|
2415
2470
|
let W;
|
|
2416
2471
|
r === "center" ? W = -x / 2 : r === "right" ? W = L !== void 0 ? L / 2 - x : -x : W = L !== void 0 ? -L / 2 : 0;
|
|
2417
|
-
const O =
|
|
2418
|
-
B = 0,
|
|
2419
|
-
const
|
|
2472
|
+
const O = m + l.ascent + T * h;
|
|
2473
|
+
B = 0, w.forEach((E) => {
|
|
2474
|
+
const j = E.style.fontSize !== void 0 ? E.style.fontSize : n, _ = E.style.fontFamily !== void 0 ? E.style.fontFamily : o;
|
|
2420
2475
|
E.style.color !== void 0 ? E.style.color : e.color;
|
|
2421
|
-
const
|
|
2476
|
+
const $ = E.style.bold !== void 0 ? E.style.bold : i, Y = E.style.italic !== void 0 ? E.style.italic : a;
|
|
2422
2477
|
let k = E.text;
|
|
2423
|
-
const
|
|
2424
|
-
if (!C &&
|
|
2425
|
-
const
|
|
2426
|
-
k = k.substring(
|
|
2478
|
+
const H = B, X = B + E.text.length;
|
|
2479
|
+
if (!C && M > 0 && H < M) {
|
|
2480
|
+
const I = Math.min(M - H, E.text.length);
|
|
2481
|
+
k = k.substring(I);
|
|
2427
2482
|
}
|
|
2428
2483
|
if (!R && A > 0) {
|
|
2429
|
-
const
|
|
2430
|
-
if (
|
|
2431
|
-
const
|
|
2432
|
-
k = k.substring(0,
|
|
2484
|
+
const I = P.length - A;
|
|
2485
|
+
if (X > I) {
|
|
2486
|
+
const z = !C && H < M ? Math.min(M - H, E.text.length) : 0, G = Math.max(0, I - H - z);
|
|
2487
|
+
k = k.substring(0, G);
|
|
2433
2488
|
}
|
|
2434
2489
|
}
|
|
2435
|
-
B += E.text.length, k.length > 0 && (p.font = Ht(
|
|
2490
|
+
B += E.text.length, k.length > 0 && (p.font = Ht(j, _, $, Y), p.textAlign = "left", p.globalCompositeOperation = "source-over", p.strokeStyle = t.strokeStyle, p.globalAlpha = Math.min(t.globalAlpha * 1.6, 0.8), p.lineWidth = (d + c) * 2, p.strokeText(k, W, O), p.globalCompositeOperation = "destination-out", p.globalAlpha = 1, p.lineWidth = d * 2, p.strokeText(k, W, O), p.fillText(k, W, O), W += p.measureText(k).width);
|
|
2436
2491
|
});
|
|
2437
2492
|
});
|
|
2438
2493
|
} else {
|
|
2439
|
-
t.font = Ht(n,
|
|
2440
|
-
let g,
|
|
2494
|
+
t.font = Ht(n, o, i, a), p.font = t.font, p.textAlign = r;
|
|
2495
|
+
let g, u;
|
|
2441
2496
|
if (e.transformType === "custom" && e.transformData) {
|
|
2442
|
-
const C = e.transformData.width -
|
|
2497
|
+
const C = e.transformData.width - gt * 2, { lines: R } = fe(
|
|
2443
2498
|
e.text,
|
|
2444
2499
|
C,
|
|
2445
2500
|
n,
|
|
2446
|
-
|
|
2501
|
+
o,
|
|
2447
2502
|
i,
|
|
2448
2503
|
a,
|
|
2449
2504
|
void 0,
|
|
@@ -2457,17 +2512,17 @@ class _t {
|
|
|
2457
2512
|
`);
|
|
2458
2513
|
g = Te(g, C);
|
|
2459
2514
|
}
|
|
2460
|
-
g.length === 0 ?
|
|
2461
|
-
const y = -
|
|
2462
|
-
`),
|
|
2463
|
-
let
|
|
2464
|
-
r === "center" ?
|
|
2465
|
-
const x = y + l.ascent + R * h, P =
|
|
2515
|
+
g.length === 0 ? u = 0 : g.length === 1 ? u = l.height : u = (g.length - 1) * h + l.height;
|
|
2516
|
+
const y = -u / 2, S = e.text.includes(`
|
|
2517
|
+
`), m = e.transformType === "custom" && e.transformData ? e.transformData.width : 0, w = -m / 2;
|
|
2518
|
+
let T = w + gt;
|
|
2519
|
+
r === "center" ? T = w + m / 2 : r === "right" && (T = w + m - gt), g.forEach((C, R) => {
|
|
2520
|
+
const x = y + l.ascent + R * h, P = S || R === 0, M = S || R === g.length - 1;
|
|
2466
2521
|
let A = C;
|
|
2467
|
-
P || (A = A.replace(/^ +/, "")),
|
|
2522
|
+
P || (A = A.replace(/^ +/, "")), M || (A = A.replace(/ +$/, "")), p.globalCompositeOperation = "source-over", p.strokeStyle = t.strokeStyle, p.globalAlpha = Math.min(t.globalAlpha * 1.6, 0.8), p.lineWidth = (d + c) * 2, p.lineJoin = "round", p.strokeText(A, T, x), p.globalCompositeOperation = "destination-out", p.globalAlpha = 1, p.lineWidth = d * 2, p.strokeText(A, T, x), p.fillText(A, T, x);
|
|
2468
2523
|
});
|
|
2469
2524
|
}
|
|
2470
|
-
t.setTransform(1, 0, 0, 1, 0, 0), t.drawImage(
|
|
2525
|
+
t.setTransform(1, 0, 0, 1, 0, 0), t.drawImage(f, 0, 0), t.restore();
|
|
2471
2526
|
}
|
|
2472
2527
|
/**
|
|
2473
2528
|
* HOVER RING EFFECT for transformed text (circle, wave, arch, lean, ascend, flag)
|
|
@@ -2480,34 +2535,34 @@ class _t {
|
|
|
2480
2535
|
* - Element stroke (StrokeRenderer.ts - only when stroke.enabled = true)
|
|
2481
2536
|
* - Selection box (dashed outline shown by each transform's render() method)
|
|
2482
2537
|
*/
|
|
2483
|
-
static renderTransformHoverRingEffect(t, e,
|
|
2484
|
-
t.save(), t.translate(e.x *
|
|
2485
|
-
const n = 4 /
|
|
2538
|
+
static renderTransformHoverRingEffect(t, e, s) {
|
|
2539
|
+
t.save(), t.translate(e.x * s, e.y * s), s !== 1 && t.scale(s, s), t.rotate(-e.rotation * Math.PI / 180);
|
|
2540
|
+
const n = 4 / s, o = 4 / s, i = document.createElement("canvas");
|
|
2486
2541
|
i.width = t.canvas.width, i.height = t.canvas.height;
|
|
2487
2542
|
const a = i.getContext("2d");
|
|
2488
2543
|
if (!a) {
|
|
2489
2544
|
t.restore();
|
|
2490
2545
|
return;
|
|
2491
2546
|
}
|
|
2492
|
-
a.setTransform(t.getTransform()), this.renderTransformWithHoverEffect(a, e, n,
|
|
2547
|
+
a.setTransform(t.getTransform()), this.renderTransformWithHoverEffect(a, e, n, o, t.strokeStyle), t.setTransform(1, 0, 0, 1, 0, 0), t.drawImage(i, 0, 0), t.restore();
|
|
2493
2548
|
}
|
|
2494
2549
|
/**
|
|
2495
2550
|
* Helper to render text along a transform path with hover effect
|
|
2496
2551
|
*/
|
|
2497
|
-
static renderTransformWithHoverEffect(t, e,
|
|
2552
|
+
static renderTransformWithHoverEffect(t, e, s, n, o) {
|
|
2498
2553
|
const i = e, a = i.fontSize, r = i.fontFamily, l = i.bold || !1, h = i.italic || !1, c = l ? "bold" : "normal", d = h ? "italic" : "normal";
|
|
2499
2554
|
if (t.font = `${d} ${c} ${a}px ${r}`, t.textAlign = "center", t.textBaseline = "middle", i.transformType === "lean") {
|
|
2500
2555
|
const y = -i.transformData.leanAmount * Math.PI / 4;
|
|
2501
|
-
t.transform(1, 0, Math.tan(y), 1, 0, 0), t.globalCompositeOperation = "source-over", t.strokeStyle =
|
|
2556
|
+
t.transform(1, 0, Math.tan(y), 1, 0, 0), t.globalCompositeOperation = "source-over", t.strokeStyle = o, t.globalAlpha = 0.8, t.lineWidth = (n + s) * 2, t.lineJoin = "round", t.strokeText(i.text, 0, 0), t.globalCompositeOperation = "destination-out", t.globalAlpha = 1, t.lineWidth = n * 2, t.strokeText(i.text, 0, 0), t.fillText(i.text, 0, 0);
|
|
2502
2557
|
return;
|
|
2503
2558
|
}
|
|
2504
|
-
const
|
|
2505
|
-
t.translate(
|
|
2559
|
+
const f = i.text.split(""), p = f.map((u) => t.measureText(u).width), b = this.calculateCharPositions(e, f, p), g = (u) => {
|
|
2560
|
+
t.translate(u.x, u.y), u.angle && t.rotate(u.angle), u.skewY && t.transform(1, u.skewY, 0, 1, 0, 0);
|
|
2506
2561
|
};
|
|
2507
|
-
t.globalCompositeOperation = "source-over", t.strokeStyle =
|
|
2508
|
-
t.save(), g(
|
|
2509
|
-
}), t.globalCompositeOperation = "destination-out", t.globalAlpha = 1, t.lineWidth = n * 2, b.forEach((
|
|
2510
|
-
t.save(), g(
|
|
2562
|
+
t.globalCompositeOperation = "source-over", t.strokeStyle = o, t.globalAlpha = 0.8, t.lineWidth = (n + s) * 2, t.lineJoin = "round", b.forEach((u, y) => {
|
|
2563
|
+
t.save(), g(u), t.strokeText(f[y], 0, 0), t.restore();
|
|
2564
|
+
}), t.globalCompositeOperation = "destination-out", t.globalAlpha = 1, t.lineWidth = n * 2, b.forEach((u, y) => {
|
|
2565
|
+
t.save(), g(u), t.strokeText(f[y], 0, 0), t.fillText(f[y], 0, 0), t.restore();
|
|
2511
2566
|
});
|
|
2512
2567
|
}
|
|
2513
2568
|
/**
|
|
@@ -2515,26 +2570,26 @@ class _t {
|
|
|
2515
2570
|
*
|
|
2516
2571
|
* Also used by EditModeRenderer for cursor positioning on transformed text.
|
|
2517
2572
|
*/
|
|
2518
|
-
static calculateCharPositions(t, e,
|
|
2519
|
-
const n = t.transformType,
|
|
2520
|
-
return n === "circle" ? this.calculateCirclePositions(
|
|
2573
|
+
static calculateCharPositions(t, e, s) {
|
|
2574
|
+
const n = t.transformType, o = t.transformData;
|
|
2575
|
+
return n === "circle" ? this.calculateCirclePositions(o, e, s) : n === "wave" ? this.calculateWavePositions(t, e, s, o) : n === "arch" ? this.calculateArchPositions(t, e, s, o) : n === "lean" ? this.calculateLeanPositions(e, s) : n === "ascend" ? this.calculateAscendPositions(t, e, s, o) : n === "flag" ? this.calculateFlagPositions(t, e, s, o) : e.map(() => ({ x: 0, y: 0, angle: 0 }));
|
|
2521
2576
|
}
|
|
2522
2577
|
/**
|
|
2523
2578
|
* Calculate positions for circle transform
|
|
2524
2579
|
*/
|
|
2525
|
-
static calculateCirclePositions(t, e,
|
|
2526
|
-
const n = [],
|
|
2580
|
+
static calculateCirclePositions(t, e, s) {
|
|
2581
|
+
const n = [], o = s.reduce((a, r) => a + r, 0), i = t.radius * t.scale;
|
|
2527
2582
|
if (t.reverse) {
|
|
2528
|
-
let a = Math.PI / 2 +
|
|
2583
|
+
let a = Math.PI / 2 + o / (2 * i);
|
|
2529
2584
|
e.forEach((r, l) => {
|
|
2530
|
-
const c =
|
|
2531
|
-
n.push({ x: d, y:
|
|
2585
|
+
const c = s[l] / i, d = Math.cos(a - c / 2) * i, f = Math.sin(a - c / 2) * i, p = a - c / 2 - Math.PI / 2;
|
|
2586
|
+
n.push({ x: d, y: f, angle: p }), a -= c;
|
|
2532
2587
|
});
|
|
2533
2588
|
} else {
|
|
2534
|
-
let a = -Math.PI / 2 -
|
|
2589
|
+
let a = -Math.PI / 2 - o / (2 * i);
|
|
2535
2590
|
e.forEach((r, l) => {
|
|
2536
|
-
const c =
|
|
2537
|
-
n.push({ x: d, y:
|
|
2591
|
+
const c = s[l] / i, d = Math.cos(a + c / 2) * i, f = Math.sin(a + c / 2) * i, p = a + c / 2 + Math.PI / 2;
|
|
2592
|
+
n.push({ x: d, y: f, angle: p }), a += c;
|
|
2538
2593
|
});
|
|
2539
2594
|
}
|
|
2540
2595
|
return n;
|
|
@@ -2542,99 +2597,99 @@ class _t {
|
|
|
2542
2597
|
/**
|
|
2543
2598
|
* Calculate positions for wave transform
|
|
2544
2599
|
*/
|
|
2545
|
-
static calculateWavePositions(t, e,
|
|
2546
|
-
const
|
|
2547
|
-
let a = -
|
|
2600
|
+
static calculateWavePositions(t, e, s, n) {
|
|
2601
|
+
const o = [];
|
|
2602
|
+
let a = -s.reduce((r, l) => r + l, 0) / 2;
|
|
2548
2603
|
return e.forEach((r, l) => {
|
|
2549
|
-
const h =
|
|
2550
|
-
|
|
2551
|
-
}),
|
|
2604
|
+
const h = s[l], c = a + h / 2, d = c / (n.width / 2), f = n.amplitude * t.fontSize * Math.sin(n.frequency * Math.PI * d), p = n.amplitude * n.frequency * Math.PI * Math.cos(n.frequency * Math.PI * d);
|
|
2605
|
+
o.push({ x: c, y: f, angle: 0, skewY: p * ge }), a += h;
|
|
2606
|
+
}), o;
|
|
2552
2607
|
}
|
|
2553
2608
|
/**
|
|
2554
2609
|
* Calculate positions for arch transform
|
|
2555
2610
|
*/
|
|
2556
|
-
static calculateArchPositions(t, e,
|
|
2557
|
-
const
|
|
2611
|
+
static calculateArchPositions(t, e, s, n) {
|
|
2612
|
+
const o = [], i = s.reduce((l, h) => l + h, 0), a = n.width / 2;
|
|
2558
2613
|
let r = -i / 2;
|
|
2559
2614
|
return e.forEach((l, h) => {
|
|
2560
|
-
const c =
|
|
2561
|
-
|
|
2562
|
-
}),
|
|
2615
|
+
const c = s[h], d = r + c / 2, f = d / a, p = (Math.pow(f, 2) - 1) * n.archHeight * t.fontSize, b = 2 * f * n.archHeight;
|
|
2616
|
+
o.push({ x: d, y: p, angle: 0, skewY: b * 0.3 }), r += c;
|
|
2617
|
+
}), o;
|
|
2563
2618
|
}
|
|
2564
2619
|
/**
|
|
2565
2620
|
* Calculate positions for lean transform
|
|
2566
2621
|
*/
|
|
2567
2622
|
static calculateLeanPositions(t, e) {
|
|
2568
|
-
const
|
|
2569
|
-
let
|
|
2623
|
+
const s = [];
|
|
2624
|
+
let o = -e.reduce((i, a) => i + a, 0) / 2;
|
|
2570
2625
|
return t.forEach((i, a) => {
|
|
2571
|
-
const r = e[a], l =
|
|
2572
|
-
|
|
2573
|
-
}),
|
|
2626
|
+
const r = e[a], l = o + r / 2;
|
|
2627
|
+
s.push({ x: l, y: 0, angle: 0 }), o += r;
|
|
2628
|
+
}), s;
|
|
2574
2629
|
}
|
|
2575
2630
|
/**
|
|
2576
2631
|
* Calculate positions for ascend transform
|
|
2577
2632
|
*/
|
|
2578
|
-
static calculateAscendPositions(t, e,
|
|
2579
|
-
const
|
|
2633
|
+
static calculateAscendPositions(t, e, s, n) {
|
|
2634
|
+
const o = [], i = s.reduce((h, c) => h + c, 0), a = n.ascendAngle * Math.PI / 180, r = Math.tan(a);
|
|
2580
2635
|
let l = -i / 2;
|
|
2581
2636
|
return e.forEach((h, c) => {
|
|
2582
|
-
const d =
|
|
2583
|
-
|
|
2584
|
-
}),
|
|
2637
|
+
const d = s[c], f = l + d / 2, p = f * r;
|
|
2638
|
+
o.push({ x: f, y: p, angle: 0, skewY: r * 1 }), l += d;
|
|
2639
|
+
}), o;
|
|
2585
2640
|
}
|
|
2586
2641
|
/**
|
|
2587
2642
|
* Calculate positions for flag transform
|
|
2588
2643
|
*/
|
|
2589
|
-
static calculateFlagPositions(t, e,
|
|
2590
|
-
const
|
|
2591
|
-
let a = -
|
|
2644
|
+
static calculateFlagPositions(t, e, s, n) {
|
|
2645
|
+
const o = [];
|
|
2646
|
+
let a = -s.reduce((r, l) => r + l, 0) / 2;
|
|
2592
2647
|
return e.forEach((r, l) => {
|
|
2593
|
-
const h =
|
|
2594
|
-
|
|
2595
|
-
}),
|
|
2648
|
+
const h = s[l], c = a + h / 2, d = c / (n.width / 2), f = Math.abs(d), p = n.amplitude * f, b = p * t.fontSize * Math.sin(n.frequency * Math.PI * d), g = p * n.frequency * Math.PI * Math.cos(n.frequency * Math.PI * d), u = n.amplitude * Math.sign(d) * Math.sin(n.frequency * Math.PI * d), y = g + u;
|
|
2649
|
+
o.push({ x: c, y: b, angle: 0, skewY: y * 0.3 }), a += h;
|
|
2650
|
+
}), o;
|
|
2596
2651
|
}
|
|
2597
2652
|
}
|
|
2598
|
-
class
|
|
2653
|
+
class Mt {
|
|
2599
2654
|
/**
|
|
2600
2655
|
* Render snap guides layer
|
|
2601
2656
|
*/
|
|
2602
2657
|
static renderSnapGuidesLayer(t, e = []) {
|
|
2603
|
-
e.length !== 0 && (t.save(), t.strokeStyle =
|
|
2604
|
-
t.beginPath(),
|
|
2658
|
+
e.length !== 0 && (t.save(), t.strokeStyle = et(t.canvas), t.lineWidth = rt.canvas.snapGuideWidth, t.setLineDash(rt.canvas.snapGuideDash), e.forEach((s) => {
|
|
2659
|
+
t.beginPath(), s.type === "vertical" ? (t.moveTo(s.x ?? 0, s.y1 ?? 0), t.lineTo(s.x ?? 0, s.y2 ?? 0)) : s.type === "horizontal" ? (t.moveTo(s.x1 ?? 0, s.y ?? 0), t.lineTo(s.x2 ?? 0, s.y ?? 0)) : (t.moveTo(s.x1 ?? 0, s.y1 ?? 0), t.lineTo(s.x2 ?? 0, s.y2 ?? 0)), t.stroke();
|
|
2605
2660
|
}), t.restore());
|
|
2606
2661
|
}
|
|
2607
2662
|
/**
|
|
2608
2663
|
* Render spacing indicators layer
|
|
2609
2664
|
*/
|
|
2610
2665
|
static renderSpacingIndicatorsLayer(t, e = []) {
|
|
2611
|
-
e.length !== 0 && (t.save(), t.setLineDash([]), e.forEach((
|
|
2666
|
+
e.length !== 0 && (t.save(), t.setLineDash([]), e.forEach((s) => {
|
|
2612
2667
|
const n = Ot(t.canvas);
|
|
2613
|
-
if (t.strokeStyle = n, t.fillStyle = n, t.lineWidth =
|
|
2614
|
-
const
|
|
2615
|
-
t.moveTo(
|
|
2668
|
+
if (t.strokeStyle = n, t.fillStyle = n, t.lineWidth = rt.canvas.spacingIndicatorWidth, t.beginPath(), s.type === "horizontal") {
|
|
2669
|
+
const o = s.x1 ?? 0, i = s.x2 ?? 0, a = s.y ?? 0;
|
|
2670
|
+
t.moveTo(o, a), t.lineTo(i, a), t.stroke();
|
|
2616
2671
|
const r = 6;
|
|
2617
|
-
t.beginPath(), t.moveTo(
|
|
2618
|
-
const l =
|
|
2619
|
-
this.renderDistanceLabel(t, l, h,
|
|
2620
|
-
} else if (
|
|
2621
|
-
const
|
|
2622
|
-
t.moveTo(
|
|
2672
|
+
t.beginPath(), t.moveTo(o, a - r), t.lineTo(o, a + r), t.stroke(), t.beginPath(), t.moveTo(i, a - r), t.lineTo(i, a + r), t.stroke();
|
|
2673
|
+
const l = s.labelX, h = s.labelY;
|
|
2674
|
+
this.renderDistanceLabel(t, l, h, s.distance);
|
|
2675
|
+
} else if (s.type === "vertical") {
|
|
2676
|
+
const o = s.x ?? 0, i = s.y1 ?? 0, a = s.y2 ?? 0;
|
|
2677
|
+
t.moveTo(o, i), t.lineTo(o, a), t.stroke();
|
|
2623
2678
|
const r = 6;
|
|
2624
|
-
t.beginPath(), t.moveTo(
|
|
2625
|
-
const l =
|
|
2626
|
-
this.renderDistanceLabel(t, l, h,
|
|
2679
|
+
t.beginPath(), t.moveTo(o - r, i), t.lineTo(o + r, i), t.stroke(), t.beginPath(), t.moveTo(o - r, a), t.lineTo(o + r, a), t.stroke();
|
|
2680
|
+
const l = s.labelX, h = s.labelY;
|
|
2681
|
+
this.renderDistanceLabel(t, l, h, s.distance);
|
|
2627
2682
|
}
|
|
2628
2683
|
}), t.restore());
|
|
2629
2684
|
}
|
|
2630
2685
|
/**
|
|
2631
2686
|
* Render a distance label with background
|
|
2632
2687
|
*/
|
|
2633
|
-
static renderDistanceLabel(t, e,
|
|
2634
|
-
const
|
|
2635
|
-
t.font = `600 ${
|
|
2636
|
-
const a = t.measureText(
|
|
2637
|
-
t.fillStyle = Ot(t.canvas), t.beginPath(), t.roundRect(e - h / 2,
|
|
2688
|
+
static renderDistanceLabel(t, e, s, n) {
|
|
2689
|
+
const o = `${n}`;
|
|
2690
|
+
t.font = `600 ${rt.canvas.spacingLabelFontSize}px ${rt.canvas.spacingLabelFontFamily}`;
|
|
2691
|
+
const a = t.measureText(o).width, r = rt.canvas.spacingLabelFontSize, l = 4, h = a + l * 2, c = r + l * 2;
|
|
2692
|
+
t.fillStyle = Ot(t.canvas), t.beginPath(), t.roundRect(e - h / 2, s - c / 2, h, c, ue), t.fill(), t.fillStyle = pe, t.textAlign = "center", t.textBaseline = "middle", t.fillText(o, e, s);
|
|
2638
2693
|
}
|
|
2639
2694
|
}
|
|
2640
2695
|
class Dt {
|
|
@@ -2642,32 +2697,32 @@ class Dt {
|
|
|
2642
2697
|
* Render edit mode features: cursor and text selection highlight
|
|
2643
2698
|
* This renders on the main canvas at world coordinates (same as the element)
|
|
2644
2699
|
*/
|
|
2645
|
-
static renderEditModeLayer(t, e,
|
|
2700
|
+
static renderEditModeLayer(t, e, s, n) {
|
|
2646
2701
|
if (!e || e.transformType === "image" || e.transformType === "group") return;
|
|
2647
|
-
const
|
|
2702
|
+
const o = e, { cursorPosition: i, selectionStart: a, selectionEnd: r, editText: l, editRichText: h, cursorOpacity: c, isTouchDevice: d, selectionHandlePositionsRef: f } = s, p = n || 1, b = o.transformType;
|
|
2648
2703
|
if (b === "circle" || b === "wave" || b === "arch" || b === "lean" || b === "ascend" || b === "flag") {
|
|
2649
|
-
this.renderTransformEditModeLayer(t,
|
|
2704
|
+
this.renderTransformEditModeLayer(t, o, s, p);
|
|
2650
2705
|
return;
|
|
2651
2706
|
}
|
|
2652
|
-
const g =
|
|
2653
|
-
t.save(), t.translate(
|
|
2654
|
-
const C = jt(g,
|
|
2655
|
-
let P,
|
|
2656
|
-
if (h &&
|
|
2657
|
-
const
|
|
2658
|
-
A =
|
|
2707
|
+
const g = o.fontSize || 24, u = o.fontFamily || "Arial", y = o.bold || !1, S = o.italic || !1, m = o.underline || !1, w = o.strikethrough || !1, T = o.textAlign || "center";
|
|
2708
|
+
t.save(), t.translate(o.x, o.y), t.rotate(-o.rotation * Math.PI / 180);
|
|
2709
|
+
const C = jt(g, u, y, S), R = C.height, x = g * 1.2;
|
|
2710
|
+
let P, M, A;
|
|
2711
|
+
if (h && o.transformType === "custom" && o.transformData.width) {
|
|
2712
|
+
const Y = o.transformData.width - gt * 2;
|
|
2713
|
+
A = Y;
|
|
2659
2714
|
const k = qt(h);
|
|
2660
|
-
P = [],
|
|
2661
|
-
const
|
|
2662
|
-
fontSize:
|
|
2663
|
-
fontFamily:
|
|
2664
|
-
bold:
|
|
2665
|
-
italic:
|
|
2715
|
+
P = [], M = [], k.forEach((H) => {
|
|
2716
|
+
const X = Ut(H, Y, {
|
|
2717
|
+
fontSize: o.fontSize,
|
|
2718
|
+
fontFamily: o.fontFamily,
|
|
2719
|
+
bold: o.bold,
|
|
2720
|
+
italic: o.italic
|
|
2666
2721
|
});
|
|
2667
|
-
|
|
2668
|
-
P.push(
|
|
2669
|
-
isParagraphStart:
|
|
2670
|
-
isParagraphEnd:
|
|
2722
|
+
X.forEach((I, z) => {
|
|
2723
|
+
P.push(I), M.push({
|
|
2724
|
+
isParagraphStart: z === 0,
|
|
2725
|
+
isParagraphEnd: z === X.length - 1
|
|
2671
2726
|
});
|
|
2672
2727
|
});
|
|
2673
2728
|
});
|
|
@@ -2676,194 +2731,194 @@ class Dt {
|
|
|
2676
2731
|
`).map((k) => [
|
|
2677
2732
|
{
|
|
2678
2733
|
text: k,
|
|
2679
|
-
style: { fontSize: g, fontFamily:
|
|
2734
|
+
style: { fontSize: g, fontFamily: u, bold: y, italic: S }
|
|
2680
2735
|
}
|
|
2681
|
-
]),
|
|
2736
|
+
]), M = P.map(() => ({
|
|
2682
2737
|
isParagraphStart: !0,
|
|
2683
2738
|
// Each line is its own paragraph
|
|
2684
2739
|
isParagraphEnd: !0
|
|
2685
2740
|
}));
|
|
2686
2741
|
const B = P.length > 1 ? C.height + (P.length - 1) * x : C.height;
|
|
2687
2742
|
let L = -B / 2, W = 0, O = L, D = R;
|
|
2688
|
-
const
|
|
2743
|
+
const Q = [];
|
|
2689
2744
|
let E = 0;
|
|
2690
|
-
P.forEach((
|
|
2691
|
-
var
|
|
2692
|
-
const
|
|
2693
|
-
|
|
2694
|
-
Array.from(
|
|
2695
|
-
let
|
|
2745
|
+
P.forEach((Y, k) => {
|
|
2746
|
+
var z, G;
|
|
2747
|
+
const H = M[k].isParagraphStart, X = M[k].isParagraphEnd, I = [];
|
|
2748
|
+
Y.forEach((st) => {
|
|
2749
|
+
Array.from(st.text).forEach((U) => {
|
|
2750
|
+
let F = g, nt = u, ot = y, Z = S;
|
|
2696
2751
|
if (h && E < l.length) {
|
|
2697
|
-
const
|
|
2698
|
-
|
|
2752
|
+
const J = h.getStyleAt(E);
|
|
2753
|
+
F = J.fontSize || g, nt = J.fontFamily || u, ot = J.bold !== void 0 ? J.bold : y, Z = J.italic !== void 0 ? J.italic : S;
|
|
2699
2754
|
}
|
|
2700
2755
|
t.save();
|
|
2701
|
-
const
|
|
2702
|
-
t.font = `${
|
|
2703
|
-
const q = t.measureText(
|
|
2704
|
-
t.restore(),
|
|
2756
|
+
const it = ot ? "bold" : "normal", V = Z ? "italic" : "normal";
|
|
2757
|
+
t.font = `${V} ${it} ${F}px "${nt}", Arial, sans-serif`;
|
|
2758
|
+
const q = t.measureText(U).width;
|
|
2759
|
+
t.restore(), I.push({ char: U, width: q, fontSize: F, index: E }), E++;
|
|
2705
2760
|
});
|
|
2706
2761
|
});
|
|
2707
2762
|
{
|
|
2708
|
-
const
|
|
2709
|
-
let
|
|
2710
|
-
for (let
|
|
2711
|
-
!
|
|
2712
|
-
let
|
|
2713
|
-
|
|
2714
|
-
let
|
|
2715
|
-
for (let
|
|
2716
|
-
const q =
|
|
2717
|
-
|
|
2718
|
-
x:
|
|
2763
|
+
const st = k === 0, lt = k === P.length - 1, U = I.map((V) => V.char).join(""), F = ((z = U.match(/^ +/)) == null ? void 0 : z[0].length) || 0, nt = ((G = U.match(/ +$/)) == null ? void 0 : G[0].length) || 0;
|
|
2764
|
+
let ot = 0;
|
|
2765
|
+
for (let V = 0; V < I.length; V++)
|
|
2766
|
+
!st && V < F || !lt && V >= I.length - nt || (ot += I[V].width);
|
|
2767
|
+
let Z;
|
|
2768
|
+
T === "center" ? Z = -ot / 2 : T === "right" ? Z = A !== void 0 ? A / 2 - ot : -ot : Z = A !== void 0 ? -A / 2 : 0;
|
|
2769
|
+
let it = Z;
|
|
2770
|
+
for (let V = 0; V < I.length; V++) {
|
|
2771
|
+
const q = I[V];
|
|
2772
|
+
Q[q.index] = {
|
|
2773
|
+
x: it,
|
|
2719
2774
|
y: L,
|
|
2720
2775
|
width: q.width,
|
|
2721
2776
|
// All characters keep their width for cursor navigation
|
|
2722
2777
|
height: q.fontSize
|
|
2723
|
-
},
|
|
2778
|
+
}, it += q.width;
|
|
2724
2779
|
}
|
|
2725
|
-
if (
|
|
2726
|
-
const
|
|
2727
|
-
if (i >=
|
|
2728
|
-
if (i ===
|
|
2729
|
-
W =
|
|
2780
|
+
if (I.length > 0) {
|
|
2781
|
+
const V = I[0].index, q = I[I.length - 1].index, ft = k < P.length - 1 && q + 1 === E ? q : q + 1;
|
|
2782
|
+
if (i >= V && i <= ft)
|
|
2783
|
+
if (i === V)
|
|
2784
|
+
W = Z, O = L, D = R;
|
|
2730
2785
|
else {
|
|
2731
2786
|
let pt = 0;
|
|
2732
|
-
for (let
|
|
2733
|
-
const
|
|
2787
|
+
for (let at = 0; at < I.length && I[at].index < i; at++) {
|
|
2788
|
+
const ht = I[at], Ct = ht.char === " ";
|
|
2734
2789
|
let yt = !0;
|
|
2735
|
-
if (
|
|
2736
|
-
const Rt =
|
|
2737
|
-
yt = !(Rt && Tt || N &&
|
|
2790
|
+
if (Ct) {
|
|
2791
|
+
const Rt = at < F, N = at >= I.length - nt, Tt = !H && F > 0, wt = !X && nt > 0;
|
|
2792
|
+
yt = !(Rt && Tt || N && wt);
|
|
2738
2793
|
}
|
|
2739
|
-
yt && (pt +=
|
|
2794
|
+
yt && (pt += ht.width);
|
|
2740
2795
|
}
|
|
2741
|
-
W =
|
|
2796
|
+
W = Z + pt, O = L, D = R;
|
|
2742
2797
|
}
|
|
2743
2798
|
}
|
|
2744
2799
|
k < P.length - 1 && (L += x);
|
|
2745
2800
|
}
|
|
2746
2801
|
});
|
|
2747
|
-
const
|
|
2748
|
-
let
|
|
2749
|
-
if (
|
|
2750
|
-
const
|
|
2802
|
+
const j = a !== r;
|
|
2803
|
+
let _ = null, $ = null;
|
|
2804
|
+
if (j) {
|
|
2805
|
+
const Y = Math.min(a, r), k = Math.max(a, r);
|
|
2751
2806
|
t.save(), t.fillStyle = ye(t.canvas);
|
|
2752
|
-
let
|
|
2753
|
-
if (P.forEach((
|
|
2754
|
-
var
|
|
2755
|
-
const
|
|
2756
|
-
if (
|
|
2757
|
-
Array.from(
|
|
2758
|
-
const
|
|
2807
|
+
let H = 0, X = -B / 2;
|
|
2808
|
+
if (P.forEach((I, z) => {
|
|
2809
|
+
var nt, ot;
|
|
2810
|
+
const G = M[z].isParagraphStart, st = M[z].isParagraphEnd, lt = z === 0, U = z === P.length - 1, F = [];
|
|
2811
|
+
if (I.forEach((Z) => {
|
|
2812
|
+
Array.from(Z.text).forEach((it) => {
|
|
2813
|
+
const V = Z.style || {}, q = V.fontSize !== void 0 ? V.fontSize : g, J = V.fontFamily !== void 0 ? V.fontFamily : u, ut = V.bold !== void 0 ? V.bold : y, ft = V.italic !== void 0 ? V.italic : S;
|
|
2759
2814
|
t.save();
|
|
2760
|
-
const pt = ut ? "bold" : "normal",
|
|
2761
|
-
t.font = `${
|
|
2762
|
-
const
|
|
2763
|
-
t.restore(),
|
|
2815
|
+
const pt = ut ? "bold" : "normal", at = ft ? "italic" : "normal";
|
|
2816
|
+
t.font = `${at} ${pt} ${q}px "${J}", Arial, sans-serif`;
|
|
2817
|
+
const ht = t.measureText(it).width;
|
|
2818
|
+
t.restore(), F.push({ char: it, index: H, width: ht, style: V }), H++;
|
|
2764
2819
|
});
|
|
2765
|
-
}),
|
|
2766
|
-
const
|
|
2767
|
-
if (k >
|
|
2820
|
+
}), F.length > 0) {
|
|
2821
|
+
const Z = F[0].index, it = F[F.length - 1].index;
|
|
2822
|
+
if (k > Z && Y <= it) {
|
|
2768
2823
|
t.save();
|
|
2769
|
-
const
|
|
2824
|
+
const V = F.map((N) => N.char).join(""), q = ((nt = V.match(/^ +/)) == null ? void 0 : nt[0].length) || 0, J = ((ot = V.match(/ +$/)) == null ? void 0 : ot[0].length) || 0;
|
|
2770
2825
|
let ut = 0;
|
|
2771
|
-
for (let N = 0; N <
|
|
2772
|
-
!
|
|
2773
|
-
let
|
|
2774
|
-
|
|
2775
|
-
const pt = Math.max(
|
|
2776
|
-
let
|
|
2777
|
-
for (let N = 0; N <
|
|
2778
|
-
const Tt =
|
|
2779
|
-
!(
|
|
2826
|
+
for (let N = 0; N < F.length; N++)
|
|
2827
|
+
!lt && N < q || !U && N >= F.length - J || (ut += F[N].width);
|
|
2828
|
+
let ft = 0;
|
|
2829
|
+
T === "center" ? ft = -ut / 2 : T === "right" && (ft = -ut);
|
|
2830
|
+
const pt = Math.max(Y, Z), at = Math.min(k, it + 1);
|
|
2831
|
+
let ht = 0;
|
|
2832
|
+
for (let N = 0; N < F.length && F[N].index < pt; N++) {
|
|
2833
|
+
const Tt = F[N], wt = N < q, At = N >= F.length - J, Et = !G && q > 0, It = !st && J > 0;
|
|
2834
|
+
!(wt && Et || At && It) && (ht += Tt.width);
|
|
2780
2835
|
}
|
|
2781
|
-
let
|
|
2782
|
-
for (let N = 0; N <
|
|
2783
|
-
const Tt =
|
|
2784
|
-
!(
|
|
2836
|
+
let Ct = 0;
|
|
2837
|
+
for (let N = 0; N < F.length && F[N].index < at; N++) {
|
|
2838
|
+
const Tt = F[N], wt = N < q, At = N >= F.length - J, Et = !G && q > 0, It = !st && J > 0;
|
|
2839
|
+
!(wt && Et || At && It) && (Ct += Tt.width);
|
|
2785
2840
|
}
|
|
2786
|
-
const yt =
|
|
2787
|
-
t.fillRect(yt,
|
|
2841
|
+
const yt = ft + ht, Rt = Ct - ht;
|
|
2842
|
+
t.fillRect(yt, X, Rt, R), _ === null && (_ = { x: yt, y: X }), $ = { x: yt + Rt, y: X + R }, t.restore();
|
|
2788
2843
|
}
|
|
2789
2844
|
}
|
|
2790
|
-
|
|
2845
|
+
z < P.length - 1 && (X += x);
|
|
2791
2846
|
}), t.restore(), h) {
|
|
2792
2847
|
t.save();
|
|
2793
|
-
const
|
|
2794
|
-
|
|
2848
|
+
const I = o.transformType === "custom" ? o.transformData : null, z = I != null && I.width ? I.width - gt * 2 : void 0;
|
|
2849
|
+
we(t, h, {
|
|
2795
2850
|
fontSize: g,
|
|
2796
|
-
fontFamily:
|
|
2797
|
-
color:
|
|
2851
|
+
fontFamily: u,
|
|
2852
|
+
color: o.color || "#000000",
|
|
2798
2853
|
bold: y,
|
|
2799
|
-
italic:
|
|
2800
|
-
underline:
|
|
2801
|
-
strikethrough:
|
|
2802
|
-
textAlign:
|
|
2803
|
-
},
|
|
2854
|
+
italic: S,
|
|
2855
|
+
underline: m,
|
|
2856
|
+
strikethrough: w,
|
|
2857
|
+
textAlign: T
|
|
2858
|
+
}, z), t.restore();
|
|
2804
2859
|
}
|
|
2805
2860
|
}
|
|
2806
|
-
if (
|
|
2807
|
-
const
|
|
2861
|
+
if (j && d && _ && $) {
|
|
2862
|
+
const Y = _, k = $, H = 6 / p, X = 2 / p;
|
|
2808
2863
|
t.save();
|
|
2809
|
-
const
|
|
2810
|
-
t.fillStyle =
|
|
2811
|
-
const
|
|
2812
|
-
t.beginPath(), t.moveTo(
|
|
2864
|
+
const I = et(t.canvas);
|
|
2865
|
+
t.fillStyle = I, t.strokeStyle = I, t.lineWidth = X, t.lineCap = "round";
|
|
2866
|
+
const z = { x: Y.x, y: Y.y - H }, G = { x: k.x, y: k.y + H };
|
|
2867
|
+
t.beginPath(), t.moveTo(Y.x, Y.y), t.lineTo(Y.x, Y.y + R), t.stroke(), t.beginPath(), t.arc(z.x, z.y, H, 0, Math.PI * 2), t.fill(), t.strokeStyle = "white", t.lineWidth = 2 / p, t.stroke(), t.strokeStyle = I, t.lineWidth = X, t.beginPath(), t.moveTo(k.x, k.y - R), t.lineTo(k.x, k.y), t.stroke(), t.beginPath(), t.arc(G.x, G.y, H, 0, Math.PI * 2), t.fill(), t.strokeStyle = "white", t.lineWidth = 2 / p, t.stroke(), t.restore(), f && (f.current = {
|
|
2813
2868
|
start: {
|
|
2814
|
-
center:
|
|
2815
|
-
textEdge:
|
|
2869
|
+
center: z,
|
|
2870
|
+
textEdge: Y
|
|
2816
2871
|
// Original selection edge (top-left of selection on first line)
|
|
2817
2872
|
},
|
|
2818
2873
|
end: {
|
|
2819
|
-
center:
|
|
2874
|
+
center: G,
|
|
2820
2875
|
textEdge: k
|
|
2821
2876
|
// Original selection edge (bottom-right of selection on last line)
|
|
2822
2877
|
}
|
|
2823
2878
|
});
|
|
2824
|
-
} else
|
|
2825
|
-
|
|
2879
|
+
} else f && (f.current = { start: null, end: null });
|
|
2880
|
+
!j && c > 0 && (t.save(), t.globalAlpha = c, t.strokeStyle = et(t.canvas), t.lineWidth = 3 / p, t.lineCap = "round", t.beginPath(), t.moveTo(W, O), t.lineTo(W, O + D), t.stroke(), t.restore()), t.restore();
|
|
2826
2881
|
}
|
|
2827
2882
|
/**
|
|
2828
2883
|
* Render edit mode features for transformed text (circle, wave, arch, etc.)
|
|
2829
2884
|
* Renders cursor along the transform path
|
|
2830
2885
|
*/
|
|
2831
|
-
static renderTransformEditModeLayer(t, e,
|
|
2832
|
-
const { cursorPosition:
|
|
2886
|
+
static renderTransformEditModeLayer(t, e, s, n = 1) {
|
|
2887
|
+
const { cursorPosition: o, cursorOpacity: i } = s, a = e.fontSize || 24, r = e.fontFamily || "Arial", l = e.bold || !1, h = e.italic || !1;
|
|
2833
2888
|
t.save(), t.translate(e.x, e.y), t.rotate(-e.rotation * Math.PI / 180);
|
|
2834
2889
|
const c = l ? "bold" : "normal", d = h ? "italic" : "normal";
|
|
2835
2890
|
t.font = `${d} ${c} ${a}px ${r}`;
|
|
2836
|
-
const
|
|
2837
|
-
if (
|
|
2891
|
+
const f = Array.from(e.text), p = f.map((g) => t.measureText(g).width), b = _t.calculateCharPositions(e, f, p);
|
|
2892
|
+
if (o >= 0 && o <= f.length && i > 0) {
|
|
2838
2893
|
let g;
|
|
2839
|
-
if (
|
|
2894
|
+
if (o === 0)
|
|
2840
2895
|
if (b.length > 0) {
|
|
2841
|
-
const y = b[0],
|
|
2896
|
+
const y = b[0], S = p[0];
|
|
2842
2897
|
g = {
|
|
2843
|
-
x: y.x - Math.cos(y.angle) * (
|
|
2844
|
-
y: y.y - Math.sin(y.angle) * (
|
|
2898
|
+
x: y.x - Math.cos(y.angle) * (S / 2),
|
|
2899
|
+
y: y.y - Math.sin(y.angle) * (S / 2),
|
|
2845
2900
|
angle: y.angle
|
|
2846
2901
|
};
|
|
2847
2902
|
} else
|
|
2848
2903
|
g = { x: 0, y: 0, angle: 0 };
|
|
2849
|
-
else if (
|
|
2850
|
-
const y = b[b.length - 1],
|
|
2904
|
+
else if (o >= b.length) {
|
|
2905
|
+
const y = b[b.length - 1], S = p[p.length - 1];
|
|
2851
2906
|
g = {
|
|
2852
|
-
x: y.x + Math.cos(y.angle) * (
|
|
2853
|
-
y: y.y + Math.sin(y.angle) * (
|
|
2907
|
+
x: y.x + Math.cos(y.angle) * (S / 2),
|
|
2908
|
+
y: y.y + Math.sin(y.angle) * (S / 2),
|
|
2854
2909
|
angle: y.angle
|
|
2855
2910
|
};
|
|
2856
2911
|
} else {
|
|
2857
|
-
const y = b[
|
|
2912
|
+
const y = b[o], S = p[o];
|
|
2858
2913
|
g = {
|
|
2859
|
-
x: y.x - Math.cos(y.angle) * (
|
|
2860
|
-
y: y.y - Math.sin(y.angle) * (
|
|
2914
|
+
x: y.x - Math.cos(y.angle) * (S / 2),
|
|
2915
|
+
y: y.y - Math.sin(y.angle) * (S / 2),
|
|
2861
2916
|
angle: y.angle
|
|
2862
2917
|
};
|
|
2863
2918
|
}
|
|
2864
|
-
t.save(), t.translate(g.x, g.y), t.rotate(g.angle), t.globalAlpha = i, t.strokeStyle =
|
|
2865
|
-
const
|
|
2866
|
-
t.beginPath(), t.moveTo(0, -
|
|
2919
|
+
t.save(), t.translate(g.x, g.y), t.rotate(g.angle), t.globalAlpha = i, t.strokeStyle = et(t.canvas), t.lineWidth = 2 / n;
|
|
2920
|
+
const u = a * 1.2;
|
|
2921
|
+
t.beginPath(), t.moveTo(0, -u / 2), t.lineTo(0, u / 2), t.stroke(), t.restore();
|
|
2867
2922
|
}
|
|
2868
2923
|
t.restore();
|
|
2869
2924
|
}
|
|
@@ -2871,25 +2926,25 @@ class Dt {
|
|
|
2871
2926
|
* Render crop box layer (for images in crop mode)
|
|
2872
2927
|
* Shows both image resize handles and crop handles
|
|
2873
2928
|
*/
|
|
2874
|
-
static renderCropBoxLayer(t, e,
|
|
2929
|
+
static renderCropBoxLayer(t, e, s, n = 1) {
|
|
2875
2930
|
if (!(e instanceof be) || !e.isCropping) return;
|
|
2876
|
-
const
|
|
2931
|
+
const o = e, i = o.getCropBoxBounds();
|
|
2877
2932
|
if (!i) return;
|
|
2878
2933
|
const a = 4 / n, r = 2 / n, l = Se / n, h = me / n, c = 1 / n;
|
|
2879
|
-
t.save(), t.translate(e.x * n, e.y * n), t.rotate(
|
|
2880
|
-
const d =
|
|
2881
|
-
t.scale(d * n,
|
|
2882
|
-
const p =
|
|
2934
|
+
t.save(), t.translate(e.x * n, e.y * n), t.rotate(dt.toRadians(e.rotation));
|
|
2935
|
+
const d = o.transformData.flipHorizontal ? -1 : 1, f = o.transformData.flipVertical ? -1 : 1;
|
|
2936
|
+
t.scale(d * n, f * n);
|
|
2937
|
+
const p = o.transformData.width * o.transformData.cropWidth, b = o.transformData.height * o.transformData.cropHeight, g = o.transformData.width / 2 - (o.transformData.cropX * o.transformData.width + p / 2), u = o.transformData.height / 2 - (o.transformData.cropY * o.transformData.height + b / 2), y = o.transformData.width / 2, S = o.transformData.height / 2, m = {
|
|
2883
2938
|
x: g - y,
|
|
2884
|
-
y:
|
|
2885
|
-
width:
|
|
2886
|
-
height:
|
|
2939
|
+
y: u - S,
|
|
2940
|
+
width: o.transformData.width,
|
|
2941
|
+
height: o.transformData.height
|
|
2887
2942
|
};
|
|
2888
|
-
t.fillStyle = "rgba(0, 0, 0, 0.5)", i.y >
|
|
2889
|
-
const
|
|
2890
|
-
|
|
2891
|
-
const C = i.x + i.width, R =
|
|
2892
|
-
C < R && t.fillRect(C, i.y, R - C, i.height), t.strokeStyle =
|
|
2943
|
+
t.fillStyle = "rgba(0, 0, 0, 0.5)", i.y > m.y && t.fillRect(m.x, m.y, m.width, i.y - m.y);
|
|
2944
|
+
const w = i.y + i.height, T = m.y + m.height;
|
|
2945
|
+
w < T && t.fillRect(m.x, w, m.width, T - w), i.x > m.x && t.fillRect(m.x, i.y, i.x - m.x, i.height);
|
|
2946
|
+
const C = i.x + i.width, R = m.x + m.width;
|
|
2947
|
+
C < R && t.fillRect(C, i.y, R - C, i.height), t.strokeStyle = et(t.canvas), t.lineWidth = r, t.strokeRect(i.x, i.y, i.width, i.height), t.strokeStyle = "rgba(255, 255, 255, 0.5)", t.lineWidth = c;
|
|
2893
2948
|
const x = i.width / 3;
|
|
2894
2949
|
t.beginPath(), t.moveTo(i.x + x, i.y), t.lineTo(i.x + x, i.y + i.height), t.moveTo(i.x + 2 * x, i.y), t.lineTo(i.x + 2 * x, i.y + i.height), t.stroke();
|
|
2895
2950
|
const P = i.height / 3;
|
|
@@ -2918,27 +2973,27 @@ class Dt {
|
|
|
2918
2973
|
B.orientation === "horizontal" ? (L = h, W = a) : (L = a, W = h);
|
|
2919
2974
|
const O = B.x - L / 2, D = B.y - W / 2;
|
|
2920
2975
|
t.fillStyle = "#fff", t.fillRect(O, D, L, W), t.strokeStyle = "#bbb", t.lineWidth = c, t.strokeRect(O, D, L, W);
|
|
2921
|
-
}), t.restore(),
|
|
2922
|
-
const B =
|
|
2976
|
+
}), t.restore(), s && s.resizeHandles) {
|
|
2977
|
+
const B = s.resizeHandles.filter(
|
|
2923
2978
|
(D) => D.anchor === "top-left" || D.anchor === "top-right" || D.anchor === "bottom-left" || D.anchor === "bottom-right"
|
|
2924
|
-
), L =
|
|
2979
|
+
), L = o.getCropBoxWorldCorners(), W = 6, O = 20;
|
|
2925
2980
|
B.forEach((D) => {
|
|
2926
|
-
let
|
|
2981
|
+
let Q = !1;
|
|
2927
2982
|
if (L)
|
|
2928
2983
|
for (const E of L) {
|
|
2929
|
-
const
|
|
2930
|
-
if (Math.sqrt(
|
|
2931
|
-
|
|
2984
|
+
const j = D.x - E.x, _ = D.y - E.y;
|
|
2985
|
+
if (Math.sqrt(j * j + _ * _) < O) {
|
|
2986
|
+
Q = !0;
|
|
2932
2987
|
break;
|
|
2933
2988
|
}
|
|
2934
2989
|
}
|
|
2935
|
-
|
|
2990
|
+
Q || (t.save(), t.globalAlpha = 1, t.beginPath(), t.arc(D.x * n, D.y * n, W, 0, 2 * Math.PI), t.fillStyle = "#fff", t.fill(), t.strokeStyle = et(t.canvas), t.lineWidth = 2, t.stroke(), t.restore());
|
|
2936
2991
|
});
|
|
2937
2992
|
}
|
|
2938
2993
|
}
|
|
2939
2994
|
}
|
|
2940
|
-
|
|
2941
|
-
const
|
|
2995
|
+
Ce();
|
|
2996
|
+
const Oe = $t("CanvasRenderer"), K = class K {
|
|
2942
2997
|
/**
|
|
2943
2998
|
* Get a pooled offscreen canvas for clipping content, only recreating
|
|
2944
2999
|
* when dimensions change. Eliminates per-frame canvas allocation.
|
|
@@ -2957,12 +3012,12 @@ const De = $t("CanvasRenderer"), K = class K {
|
|
|
2957
3012
|
* Safely render an element, catching errors so one element's failure
|
|
2958
3013
|
* doesn't crash the entire canvas render loop.
|
|
2959
3014
|
*/
|
|
2960
|
-
static safeRender(t, e,
|
|
3015
|
+
static safeRender(t, e, s, n) {
|
|
2961
3016
|
try {
|
|
2962
|
-
e.render(t,
|
|
2963
|
-
} catch (
|
|
2964
|
-
const i =
|
|
2965
|
-
|
|
3017
|
+
e.render(t, s, n);
|
|
3018
|
+
} catch (o) {
|
|
3019
|
+
const i = o instanceof Error ? o : new Error(String(o));
|
|
3020
|
+
Oe.error(`Failed to render element ${e.id}:`, i), K.onRenderError && K.onRenderError({
|
|
2966
3021
|
category: "render",
|
|
2967
3022
|
message: `Failed to render element: ${i.message}`,
|
|
2968
3023
|
originalError: i,
|
|
@@ -2978,8 +3033,8 @@ const De = $t("CanvasRenderer"), K = class K {
|
|
|
2978
3033
|
* Helper function to render an element (using actual element instance, not config)
|
|
2979
3034
|
* Used by knockout rendering system
|
|
2980
3035
|
*/
|
|
2981
|
-
static renderElement(t, e,
|
|
2982
|
-
|
|
3036
|
+
static renderElement(t, e, s = !0) {
|
|
3037
|
+
s && (t.save(), t.globalAlpha = tt), e.render(t, !1, !1), s && t.restore();
|
|
2983
3038
|
}
|
|
2984
3039
|
/**
|
|
2985
3040
|
* Apply artboard clip path to the context, respecting clipShape.
|
|
@@ -2987,38 +3042,38 @@ const De = $t("CanvasRenderer"), K = class K {
|
|
|
2987
3042
|
* Caller must call ctx.beginPath() before this if needed.
|
|
2988
3043
|
*/
|
|
2989
3044
|
static applyArtboardClipPath(t, e) {
|
|
2990
|
-
const { x:
|
|
3045
|
+
const { x: s, y: n, width: o, height: i, clipShape: a } = e, r = e.borderRadius || 0;
|
|
2991
3046
|
if (t.beginPath(), !a || a === "rectangle")
|
|
2992
|
-
r > 0 ? t.roundRect(
|
|
3047
|
+
r > 0 ? t.roundRect(s, n, o, i, r) : t.rect(s, n, o, i);
|
|
2993
3048
|
else if (a === "circle") {
|
|
2994
|
-
const l =
|
|
3049
|
+
const l = s + o / 2, h = n + i / 2, c = Math.min(o, i) / 2;
|
|
2995
3050
|
t.arc(l, h, c, 0, Math.PI * 2);
|
|
2996
3051
|
} else if (typeof a == "object" && a.type === "rounded") {
|
|
2997
|
-
const l = Math.min(a.radius, Math.min(
|
|
2998
|
-
t.roundRect(
|
|
3052
|
+
const l = Math.min(a.radius, Math.min(o, i) / 2);
|
|
3053
|
+
t.roundRect(s, n, o, i, l);
|
|
2999
3054
|
} else if (typeof a == "object" && a.type === "path")
|
|
3000
3055
|
try {
|
|
3001
3056
|
const l = new Path2D(a.d);
|
|
3002
|
-
t.translate(
|
|
3057
|
+
t.translate(s, n), t.clip(l), t.translate(-s, -n);
|
|
3003
3058
|
return;
|
|
3004
3059
|
} catch {
|
|
3005
|
-
t.rect(
|
|
3060
|
+
t.rect(s, n, o, i);
|
|
3006
3061
|
}
|
|
3007
3062
|
else if (typeof a == "object" && a.type === "composite-path")
|
|
3008
3063
|
try {
|
|
3009
3064
|
const l = new Path2D();
|
|
3010
3065
|
for (const h of a.pieces) {
|
|
3011
|
-
const c = new Path2D(h.d), d = h.rotation ?? 0,
|
|
3012
|
-
if (
|
|
3013
|
-
const p = (h.baseWidth ?? 0) / 2, b = (h.baseHeight ?? 0) / 2, g = d === 90 || d === 270,
|
|
3014
|
-
|
|
3066
|
+
const c = new Path2D(h.d), d = h.rotation ?? 0, f = new DOMMatrix();
|
|
3067
|
+
if (f.translateSelf(h.x, h.y), d !== 0) {
|
|
3068
|
+
const p = (h.baseWidth ?? 0) / 2, b = (h.baseHeight ?? 0) / 2, g = d === 90 || d === 270, u = g ? h.baseHeight ?? 0 : h.baseWidth ?? 0, y = g ? h.baseWidth ?? 0 : h.baseHeight ?? 0;
|
|
3069
|
+
f.translateSelf(u / 2, y / 2), f.rotateSelf(d), f.translateSelf(-p, -b);
|
|
3015
3070
|
}
|
|
3016
|
-
l.addPath(c,
|
|
3071
|
+
l.addPath(c, f);
|
|
3017
3072
|
}
|
|
3018
|
-
t.translate(
|
|
3073
|
+
t.translate(s, n), t.clip(l), t.translate(-s, -n);
|
|
3019
3074
|
return;
|
|
3020
3075
|
} catch {
|
|
3021
|
-
t.rect(
|
|
3076
|
+
t.rect(s, n, o, i);
|
|
3022
3077
|
}
|
|
3023
3078
|
t.clip();
|
|
3024
3079
|
}
|
|
@@ -3026,25 +3081,25 @@ const De = $t("CanvasRenderer"), K = class K {
|
|
|
3026
3081
|
* Render an element with overflow dimming - parts outside the artboard render at 30% opacity
|
|
3027
3082
|
* Uses two-pass rendering: first at 30% opacity (overflow), then clipped to artboard at 100% (inside)
|
|
3028
3083
|
*/
|
|
3029
|
-
static renderElementWithOverflowDimming(t, e,
|
|
3030
|
-
const a = t.getTransform(), r =
|
|
3031
|
-
t.save(), t.globalAlpha = 0.3 * (i ?
|
|
3032
|
-
const h = t.getTransform().inverse(), c = t.canvas.width, d = t.canvas.height,
|
|
3033
|
-
if (
|
|
3034
|
-
const
|
|
3035
|
-
|
|
3036
|
-
for (const
|
|
3037
|
-
const C = new Path2D(
|
|
3038
|
-
if (x.translateSelf(
|
|
3039
|
-
const P = (
|
|
3040
|
-
x.translateSelf(B / 2, L / 2), x.rotateSelf(R), x.translateSelf(-P, -
|
|
3084
|
+
static renderElementWithOverflowDimming(t, e, s, n, o, i) {
|
|
3085
|
+
const a = t.getTransform(), r = s.borderRadius || 0;
|
|
3086
|
+
t.save(), t.globalAlpha = 0.3 * (i ? tt : 1), t.filter = "blur(4px)", t.beginPath();
|
|
3087
|
+
const h = t.getTransform().inverse(), c = t.canvas.width, d = t.canvas.height, f = new DOMPoint(0, 0).matrixTransform(h), p = new DOMPoint(c, d).matrixTransform(h), b = Math.max(p.x - f.x, p.y - f.y), g = f.x - b, u = f.y - b, y = p.x + b, S = p.y + b, m = typeof s.clipShape == "object" && s.clipShape !== null && s.clipShape.type === "composite-path" ? s.clipShape : null;
|
|
3088
|
+
if (m) {
|
|
3089
|
+
const w = new Path2D();
|
|
3090
|
+
w.rect(g, u, y - g, S - u);
|
|
3091
|
+
for (const T of m.pieces) {
|
|
3092
|
+
const C = new Path2D(T.d), R = T.rotation ?? 0, x = new DOMMatrix();
|
|
3093
|
+
if (x.translateSelf(s.x + T.x, s.y + T.y), R !== 0) {
|
|
3094
|
+
const P = (T.baseWidth ?? 0) / 2, M = (T.baseHeight ?? 0) / 2, A = R === 90 || R === 270, B = A ? T.baseHeight ?? 0 : T.baseWidth ?? 0, L = A ? T.baseWidth ?? 0 : T.baseHeight ?? 0;
|
|
3095
|
+
x.translateSelf(B / 2, L / 2), x.rotateSelf(R), x.translateSelf(-P, -M);
|
|
3041
3096
|
}
|
|
3042
|
-
|
|
3097
|
+
w.addPath(C, x);
|
|
3043
3098
|
}
|
|
3044
|
-
t.clip(
|
|
3099
|
+
t.clip(w, "evenodd");
|
|
3045
3100
|
} else
|
|
3046
|
-
t.rect(g,
|
|
3047
|
-
e.render(t, !1, !1), t.restore(), t.save(), this.applyArtboardClipPath(t,
|
|
3101
|
+
t.rect(g, u, y - g, S - u), r > 0 ? t.roundRect(s.x, s.y, s.width, s.height, r) : t.rect(s.x, s.y, s.width, s.height), t.clip("evenodd");
|
|
3102
|
+
e.render(t, !1, !1), t.restore(), t.save(), this.applyArtboardClipPath(t, s), i && (t.globalAlpha = tt), e.render(t, n, o), t.restore(), t.setTransform(a);
|
|
3048
3103
|
}
|
|
3049
3104
|
/**
|
|
3050
3105
|
* Render all elements layer
|
|
@@ -3055,18 +3110,18 @@ const De = $t("CanvasRenderer"), K = class K {
|
|
|
3055
3110
|
* a coloured halo rather than useful UX. Selected/hovered elements fall through to the
|
|
3056
3111
|
* clipped-only branch which respects `clipShape` correctly.
|
|
3057
3112
|
*/
|
|
3058
|
-
static renderElementsLayer(t, e,
|
|
3059
|
-
const c =
|
|
3060
|
-
e !== K._cachedElementsRef && (K._cachedElementConfigs = e.map((
|
|
3061
|
-
const
|
|
3062
|
-
b.clear(), e.forEach((
|
|
3063
|
-
var
|
|
3064
|
-
if (
|
|
3065
|
-
const
|
|
3066
|
-
P && (R === "artboard" ||
|
|
3113
|
+
static renderElementsLayer(t, e, s, n, o, i, a, r = !0, l = !1, h = !1) {
|
|
3114
|
+
const c = o != null && o.getMode() === "drag", d = o == null ? void 0 : o._activeChildContext;
|
|
3115
|
+
e !== K._cachedElementsRef && (K._cachedElementConfigs = e.map((u) => u.toJSON()), K._cachedElementMap = new Map(e.map((u) => [u.id, u])), K._cachedElementsRef = e);
|
|
3116
|
+
const f = K._cachedElementConfigs, p = K._cachedElementMap, b = K._knockoutRenderedIds;
|
|
3117
|
+
b.clear(), e.forEach((u, y) => {
|
|
3118
|
+
var S, m, w;
|
|
3119
|
+
if (u.blendMode === "knockout" || u.blendMode === "clip") {
|
|
3120
|
+
const T = f[y], C = u.blendMode === "knockout" ? "destination-out" : "destination-in", R = ((S = T.knockoutParts) == null ? void 0 : S.scope) || "group", x = f.findIndex((B) => B.id === T.id), P = ((m = T.knockoutParts) == null ? void 0 : m.fill) || ((w = T.knockoutParts) == null ? void 0 : w.stroke), M = R === "artboard" && x !== -1 ? f.slice(0, x) : [];
|
|
3121
|
+
P && (R === "artboard" || M.length > 0) && (M.forEach((B) => B.id && b.add(B.id)), ve(
|
|
3067
3122
|
t,
|
|
3068
|
-
|
|
3069
|
-
|
|
3123
|
+
T,
|
|
3124
|
+
f,
|
|
3070
3125
|
(B, L) => {
|
|
3071
3126
|
const W = L.id && p.get(L.id);
|
|
3072
3127
|
W && this.renderElement(B, W, r);
|
|
@@ -3074,60 +3129,60 @@ const De = $t("CanvasRenderer"), K = class K {
|
|
|
3074
3129
|
i,
|
|
3075
3130
|
a,
|
|
3076
3131
|
C
|
|
3077
|
-
), b.add(
|
|
3132
|
+
), b.add(u.id));
|
|
3078
3133
|
}
|
|
3079
|
-
}), e.some((
|
|
3134
|
+
}), e.some((u) => !b.has(u.id) && u.isClipping) ? this._renderWithClipping(
|
|
3080
3135
|
t,
|
|
3081
3136
|
e,
|
|
3082
3137
|
b,
|
|
3083
|
-
|
|
3138
|
+
s,
|
|
3084
3139
|
n,
|
|
3085
3140
|
c,
|
|
3086
3141
|
d,
|
|
3087
|
-
|
|
3142
|
+
f,
|
|
3088
3143
|
r
|
|
3089
|
-
) : e.forEach((
|
|
3144
|
+
) : e.forEach((u) => {
|
|
3090
3145
|
var R, x;
|
|
3091
|
-
if (b.has(
|
|
3092
|
-
const y =
|
|
3093
|
-
if (
|
|
3094
|
-
kt(t,
|
|
3095
|
-
const
|
|
3096
|
-
r && (A.save(), A.globalAlpha =
|
|
3146
|
+
if (b.has(u.id) || u.visible === !1) return;
|
|
3147
|
+
const y = u.id === s, S = (n == null ? void 0 : n.type) === "element" && ((R = n == null ? void 0 : n.data) == null ? void 0 : R.id) === u.id, m = c && d && Lt(u) && u.id === s, w = y && !m, T = f[e.indexOf(u)], C = ((x = T == null ? void 0 : T.distressEffect) == null ? void 0 : x.enabled) && T.distressEffect.style === "custom" && T.distressEffect.textureUrl;
|
|
3148
|
+
if (T && T.masks && T.masks.length > 0)
|
|
3149
|
+
kt(t, T, (P) => {
|
|
3150
|
+
const M = (A) => {
|
|
3151
|
+
r && (A.save(), A.globalAlpha = tt), this.safeRender(A, u, w, S), r && A.restore();
|
|
3097
3152
|
};
|
|
3098
3153
|
if (C) {
|
|
3099
|
-
const A =
|
|
3100
|
-
Yt(P,
|
|
3154
|
+
const A = u.getVisualBoundingBox();
|
|
3155
|
+
Yt(P, T.distressEffect, A, M);
|
|
3101
3156
|
} else
|
|
3102
|
-
|
|
3157
|
+
M(P);
|
|
3103
3158
|
});
|
|
3104
3159
|
else if (C) {
|
|
3105
|
-
const P =
|
|
3106
|
-
Yt(t,
|
|
3107
|
-
r && (
|
|
3160
|
+
const P = u.getVisualBoundingBox();
|
|
3161
|
+
Yt(t, T.distressEffect, P, (M) => {
|
|
3162
|
+
r && (M.save(), M.globalAlpha = tt), this.safeRender(M, u, w, S), r && M.restore();
|
|
3108
3163
|
});
|
|
3109
|
-
} else l && !h && a &&
|
|
3164
|
+
} else l && !h && a && w ? this.renderElementWithOverflowDimming(t, u, a, w, S, r) : l && a ? (t.save(), this.applyArtboardClipPath(t, a), r && (t.globalAlpha = tt), this.safeRender(t, u, w, S), t.restore()) : (r && (t.save(), t.globalAlpha = tt), this.safeRender(t, u, w, S), r && t.restore());
|
|
3110
3165
|
});
|
|
3111
3166
|
}
|
|
3112
3167
|
/**
|
|
3113
3168
|
* Render elements with clipping mask support at artboard level
|
|
3114
3169
|
* Elements with isClipping=true clip all elements below them
|
|
3115
3170
|
*/
|
|
3116
|
-
static _renderWithClipping(t, e,
|
|
3117
|
-
var
|
|
3118
|
-
const h = t.canvas, c = h.width, d = h.height,
|
|
3171
|
+
static _renderWithClipping(t, e, s, n, o, i, a, r, l = !0) {
|
|
3172
|
+
var u;
|
|
3173
|
+
const h = t.canvas, c = h.width, d = h.height, f = t.getTransform(), p = [];
|
|
3119
3174
|
let b = [], g = [];
|
|
3120
3175
|
for (let y = 0; y < e.length; y++) {
|
|
3121
|
-
const
|
|
3122
|
-
|
|
3176
|
+
const S = e[y], m = r[y];
|
|
3177
|
+
s.has(S.id) || S.visible !== !1 && (S.isClipping ? b.length > 0 ? (p.push({
|
|
3123
3178
|
content: b,
|
|
3124
|
-
mask:
|
|
3179
|
+
mask: S,
|
|
3125
3180
|
contentConfigs: g,
|
|
3126
|
-
maskConfig:
|
|
3181
|
+
maskConfig: m
|
|
3127
3182
|
}), b = [], g = []) : p.push({
|
|
3128
|
-
content: [
|
|
3129
|
-
contentConfigs: [
|
|
3130
|
-
}) : (b.push(
|
|
3183
|
+
content: [S],
|
|
3184
|
+
contentConfigs: [m]
|
|
3185
|
+
}) : (b.push(S), g.push(m)));
|
|
3131
3186
|
}
|
|
3132
3187
|
b.length > 0 && p.push({
|
|
3133
3188
|
content: b,
|
|
@@ -3135,30 +3190,30 @@ const De = $t("CanvasRenderer"), K = class K {
|
|
|
3135
3190
|
});
|
|
3136
3191
|
for (const y of p)
|
|
3137
3192
|
if (!y.mask)
|
|
3138
|
-
y.content.forEach((
|
|
3193
|
+
y.content.forEach((S, m) => {
|
|
3139
3194
|
var P;
|
|
3140
|
-
const
|
|
3141
|
-
x && x.masks && x.masks.length > 0 ? kt(t, x, (
|
|
3142
|
-
l && (
|
|
3143
|
-
}) : (l && (t.save(), t.globalAlpha =
|
|
3195
|
+
const w = S.id === n, T = (o == null ? void 0 : o.type) === "element" && ((P = o == null ? void 0 : o.data) == null ? void 0 : P.id) === S.id, C = i && a && Lt(S) && S.id === n, R = w && !C, x = y.contentConfigs[m];
|
|
3196
|
+
x && x.masks && x.masks.length > 0 ? kt(t, x, (M) => {
|
|
3197
|
+
l && (M.save(), M.globalAlpha = tt), S.render(M, R, T), l && M.restore();
|
|
3198
|
+
}) : (l && (t.save(), t.globalAlpha = tt), S.render(t, R, T), l && t.restore());
|
|
3144
3199
|
});
|
|
3145
3200
|
else {
|
|
3146
|
-
const
|
|
3147
|
-
if (!
|
|
3148
|
-
|
|
3201
|
+
const S = this._getContentCanvas(c, d), m = S.getContext("2d");
|
|
3202
|
+
if (!m) continue;
|
|
3203
|
+
m.setTransform(1, 0, 0, 1, 0, 0), m.clearRect(0, 0, c, d), m.globalCompositeOperation = "source-over", m.setTransform(f), y.content.forEach((x, P) => {
|
|
3149
3204
|
var O;
|
|
3150
|
-
const
|
|
3151
|
-
W && W.masks && W.masks.length > 0 ? kt(
|
|
3152
|
-
l && (D.save(), D.globalAlpha =
|
|
3153
|
-
}) : (l && (
|
|
3205
|
+
const M = x.id === n, A = (o == null ? void 0 : o.type) === "element" && ((O = o == null ? void 0 : o.data) == null ? void 0 : O.id) === x.id, B = i && a && Lt(x) && x.id === n, L = M && !B, W = y.contentConfigs[P];
|
|
3206
|
+
W && W.masks && W.masks.length > 0 ? kt(m, W, (D) => {
|
|
3207
|
+
l && (D.save(), D.globalAlpha = tt), x.render(D, L, A), l && D.restore();
|
|
3208
|
+
}) : (l && (m.save(), m.globalAlpha = tt), x.render(m, L, A), l && m.restore());
|
|
3154
3209
|
});
|
|
3155
|
-
const
|
|
3156
|
-
if (!
|
|
3157
|
-
|
|
3158
|
-
const C = y.mask.id === n, R = (
|
|
3159
|
-
y.maskConfig && y.maskConfig.masks && y.maskConfig.masks.length > 0 ? kt(
|
|
3160
|
-
l && (x.save(), x.globalAlpha =
|
|
3161
|
-
}) : (l && (
|
|
3210
|
+
const w = this._getMaskCanvas(c, d), T = w.getContext("2d");
|
|
3211
|
+
if (!T) continue;
|
|
3212
|
+
T.setTransform(1, 0, 0, 1, 0, 0), T.clearRect(0, 0, c, d), T.globalCompositeOperation = "source-over", T.setTransform(f);
|
|
3213
|
+
const C = y.mask.id === n, R = (o == null ? void 0 : o.type) === "element" && ((u = o == null ? void 0 : o.data) == null ? void 0 : u.id) === y.mask.id;
|
|
3214
|
+
y.maskConfig && y.maskConfig.masks && y.maskConfig.masks.length > 0 ? kt(T, y.maskConfig, (x) => {
|
|
3215
|
+
l && (x.save(), x.globalAlpha = tt), y.mask.render(x, C, R), l && x.restore();
|
|
3216
|
+
}) : (l && (T.save(), T.globalAlpha = tt), y.mask.render(T, C, R), l && T.restore()), m.globalCompositeOperation = "destination-in", m.setTransform(1, 0, 0, 1, 0, 0), m.drawImage(w, 0, 0), t.save(), t.setTransform(1, 0, 0, 1, 0, 0), t.drawImage(S, 0, 0), t.restore();
|
|
3162
3217
|
}
|
|
3163
3218
|
}
|
|
3164
3219
|
// =========================================================================
|
|
@@ -3169,47 +3224,47 @@ const De = $t("CanvasRenderer"), K = class K {
|
|
|
3169
3224
|
* @see InteractionFeedbackRenderer.renderSnapGuidesLayer
|
|
3170
3225
|
*/
|
|
3171
3226
|
static renderSnapGuidesLayer(t, e = []) {
|
|
3172
|
-
|
|
3227
|
+
Mt.renderSnapGuidesLayer(t, e);
|
|
3173
3228
|
}
|
|
3174
3229
|
/**
|
|
3175
3230
|
* Render spacing indicators layer
|
|
3176
3231
|
* @see InteractionFeedbackRenderer.renderSpacingIndicatorsLayer
|
|
3177
3232
|
*/
|
|
3178
3233
|
static renderSpacingIndicatorsLayer(t, e = []) {
|
|
3179
|
-
|
|
3234
|
+
Mt.renderSpacingIndicatorsLayer(t, e);
|
|
3180
3235
|
}
|
|
3181
3236
|
/**
|
|
3182
3237
|
* Render a distance label with background
|
|
3183
3238
|
* @see InteractionFeedbackRenderer.renderDistanceLabel
|
|
3184
3239
|
*/
|
|
3185
|
-
static renderDistanceLabel(t, e,
|
|
3186
|
-
|
|
3240
|
+
static renderDistanceLabel(t, e, s, n) {
|
|
3241
|
+
Mt.renderDistanceLabel(t, e, s, n);
|
|
3187
3242
|
}
|
|
3188
3243
|
/**
|
|
3189
3244
|
* Render selection box layer
|
|
3190
3245
|
* @see SelectionRenderer.renderSelectionLayer
|
|
3191
3246
|
*/
|
|
3192
|
-
static renderSelectionLayer(t, e,
|
|
3193
|
-
mt.renderSelectionLayer(t, e,
|
|
3247
|
+
static renderSelectionLayer(t, e, s, n = 1) {
|
|
3248
|
+
mt.renderSelectionLayer(t, e, s, n);
|
|
3194
3249
|
}
|
|
3195
3250
|
/**
|
|
3196
3251
|
* Render position and size info below the selected element
|
|
3197
3252
|
* @see SelectionRenderer.renderPositionSizeInfo
|
|
3198
3253
|
*/
|
|
3199
|
-
static renderPositionSizeInfo(t, e,
|
|
3200
|
-
mt.renderPositionSizeInfo(t, e,
|
|
3254
|
+
static renderPositionSizeInfo(t, e, s, n, o = 1) {
|
|
3255
|
+
mt.renderPositionSizeInfo(t, e, s, n, o);
|
|
3201
3256
|
}
|
|
3202
3257
|
/**
|
|
3203
3258
|
* Render transform handles layer
|
|
3204
3259
|
* @see SelectionRenderer.renderHandlesLayer
|
|
3205
3260
|
*/
|
|
3206
|
-
static renderHandlesLayer(t, e,
|
|
3261
|
+
static renderHandlesLayer(t, e, s, n, o, i, a, r = 1, l = !0) {
|
|
3207
3262
|
mt.renderHandlesLayer(
|
|
3208
3263
|
t,
|
|
3209
3264
|
e,
|
|
3210
|
-
o,
|
|
3211
|
-
n,
|
|
3212
3265
|
s,
|
|
3266
|
+
n,
|
|
3267
|
+
o,
|
|
3213
3268
|
i,
|
|
3214
3269
|
a,
|
|
3215
3270
|
r,
|
|
@@ -3220,15 +3275,15 @@ const De = $t("CanvasRenderer"), K = class K {
|
|
|
3220
3275
|
* Render hover highlights layer with fade-in animation
|
|
3221
3276
|
* @see HoverRenderer.renderHoverLayer
|
|
3222
3277
|
*/
|
|
3223
|
-
static renderHoverLayer(t, e,
|
|
3224
|
-
_t.renderHoverLayer(t, e,
|
|
3278
|
+
static renderHoverLayer(t, e, s, n = !1, o = 1, i) {
|
|
3279
|
+
_t.renderHoverLayer(t, e, s, n, o, i);
|
|
3225
3280
|
}
|
|
3226
3281
|
/**
|
|
3227
3282
|
* Render crop box layer (for images in crop mode)
|
|
3228
3283
|
* @see EditModeRenderer.renderCropBoxLayer
|
|
3229
3284
|
*/
|
|
3230
|
-
static renderCropBoxLayer(t, e,
|
|
3231
|
-
Dt.renderCropBoxLayer(t, e,
|
|
3285
|
+
static renderCropBoxLayer(t, e, s, n = 1) {
|
|
3286
|
+
Dt.renderCropBoxLayer(t, e, s, n);
|
|
3232
3287
|
}
|
|
3233
3288
|
// =========================================================================
|
|
3234
3289
|
// Main Render Orchestration
|
|
@@ -3240,7 +3295,7 @@ const De = $t("CanvasRenderer"), K = class K {
|
|
|
3240
3295
|
static render({
|
|
3241
3296
|
ctx: t,
|
|
3242
3297
|
elements: e,
|
|
3243
|
-
selectedId:
|
|
3298
|
+
selectedId: s,
|
|
3244
3299
|
selectedElement: n,
|
|
3245
3300
|
// Chrome-related fields (transformHandles, currentRotation,
|
|
3246
3301
|
// isRotating, hideHandles, isAltKeyPressed, showRotationHandle)
|
|
@@ -3249,7 +3304,7 @@ const De = $t("CanvasRenderer"), K = class K {
|
|
|
3249
3304
|
// consumed here — single-selection chrome is now drawn by
|
|
3250
3305
|
// `renderInteractionChromeLayer` after piece guides. See that
|
|
3251
3306
|
// method for the actual chrome rendering.
|
|
3252
|
-
hoverState:
|
|
3307
|
+
hoverState: o,
|
|
3253
3308
|
isEditing: i,
|
|
3254
3309
|
stateMachine: a,
|
|
3255
3310
|
snapGuides: r = [],
|
|
@@ -3257,50 +3312,50 @@ const De = $t("CanvasRenderer"), K = class K {
|
|
|
3257
3312
|
artboardBackgroundColor: h,
|
|
3258
3313
|
artboard: c,
|
|
3259
3314
|
isPreview: d = !0,
|
|
3260
|
-
zoom:
|
|
3315
|
+
zoom: f = 1,
|
|
3261
3316
|
paddingOffset: p = { x: 0, y: 0 },
|
|
3262
3317
|
showOverflowDimmed: b = !1,
|
|
3263
3318
|
suppressOverflowDim: g = !1,
|
|
3264
|
-
distressTexture:
|
|
3319
|
+
distressTexture: u,
|
|
3265
3320
|
imageMask: y,
|
|
3266
|
-
editModeData:
|
|
3321
|
+
editModeData: S
|
|
3267
3322
|
}) {
|
|
3268
3323
|
if (this.renderElementsLayer(
|
|
3269
3324
|
t,
|
|
3270
3325
|
e,
|
|
3271
|
-
o,
|
|
3272
3326
|
s,
|
|
3327
|
+
o,
|
|
3273
3328
|
a ?? void 0,
|
|
3274
3329
|
h,
|
|
3275
3330
|
c,
|
|
3276
3331
|
d,
|
|
3277
3332
|
b,
|
|
3278
3333
|
g
|
|
3279
|
-
),
|
|
3334
|
+
), u != null && u.enabled && c && Me(t, u, c, h), y != null && y.enabled && c && xe(t, y, c, h), i && S && n && Dt.renderEditModeLayer(t, n, S, f), f !== 1) {
|
|
3280
3335
|
t.save();
|
|
3281
|
-
const C = t.getTransform().a /
|
|
3336
|
+
const C = t.getTransform().a / f, R = p.x * f * C, x = p.y * f * C;
|
|
3282
3337
|
t.setTransform(C, 0, 0, C, R, x);
|
|
3283
3338
|
}
|
|
3284
|
-
const
|
|
3285
|
-
...
|
|
3286
|
-
x:
|
|
3287
|
-
y:
|
|
3288
|
-
x1:
|
|
3289
|
-
y1:
|
|
3290
|
-
x2:
|
|
3291
|
-
y2:
|
|
3292
|
-
})),
|
|
3293
|
-
...
|
|
3294
|
-
x:
|
|
3295
|
-
y:
|
|
3296
|
-
x1:
|
|
3297
|
-
y1:
|
|
3298
|
-
x2:
|
|
3299
|
-
y2:
|
|
3300
|
-
labelX:
|
|
3301
|
-
labelY:
|
|
3339
|
+
const m = r.map((T) => ({
|
|
3340
|
+
...T,
|
|
3341
|
+
x: T.x !== void 0 ? T.x * f : void 0,
|
|
3342
|
+
y: T.y !== void 0 ? T.y * f : void 0,
|
|
3343
|
+
x1: T.x1 !== void 0 ? T.x1 * f : void 0,
|
|
3344
|
+
y1: T.y1 !== void 0 ? T.y1 * f : void 0,
|
|
3345
|
+
x2: T.x2 !== void 0 ? T.x2 * f : void 0,
|
|
3346
|
+
y2: T.y2 !== void 0 ? T.y2 * f : void 0
|
|
3347
|
+
})), w = l.map((T) => ({
|
|
3348
|
+
...T,
|
|
3349
|
+
x: T.x !== void 0 ? T.x * f : void 0,
|
|
3350
|
+
y: T.y !== void 0 ? T.y * f : void 0,
|
|
3351
|
+
x1: T.x1 !== void 0 ? T.x1 * f : void 0,
|
|
3352
|
+
y1: T.y1 !== void 0 ? T.y1 * f : void 0,
|
|
3353
|
+
x2: T.x2 !== void 0 ? T.x2 * f : void 0,
|
|
3354
|
+
y2: T.y2 !== void 0 ? T.y2 * f : void 0,
|
|
3355
|
+
labelX: T.labelX * f,
|
|
3356
|
+
labelY: T.labelY * f
|
|
3302
3357
|
}));
|
|
3303
|
-
|
|
3358
|
+
Mt.renderSnapGuidesLayer(t, m), Mt.renderSpacingIndicatorsLayer(t, w), f !== 1 && t.restore();
|
|
3304
3359
|
}
|
|
3305
3360
|
/**
|
|
3306
3361
|
* Single-selection interaction chrome: bbox, handles, position/size
|
|
@@ -3317,9 +3372,9 @@ const De = $t("CanvasRenderer"), K = class K {
|
|
|
3317
3372
|
static renderInteractionChromeLayer({
|
|
3318
3373
|
ctx: t,
|
|
3319
3374
|
selectedElement: e,
|
|
3320
|
-
transformHandles:
|
|
3375
|
+
transformHandles: s,
|
|
3321
3376
|
stateMachine: n,
|
|
3322
|
-
currentRotation:
|
|
3377
|
+
currentRotation: o,
|
|
3323
3378
|
isRotating: i,
|
|
3324
3379
|
hoverState: a,
|
|
3325
3380
|
selectedId: r,
|
|
@@ -3327,35 +3382,35 @@ const De = $t("CanvasRenderer"), K = class K {
|
|
|
3327
3382
|
isEditing: h,
|
|
3328
3383
|
isAltKeyPressed: c = !1,
|
|
3329
3384
|
artboardBackgroundColor: d,
|
|
3330
|
-
hoverClipArtboard:
|
|
3385
|
+
hoverClipArtboard: f,
|
|
3331
3386
|
showRotationHandle: p = !0,
|
|
3332
3387
|
zoom: b = 1,
|
|
3333
3388
|
paddingOffset: g = { x: 0, y: 0 }
|
|
3334
3389
|
}) {
|
|
3335
3390
|
if (b !== 1) {
|
|
3336
3391
|
t.save();
|
|
3337
|
-
const
|
|
3338
|
-
t.setTransform(
|
|
3392
|
+
const S = t.getTransform().a / b, m = g.x * b * S, w = g.y * b * S;
|
|
3393
|
+
t.setTransform(S, 0, 0, S, m, w);
|
|
3339
3394
|
}
|
|
3340
3395
|
if (e && Re(e) && e.isCropping)
|
|
3341
|
-
|
|
3342
|
-
else if (!l && n && mt.renderSelectionLayer(t, e, n, b),
|
|
3396
|
+
s && Dt.renderCropBoxLayer(t, e, s, b);
|
|
3397
|
+
else if (!l && n && mt.renderSelectionLayer(t, e, n, b), s && n && mt.renderPositionSizeInfo(t, e, s, n, b), !l && s && n && mt.renderHandlesLayer(
|
|
3343
3398
|
t,
|
|
3344
3399
|
e,
|
|
3345
|
-
o,
|
|
3346
3400
|
s,
|
|
3401
|
+
o,
|
|
3347
3402
|
i,
|
|
3348
3403
|
a,
|
|
3349
3404
|
n,
|
|
3350
3405
|
b,
|
|
3351
3406
|
p
|
|
3352
3407
|
), !h) {
|
|
3353
|
-
if (
|
|
3408
|
+
if (f) {
|
|
3354
3409
|
t.save();
|
|
3355
|
-
const y =
|
|
3356
|
-
t.beginPath(), C > 0 ? t.roundRect(
|
|
3410
|
+
const y = f, S = y.x * b, m = y.y * b, w = y.width * b, T = y.height * b, C = (y.borderRadius ?? 0) * b;
|
|
3411
|
+
t.beginPath(), C > 0 ? t.roundRect(S, m, w, T, C) : t.rect(S, m, w, T), t.clip();
|
|
3357
3412
|
}
|
|
3358
|
-
_t.renderHoverLayer(t, a, r, c, b, d),
|
|
3413
|
+
_t.renderHoverLayer(t, a, r, c, b, d), f && t.restore();
|
|
3359
3414
|
}
|
|
3360
3415
|
b !== 1 && t.restore();
|
|
3361
3416
|
}
|
|
@@ -3363,17 +3418,18 @@ const De = $t("CanvasRenderer"), K = class K {
|
|
|
3363
3418
|
K._contentCanvas = null, K._contentCanvasSize = { width: 0, height: 0 }, K._maskCanvas = null, K._maskCanvasSize = { width: 0, height: 0 }, K._cachedElementsRef = null, K._cachedElementConfigs = null, K._cachedElementMap = null, K._knockoutRenderedIds = /* @__PURE__ */ new Set(), K.onRenderError = null;
|
|
3364
3419
|
let Kt = K;
|
|
3365
3420
|
export {
|
|
3366
|
-
|
|
3421
|
+
Ze as A,
|
|
3367
3422
|
Kt as C,
|
|
3368
|
-
|
|
3369
|
-
|
|
3370
|
-
|
|
3371
|
-
|
|
3423
|
+
Ue as I,
|
|
3424
|
+
Ve as R,
|
|
3425
|
+
Je as S,
|
|
3426
|
+
je as T,
|
|
3372
3427
|
Jt as a,
|
|
3373
|
-
|
|
3374
|
-
|
|
3375
|
-
|
|
3428
|
+
Ke as b,
|
|
3429
|
+
Ne as c,
|
|
3430
|
+
We as d,
|
|
3431
|
+
qe as e,
|
|
3376
3432
|
Gt as g,
|
|
3377
|
-
|
|
3433
|
+
$e as r
|
|
3378
3434
|
};
|
|
3379
|
-
//# sourceMappingURL=CanvasRenderer-
|
|
3435
|
+
//# sourceMappingURL=CanvasRenderer-B_3GISlW.js.map
|