@snowcone-app/canvas 0.38.0 → 0.39.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{CanvasRenderer-D-E5WWLm.js → CanvasRenderer-COO5UXtZ.js} +704 -669
- package/dist/CanvasRenderer-COO5UXtZ.js.map +1 -0
- package/dist/{CanvasStateV1-C9LQt2J0.js → CanvasStateV1-CJJff7Ci.js} +315 -314
- package/dist/{CanvasStateV1-C9LQt2J0.js.map → CanvasStateV1-CJJff7Ci.js.map} +1 -1
- package/dist/{EditorCanvasImpl-BnxEbr2p.js → EditorCanvasImpl-C_72UKu3.js} +3 -3
- package/dist/{EditorCanvasImpl-BnxEbr2p.js.map → EditorCanvasImpl-C_72UKu3.js.map} +1 -1
- package/dist/FontAnalyzer-DWHS41ba.js.map +1 -1
- package/dist/{SnowconeCanvas-CWSPyqqj.js → SnowconeCanvas-C-YbGCcQ.js} +4 -4
- package/dist/{SnowconeCanvas-CWSPyqqj.js.map → SnowconeCanvas-C-YbGCcQ.js.map} +1 -1
- package/dist/advanced.mjs +358 -360
- package/dist/advanced.mjs.map +1 -1
- package/dist/components/VisualGuideOverlay.d.ts +4 -1
- package/dist/components/embed-realtime/usePieceGuideBundle.d.ts +2 -0
- package/dist/{embed-SOFUZlGB.js → embed-DtlgX9iG.js} +5 -5
- package/dist/{embed-SOFUZlGB.js.map → embed-DtlgX9iG.js.map} +1 -1
- package/dist/embed.mjs +3 -3
- package/dist/index.mjs +4 -4
- package/dist/internals.mjs +2 -2
- package/dist/rendering/PieceGuideRenderer.d.ts +4 -1
- package/dist/state/CanvasStateV1.d.ts +3 -3
- package/dist/{template-fields-CBLHgW7G.js → template-fields-Dltc4Ztb.js} +2 -2
- package/dist/{template-fields-CBLHgW7G.js.map → template-fields-Dltc4Ztb.js.map} +1 -1
- package/dist/types/index.d.ts +2 -1
- package/dist/{usePieceGuideBundle-C7r06a_x.js → usePieceGuideBundle-Cab2gRnn.js} +19 -16
- package/dist/usePieceGuideBundle-Cab2gRnn.js.map +1 -0
- package/dist/utils/pieceRotation.d.ts +35 -0
- package/dist/{validation-BG-V98h0.js → validation-Dh9sVEb9.js} +1428 -1430
- package/dist/validation-Dh9sVEb9.js.map +1 -0
- package/example/package.json +1 -1
- package/package.json +1 -1
- package/dist/CanvasRenderer-D-E5WWLm.js.map +0 -1
- package/dist/usePieceGuideBundle-C7r06a_x.js.map +0 -1
- package/dist/validation-BG-V98h0.js.map +0 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { k as
|
|
2
|
-
import { T as Wt, b as
|
|
3
|
-
import { a as _t, i as
|
|
1
|
+
import { k as re, l as le, Y as nt, m as Ot, Z as he, _ as ce, $ as Yt, a0 as de, a1 as gt, a2 as fe, a3 as Gt, a4 as ge, a5 as ue, c as Qt, a6 as pe, a7 as ye, a8 as be, a9 as Se, aa as te, s as ee, ab as pt, w as ne, ac as Lt, ad as Xt, ae as Pt, af as Nt, ag as me, ah as Te, ai as Kt, aj as we, ak as ve, al as Me, I as xe, am as Re, an as Ce, ao as tt } from "./FontAnalyzer-DWHS41ba.js";
|
|
2
|
+
import { T as Wt, b as ke, u as Pe, K as Ae, L as Dt, z as At, M as Ee, N as He, O as Ie, P as $t } from "./ExportManager-BbBfO22S.js";
|
|
3
|
+
import { a as _t, i as Be } from "./guards-DMmhw_Ow.js";
|
|
4
4
|
const ct = {
|
|
5
5
|
// Canvas-specific
|
|
6
6
|
canvas: {
|
|
@@ -15,30 +15,30 @@ const ct = {
|
|
|
15
15
|
spacingLabelFontSize: 11,
|
|
16
16
|
spacingLabelFontFamily: "-apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif"
|
|
17
17
|
}
|
|
18
|
-
},
|
|
19
|
-
function jt(
|
|
20
|
-
return
|
|
18
|
+
}, Le = 2, Ct = 6, We = 16, De = 5, _e = 5, se = 0.5;
|
|
19
|
+
function jt(v) {
|
|
20
|
+
return Le / v;
|
|
21
21
|
}
|
|
22
|
-
function
|
|
23
|
-
return Ct /
|
|
22
|
+
function Qe(v) {
|
|
23
|
+
return Ct / v;
|
|
24
24
|
}
|
|
25
|
-
function
|
|
26
|
-
return
|
|
25
|
+
function ze(v) {
|
|
26
|
+
return We / v;
|
|
27
27
|
}
|
|
28
|
-
function
|
|
29
|
-
return [
|
|
28
|
+
function tn(v) {
|
|
29
|
+
return [De / v, _e / v];
|
|
30
30
|
}
|
|
31
|
-
function
|
|
32
|
-
|
|
33
|
-
const n =
|
|
34
|
-
|
|
31
|
+
function Ve(v, t, e, s) {
|
|
32
|
+
v.save();
|
|
33
|
+
const n = se / 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 =
|
|
38
|
-
|
|
36
|
+
function en(v, t, e, s = 1, n = "#3b82f6", o = !1) {
|
|
37
|
+
const i = ze(s);
|
|
38
|
+
v.save(), v.fillStyle = "#fff", v.strokeStyle = n, v.lineWidth = o ? jt(s) * 1.25 : jt(s), v.beginPath(), v.arc(t, e, i, 0, Math.PI * 2), v.fill(), v.stroke(), Ve(v, t, e, s), v.restore();
|
|
39
39
|
}
|
|
40
40
|
const qt = Ct * 2;
|
|
41
|
-
class
|
|
41
|
+
class nn {
|
|
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 Qe {
|
|
|
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 =
|
|
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
53
|
const a = ct.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 =
|
|
59
|
-
this.resizeHandles = l.filter((c) => !(!i.includes(c.anchor) || h && c.anchor.includes("middle"))), this.rotationHandle =
|
|
58
|
+
}, l = re(r, t.rotation, o), h = Math.abs(t.rotation % 360) > 0.1;
|
|
59
|
+
this.resizeHandles = l.filter((c) => !(!i.includes(c.anchor) || h && c.anchor.includes("middle"))), this.rotationHandle = le(
|
|
60
60
|
r,
|
|
61
61
|
t.rotation,
|
|
62
|
-
|
|
62
|
+
o,
|
|
63
63
|
e
|
|
64
64
|
);
|
|
65
65
|
}
|
|
@@ -67,67 +67,67 @@ class Qe {
|
|
|
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
74
|
const d = !!(i && i.anchor === c.anchor), f = !!(a && r && r.anchor === c.anchor);
|
|
75
75
|
this.renderResizeHandle(t, c, d, f, l);
|
|
76
|
-
}), h && e && this.rotationHandle && !n && !a && this.renderRotationHandle(t, this.rotationHandle,
|
|
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
88
|
const h = qt * 0.6, c = qt * 1.4, d = h / 2, f = i - h / 2, b = a - c / 2;
|
|
89
|
-
t.fillStyle = "#fff", t.strokeStyle = nt(t.canvas), t.lineWidth =
|
|
89
|
+
t.fillStyle = "#fff", t.strokeStyle = nt(t.canvas), t.lineWidth = s || n ? 2.5 : 2, t.beginPath(), t.roundRect(f, b, h, c, d), t.fill(), t.stroke();
|
|
90
90
|
} else
|
|
91
|
-
t.fillStyle = "#fff", t.strokeStyle = nt(t.canvas), t.lineWidth =
|
|
91
|
+
t.fillStyle = "#fff", t.strokeStyle = nt(t.canvas), t.lineWidth = s || n ? 2.5 : 2, t.beginPath(), t.arc(i, a, Ct, 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 = nt(t.canvas), t.lineWidth =
|
|
102
|
-
const r =
|
|
103
|
-
t.translate(
|
|
100
|
+
const o = e.x * n, i = e.y * n, a = Ct * 2.67;
|
|
101
|
+
t.fillStyle = "#fff", t.strokeStyle = nt(t.canvas), t.lineWidth = s ? 2.5 : 2, t.beginPath(), t.arc(o, i, a, 0, Math.PI * 2), t.fill(), t.stroke();
|
|
102
|
+
const r = se;
|
|
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 =
|
|
119
|
-
for (const
|
|
120
|
-
if (Ot(t, e,
|
|
121
|
-
return
|
|
117
|
+
hitTestResize(t, e, s = 1) {
|
|
118
|
+
const n = ce / s;
|
|
119
|
+
for (const o of this.resizeHandles)
|
|
120
|
+
if (Ot(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 = (Ct * 2.67 + 2) /
|
|
130
|
+
const n = (Ct * 2.67 + 2) / s;
|
|
131
131
|
return Ot(t, e, this.rotationHandle.x, this.rotationHandle.y, n);
|
|
132
132
|
}
|
|
133
133
|
/**
|
|
@@ -142,65 +142,65 @@ class Qe {
|
|
|
142
142
|
* @param rotation - Element rotation in degrees
|
|
143
143
|
*/
|
|
144
144
|
getCursor(t, e) {
|
|
145
|
-
const
|
|
146
|
-
return
|
|
145
|
+
const s = t.anchor.includes("middle") ? "edge" : "corner";
|
|
146
|
+
return he(
|
|
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
|
-
const
|
|
158
|
-
function
|
|
159
|
-
return Math.abs(
|
|
157
|
+
const Fe = 15;
|
|
158
|
+
function Oe(v, t) {
|
|
159
|
+
return Math.abs(v) >= Math.abs(t) ? "x" : "y";
|
|
160
160
|
}
|
|
161
|
-
function
|
|
162
|
-
return e != null && e.shift ?
|
|
161
|
+
function Ye(v, t, e) {
|
|
162
|
+
return e != null && e.shift ? Oe(v, t) === "x" ? { dx: v, dy: 0, lockedAxis: "y" } : { dx: 0, dy: t, lockedAxis: "x" } : { dx: v, dy: t, lockedAxis: null };
|
|
163
163
|
}
|
|
164
|
-
function
|
|
165
|
-
let
|
|
166
|
-
return
|
|
164
|
+
function Ge(v, t = Fe) {
|
|
165
|
+
let s = (Math.round(v / t) * t % 360 + 360) % 360;
|
|
166
|
+
return s > 180 && (s -= 360), s === 0 ? 0 : s;
|
|
167
167
|
}
|
|
168
|
-
function
|
|
169
|
-
anchor:
|
|
168
|
+
function Xe({
|
|
169
|
+
anchor: v,
|
|
170
170
|
startVisualWidth: t,
|
|
171
171
|
startVisualHeight: e,
|
|
172
|
-
newVisualWidth:
|
|
172
|
+
newVisualWidth: s,
|
|
173
173
|
newVisualHeight: n
|
|
174
174
|
}) {
|
|
175
|
-
const
|
|
175
|
+
const o = t !== 0 ? t : 1, i = e !== 0 ? e : 1, a = s / o, r = n / i;
|
|
176
176
|
let l;
|
|
177
|
-
return
|
|
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
178
|
scale: l,
|
|
179
179
|
newVisualWidth: t * l,
|
|
180
180
|
newVisualHeight: e * l
|
|
181
181
|
};
|
|
182
182
|
}
|
|
183
|
-
class
|
|
183
|
+
class Ne {
|
|
184
184
|
/**
|
|
185
185
|
* Calculate new dimensions and position for a resize operation
|
|
186
186
|
*/
|
|
187
187
|
static calculateResize({
|
|
188
188
|
element: t,
|
|
189
189
|
handle: e,
|
|
190
|
-
dx:
|
|
190
|
+
dx: s,
|
|
191
191
|
dy: n,
|
|
192
|
-
startData:
|
|
192
|
+
startData: o,
|
|
193
193
|
snapSystem: i,
|
|
194
194
|
modifiers: a
|
|
195
195
|
}) {
|
|
196
196
|
var F, D, N, j, H;
|
|
197
|
-
const l = new Yt(t).worldDeltaToLocal(
|
|
197
|
+
const l = new Yt(t).worldDeltaToLocal(s, n), h = l.dx, c = l.dy, d = o.visualWidth ?? o.width ?? 0, f = o.visualHeight ?? o.height ?? 0, b = o.width ?? 0, u = o.height ?? 0;
|
|
198
198
|
let p = d, g = f;
|
|
199
199
|
e.anchor.includes("right") ? p = d + h : e.anchor.includes("left") && (p = d - h), e.anchor !== "middle-left" && e.anchor !== "middle-right" && (e.anchor.includes("bottom") ? g = f + c : e.anchor.includes("top") && (g = f - c));
|
|
200
200
|
const y = (a == null ? void 0 : a.shift) === !0;
|
|
201
201
|
let S = null;
|
|
202
202
|
if (y) {
|
|
203
|
-
const z =
|
|
203
|
+
const z = Xe({
|
|
204
204
|
anchor: e.anchor,
|
|
205
205
|
startVisualWidth: d,
|
|
206
206
|
startVisualHeight: f,
|
|
@@ -233,7 +233,7 @@ class Ge {
|
|
|
233
233
|
(E) => typeof E == "object" && E !== null && "frozenWidth" in E
|
|
234
234
|
);
|
|
235
235
|
if (G) {
|
|
236
|
-
const E = t, _ =
|
|
236
|
+
const E = t, _ = o.transformData, U = G.frozenWidth ?? ((N = E.transformData) == null ? void 0 : N.width) ?? b, ot = E.imageAspectRatio || (_ != null && _.width && (_ != null && _.height) ? _.width / _.height : null);
|
|
237
237
|
let et = G.frozenHeight;
|
|
238
238
|
et == null && (ot && ot !== 0 ? et = U / ot : (j = E.transformData) != null && j.height ? et = E.transformData.height : et = u);
|
|
239
239
|
const lt = b !== 0 ? U / b : 1, Y = u !== 0 ? et / u : 1;
|
|
@@ -243,23 +243,23 @@ class Ge {
|
|
|
243
243
|
}
|
|
244
244
|
}
|
|
245
245
|
m = Math.max(50, m), w = Math.max(40, w);
|
|
246
|
-
const
|
|
247
|
-
if (!e.anchor.includes("middle") && ((H =
|
|
248
|
-
const z =
|
|
249
|
-
|
|
246
|
+
const x = t.clone(), I = x.resize(e.anchor, m, w, o);
|
|
247
|
+
if (!e.anchor.includes("middle") && ((H = x.stroke) != null && H.enabled) && o.strokeWidth !== void 0 && o.strokeWidth > 0) {
|
|
248
|
+
const z = o.width ?? 1, K = o.height ?? 1, Q = Math.sqrt(m / z * (w / K)), L = Math.max(1, Math.round(o.strokeWidth * Q * 10) / 10);
|
|
249
|
+
x.stroke = { ...x.stroke, width: L };
|
|
250
250
|
}
|
|
251
|
-
const P = C || I === !1, k = e.anchor.includes("top") || e.anchor.includes("bottom"), B = "isCropping" in
|
|
251
|
+
const P = C || I === !1, k = e.anchor.includes("top") || e.anchor.includes("bottom"), B = "isCropping" in x && x.isCropping, W = "isGroup" in x && x.isGroup;
|
|
252
252
|
if (k && !B && !W) {
|
|
253
253
|
const z = t.getRotationAnchor(), K = this._calculateFixedCornerOffset({
|
|
254
254
|
element: t,
|
|
255
|
-
updatedElement:
|
|
255
|
+
updatedElement: x,
|
|
256
256
|
handle: e,
|
|
257
257
|
rotationAnchor: z
|
|
258
258
|
});
|
|
259
|
-
|
|
259
|
+
x.x += K.x, x.y += K.y;
|
|
260
260
|
}
|
|
261
261
|
return {
|
|
262
|
-
element:
|
|
262
|
+
element: x,
|
|
263
263
|
isFrozen: P,
|
|
264
264
|
// For snap system to detect break-free: dimensions before freeze was applied
|
|
265
265
|
unfrozenDimensions: C ? { width: T, height: R } : void 0
|
|
@@ -273,10 +273,10 @@ class Ge {
|
|
|
273
273
|
static _calculateFixedCornerOffset({
|
|
274
274
|
element: t,
|
|
275
275
|
updatedElement: e,
|
|
276
|
-
handle:
|
|
276
|
+
handle: s,
|
|
277
277
|
rotationAnchor: n
|
|
278
278
|
}) {
|
|
279
|
-
const
|
|
279
|
+
const o = new Yt(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, b = d.y, u = r.x - h.x, p = r.y - h.y, g = u + f, y = p + b, S = g * i - y * a, m = g * a + y * i, w = h.x + S, T = h.y + m, R = this._getFixedLocalCoords(s.anchor, l.width, l.height), C = R.x, x = R.y, I = l.x - c.x, M = l.y - c.y, P = I + C, k = M + x, B = P * i - k * a, W = P * a + k * i, F = c.x + B, D = c.y + W;
|
|
280
280
|
return {
|
|
281
281
|
x: w - F,
|
|
282
282
|
y: T - D
|
|
@@ -286,14 +286,14 @@ class Ge {
|
|
|
286
286
|
* Get local coordinates of the fixed point for a given handle
|
|
287
287
|
* @private
|
|
288
288
|
*/
|
|
289
|
-
static _getFixedLocalCoords(t, e,
|
|
289
|
+
static _getFixedLocalCoords(t, e, s) {
|
|
290
290
|
const n = { x: 0, y: 0 };
|
|
291
291
|
switch (t) {
|
|
292
292
|
case "top-left":
|
|
293
|
-
n.x = e, n.y =
|
|
293
|
+
n.x = e, n.y = s;
|
|
294
294
|
break;
|
|
295
295
|
case "top-right":
|
|
296
|
-
n.x = 0, n.y =
|
|
296
|
+
n.x = 0, n.y = s;
|
|
297
297
|
break;
|
|
298
298
|
case "bottom-left":
|
|
299
299
|
n.x = e, n.y = 0;
|
|
@@ -302,13 +302,13 @@ class Ge {
|
|
|
302
302
|
n.x = 0, n.y = 0;
|
|
303
303
|
break;
|
|
304
304
|
case "middle-left":
|
|
305
|
-
n.x = e, n.y =
|
|
305
|
+
n.x = e, n.y = s / 2;
|
|
306
306
|
break;
|
|
307
307
|
case "middle-right":
|
|
308
|
-
n.x = 0, n.y =
|
|
308
|
+
n.x = 0, n.y = s / 2;
|
|
309
309
|
break;
|
|
310
310
|
case "middle-top":
|
|
311
|
-
n.x = e / 2, n.y =
|
|
311
|
+
n.x = e / 2, n.y = s;
|
|
312
312
|
break;
|
|
313
313
|
case "middle-bottom":
|
|
314
314
|
n.x = e / 2, n.y = 0;
|
|
@@ -317,7 +317,7 @@ class Ge {
|
|
|
317
317
|
return n;
|
|
318
318
|
}
|
|
319
319
|
}
|
|
320
|
-
class
|
|
320
|
+
class Ke {
|
|
321
321
|
constructor() {
|
|
322
322
|
this.hooks = {
|
|
323
323
|
beforeResize: [],
|
|
@@ -341,8 +341,8 @@ class Xe {
|
|
|
341
341
|
*/
|
|
342
342
|
removeHook(t, e) {
|
|
343
343
|
if (!this.hooks[t]) return;
|
|
344
|
-
const
|
|
345
|
-
|
|
344
|
+
const s = this.hooks[t].indexOf(e);
|
|
345
|
+
s !== -1 && this.hooks[t].splice(s, 1);
|
|
346
346
|
}
|
|
347
347
|
/**
|
|
348
348
|
* Clear all hooks at a stage
|
|
@@ -362,9 +362,9 @@ class Xe {
|
|
|
362
362
|
* Run hooks at a specific stage
|
|
363
363
|
*/
|
|
364
364
|
runHooks(t, e) {
|
|
365
|
-
return this.hooks[t] ? this.hooks[t].reduce((
|
|
366
|
-
const
|
|
367
|
-
return
|
|
365
|
+
return this.hooks[t] ? this.hooks[t].reduce((s, n) => {
|
|
366
|
+
const o = n(s);
|
|
367
|
+
return o !== void 0 ? o : s;
|
|
368
368
|
}, e) : e;
|
|
369
369
|
}
|
|
370
370
|
/**
|
|
@@ -372,24 +372,24 @@ class Xe {
|
|
|
372
372
|
*/
|
|
373
373
|
executeResize(t) {
|
|
374
374
|
const e = this.runHooks("beforeResize", t);
|
|
375
|
-
let
|
|
375
|
+
let s = Ne.calculateResize({
|
|
376
376
|
...e,
|
|
377
377
|
snapSystem: t.snapSystem,
|
|
378
378
|
modifiers: t.modifiers
|
|
379
379
|
});
|
|
380
|
-
return
|
|
380
|
+
return s.handle = t.handle, s.startData = t.startData, s = this.runHooks("afterResize", s), s;
|
|
381
381
|
}
|
|
382
382
|
/**
|
|
383
383
|
* Execute position update with hooks
|
|
384
384
|
* Used for drag operations
|
|
385
385
|
*/
|
|
386
386
|
executePositionUpdate(t, e) {
|
|
387
|
-
const
|
|
388
|
-
return this.runHooks("afterPositionUpdate",
|
|
387
|
+
const s = this.runHooks("beforePositionUpdate", { position: t, element: e });
|
|
388
|
+
return this.runHooks("afterPositionUpdate", s).position;
|
|
389
389
|
}
|
|
390
390
|
}
|
|
391
|
-
const
|
|
392
|
-
class
|
|
391
|
+
const sn = new Ke();
|
|
392
|
+
class on {
|
|
393
393
|
constructor(t = null) {
|
|
394
394
|
this.state = "IDLE", this.context = {
|
|
395
395
|
mode: null,
|
|
@@ -433,14 +433,14 @@ class en {
|
|
|
433
433
|
/**
|
|
434
434
|
* Start drag operation
|
|
435
435
|
*/
|
|
436
|
-
startDrag(t, e,
|
|
436
|
+
startDrag(t, e, s, n = null) {
|
|
437
437
|
this.state = "DRAGGING";
|
|
438
|
-
const
|
|
439
|
-
let i =
|
|
438
|
+
const o = t.getTransformStartData();
|
|
439
|
+
let i = o;
|
|
440
440
|
if (n === "crop-image-drag" && t.transformData) {
|
|
441
441
|
const a = t.transformData;
|
|
442
442
|
i = {
|
|
443
|
-
...
|
|
443
|
+
...o,
|
|
444
444
|
cropX: a.cropX,
|
|
445
445
|
cropY: a.cropY,
|
|
446
446
|
cropWidth: a.cropWidth,
|
|
@@ -452,7 +452,7 @@ class en {
|
|
|
452
452
|
dragMode: n,
|
|
453
453
|
// 'crop-image-drag' for moving image within crop, null for normal drag
|
|
454
454
|
startX: e,
|
|
455
|
-
startY:
|
|
455
|
+
startY: s,
|
|
456
456
|
startData: i,
|
|
457
457
|
activeHandle: null,
|
|
458
458
|
element: t
|
|
@@ -481,13 +481,13 @@ class en {
|
|
|
481
481
|
* element off the locked axis. Read modifiers from the CURRENT
|
|
482
482
|
* pointer event — users press/release Shift mid-gesture.
|
|
483
483
|
*/
|
|
484
|
-
updateDrag(t, e,
|
|
484
|
+
updateDrag(t, e, s = null, n) {
|
|
485
485
|
if (this.state !== "DRAGGING")
|
|
486
486
|
throw new Error("Cannot update drag: not in DRAGGING state");
|
|
487
|
-
const
|
|
487
|
+
const o = t - this.context.startX, i = e - this.context.startY, { dx: a, dy: r, lockedAxis: l } = Ye(o, i, n), h = this.context.startData;
|
|
488
488
|
let c = h.x + a, d = h.y + r;
|
|
489
489
|
if (this.snapHandler && this.snapHandler.snapPosition && this.context.element) {
|
|
490
|
-
const f = this.snapHandler.snapPosition({ x: c, y: d }, this.context.element,
|
|
490
|
+
const f = this.snapHandler.snapPosition({ x: c, y: d }, this.context.element, s);
|
|
491
491
|
c = f.x, d = f.y;
|
|
492
492
|
}
|
|
493
493
|
return l === "x" ? c = h.x : l === "y" && (d = h.y), { x: c, y: d };
|
|
@@ -495,12 +495,12 @@ class en {
|
|
|
495
495
|
/**
|
|
496
496
|
* Start resize operation
|
|
497
497
|
*/
|
|
498
|
-
startResize(t, e,
|
|
498
|
+
startResize(t, e, s, n, o, i) {
|
|
499
499
|
this.state = "RESIZING";
|
|
500
500
|
const a = t.getTransformStartData(), r = t.clone();
|
|
501
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 = {
|
|
502
502
|
mode: "resize",
|
|
503
|
-
startX:
|
|
503
|
+
startX: s,
|
|
504
504
|
startY: n,
|
|
505
505
|
startData: {
|
|
506
506
|
...a,
|
|
@@ -508,8 +508,8 @@ class en {
|
|
|
508
508
|
visualY: i.y,
|
|
509
509
|
visualWidth: i.width,
|
|
510
510
|
visualHeight: i.height,
|
|
511
|
-
bboxX:
|
|
512
|
-
bboxY:
|
|
511
|
+
bboxX: o.x,
|
|
512
|
+
bboxY: o.y
|
|
513
513
|
},
|
|
514
514
|
activeHandle: e,
|
|
515
515
|
element: r
|
|
@@ -523,8 +523,8 @@ class en {
|
|
|
523
523
|
updateResize(t, e) {
|
|
524
524
|
if (this.state !== "RESIZING")
|
|
525
525
|
throw new Error("Cannot update resize: not in RESIZING state");
|
|
526
|
-
const
|
|
527
|
-
return { dx:
|
|
526
|
+
const s = t - this.context.startX, n = e - this.context.startY;
|
|
527
|
+
return { dx: s, dy: n };
|
|
528
528
|
}
|
|
529
529
|
/**
|
|
530
530
|
* Adjust the resize start position to account for snap corrections
|
|
@@ -556,16 +556,16 @@ class en {
|
|
|
556
556
|
* Reset resize start data to current element state (for unfreezing)
|
|
557
557
|
* This updates startData to use the current element dimensions, preventing jumps
|
|
558
558
|
*/
|
|
559
|
-
resetResizeStartData(t, e,
|
|
559
|
+
resetResizeStartData(t, e, s) {
|
|
560
560
|
if (this.state !== "RESIZING")
|
|
561
561
|
return;
|
|
562
|
-
const n = t.getBoundingBox(),
|
|
563
|
-
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 = {
|
|
564
564
|
...i,
|
|
565
|
-
visualX:
|
|
566
|
-
visualY:
|
|
567
|
-
visualWidth:
|
|
568
|
-
visualHeight:
|
|
565
|
+
visualX: o.x,
|
|
566
|
+
visualY: o.y,
|
|
567
|
+
visualWidth: o.width,
|
|
568
|
+
visualHeight: o.height,
|
|
569
569
|
bboxX: n.x,
|
|
570
570
|
bboxY: n.y
|
|
571
571
|
};
|
|
@@ -573,14 +573,14 @@ class en {
|
|
|
573
573
|
/**
|
|
574
574
|
* Start rotation operation
|
|
575
575
|
*/
|
|
576
|
-
startRotate(t, e,
|
|
576
|
+
startRotate(t, e, s, n, o) {
|
|
577
577
|
this.state = "ROTATING", this.context = {
|
|
578
578
|
mode: "rotate",
|
|
579
579
|
startX: e,
|
|
580
|
-
startY:
|
|
580
|
+
startY: s,
|
|
581
581
|
startData: {
|
|
582
582
|
startAngle: n,
|
|
583
|
-
currentRotation:
|
|
583
|
+
currentRotation: o,
|
|
584
584
|
elementData: t.getTransformStartData()
|
|
585
585
|
},
|
|
586
586
|
activeHandle: null,
|
|
@@ -597,12 +597,12 @@ class en {
|
|
|
597
597
|
* is a superset of the usual 0/90/180 magnets and must win
|
|
598
598
|
* deterministically. Read modifiers from the CURRENT pointer event.
|
|
599
599
|
*/
|
|
600
|
-
updateRotate(t, e,
|
|
600
|
+
updateRotate(t, e, s, n, o) {
|
|
601
601
|
if (this.state !== "ROTATING")
|
|
602
602
|
throw new Error("Cannot update rotate: not in ROTATING state");
|
|
603
|
-
const i = this.context.startData, r = (
|
|
603
|
+
const i = this.context.startData, r = (de(s, n, t, e) - i.startAngle) * 180 / Math.PI;
|
|
604
604
|
let l = i.currentRotation - r;
|
|
605
|
-
return l = (l % 360 + 360) % 360, l > 180 && (l -= 360),
|
|
605
|
+
return l = (l % 360 + 360) % 360, l > 180 && (l -= 360), o != null && o.shift ? Ge(l) : this.snapHandler && this.snapHandler.snapRotation && this.context.element ? this.snapHandler.snapRotation(l, this.context.element) : l;
|
|
606
606
|
}
|
|
607
607
|
/**
|
|
608
608
|
* Get rotation context
|
|
@@ -624,12 +624,12 @@ class en {
|
|
|
624
624
|
* frame. PinchHandler consumes both via `getPinchContext()` to
|
|
625
625
|
* produce the next element.
|
|
626
626
|
*/
|
|
627
|
-
startPinch(t, e,
|
|
627
|
+
startPinch(t, e, s) {
|
|
628
628
|
this.state = "PINCHING";
|
|
629
629
|
const n = {
|
|
630
|
-
x: (e.x +
|
|
631
|
-
y: (e.y +
|
|
632
|
-
},
|
|
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 = {
|
|
633
633
|
elementData: t.getTransformStartData(),
|
|
634
634
|
startCentroid: n,
|
|
635
635
|
startDistance: a,
|
|
@@ -660,14 +660,14 @@ class en {
|
|
|
660
660
|
updatePinch(t, e) {
|
|
661
661
|
if (this.state !== "PINCHING")
|
|
662
662
|
throw new Error("Cannot update pinch: not in PINCHING state");
|
|
663
|
-
const
|
|
663
|
+
const s = this.context.startData, n = {
|
|
664
664
|
x: (t.x + e.x) / 2,
|
|
665
665
|
y: (t.y + e.y) / 2
|
|
666
|
-
},
|
|
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;
|
|
667
667
|
return {
|
|
668
668
|
scale: c,
|
|
669
669
|
rotationDelta: d,
|
|
670
|
-
startCentroid:
|
|
670
|
+
startCentroid: s.startCentroid,
|
|
671
671
|
currentCentroid: n
|
|
672
672
|
};
|
|
673
673
|
}
|
|
@@ -736,7 +736,7 @@ class mt {
|
|
|
736
736
|
* - 1 rotation anchor (may be same as center)
|
|
737
737
|
*/
|
|
738
738
|
static getSnapAnchors(t) {
|
|
739
|
-
const e = t.getVisualBoundingBox(),
|
|
739
|
+
const e = t.getVisualBoundingBox(), s = {
|
|
740
740
|
// Corners
|
|
741
741
|
topLeft: { x: e.x, y: e.y },
|
|
742
742
|
topRight: { x: e.x + e.width, y: e.y },
|
|
@@ -753,17 +753,17 @@ class mt {
|
|
|
753
753
|
rotation: this.resolve(t)
|
|
754
754
|
};
|
|
755
755
|
if (t.rotation !== 0) {
|
|
756
|
-
const n =
|
|
757
|
-
Object.keys(
|
|
756
|
+
const n = s.rotation, o = gt.toRadiansInverse(t.rotation);
|
|
757
|
+
Object.keys(s).forEach((i) => {
|
|
758
758
|
if (i === "rotation") return;
|
|
759
|
-
const a =
|
|
760
|
-
|
|
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] = {
|
|
761
761
|
x: n.x + h,
|
|
762
762
|
y: n.y + c
|
|
763
763
|
};
|
|
764
764
|
});
|
|
765
765
|
}
|
|
766
|
-
return
|
|
766
|
+
return s;
|
|
767
767
|
}
|
|
768
768
|
/**
|
|
769
769
|
* Get edge lines for an element (for edge-to-edge snapping)
|
|
@@ -817,11 +817,11 @@ class mt {
|
|
|
817
817
|
* (different from center of visual bbox)
|
|
818
818
|
*/
|
|
819
819
|
static hasCustomRotationAnchor(t) {
|
|
820
|
-
const e = t.getVisualBoundingBox(),
|
|
820
|
+
const e = t.getVisualBoundingBox(), s = {
|
|
821
821
|
x: e.x + e.width / 2,
|
|
822
822
|
y: e.y + e.height / 2
|
|
823
|
-
}, n = this.resolve(t),
|
|
824
|
-
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;
|
|
825
825
|
}
|
|
826
826
|
}
|
|
827
827
|
class Ut {
|
|
@@ -835,8 +835,8 @@ class Ut {
|
|
|
835
835
|
/** Insert a point into the grid */
|
|
836
836
|
insert(t) {
|
|
837
837
|
const e = this.getCellKey(t.x, t.y);
|
|
838
|
-
let
|
|
839
|
-
|
|
838
|
+
let s = this.cells.get(e);
|
|
839
|
+
s || (s = /* @__PURE__ */ new Set(), this.cells.set(e, s)), s.add(t);
|
|
840
840
|
let n = this.idIndex.get(t.id);
|
|
841
841
|
n || (n = /* @__PURE__ */ new Set(), this.idIndex.set(t.id, n)), n.add(e);
|
|
842
842
|
}
|
|
@@ -844,12 +844,12 @@ class Ut {
|
|
|
844
844
|
removeById(t) {
|
|
845
845
|
const e = this.idIndex.get(t);
|
|
846
846
|
if (e) {
|
|
847
|
-
for (const
|
|
848
|
-
const n = this.cells.get(
|
|
847
|
+
for (const s of e) {
|
|
848
|
+
const n = this.cells.get(s);
|
|
849
849
|
if (n) {
|
|
850
|
-
for (const
|
|
851
|
-
|
|
852
|
-
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);
|
|
853
853
|
}
|
|
854
854
|
}
|
|
855
855
|
this.idIndex.delete(t);
|
|
@@ -862,8 +862,8 @@ class Ut {
|
|
|
862
862
|
* [x - radius, x + radius] x [y - radius, y + radius].
|
|
863
863
|
* Each candidate is then distance-checked against the radius.
|
|
864
864
|
*/
|
|
865
|
-
queryNear(t, e,
|
|
866
|
-
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);
|
|
867
867
|
for (let h = i; h <= a; h++)
|
|
868
868
|
for (let c = r; c <= l; c++) {
|
|
869
869
|
const d = `${h},${c}`, f = this.cells.get(d);
|
|
@@ -871,10 +871,10 @@ class Ut {
|
|
|
871
871
|
for (const b of f) {
|
|
872
872
|
if (n !== void 0 && b.id === n) continue;
|
|
873
873
|
const u = b.x - t, p = b.y - e;
|
|
874
|
-
u * u + p * p <=
|
|
874
|
+
u * u + p * p <= s * s && o.push(b);
|
|
875
875
|
}
|
|
876
876
|
}
|
|
877
|
-
return
|
|
877
|
+
return o;
|
|
878
878
|
}
|
|
879
879
|
/**
|
|
880
880
|
* Query all items whose coordinate on `axis` is within `radius` of the
|
|
@@ -888,26 +888,26 @@ class Ut {
|
|
|
888
888
|
*
|
|
889
889
|
* Scans all cells in the band along the target axis.
|
|
890
890
|
*/
|
|
891
|
-
queryNearAxis(t, e,
|
|
892
|
-
const
|
|
891
|
+
queryNearAxis(t, e, s, n) {
|
|
892
|
+
const o = [];
|
|
893
893
|
if (t === "x") {
|
|
894
|
-
const i = Math.floor((e -
|
|
894
|
+
const i = Math.floor((e - s) / this.cellSize), a = Math.floor((e + s) / this.cellSize);
|
|
895
895
|
for (const [r, l] of this.cells) {
|
|
896
896
|
const h = r.indexOf(","), c = parseInt(r.substring(0, h), 10);
|
|
897
897
|
if (!(c < i || c > a))
|
|
898
898
|
for (const d of l)
|
|
899
|
-
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);
|
|
900
900
|
}
|
|
901
901
|
} else {
|
|
902
|
-
const i = Math.floor((e -
|
|
902
|
+
const i = Math.floor((e - s) / this.cellSize), a = Math.floor((e + s) / this.cellSize);
|
|
903
903
|
for (const [r, l] of this.cells) {
|
|
904
904
|
const h = r.indexOf(","), c = parseInt(r.substring(h + 1), 10);
|
|
905
905
|
if (!(c < i || c > a))
|
|
906
906
|
for (const d of l)
|
|
907
|
-
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);
|
|
908
908
|
}
|
|
909
909
|
}
|
|
910
|
-
return
|
|
910
|
+
return o;
|
|
911
911
|
}
|
|
912
912
|
/** Rebuild from a full list of items (clears existing data first) */
|
|
913
913
|
rebuild(t) {
|
|
@@ -920,25 +920,25 @@ class Ut {
|
|
|
920
920
|
return `${Math.floor(t / this.cellSize)},${Math.floor(e / this.cellSize)}`;
|
|
921
921
|
}
|
|
922
922
|
}
|
|
923
|
-
function ft(
|
|
924
|
-
const t =
|
|
923
|
+
function ft(v) {
|
|
924
|
+
const t = v.transformData;
|
|
925
925
|
if (t && "width" in t && typeof t.width == "number")
|
|
926
926
|
return t.width;
|
|
927
927
|
}
|
|
928
|
-
function Tt(
|
|
929
|
-
const t =
|
|
928
|
+
function Tt(v) {
|
|
929
|
+
const t = v.transformData;
|
|
930
930
|
if (t && "height" in t && typeof t.height == "number")
|
|
931
931
|
return t.height;
|
|
932
932
|
}
|
|
933
|
-
function
|
|
934
|
-
const e =
|
|
933
|
+
function xt(v, t) {
|
|
934
|
+
const e = v.transformData;
|
|
935
935
|
return e && "width" in e ? (e.width = t, !0) : !1;
|
|
936
936
|
}
|
|
937
|
-
function Et(
|
|
938
|
-
const e =
|
|
937
|
+
function Et(v, t) {
|
|
938
|
+
const e = v.transformData;
|
|
939
939
|
return e && "height" in e ? (e.height = t, !0) : !1;
|
|
940
940
|
}
|
|
941
|
-
class
|
|
941
|
+
class an {
|
|
942
942
|
constructor(t = {}) {
|
|
943
943
|
this._extraSnapRects = [], this.snapThreshold = t.snapThreshold || ct.canvas.snapThreshold, this.enabled = t.enabled !== !1, this.showGuides = t.showGuides !== !1, this.guides = [], this.activeSnaps = {
|
|
944
944
|
x: null,
|
|
@@ -996,31 +996,31 @@ class nn {
|
|
|
996
996
|
_populateSpatialGrid(t) {
|
|
997
997
|
this._spatialGrid.clear(), this._anchorMetadata.clear();
|
|
998
998
|
for (const e of t) {
|
|
999
|
-
const
|
|
1000
|
-
for (const [n,
|
|
999
|
+
const s = mt.getSnapAnchors(e);
|
|
1000
|
+
for (const [n, o] of Object.entries(s)) {
|
|
1001
1001
|
const i = `${e.id}:${n}`, a = {
|
|
1002
|
-
x:
|
|
1003
|
-
y:
|
|
1002
|
+
x: o.x,
|
|
1003
|
+
y: o.y,
|
|
1004
1004
|
id: i
|
|
1005
1005
|
};
|
|
1006
1006
|
this._spatialGrid.insert(a), this._anchorMetadata.set(i, {
|
|
1007
1007
|
elementId: e.id,
|
|
1008
1008
|
anchorKey: n,
|
|
1009
|
-
point:
|
|
1009
|
+
point: o
|
|
1010
1010
|
});
|
|
1011
1011
|
}
|
|
1012
1012
|
}
|
|
1013
1013
|
for (const e of this._extraSnapRects) {
|
|
1014
|
-
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 = {
|
|
1015
1015
|
topLeft: { x: e.x, y: e.y },
|
|
1016
|
-
topRight: { x:
|
|
1016
|
+
topRight: { x: o, y: e.y },
|
|
1017
1017
|
bottomLeft: { x: e.x, y: i },
|
|
1018
|
-
bottomRight: { x:
|
|
1019
|
-
topCenter: { x:
|
|
1020
|
-
rightCenter: { x:
|
|
1021
|
-
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 },
|
|
1022
1022
|
leftCenter: { x: e.x, y: n },
|
|
1023
|
-
center: { x:
|
|
1023
|
+
center: { x: s, y: n }
|
|
1024
1024
|
// No `rotation` anchor — extras are un-rotated by definition.
|
|
1025
1025
|
}, r = `__snap-rect:${e.id}`;
|
|
1026
1026
|
for (const [l, h] of Object.entries(a)) {
|
|
@@ -1040,23 +1040,23 @@ class nn {
|
|
|
1040
1040
|
/**
|
|
1041
1041
|
* Snap a position during drag operation
|
|
1042
1042
|
*/
|
|
1043
|
-
snapPosition(t, e,
|
|
1044
|
-
if (!this.enabled || !
|
|
1043
|
+
snapPosition(t, e, s) {
|
|
1044
|
+
if (!this.enabled || !s)
|
|
1045
1045
|
return this.clearGuides(), t;
|
|
1046
1046
|
const n = e.clone();
|
|
1047
1047
|
n.x = t.x, n.y = t.y;
|
|
1048
|
-
const
|
|
1048
|
+
const o = mt.getSnapAnchors(n), i = s.filter((y) => y.id !== e.id);
|
|
1049
1049
|
this._populateSpatialGrid(i);
|
|
1050
1050
|
let a = null, r = null, l = 1 / 0, h = 1 / 0;
|
|
1051
1051
|
const c = [], d = [], f = [];
|
|
1052
|
-
for (const [y, S] of Object.entries(
|
|
1052
|
+
for (const [y, S] of Object.entries(o)) {
|
|
1053
1053
|
const m = this._spatialGrid.queryNearAxis("x", S.x, this.snapThreshold);
|
|
1054
1054
|
for (const T of m) {
|
|
1055
1055
|
const R = this._anchorMetadata.get(T.id);
|
|
1056
1056
|
if (!R) continue;
|
|
1057
|
-
const C = R.point,
|
|
1057
|
+
const C = R.point, x = R.anchorKey, I = Math.abs(S.x - C.x);
|
|
1058
1058
|
if (I < this.snapThreshold) {
|
|
1059
|
-
const
|
|
1059
|
+
const M = {
|
|
1060
1060
|
snapTo: C.x,
|
|
1061
1061
|
offset: S.x - t.x,
|
|
1062
1062
|
// How far anchor is from element position
|
|
@@ -1067,19 +1067,19 @@ class nn {
|
|
|
1067
1067
|
y1: Math.min(S.y, C.y) - 50,
|
|
1068
1068
|
y2: Math.max(S.y, C.y) + 50,
|
|
1069
1069
|
movingKey: y,
|
|
1070
|
-
otherKey:
|
|
1070
|
+
otherKey: x
|
|
1071
1071
|
}
|
|
1072
1072
|
};
|
|
1073
|
-
c.push(
|
|
1073
|
+
c.push(M), I < l && (l = I, a = M);
|
|
1074
1074
|
}
|
|
1075
1075
|
}
|
|
1076
1076
|
const w = this._spatialGrid.queryNearAxis("y", S.y, this.snapThreshold);
|
|
1077
1077
|
for (const T of w) {
|
|
1078
1078
|
const R = this._anchorMetadata.get(T.id);
|
|
1079
1079
|
if (!R) continue;
|
|
1080
|
-
const C = R.point,
|
|
1080
|
+
const C = R.point, x = R.anchorKey, I = Math.abs(S.y - C.y);
|
|
1081
1081
|
if (I < this.snapThreshold) {
|
|
1082
|
-
const
|
|
1082
|
+
const M = {
|
|
1083
1083
|
snapTo: C.y,
|
|
1084
1084
|
offset: S.y - t.y,
|
|
1085
1085
|
distance: I,
|
|
@@ -1089,10 +1089,10 @@ class nn {
|
|
|
1089
1089
|
x1: Math.min(S.x, C.x) - 50,
|
|
1090
1090
|
x2: Math.max(S.x, C.x) + 50,
|
|
1091
1091
|
movingKey: y,
|
|
1092
|
-
otherKey:
|
|
1092
|
+
otherKey: x
|
|
1093
1093
|
}
|
|
1094
1094
|
};
|
|
1095
|
-
d.push(
|
|
1095
|
+
d.push(M), I < h && (h = I, r = M);
|
|
1096
1096
|
}
|
|
1097
1097
|
}
|
|
1098
1098
|
}
|
|
@@ -1117,16 +1117,16 @@ class nn {
|
|
|
1117
1117
|
* Calculate what the frozen font size should be at the snap point
|
|
1118
1118
|
* This ensures consistent font size regardless of which side of threshold you enter from
|
|
1119
1119
|
*/
|
|
1120
|
-
_calculateFrozenFontSizeAtSnap(t, e,
|
|
1121
|
-
if (!
|
|
1120
|
+
_calculateFrozenFontSizeAtSnap(t, e, s, n, o) {
|
|
1121
|
+
if (!o) return t.fontSize ?? 0;
|
|
1122
1122
|
const i = n != null && n.anchor ? String(n.anchor) : "";
|
|
1123
1123
|
if (!(n && (i.includes("top") || i.includes("bottom"))))
|
|
1124
|
-
return
|
|
1125
|
-
const r = ft(t) ?? t.width ??
|
|
1124
|
+
return o.fontSize ?? 0;
|
|
1125
|
+
const r = ft(t) ?? t.width ?? o.width;
|
|
1126
1126
|
let l = r;
|
|
1127
1127
|
i.includes("right") && e !== 0 ? l = r + e : i.includes("left") && e !== 0 && (l = r - e);
|
|
1128
|
-
const h = l /
|
|
1129
|
-
return (
|
|
1128
|
+
const h = l / o.width;
|
|
1129
|
+
return (o.fontSize ?? 0) * h;
|
|
1130
1130
|
}
|
|
1131
1131
|
/**
|
|
1132
1132
|
* Check if this will be a position-based snap (vs dimension-based)
|
|
@@ -1153,9 +1153,9 @@ class nn {
|
|
|
1153
1153
|
* Uses the spatial grid (pre-populated via _populateSpatialGrid) for
|
|
1154
1154
|
* O(1) amortized lookup instead of scanning all other elements.
|
|
1155
1155
|
*/
|
|
1156
|
-
_findXSnaps(t, e,
|
|
1157
|
-
const
|
|
1158
|
-
for (const a of
|
|
1156
|
+
_findXSnaps(t, e, s, n) {
|
|
1157
|
+
const o = [], i = new Set(n);
|
|
1158
|
+
for (const a of s) {
|
|
1159
1159
|
const r = t[a];
|
|
1160
1160
|
if (!r) continue;
|
|
1161
1161
|
const l = this._spatialGrid.queryNearAxis("x", r.x, this.snapThreshold);
|
|
@@ -1163,7 +1163,7 @@ class nn {
|
|
|
1163
1163
|
const c = this._anchorMetadata.get(h.id);
|
|
1164
1164
|
if (!c || !i.has(c.anchorKey)) continue;
|
|
1165
1165
|
const d = c.point, f = c.anchorKey, b = Math.abs(r.x - d.x);
|
|
1166
|
-
b < this.snapThreshold &&
|
|
1166
|
+
b < this.snapThreshold && o.push({
|
|
1167
1167
|
distance: b,
|
|
1168
1168
|
snapTo: d.x,
|
|
1169
1169
|
currentValue: r.x,
|
|
@@ -1178,16 +1178,16 @@ class nn {
|
|
|
1178
1178
|
});
|
|
1179
1179
|
}
|
|
1180
1180
|
}
|
|
1181
|
-
return
|
|
1181
|
+
return o;
|
|
1182
1182
|
}
|
|
1183
1183
|
/**
|
|
1184
1184
|
* Find all Y-axis snaps within threshold.
|
|
1185
1185
|
* Uses the spatial grid (pre-populated via _populateSpatialGrid) for
|
|
1186
1186
|
* O(1) amortized lookup instead of scanning all other elements.
|
|
1187
1187
|
*/
|
|
1188
|
-
_findYSnaps(t, e,
|
|
1189
|
-
const
|
|
1190
|
-
for (const a of
|
|
1188
|
+
_findYSnaps(t, e, s, n) {
|
|
1189
|
+
const o = [], i = new Set(n);
|
|
1190
|
+
for (const a of s) {
|
|
1191
1191
|
const r = t[a];
|
|
1192
1192
|
if (!r) continue;
|
|
1193
1193
|
const l = this._spatialGrid.queryNearAxis("y", r.y, this.snapThreshold);
|
|
@@ -1195,7 +1195,7 @@ class nn {
|
|
|
1195
1195
|
const c = this._anchorMetadata.get(h.id);
|
|
1196
1196
|
if (!c || !i.has(c.anchorKey)) continue;
|
|
1197
1197
|
const d = c.point, f = c.anchorKey, b = Math.abs(r.y - d.y);
|
|
1198
|
-
b < this.snapThreshold &&
|
|
1198
|
+
b < this.snapThreshold && o.push({
|
|
1199
1199
|
distance: b,
|
|
1200
1200
|
snapTo: d.y,
|
|
1201
1201
|
currentValue: r.y,
|
|
@@ -1210,39 +1210,39 @@ class nn {
|
|
|
1210
1210
|
});
|
|
1211
1211
|
}
|
|
1212
1212
|
}
|
|
1213
|
-
return
|
|
1213
|
+
return o;
|
|
1214
1214
|
}
|
|
1215
1215
|
/**
|
|
1216
1216
|
* Sort snaps by distance and prioritize based on handle anchor
|
|
1217
1217
|
*/
|
|
1218
|
-
_prioritizeSnaps(t, e,
|
|
1218
|
+
_prioritizeSnaps(t, e, s) {
|
|
1219
1219
|
if (!e || !e.anchor) {
|
|
1220
|
-
t.sort((n,
|
|
1220
|
+
t.sort((n, o) => n.distance - o.distance);
|
|
1221
1221
|
return;
|
|
1222
1222
|
}
|
|
1223
|
-
|
|
1224
|
-
const i = n.guide.movingKey.includes("left") ? -1e3 : 0, a =
|
|
1225
|
-
return n.distance + i - (
|
|
1226
|
-
}) : e.anchor.includes("right") ? t.sort((n,
|
|
1227
|
-
const i = n.guide.movingKey.includes("right") ? -1e3 : 0, a =
|
|
1228
|
-
return n.distance + i - (
|
|
1229
|
-
}) : t.sort((n,
|
|
1230
|
-
const i = n.guide.movingKey.includes("top") ? -1e3 : 0, a =
|
|
1231
|
-
return n.distance + i - (
|
|
1232
|
-
}) : e.anchor.includes("bottom") ? t.sort((n,
|
|
1233
|
-
const i = n.guide.movingKey.includes("bottom") ? -1e3 : 0, a =
|
|
1234
|
-
return n.distance + i - (
|
|
1235
|
-
}) : 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));
|
|
1236
1236
|
}
|
|
1237
1237
|
/**
|
|
1238
1238
|
* Create a guide visualization for an active snap
|
|
1239
1239
|
*/
|
|
1240
|
-
_createGuideForSnap(t, e,
|
|
1241
|
-
const i =
|
|
1240
|
+
_createGuideForSnap(t, e, s, n, o) {
|
|
1241
|
+
const i = s[e];
|
|
1242
1242
|
if (!i) return null;
|
|
1243
|
-
if (
|
|
1243
|
+
if (o === "x") {
|
|
1244
1244
|
let a = 1 / 0, r = -1 / 0;
|
|
1245
|
-
for (const l of Object.values(
|
|
1245
|
+
for (const l of Object.values(s))
|
|
1246
1246
|
Math.abs(l.x - t.snapTo) < 5 && (a = Math.min(a, l.y), r = Math.max(r, l.y));
|
|
1247
1247
|
for (const l of n) {
|
|
1248
1248
|
const h = mt.getSnapAnchors(l);
|
|
@@ -1262,9 +1262,9 @@ class nn {
|
|
|
1262
1262
|
otherKey: "snap"
|
|
1263
1263
|
}
|
|
1264
1264
|
};
|
|
1265
|
-
} else if (
|
|
1265
|
+
} else if (o === "y") {
|
|
1266
1266
|
let a = 1 / 0, r = -1 / 0;
|
|
1267
|
-
for (const l of Object.values(
|
|
1267
|
+
for (const l of Object.values(s))
|
|
1268
1268
|
Math.abs(l.y - t.snapTo) < 5 && (a = Math.min(a, l.x), r = Math.max(r, l.x));
|
|
1269
1269
|
for (const l of n) {
|
|
1270
1270
|
const h = mt.getSnapAnchors(l);
|
|
@@ -1293,9 +1293,9 @@ class nn {
|
|
|
1293
1293
|
* Adjust threshold to compensate for this velocity difference
|
|
1294
1294
|
*/
|
|
1295
1295
|
_getAdjustedStickyThreshold(t, e) {
|
|
1296
|
-
const
|
|
1297
|
-
let
|
|
1298
|
-
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;
|
|
1299
1299
|
}
|
|
1300
1300
|
/**
|
|
1301
1301
|
* Calculate what dimensions should be when edge reaches snap point
|
|
@@ -1313,17 +1313,17 @@ class nn {
|
|
|
1313
1313
|
* @param handle - The resize handle being dragged
|
|
1314
1314
|
* @returns {Object} { frozenWidth, frozenHeight } - Dimensions at snap point
|
|
1315
1315
|
*/
|
|
1316
|
-
_calculateFrozenDimensionsAtSnap(t, e,
|
|
1316
|
+
_calculateFrozenDimensionsAtSnap(t, e, s, n, o) {
|
|
1317
1317
|
const i = ft(t) ?? t.width ?? 0, a = Tt(t) ?? t.height ?? 0;
|
|
1318
1318
|
let r = i, l = a;
|
|
1319
1319
|
const h = t.transformType === "image", c = h ? t.imageAspectRatio || (i && a ? i / a : null) : null, d = n.toLowerCase();
|
|
1320
|
-
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 };
|
|
1321
1321
|
}
|
|
1322
1322
|
/**
|
|
1323
1323
|
* Process sticky snapping for a single axis
|
|
1324
1324
|
* @returns {Object} { snapDelta, bestSnap }
|
|
1325
1325
|
*/
|
|
1326
|
-
_processStickySnap(t, e,
|
|
1326
|
+
_processStickySnap(t, e, s, n, o, i, a) {
|
|
1327
1327
|
const r = this.activeSnaps[t];
|
|
1328
1328
|
let l = 0, h = null;
|
|
1329
1329
|
if (r) {
|
|
@@ -1336,7 +1336,7 @@ class nn {
|
|
|
1336
1336
|
n,
|
|
1337
1337
|
t === "x" ? l : 0,
|
|
1338
1338
|
t === "y" ? l : 0,
|
|
1339
|
-
|
|
1339
|
+
o,
|
|
1340
1340
|
i
|
|
1341
1341
|
);
|
|
1342
1342
|
p !== r.frozenFontSize && (r.frozenFontSize = p);
|
|
@@ -1344,13 +1344,13 @@ class nn {
|
|
|
1344
1344
|
h = this._createGuideForSnap(r, r.anchorKey, e, a, t);
|
|
1345
1345
|
} else {
|
|
1346
1346
|
const u = r;
|
|
1347
|
-
if (this.activeSnaps[t] = null,
|
|
1348
|
-
h =
|
|
1347
|
+
if (this.activeSnaps[t] = null, s.length > 0 && s[0].distance < this.snapThreshold) {
|
|
1348
|
+
h = s[0], l = h.snapTo - h.currentValue;
|
|
1349
1349
|
const p = u && u.anchorKey === h.guide.movingKey && Math.abs(u.snapTo - h.snapTo) < 1, g = p ? u.frozenFontSize : this._calculateFrozenFontSizeAtSnap(
|
|
1350
1350
|
n,
|
|
1351
1351
|
t === "x" ? l : 0,
|
|
1352
1352
|
t === "y" ? l : 0,
|
|
1353
|
-
|
|
1353
|
+
o,
|
|
1354
1354
|
i
|
|
1355
1355
|
), y = this._isPositionBasedSnap(n, t);
|
|
1356
1356
|
let S;
|
|
@@ -1363,7 +1363,7 @@ class nn {
|
|
|
1363
1363
|
t,
|
|
1364
1364
|
l,
|
|
1365
1365
|
h.guide.movingKey,
|
|
1366
|
-
|
|
1366
|
+
o
|
|
1367
1367
|
);
|
|
1368
1368
|
this.activeSnaps[t] = {
|
|
1369
1369
|
snapTo: h.snapTo,
|
|
@@ -1378,13 +1378,13 @@ class nn {
|
|
|
1378
1378
|
}
|
|
1379
1379
|
} else
|
|
1380
1380
|
this.activeSnaps[t] = null;
|
|
1381
|
-
} else if (
|
|
1382
|
-
h =
|
|
1381
|
+
} else if (s.length > 0 && s[0].distance < this.snapThreshold) {
|
|
1382
|
+
h = s[0], l = h.snapTo - h.currentValue;
|
|
1383
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(
|
|
1384
1384
|
n,
|
|
1385
1385
|
t === "x" ? l : 0,
|
|
1386
1386
|
t === "y" ? l : 0,
|
|
1387
|
-
|
|
1387
|
+
o,
|
|
1388
1388
|
i
|
|
1389
1389
|
), b = this._isPositionBasedSnap(n, t);
|
|
1390
1390
|
let u;
|
|
@@ -1397,7 +1397,7 @@ class nn {
|
|
|
1397
1397
|
t,
|
|
1398
1398
|
l,
|
|
1399
1399
|
h.guide.movingKey,
|
|
1400
|
-
|
|
1400
|
+
o
|
|
1401
1401
|
);
|
|
1402
1402
|
this.activeSnaps[t] = {
|
|
1403
1403
|
snapTo: h.snapTo,
|
|
@@ -1414,16 +1414,16 @@ class nn {
|
|
|
1414
1414
|
/**
|
|
1415
1415
|
* Adjust element for right edge resize
|
|
1416
1416
|
*/
|
|
1417
|
-
_adjustElementForRightResize(t, e,
|
|
1418
|
-
const n = t.getVisualBoundingBox(),
|
|
1419
|
-
if (!
|
|
1417
|
+
_adjustElementForRightResize(t, e, s) {
|
|
1418
|
+
const n = t.getVisualBoundingBox(), o = t.transformType === "image";
|
|
1419
|
+
if (!o) {
|
|
1420
1420
|
const i = ft(t);
|
|
1421
|
-
i !== void 0 ?
|
|
1421
|
+
i !== void 0 ? xt(t, i + e) : t.width !== void 0 && (t.width += e);
|
|
1422
1422
|
}
|
|
1423
|
-
if (
|
|
1423
|
+
if (s.anchor === "middle-right") {
|
|
1424
1424
|
const i = gt.toRadiansInverse(t.rotation), a = Math.cos(i), r = Math.sin(i);
|
|
1425
1425
|
t.x += e / 2 * a, t.y += e / 2 * r;
|
|
1426
|
-
} else if (!
|
|
1426
|
+
} else if (!o) {
|
|
1427
1427
|
const a = t.getVisualBoundingBox().x - n.x;
|
|
1428
1428
|
a !== 0 && (t.x -= a);
|
|
1429
1429
|
}
|
|
@@ -1431,16 +1431,16 @@ class nn {
|
|
|
1431
1431
|
/**
|
|
1432
1432
|
* Adjust element for left edge resize
|
|
1433
1433
|
*/
|
|
1434
|
-
_adjustElementForLeftResize(t, e,
|
|
1435
|
-
const n = t.getVisualBoundingBox(),
|
|
1436
|
-
if (!
|
|
1434
|
+
_adjustElementForLeftResize(t, e, s) {
|
|
1435
|
+
const n = t.getVisualBoundingBox(), o = t.transformType === "image";
|
|
1436
|
+
if (!o) {
|
|
1437
1437
|
const i = ft(t);
|
|
1438
|
-
i !== void 0 ?
|
|
1438
|
+
i !== void 0 ? xt(t, i - e) : t.width !== void 0 && (t.width -= e);
|
|
1439
1439
|
}
|
|
1440
|
-
if (
|
|
1440
|
+
if (s.anchor === "middle-left") {
|
|
1441
1441
|
const i = gt.toRadiansInverse(t.rotation), a = Math.cos(i), r = Math.sin(i);
|
|
1442
1442
|
t.x += e / 2 * a, t.y += e / 2 * r;
|
|
1443
|
-
} else if (t.x += e, !
|
|
1443
|
+
} else if (t.x += e, !o) {
|
|
1444
1444
|
const i = t.getVisualBoundingBox(), a = i.x + i.width - (n.x + n.width);
|
|
1445
1445
|
a !== 0 && (t.x -= a);
|
|
1446
1446
|
}
|
|
@@ -1448,36 +1448,36 @@ class nn {
|
|
|
1448
1448
|
/**
|
|
1449
1449
|
* Adjust element for bottom edge resize
|
|
1450
1450
|
*/
|
|
1451
|
-
_adjustElementForBottomResize(t, e,
|
|
1452
|
-
const n = t.getVisualBoundingBox(),
|
|
1453
|
-
if (!
|
|
1451
|
+
_adjustElementForBottomResize(t, e, s) {
|
|
1452
|
+
const n = t.getVisualBoundingBox(), o = t.transformType === "image";
|
|
1453
|
+
if (!o) {
|
|
1454
1454
|
const r = Tt(t);
|
|
1455
1455
|
r !== void 0 ? Et(t, r + e) : t.height !== void 0 && (t.height += e);
|
|
1456
1456
|
}
|
|
1457
1457
|
const i = t.getVisualBoundingBox(), a = Math.abs(i.height - n.height) > 0.01;
|
|
1458
|
-
if (
|
|
1458
|
+
if (s.anchor === "middle-bottom") {
|
|
1459
1459
|
const r = gt.toRadiansInverse(t.rotation), l = Math.cos(r), h = Math.sin(r);
|
|
1460
1460
|
t.x -= e / 2 * h, t.y += e / 2 * l;
|
|
1461
|
-
} else if (!
|
|
1461
|
+
} else if (!o && a) {
|
|
1462
1462
|
const r = i.y - n.y;
|
|
1463
1463
|
r !== 0 && (t.y -= r);
|
|
1464
|
-
} else
|
|
1464
|
+
} else o || (t.y += e);
|
|
1465
1465
|
}
|
|
1466
1466
|
/**
|
|
1467
1467
|
* Adjust element for top edge resize
|
|
1468
1468
|
*/
|
|
1469
|
-
_adjustElementForTopResize(t, e,
|
|
1470
|
-
const n = t.getVisualBoundingBox(),
|
|
1471
|
-
if (!
|
|
1469
|
+
_adjustElementForTopResize(t, e, s) {
|
|
1470
|
+
const n = t.getVisualBoundingBox(), o = t.transformType === "image";
|
|
1471
|
+
if (!o) {
|
|
1472
1472
|
const r = Tt(t);
|
|
1473
1473
|
r !== void 0 ? Et(t, r - e) : t.height !== void 0 && (t.height -= e);
|
|
1474
1474
|
}
|
|
1475
1475
|
const i = t.getVisualBoundingBox(), a = Math.abs(i.height - n.height) > 0.01;
|
|
1476
|
-
if (
|
|
1476
|
+
if (s.anchor === "middle-top") {
|
|
1477
1477
|
const r = gt.toRadiansInverse(t.rotation), l = Math.cos(r), h = Math.sin(r);
|
|
1478
1478
|
t.x -= e / 2 * h, t.y += e / 2 * l;
|
|
1479
1479
|
} else {
|
|
1480
|
-
const r = !
|
|
1480
|
+
const r = !o && a;
|
|
1481
1481
|
if (t.y += e, r) {
|
|
1482
1482
|
const l = t.getVisualBoundingBox(), h = l.y + l.height - (n.y + n.height);
|
|
1483
1483
|
h !== 0 && (t.y -= h);
|
|
@@ -1492,63 +1492,63 @@ class nn {
|
|
|
1492
1492
|
* @param {object} startData - Original data from when resize started (for font size preservation)
|
|
1493
1493
|
* @returns {object} Modified resize result with adjusted element
|
|
1494
1494
|
*/
|
|
1495
|
-
snapDimensions(t, e,
|
|
1496
|
-
var T, R, C,
|
|
1495
|
+
snapDimensions(t, e, s = null) {
|
|
1496
|
+
var T, R, C, x, I;
|
|
1497
1497
|
if (!this.enabled || !e)
|
|
1498
1498
|
return this.clearGuides(), t;
|
|
1499
|
-
const { element: n } = t,
|
|
1499
|
+
const { element: n } = t, o = t.handle;
|
|
1500
1500
|
let i;
|
|
1501
1501
|
const a = n.transformType === "image", r = this.activeSnaps.x !== null || this.activeSnaps.y !== null;
|
|
1502
1502
|
if (a && r && t.isFrozen && t.unfrozenDimensions) {
|
|
1503
|
-
const
|
|
1504
|
-
if (
|
|
1505
|
-
const P = n.getVisualBoundingBox(), k = P.width, B = P.height, W = (
|
|
1506
|
-
|
|
1503
|
+
const M = n.clone();
|
|
1504
|
+
if (M.transformData) {
|
|
1505
|
+
const P = n.getVisualBoundingBox(), k = P.width, B = P.height, W = (s == null ? void 0 : s.width) ?? n.width ?? 0, F = (s == null ? void 0 : s.height) ?? n.height ?? 0, D = (s == null ? void 0 : s.visualWidth) ?? k, N = (s == null ? void 0 : s.visualHeight) ?? B, j = t.unfrozenDimensions.width / D, H = t.unfrozenDimensions.height / N;
|
|
1506
|
+
xt(M, W * j), Et(M, F * H);
|
|
1507
1507
|
}
|
|
1508
|
-
i = mt.getSnapAnchors(
|
|
1508
|
+
i = mt.getSnapAnchors(M);
|
|
1509
1509
|
} else
|
|
1510
1510
|
i = mt.getSnapAnchors(n);
|
|
1511
|
-
const l = e.filter((
|
|
1511
|
+
const l = e.filter((M) => M.id !== n.id);
|
|
1512
1512
|
if (l.length === 0)
|
|
1513
1513
|
return this.clearGuides(), t;
|
|
1514
1514
|
this._populateSpatialGrid(l);
|
|
1515
|
-
const h = this._getSnapKeysForHandle(
|
|
1516
|
-
this._prioritizeSnaps(d,
|
|
1517
|
-
const b = this._processStickySnap("x", i, d, n,
|
|
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 b = this._processStickySnap("x", i, d, n, o, s, l), u = this._processStickySnap("y", i, f, n, o, s, l), p = b.snapDelta, g = u.snapDelta, y = b.bestSnap, S = u.bestSnap, m = [];
|
|
1518
1518
|
y && m.push(y.guide), S && m.push(S.guide), this.guides = m, m.length > 0;
|
|
1519
|
-
const w =
|
|
1519
|
+
const w = o && (o.anchor === "top-left" || o.anchor === "top-right" || o.anchor === "bottom-left" || o.anchor === "bottom-right");
|
|
1520
1520
|
if (a && w && (p !== 0 || g !== 0))
|
|
1521
1521
|
return t;
|
|
1522
1522
|
if (p !== 0 || g !== 0) {
|
|
1523
|
-
const
|
|
1523
|
+
const M = n.clone(), P = this.activeSnaps.x || this.activeSnaps.y, k = (P == null ? void 0 : P.frozenFontSize) ?? n.fontSize ?? 0, B = (P == null ? void 0 : P.frozenWidth) ?? ft(n) ?? n.width ?? 0, W = (P == null ? void 0 : P.frozenHeight) ?? Tt(n) ?? n.height ?? 0, F = (P == null ? void 0 : P.frozenPosition) ?? { x: n.x, y: n.y }, D = M.isCropping && !String(o.anchor).startsWith("crop-");
|
|
1524
1524
|
if (!D)
|
|
1525
|
-
if (
|
|
1525
|
+
if (o && o.anchor) {
|
|
1526
1526
|
if (p !== 0) {
|
|
1527
1527
|
const L = (T = this.activeSnaps.x) == null ? void 0 : T.anchorKey, A = L == null ? void 0 : L.toLowerCase();
|
|
1528
|
-
A && A.includes("right") ? this._adjustElementForRightResize(
|
|
1528
|
+
A && A.includes("right") ? this._adjustElementForRightResize(M, p, o) : A && A.includes("left") ? this._adjustElementForLeftResize(M, p, o) : M.x += p;
|
|
1529
1529
|
}
|
|
1530
1530
|
if (g !== 0) {
|
|
1531
1531
|
const L = (R = this.activeSnaps.y) == null ? void 0 : R.anchorKey, A = L == null ? void 0 : L.toLowerCase();
|
|
1532
|
-
A && A.includes("bottom") ? this._adjustElementForBottomResize(
|
|
1532
|
+
A && A.includes("bottom") ? this._adjustElementForBottomResize(M, g, o) : A && A.includes("top") ? this._adjustElementForTopResize(M, g, o) : M.y += g;
|
|
1533
1533
|
}
|
|
1534
1534
|
} else
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
const N =
|
|
1535
|
+
M.x += p, M.y += g;
|
|
1536
|
+
M.fontSize !== void 0 && (M.fontSize = k);
|
|
1537
|
+
const N = M.transformType === "image", j = this.activeSnaps.x !== null || this.activeSnaps.y !== null;
|
|
1538
1538
|
if (N && j) {
|
|
1539
|
-
if (ft(
|
|
1539
|
+
if (ft(M) !== void 0) {
|
|
1540
1540
|
const L = this.activeSnaps.x || this.activeSnaps.y;
|
|
1541
1541
|
let A = B, O = W;
|
|
1542
1542
|
L && (A = L.frozenWidth ?? A, O = L.frozenHeight ?? O);
|
|
1543
|
-
const G = ft(n), E = Tt(n), _ =
|
|
1544
|
-
_ && _ !== 0 && (O = A / _),
|
|
1543
|
+
const G = ft(n), E = Tt(n), _ = M.imageAspectRatio || (G && E ? G / E : null);
|
|
1544
|
+
_ && _ !== 0 && (O = A / _), xt(M, A), Et(M, O), L && (L.frozenWidth = A, L.frozenHeight = O);
|
|
1545
1545
|
}
|
|
1546
1546
|
} else
|
|
1547
|
-
(((C = this.activeSnaps.y) == null ? void 0 : C.isPositionBasedSnap) || !1) && (ft(
|
|
1548
|
-
const H =
|
|
1549
|
-
return (p === 0 || K) && !H && !z && !D && (
|
|
1547
|
+
(((C = this.activeSnaps.y) == null ? void 0 : C.isPositionBasedSnap) || !1) && (ft(M) !== void 0 ? xt(M, B) : M.width !== void 0 && (M.width = B));
|
|
1548
|
+
const H = o && (o.anchor === "middle-left" || o.anchor === "middle-right"), z = o && (o.anchor === "middle-top" || o.anchor === "middle-bottom"), K = ((x = this.activeSnaps.x) == null ? void 0 : x.isPositionBasedSnap) || !1, Q = ((I = this.activeSnaps.y) == null ? void 0 : I.isPositionBasedSnap) || !1;
|
|
1549
|
+
return (p === 0 || K) && !H && !z && !D && (M.x = F.x), (g === 0 || Q) && !z && !H && !D && (M.y = F.y), {
|
|
1550
1550
|
...t,
|
|
1551
|
-
element:
|
|
1551
|
+
element: M,
|
|
1552
1552
|
snapAdjustment: { dx: p, dy: g },
|
|
1553
1553
|
// Flag to indicate we're in sticky snap mode (used to freeze font size)
|
|
1554
1554
|
isInStickySnap: !0
|
|
@@ -1559,16 +1559,16 @@ class nn {
|
|
|
1559
1559
|
/**
|
|
1560
1560
|
* Snap rotation (for future implementation)
|
|
1561
1561
|
*/
|
|
1562
|
-
snapRotation(t, e,
|
|
1562
|
+
snapRotation(t, e, s) {
|
|
1563
1563
|
if (!this.enabled) return t;
|
|
1564
|
-
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;
|
|
1565
1565
|
for (const i of n)
|
|
1566
|
-
if (
|
|
1566
|
+
if (fe(t, i, o))
|
|
1567
1567
|
return i;
|
|
1568
1568
|
return t;
|
|
1569
1569
|
}
|
|
1570
1570
|
}
|
|
1571
|
-
class
|
|
1571
|
+
class rn {
|
|
1572
1572
|
constructor(t = {}) {
|
|
1573
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 = [];
|
|
1574
1574
|
}
|
|
@@ -1600,17 +1600,17 @@ class sn {
|
|
|
1600
1600
|
* Snap position to match consistent spacing patterns
|
|
1601
1601
|
* Returns adjusted position if spacing snap is detected, otherwise returns original position
|
|
1602
1602
|
*/
|
|
1603
|
-
snapToSpacing(t, e,
|
|
1604
|
-
if (!this.enabled || !
|
|
1603
|
+
snapToSpacing(t, e, s) {
|
|
1604
|
+
if (!this.enabled || !s)
|
|
1605
1605
|
return t;
|
|
1606
|
-
const n = Gt,
|
|
1607
|
-
if (
|
|
1606
|
+
const n = Gt, o = s.filter((p) => p.id !== e.id);
|
|
1607
|
+
if (o.length === 0)
|
|
1608
1608
|
return t;
|
|
1609
1609
|
const i = e.clone();
|
|
1610
1610
|
i.x = t.x, i.y = t.y;
|
|
1611
1611
|
const a = i.getVisualBoundingBox(), r = a.x - t.x, l = a.y - t.y;
|
|
1612
1612
|
let h = t.x, c = t.y, d = !1, f = !1;
|
|
1613
|
-
const b =
|
|
1613
|
+
const b = o.filter((p) => {
|
|
1614
1614
|
const g = p.getVisualBoundingBox();
|
|
1615
1615
|
return !(a.x + a.width < g.x || a.x > g.x + g.width);
|
|
1616
1616
|
});
|
|
@@ -1656,7 +1656,7 @@ class sn {
|
|
|
1656
1656
|
}
|
|
1657
1657
|
}
|
|
1658
1658
|
}
|
|
1659
|
-
const u =
|
|
1659
|
+
const u = o.filter((p) => {
|
|
1660
1660
|
const g = p.getVisualBoundingBox();
|
|
1661
1661
|
return !(a.y + a.height < g.y || a.y > g.y + g.height);
|
|
1662
1662
|
});
|
|
@@ -1710,31 +1710,31 @@ class sn {
|
|
|
1710
1710
|
* Also detects consistent spacing patterns (e.g., evenly spaced rows/columns)
|
|
1711
1711
|
* @param showAllMeasurements - When true (Alt key held), shows all spacing measurements, not just to moving element
|
|
1712
1712
|
*/
|
|
1713
|
-
detectSpacing(t, e,
|
|
1713
|
+
detectSpacing(t, e, s = !1) {
|
|
1714
1714
|
if (!this.enabled || !e)
|
|
1715
1715
|
return this.clearIndicators(), [];
|
|
1716
1716
|
const n = e.filter((c) => c.id !== t.id);
|
|
1717
1717
|
if (n.length === 0)
|
|
1718
1718
|
return this.clearIndicators(), [];
|
|
1719
|
-
const
|
|
1719
|
+
const o = t.getVisualBoundingBox(), i = [], a = [], r = [], l = [];
|
|
1720
1720
|
for (const c of n) {
|
|
1721
|
-
const d = c.getVisualBoundingBox(), f =
|
|
1721
|
+
const d = c.getVisualBoundingBox(), f = o.x - (d.x + d.width), b = d.x - (o.x + o.width), u = o.y - (d.y + d.height), p = d.y - (o.y + o.height), g = !(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
1722
|
f >= this.minDistance && f < this.detectionThreshold && g && i.push({ element: c, distance: f }), b >= this.minDistance && b < this.detectionThreshold && g && a.push({ element: c, distance: b }), u >= this.minDistance && u < this.detectionThreshold && y && r.push({ element: c, distance: u }), p >= this.minDistance && p < this.detectionThreshold && y && l.push({ element: c, distance: p });
|
|
1723
1723
|
}
|
|
1724
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);
|
|
1725
1725
|
const h = [];
|
|
1726
|
-
if (
|
|
1726
|
+
if (s) {
|
|
1727
1727
|
const c = this.detectAllMeasurements(t, e);
|
|
1728
1728
|
h.push(...c);
|
|
1729
1729
|
} else {
|
|
1730
1730
|
if (i.length > 0) {
|
|
1731
|
-
const c = this.detectConsistentSpacing(t,
|
|
1731
|
+
const c = this.detectConsistentSpacing(t, o, i, "left", n);
|
|
1732
1732
|
h.push(...c);
|
|
1733
1733
|
}
|
|
1734
1734
|
if (a.length > 0) {
|
|
1735
1735
|
const c = this.detectConsistentSpacing(
|
|
1736
1736
|
t,
|
|
1737
|
-
|
|
1737
|
+
o,
|
|
1738
1738
|
a,
|
|
1739
1739
|
"right",
|
|
1740
1740
|
n
|
|
@@ -1742,13 +1742,13 @@ class sn {
|
|
|
1742
1742
|
h.push(...c);
|
|
1743
1743
|
}
|
|
1744
1744
|
if (r.length > 0) {
|
|
1745
|
-
const c = this.detectConsistentSpacing(t,
|
|
1745
|
+
const c = this.detectConsistentSpacing(t, o, r, "top", n);
|
|
1746
1746
|
h.push(...c);
|
|
1747
1747
|
}
|
|
1748
1748
|
if (l.length > 0) {
|
|
1749
1749
|
const c = this.detectConsistentSpacing(
|
|
1750
1750
|
t,
|
|
1751
|
-
|
|
1751
|
+
o,
|
|
1752
1752
|
l,
|
|
1753
1753
|
"bottom",
|
|
1754
1754
|
n
|
|
@@ -1763,9 +1763,9 @@ class sn {
|
|
|
1763
1763
|
* Shows measurements from the hovered element to other elements within detection threshold
|
|
1764
1764
|
*/
|
|
1765
1765
|
detectAllMeasurements(t, e) {
|
|
1766
|
-
const
|
|
1766
|
+
const s = [], n = t.getVisualBoundingBox(), o = e.filter((l) => l.id !== t.id), i = this.detectionThreshold * 3;
|
|
1767
1767
|
let a = 0, r = 0;
|
|
1768
|
-
for (const l of
|
|
1768
|
+
for (const l of o) {
|
|
1769
1769
|
const h = l.getVisualBoundingBox();
|
|
1770
1770
|
if (Math.min(
|
|
1771
1771
|
Math.abs(n.x - (h.x + h.width)),
|
|
@@ -1780,7 +1780,7 @@ class sn {
|
|
|
1780
1780
|
continue;
|
|
1781
1781
|
let d = 0, f = !1, b = 0, u = 0, p = 0;
|
|
1782
1782
|
const y = -30 * (a % 2 === 0 ? 1 : -1);
|
|
1783
|
-
h.x >= n.x + n.width ? (d = h.x - (n.x + n.width), d >= this.minDistance && (f = !0, b = n.x + n.width, u = h.x, p = (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, b = h.x + h.width, u = n.x, p = (n.y + n.height / 2 + h.y + h.height / 2) / 2 + y)), f && (
|
|
1783
|
+
h.x >= n.x + n.width ? (d = h.x - (n.x + n.width), d >= this.minDistance && (f = !0, b = n.x + n.width, u = h.x, p = (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, b = h.x + h.width, u = n.x, p = (n.y + n.height / 2 + h.y + h.height / 2) / 2 + y)), f && (s.push({
|
|
1784
1784
|
type: "horizontal",
|
|
1785
1785
|
distance: Math.round(d),
|
|
1786
1786
|
x1: b,
|
|
@@ -1791,8 +1791,8 @@ class sn {
|
|
|
1791
1791
|
isAltHover: !0
|
|
1792
1792
|
}), a++);
|
|
1793
1793
|
let S = 0, m = !1, w = 0, T = 0, R = 0;
|
|
1794
|
-
const
|
|
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 +
|
|
1794
|
+
const x = 30 * (r % 2 === 0 ? 1 : -1);
|
|
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, R = 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, R = n.y)), m && (s.push({
|
|
1796
1796
|
type: "vertical",
|
|
1797
1797
|
distance: Math.round(S),
|
|
1798
1798
|
x: w,
|
|
@@ -1803,16 +1803,16 @@ class sn {
|
|
|
1803
1803
|
isAltHover: !0
|
|
1804
1804
|
}), r++);
|
|
1805
1805
|
}
|
|
1806
|
-
return
|
|
1806
|
+
return s;
|
|
1807
1807
|
}
|
|
1808
1808
|
/**
|
|
1809
1809
|
* Detect consistent spacing patterns (e.g., evenly spaced rows/columns)
|
|
1810
1810
|
* and create indicators for all matching spacings
|
|
1811
1811
|
*/
|
|
1812
|
-
detectConsistentSpacing(t, e,
|
|
1813
|
-
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);
|
|
1814
1814
|
if (this.addIndicatorForDirection(i, e, h, l, n, c), n === "left" || n === "right") {
|
|
1815
|
-
const d =
|
|
1815
|
+
const d = o.filter((f) => {
|
|
1816
1816
|
if (f.id === t.id) return !1;
|
|
1817
1817
|
const b = f.getVisualBoundingBox();
|
|
1818
1818
|
return !(e.y + e.height < b.y || e.y > b.y + b.height);
|
|
@@ -1853,7 +1853,7 @@ class sn {
|
|
|
1853
1853
|
}
|
|
1854
1854
|
}
|
|
1855
1855
|
} else {
|
|
1856
|
-
const d =
|
|
1856
|
+
const d = o.filter((f) => {
|
|
1857
1857
|
if (f.id === t.id) return !1;
|
|
1858
1858
|
const b = f.getVisualBoundingBox();
|
|
1859
1859
|
return !(e.x + e.width < b.x || e.x > b.x + b.width);
|
|
@@ -1899,9 +1899,9 @@ class sn {
|
|
|
1899
1899
|
/**
|
|
1900
1900
|
* Check if spacing would snap to a pattern
|
|
1901
1901
|
*/
|
|
1902
|
-
checkIfWouldSnap(t, e,
|
|
1903
|
-
const
|
|
1904
|
-
if (
|
|
1902
|
+
checkIfWouldSnap(t, e, s, n) {
|
|
1903
|
+
const o = Gt;
|
|
1904
|
+
if (s === "top" || s === "bottom") {
|
|
1905
1905
|
const i = n.filter((a) => {
|
|
1906
1906
|
const r = a.getVisualBoundingBox();
|
|
1907
1907
|
return !(t.x + t.width < r.x || t.x > r.x + r.width);
|
|
@@ -1918,7 +1918,7 @@ class sn {
|
|
|
1918
1918
|
}
|
|
1919
1919
|
if (a.length > 0) {
|
|
1920
1920
|
const r = a.reduce((c, d) => c + d, 0) / a.length;
|
|
1921
|
-
return Math.abs(e - r) <=
|
|
1921
|
+
return Math.abs(e - r) <= o;
|
|
1922
1922
|
}
|
|
1923
1923
|
}
|
|
1924
1924
|
return !1;
|
|
@@ -1939,7 +1939,7 @@ class sn {
|
|
|
1939
1939
|
}
|
|
1940
1940
|
if (a.length > 0) {
|
|
1941
1941
|
const r = a.reduce((c, d) => c + d, 0) / a.length;
|
|
1942
|
-
return Math.abs(e - r) <=
|
|
1942
|
+
return Math.abs(e - r) <= o;
|
|
1943
1943
|
}
|
|
1944
1944
|
}
|
|
1945
1945
|
return !1;
|
|
@@ -1948,59 +1948,59 @@ class sn {
|
|
|
1948
1948
|
/**
|
|
1949
1949
|
* Helper method to add a spacing indicator in a specific direction
|
|
1950
1950
|
*/
|
|
1951
|
-
addIndicatorForDirection(t, e,
|
|
1952
|
-
if (
|
|
1953
|
-
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;
|
|
1954
1954
|
t.push({
|
|
1955
1955
|
type: "horizontal",
|
|
1956
1956
|
distance: Math.round(n),
|
|
1957
|
-
x1:
|
|
1957
|
+
x1: s.x + s.width,
|
|
1958
1958
|
x2: e.x,
|
|
1959
1959
|
y: l,
|
|
1960
|
-
labelX: (
|
|
1960
|
+
labelX: (s.x + s.width + e.x) / 2,
|
|
1961
1961
|
labelY: l,
|
|
1962
1962
|
isSnapTarget: i
|
|
1963
1963
|
});
|
|
1964
|
-
} else if (
|
|
1965
|
-
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;
|
|
1966
1966
|
t.push({
|
|
1967
1967
|
type: "horizontal",
|
|
1968
1968
|
distance: Math.round(n),
|
|
1969
1969
|
x1: e.x + e.width,
|
|
1970
|
-
x2:
|
|
1970
|
+
x2: s.x,
|
|
1971
1971
|
y: l,
|
|
1972
|
-
labelX: (e.x + e.width +
|
|
1972
|
+
labelX: (e.x + e.width + s.x) / 2,
|
|
1973
1973
|
labelY: l,
|
|
1974
1974
|
isSnapTarget: i
|
|
1975
1975
|
});
|
|
1976
|
-
} else if (
|
|
1977
|
-
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;
|
|
1978
1978
|
t.push({
|
|
1979
1979
|
type: "vertical",
|
|
1980
1980
|
distance: Math.round(n),
|
|
1981
1981
|
x: l,
|
|
1982
|
-
y1:
|
|
1982
|
+
y1: s.y + s.height,
|
|
1983
1983
|
y2: e.y,
|
|
1984
1984
|
labelX: l,
|
|
1985
|
-
labelY: (
|
|
1985
|
+
labelY: (s.y + s.height + e.y) / 2,
|
|
1986
1986
|
isSnapTarget: i
|
|
1987
1987
|
});
|
|
1988
|
-
} else if (
|
|
1989
|
-
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;
|
|
1990
1990
|
t.push({
|
|
1991
1991
|
type: "vertical",
|
|
1992
1992
|
distance: Math.round(n),
|
|
1993
1993
|
x: l,
|
|
1994
1994
|
y1: e.y + e.height,
|
|
1995
|
-
y2:
|
|
1995
|
+
y2: s.y,
|
|
1996
1996
|
labelX: l,
|
|
1997
|
-
labelY: (e.y + e.height +
|
|
1997
|
+
labelY: (e.y + e.height + s.y) / 2,
|
|
1998
1998
|
isSnapTarget: i
|
|
1999
1999
|
});
|
|
2000
2000
|
}
|
|
2001
2001
|
}
|
|
2002
2002
|
}
|
|
2003
|
-
const zt =
|
|
2003
|
+
const zt = Qt("ArtboardRenderer"), $e = {
|
|
2004
2004
|
showLabel: !0,
|
|
2005
2005
|
showBorder: !0,
|
|
2006
2006
|
borderColor: "",
|
|
@@ -2018,15 +2018,15 @@ const zt = Jt("ArtboardRenderer"), Ne = {
|
|
|
2018
2018
|
borderRadius: 0
|
|
2019
2019
|
// Default to no border radius (sharp corners)
|
|
2020
2020
|
};
|
|
2021
|
-
class
|
|
2021
|
+
class oe {
|
|
2022
2022
|
constructor(t = {}) {
|
|
2023
|
-
this.options = {
|
|
2023
|
+
this.options = { ...$e, ...t };
|
|
2024
2024
|
}
|
|
2025
2025
|
/**
|
|
2026
2026
|
* Render an artboard
|
|
2027
2027
|
*/
|
|
2028
|
-
render(t, e,
|
|
2029
|
-
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();
|
|
2030
2030
|
}
|
|
2031
2031
|
/**
|
|
2032
2032
|
* Render artboard background
|
|
@@ -2042,69 +2042,69 @@ class se {
|
|
|
2042
2042
|
* Renders preset color as base layer, then texture on top
|
|
2043
2043
|
*/
|
|
2044
2044
|
renderTextureBackground(t, e) {
|
|
2045
|
-
const
|
|
2046
|
-
if (t.fillStyle = n, t.fillRect(e.x, e.y, e.width, e.height), !
|
|
2047
|
-
Wt.loadTexture(e.backgroundTexture).catch((
|
|
2048
|
-
zt.error("Failed to load texture:",
|
|
2045
|
+
const s = Wt.getTexture(e.backgroundTexture), n = Wt.getTexturePresetColor(e.backgroundTexture);
|
|
2046
|
+
if (t.fillStyle = n, t.fillRect(e.x, e.y, e.width, e.height), !s || !s.complete) {
|
|
2047
|
+
Wt.loadTexture(e.backgroundTexture).catch((o) => {
|
|
2048
|
+
zt.error("Failed to load texture:", o);
|
|
2049
2049
|
});
|
|
2050
2050
|
return;
|
|
2051
2051
|
}
|
|
2052
|
-
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();
|
|
2053
2053
|
}
|
|
2054
2054
|
/**
|
|
2055
2055
|
* Render a checkerboard pattern for transparent backgrounds
|
|
2056
2056
|
*/
|
|
2057
|
-
renderCheckerboard(t, e,
|
|
2057
|
+
renderCheckerboard(t, e, s, n, o) {
|
|
2058
2058
|
const a = "#ffffff", r = "#d0d0d0";
|
|
2059
|
-
t.save(), t.beginPath(), t.rect(e,
|
|
2060
|
-
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++)
|
|
2061
2061
|
for (let h = 0; h < Math.ceil(n / 16); h++)
|
|
2062
|
-
(l + h) % 2 === 1 && t.fillRect(e + h * 16,
|
|
2062
|
+
(l + h) % 2 === 1 && t.fillRect(e + h * 16, s + l * 16, 16, 16);
|
|
2063
2063
|
t.restore();
|
|
2064
2064
|
}
|
|
2065
2065
|
/**
|
|
2066
2066
|
* Render artboard border (respects clipShape and borderRadius option)
|
|
2067
2067
|
*/
|
|
2068
|
-
renderBorder(t, e,
|
|
2069
|
-
const { x: n, y:
|
|
2070
|
-
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 || ge(), h = this.options.selectedBorderColor || nt();
|
|
2070
|
+
if (t.strokeStyle = s ? h : l, t.lineWidth = s ? this.options.selectedBorderWidth : this.options.borderWidth, t.beginPath(), !r || r === "rectangle")
|
|
2071
2071
|
if (this.options.borderRadius > 0) {
|
|
2072
2072
|
const c = Math.min(this.options.borderRadius, Math.min(i, a) / 2);
|
|
2073
|
-
this.roundedRect(t, n,
|
|
2073
|
+
this.roundedRect(t, n, o, i, a, c);
|
|
2074
2074
|
} else
|
|
2075
|
-
t.rect(n,
|
|
2075
|
+
t.rect(n, o, i, a);
|
|
2076
2076
|
else if (r === "circle") {
|
|
2077
|
-
const c = n + i / 2, d =
|
|
2077
|
+
const c = n + i / 2, d = o + a / 2, f = Math.min(i, a) / 2;
|
|
2078
2078
|
t.arc(c, d, f, 0, Math.PI * 2);
|
|
2079
2079
|
} else if (typeof r == "object" && r.type === "rounded") {
|
|
2080
2080
|
const c = Math.min(r.radius, Math.min(i, a) / 2);
|
|
2081
|
-
this.roundedRect(t, n,
|
|
2081
|
+
this.roundedRect(t, n, o, i, a, c);
|
|
2082
2082
|
} else if (typeof r == "object" && r.type === "path")
|
|
2083
2083
|
try {
|
|
2084
2084
|
const c = new Path2D(r.d);
|
|
2085
|
-
t.save(), t.translate(n,
|
|
2085
|
+
t.save(), t.translate(n, o), t.stroke(c), t.restore();
|
|
2086
2086
|
return;
|
|
2087
2087
|
} catch (c) {
|
|
2088
|
-
zt.warn("Invalid SVG path for border, falling back to rectangle:", c), t.rect(n,
|
|
2088
|
+
zt.warn("Invalid SVG path for border, falling back to rectangle:", c), t.rect(n, o, i, a);
|
|
2089
2089
|
}
|
|
2090
2090
|
t.stroke();
|
|
2091
2091
|
}
|
|
2092
2092
|
/**
|
|
2093
2093
|
* Render artboard label (name + dimensions)
|
|
2094
2094
|
*/
|
|
2095
|
-
renderLabel(t, e,
|
|
2096
|
-
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;
|
|
2097
2097
|
t.font = `${n}px -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif`;
|
|
2098
|
-
const l = this.options.selectedBorderColor || nt(), h = this.options.labelColor ||
|
|
2099
|
-
t.fillStyle =
|
|
2098
|
+
const l = this.options.selectedBorderColor || nt(), h = this.options.labelColor || ue();
|
|
2099
|
+
t.fillStyle = s ? l : h, t.textAlign = "left", t.textBaseline = "bottom", t.fillText(i, a, r);
|
|
2100
2100
|
}
|
|
2101
2101
|
/**
|
|
2102
2102
|
* Render multiple artboards
|
|
2103
2103
|
*/
|
|
2104
|
-
renderMultiple(t, e,
|
|
2104
|
+
renderMultiple(t, e, s) {
|
|
2105
2105
|
e.forEach((n) => {
|
|
2106
|
-
const
|
|
2107
|
-
this.render(t, n,
|
|
2106
|
+
const o = n.id === s;
|
|
2107
|
+
this.render(t, n, o);
|
|
2108
2108
|
});
|
|
2109
2109
|
}
|
|
2110
2110
|
/**
|
|
@@ -2120,26 +2120,26 @@ class se {
|
|
|
2120
2120
|
* If borderRadius option is set and no special clipShape, uses rounded rectangle
|
|
2121
2121
|
*/
|
|
2122
2122
|
applyClipPath(t, e) {
|
|
2123
|
-
const { x:
|
|
2123
|
+
const { x: s, y: n, width: o, height: i, clipShape: a } = e;
|
|
2124
2124
|
if (this.options.borderRadius > 0, t.beginPath(), !a || a === "rectangle")
|
|
2125
2125
|
if (this.options.borderRadius > 0) {
|
|
2126
|
-
const r = Math.min(this.options.borderRadius, Math.min(
|
|
2127
|
-
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);
|
|
2128
2128
|
} else
|
|
2129
|
-
t.rect(
|
|
2129
|
+
t.rect(s, n, o, i);
|
|
2130
2130
|
else if (a === "circle") {
|
|
2131
|
-
const r =
|
|
2131
|
+
const r = s + o / 2, l = n + i / 2, h = Math.min(o, i) / 2;
|
|
2132
2132
|
t.arc(r, l, h, 0, Math.PI * 2);
|
|
2133
2133
|
} else if (typeof a == "object" && a.type === "rounded") {
|
|
2134
|
-
const r = Math.min(a.radius, Math.min(
|
|
2135
|
-
this.roundedRect(t,
|
|
2134
|
+
const r = Math.min(a.radius, Math.min(o, i) / 2);
|
|
2135
|
+
this.roundedRect(t, s, n, o, i, r);
|
|
2136
2136
|
} else if (typeof a == "object" && a.type === "path")
|
|
2137
2137
|
try {
|
|
2138
2138
|
const r = new Path2D(a.d);
|
|
2139
|
-
t.translate(
|
|
2139
|
+
t.translate(s, n), t.clip(r), t.translate(-s, -n);
|
|
2140
2140
|
return;
|
|
2141
2141
|
} catch (r) {
|
|
2142
|
-
zt.warn("Invalid SVG path, falling back to rectangle:", r), t.rect(
|
|
2142
|
+
zt.warn("Invalid SVG path, falling back to rectangle:", r), t.rect(s, n, o, i);
|
|
2143
2143
|
}
|
|
2144
2144
|
t.clip();
|
|
2145
2145
|
}
|
|
@@ -2147,8 +2147,8 @@ class se {
|
|
|
2147
2147
|
* Draw a rounded rectangle path
|
|
2148
2148
|
* Helper method for rounded clip shapes
|
|
2149
2149
|
*/
|
|
2150
|
-
roundedRect(t, e,
|
|
2151
|
-
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));
|
|
2152
2152
|
}
|
|
2153
2153
|
/**
|
|
2154
2154
|
* Restore after clipping
|
|
@@ -2159,21 +2159,21 @@ class se {
|
|
|
2159
2159
|
/**
|
|
2160
2160
|
* Render artboard outline (for dragging/resizing preview)
|
|
2161
2161
|
*/
|
|
2162
|
-
renderOutline(t, e,
|
|
2163
|
-
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();
|
|
2164
2164
|
}
|
|
2165
2165
|
/**
|
|
2166
2166
|
* Render resize handles for artboard
|
|
2167
2167
|
*/
|
|
2168
2168
|
renderResizeHandles(t, e) {
|
|
2169
|
-
const { x: n, y:
|
|
2170
|
-
{ x: n, y:
|
|
2169
|
+
const { x: n, y: o, width: i, height: a } = e, r = [
|
|
2170
|
+
{ x: n, y: o },
|
|
2171
2171
|
// top-left
|
|
2172
|
-
{ x: n + i, y:
|
|
2172
|
+
{ x: n + i, y: o },
|
|
2173
2173
|
// top-right
|
|
2174
|
-
{ x: n, y:
|
|
2174
|
+
{ x: n, y: o + a },
|
|
2175
2175
|
// bottom-left
|
|
2176
|
-
{ x: n + i, y:
|
|
2176
|
+
{ x: n + i, y: o + a }
|
|
2177
2177
|
// bottom-right
|
|
2178
2178
|
];
|
|
2179
2179
|
t.save(), r.forEach((l) => {
|
|
@@ -2198,7 +2198,7 @@ class se {
|
|
|
2198
2198
|
* Use this when exporting to ensure preview background is never included
|
|
2199
2199
|
*/
|
|
2200
2200
|
static createForExport(t = {}) {
|
|
2201
|
-
return new
|
|
2201
|
+
return new oe({
|
|
2202
2202
|
...t,
|
|
2203
2203
|
showPreviewBackground: !1
|
|
2204
2204
|
// CRITICAL: Never show preview in exports
|
|
@@ -2211,12 +2211,44 @@ class se {
|
|
|
2211
2211
|
return !!(this.options.showPreviewBackground && t.previewBackgroundColor && t.previewBackgroundColor !== "transparent");
|
|
2212
2212
|
}
|
|
2213
2213
|
}
|
|
2214
|
+
function je(v) {
|
|
2215
|
+
const t = (v % 360 + 360) % 360;
|
|
2216
|
+
if (t === 0) return [1, 0];
|
|
2217
|
+
if (t === 90) return [0, 1];
|
|
2218
|
+
if (t === 180) return [-1, 0];
|
|
2219
|
+
if (t === 270) return [0, -1];
|
|
2220
|
+
const e = t * Math.PI / 180;
|
|
2221
|
+
return [Math.cos(e), Math.sin(e)];
|
|
2222
|
+
}
|
|
2223
|
+
function Zt(v, t, e) {
|
|
2224
|
+
const [s, n] = je(e);
|
|
2225
|
+
return { width: Math.abs(v * s) + Math.abs(t * n), height: Math.abs(v * n) + Math.abs(t * s) };
|
|
2226
|
+
}
|
|
2227
|
+
function ie(v) {
|
|
2228
|
+
if (v.naturalWidth && v.naturalHeight) return { width: v.naturalWidth, height: v.naturalHeight };
|
|
2229
|
+
const t = ((v.rotation ?? 0) % 360 + 360) % 360;
|
|
2230
|
+
if (t % 90 !== 0)
|
|
2231
|
+
throw new Error(`E_PIECE_NATURAL_DIMS: piece "${v.id ?? "?"}" is turned ${t}° but carries no naturalWidth/naturalHeight — the displayed box of a non-right angle doesn't determine them. Send them with the piece (the /piece-guides endpoint does)`);
|
|
2232
|
+
return t === 90 || t === 270 ? { width: v.height, height: v.width } : { width: v.width, height: v.height };
|
|
2233
|
+
}
|
|
2234
|
+
function ln(v) {
|
|
2235
|
+
const t = ((v.rotation ?? 0) % 360 + 360) % 360;
|
|
2236
|
+
if (!t) return "";
|
|
2237
|
+
const e = ie(v);
|
|
2238
|
+
return `translate(${v.width / 2} ${v.height / 2}) rotate(${t}) translate(${-e.width / 2} ${-e.height / 2})`;
|
|
2239
|
+
}
|
|
2240
|
+
function hn(v, t) {
|
|
2241
|
+
const e = ((t.rotation ?? 0) % 360 + 360) % 360;
|
|
2242
|
+
if (!e) return;
|
|
2243
|
+
const s = ie(t);
|
|
2244
|
+
v.translate(t.width / 2, t.height / 2), v.rotate(e * Math.PI / 180), v.translate(-s.width / 2, -s.height / 2);
|
|
2245
|
+
}
|
|
2214
2246
|
class wt {
|
|
2215
2247
|
/**
|
|
2216
2248
|
* Render selection box layer
|
|
2217
2249
|
*/
|
|
2218
|
-
static renderSelectionLayer(t, e,
|
|
2219
|
-
if (!e || e.visible === !1 ||
|
|
2250
|
+
static renderSelectionLayer(t, e, s, n = 1) {
|
|
2251
|
+
if (!e || e.visible === !1 || s && s.getMode() === "drag" || "isGroup" in e && e.isGroup) return;
|
|
2220
2252
|
const i = e.getVisualBoundingBox(), a = e.getRotationAnchor();
|
|
2221
2253
|
t.save(), t.strokeStyle = nt(t.canvas), t.lineWidth = 2, t.translate(a.x * n, a.y * n), t.rotate(gt.toRadians(e.rotation)), t.translate(-a.x * n, -a.y * n);
|
|
2222
2254
|
const r = ct.canvas.selectionPadding;
|
|
@@ -2231,31 +2263,31 @@ class wt {
|
|
|
2231
2263
|
* Render position and size info below the selected element
|
|
2232
2264
|
* Only shows dimensions (width x height) while resizing
|
|
2233
2265
|
*/
|
|
2234
|
-
static renderPositionSizeInfo(t, e,
|
|
2235
|
-
if (!e || !(
|
|
2236
|
-
const i = e.getVisualBoundingBox(), a = Math.round(i.width), r = Math.round(i.height), l = `${a} × ${r}`, h =
|
|
2266
|
+
static renderPositionSizeInfo(t, e, s, n, o = 1) {
|
|
2267
|
+
if (!e || !(s != null && s.rotationHandle) || (n == null ? void 0 : n.getMode()) !== "resize") return;
|
|
2268
|
+
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;
|
|
2237
2269
|
t.save(), t.font = "10px system-ui, -apple-system, sans-serif";
|
|
2238
2270
|
const b = t.measureText(l).width + 12, u = 18;
|
|
2239
|
-
t.shadowColor =
|
|
2271
|
+
t.shadowColor = pe(t.canvas), t.shadowBlur = 4, t.shadowOffsetY = 1, t.fillStyle = ye(t.canvas), t.beginPath(), t.roundRect(
|
|
2240
2272
|
c - b / 2,
|
|
2241
2273
|
d - u / 2,
|
|
2242
2274
|
b,
|
|
2243
2275
|
u,
|
|
2244
2276
|
3
|
|
2245
2277
|
// Smaller border radius
|
|
2246
|
-
), t.fill(), t.shadowColor = "transparent", t.shadowBlur = 0, t.shadowOffsetY = 0, t.fillStyle =
|
|
2278
|
+
), t.fill(), t.shadowColor = "transparent", t.shadowBlur = 0, t.shadowOffsetY = 0, t.fillStyle = be(t.canvas), t.textAlign = "center", t.textBaseline = "middle", t.fillText(l, c, d + 0.5), t.restore();
|
|
2247
2279
|
}
|
|
2248
2280
|
/**
|
|
2249
2281
|
* Render transform handles layer
|
|
2250
2282
|
*/
|
|
2251
|
-
static renderHandlesLayer(t, e,
|
|
2283
|
+
static renderHandlesLayer(t, e, s, n, o, i, a, r = 1, l = !0) {
|
|
2252
2284
|
if (!e || e.visible === !1 || a.getMode() === "drag") return;
|
|
2253
2285
|
const c = i.type === "rotation-handle", d = i.type === "resize-handle" ? i.data : null, f = a.getMode() === "resize", b = f ? a.getActiveHandle() : null;
|
|
2254
|
-
|
|
2286
|
+
s.render(
|
|
2255
2287
|
t,
|
|
2256
2288
|
l,
|
|
2257
2289
|
n,
|
|
2258
|
-
|
|
2290
|
+
o,
|
|
2259
2291
|
c,
|
|
2260
2292
|
d,
|
|
2261
2293
|
f,
|
|
@@ -2271,8 +2303,8 @@ class Ft {
|
|
|
2271
2303
|
* Render hover highlights layer with fade-in animation
|
|
2272
2304
|
* Outlines the actual element shape instead of a rectangular border
|
|
2273
2305
|
*/
|
|
2274
|
-
static renderHoverLayer(t, e,
|
|
2275
|
-
if (e.type !== "element" || !e.data || e.data.id ===
|
|
2306
|
+
static renderHoverLayer(t, e, s, n = !1, o = 1, i) {
|
|
2307
|
+
if (e.type !== "element" || !e.data || e.data.id === s) return;
|
|
2276
2308
|
const a = e.data;
|
|
2277
2309
|
t.save();
|
|
2278
2310
|
const r = 150, l = 0.5;
|
|
@@ -2281,24 +2313,24 @@ class Ft {
|
|
|
2281
2313
|
const c = performance.now() - e.startTime;
|
|
2282
2314
|
h = Math.min(c / r, 1) * l;
|
|
2283
2315
|
}
|
|
2284
|
-
t.strokeStyle =
|
|
2316
|
+
t.strokeStyle = Se(t.canvas), t.globalAlpha = h, t.lineWidth = 3, this.renderElementOutline(t, a, o, i), t.restore();
|
|
2285
2317
|
}
|
|
2286
2318
|
/**
|
|
2287
2319
|
* Render outline for a specific element type
|
|
2288
2320
|
*/
|
|
2289
|
-
static renderElementOutline(t, e,
|
|
2290
|
-
const
|
|
2291
|
-
t.translate(
|
|
2321
|
+
static renderElementOutline(t, e, s = 1, n) {
|
|
2322
|
+
const o = e.getRotationAnchor();
|
|
2323
|
+
t.translate(o.x * s, o.y * s), t.rotate(gt.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);
|
|
2292
2324
|
}
|
|
2293
2325
|
/**
|
|
2294
2326
|
* Render outline for shape elements (star, rectangle, circle, etc.)
|
|
2295
2327
|
* Creates a ring effect with a gap between the element and the stroke
|
|
2296
2328
|
*/
|
|
2297
|
-
static renderShapeOutline(t, e,
|
|
2298
|
-
const n = e.transformData,
|
|
2299
|
-
switch (t.save(), t.translate(e.x *
|
|
2329
|
+
static renderShapeOutline(t, e, s) {
|
|
2330
|
+
const n = e.transformData, o = n.width * s, i = n.height * s, a = 2, l = a + a / 2;
|
|
2331
|
+
switch (t.save(), t.translate(e.x * s, e.y * s), t.beginPath(), n.shapeType) {
|
|
2300
2332
|
case "rectangle": {
|
|
2301
|
-
const h = n.borderRadius || 0, c = -(
|
|
2333
|
+
const h = n.borderRadius || 0, c = -(o + l * 2) / 2, d = -(i + l * 2) / 2, f = o + l * 2, b = i + l * 2;
|
|
2302
2334
|
if (h > 0) {
|
|
2303
2335
|
const u = Math.min(h / 100 * Math.min(f, b), f / 2, b / 2);
|
|
2304
2336
|
t.roundRect(c, d, f, b, u);
|
|
@@ -2307,17 +2339,17 @@ class Ft {
|
|
|
2307
2339
|
break;
|
|
2308
2340
|
}
|
|
2309
2341
|
case "circle": {
|
|
2310
|
-
const h = Math.min(
|
|
2342
|
+
const h = Math.min(o, i) / 2 + l;
|
|
2311
2343
|
t.arc(0, 0, h, 0, Math.PI * 2);
|
|
2312
2344
|
break;
|
|
2313
2345
|
}
|
|
2314
2346
|
case "ellipse": {
|
|
2315
|
-
const h = (n.radiusX ??
|
|
2347
|
+
const h = (n.radiusX ?? o / 2) + l, c = (n.radiusY ?? i / 2) + l;
|
|
2316
2348
|
t.ellipse(0, 0, h, c, 0, 0, Math.PI * 2);
|
|
2317
2349
|
break;
|
|
2318
2350
|
}
|
|
2319
2351
|
case "triangle": {
|
|
2320
|
-
const h =
|
|
2352
|
+
const h = o / 2, c = i / 2, d = [
|
|
2321
2353
|
{ x: 0, y: -c },
|
|
2322
2354
|
// top
|
|
2323
2355
|
{ x: h, y: c },
|
|
@@ -2338,7 +2370,7 @@ class Ft {
|
|
|
2338
2370
|
break;
|
|
2339
2371
|
}
|
|
2340
2372
|
case "star": {
|
|
2341
|
-
const h = n.points ?? 5, c = n.innerRadius ?? 0.4, d = Math.min(
|
|
2373
|
+
const h = n.points ?? 5, c = n.innerRadius ?? 0.4, d = Math.min(o, i) / 2 + l, f = d * c;
|
|
2342
2374
|
for (let b = 0; b < h * 2; b++) {
|
|
2343
2375
|
const u = b * Math.PI / h - Math.PI / 2, p = b % 2 === 0 ? d : f, g = p * Math.cos(u), y = p * Math.sin(u);
|
|
2344
2376
|
b === 0 ? t.moveTo(g, y) : t.lineTo(g, y);
|
|
@@ -2347,7 +2379,7 @@ class Ft {
|
|
|
2347
2379
|
break;
|
|
2348
2380
|
}
|
|
2349
2381
|
case "polygon": {
|
|
2350
|
-
const h = n.sides ?? 5, c = Math.min(
|
|
2382
|
+
const h = n.sides ?? 5, c = Math.min(o, i) / 2 + l;
|
|
2351
2383
|
for (let d = 0; d < h; d++) {
|
|
2352
2384
|
const f = d * 2 * Math.PI / h - Math.PI / 2, b = c * Math.cos(f), u = c * Math.sin(f);
|
|
2353
2385
|
d === 0 ? t.moveTo(b, u) : t.lineTo(b, u);
|
|
@@ -2356,7 +2388,7 @@ class Ft {
|
|
|
2356
2388
|
break;
|
|
2357
2389
|
}
|
|
2358
2390
|
case "line": {
|
|
2359
|
-
const h =
|
|
2391
|
+
const h = o / 2 + l;
|
|
2360
2392
|
t.moveTo(-h, 0), t.lineTo(h, 0);
|
|
2361
2393
|
break;
|
|
2362
2394
|
}
|
|
@@ -2367,11 +2399,11 @@ class Ft {
|
|
|
2367
2399
|
* Render outline for image elements
|
|
2368
2400
|
* Creates a ring effect with a gap between the element and the stroke
|
|
2369
2401
|
*/
|
|
2370
|
-
static renderImageOutline(t, e,
|
|
2402
|
+
static renderImageOutline(t, e, s) {
|
|
2371
2403
|
var u;
|
|
2372
|
-
const n = e.getVisualBoundingBox(),
|
|
2373
|
-
t.save(), t.translate(e.x *
|
|
2374
|
-
const c = -(
|
|
2404
|
+
const n = e.getVisualBoundingBox(), o = n.width * s, i = n.height * s, a = ((u = e.transformData) == null ? void 0 : u.borderRadius) || 0, r = 2, h = r + r / 2;
|
|
2405
|
+
t.save(), t.translate(e.x * s, e.y * s);
|
|
2406
|
+
const c = -(o + h * 2) / 2, d = -(i + h * 2) / 2, f = o + h * 2, b = i + h * 2;
|
|
2375
2407
|
if (t.beginPath(), a > 0) {
|
|
2376
2408
|
const p = Math.min(a / 100 * Math.min(f, b), f / 2, b / 2);
|
|
2377
2409
|
t.roundRect(c, d, f, b, p);
|
|
@@ -2383,8 +2415,8 @@ class Ft {
|
|
|
2383
2415
|
* Render outline for group elements
|
|
2384
2416
|
* Creates a ring effect with a gap between the element and the stroke
|
|
2385
2417
|
*/
|
|
2386
|
-
static renderGroupOutline(t, e,
|
|
2387
|
-
const n = e.getVisualBoundingBox(),
|
|
2418
|
+
static renderGroupOutline(t, e, s) {
|
|
2419
|
+
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;
|
|
2388
2420
|
t.save(), t.setLineDash([5, 5]), t.beginPath(), t.roundRect(r, l, h, c, 8), t.stroke(), t.restore();
|
|
2389
2421
|
}
|
|
2390
2422
|
/**
|
|
@@ -2392,9 +2424,9 @@ class Ft {
|
|
|
2392
2424
|
* Creates a ring effect with a gap between text and stroke (ring behind text fill)
|
|
2393
2425
|
* Supports all transform types: custom, circle, wave, arch, etc.
|
|
2394
2426
|
*/
|
|
2395
|
-
static renderTextOutline(t, e,
|
|
2396
|
-
const
|
|
2397
|
-
|
|
2427
|
+
static renderTextOutline(t, e, s, n) {
|
|
2428
|
+
const o = e.transformType;
|
|
2429
|
+
o === "circle" || o === "wave" || o === "arch" || o === "lean" || o === "ascend" || o === "flag" ? this.renderTransformHoverRingEffect(t, e, s) : this.renderHoverRingEffect(t, e, s);
|
|
2398
2430
|
}
|
|
2399
2431
|
/**
|
|
2400
2432
|
* HOVER RING EFFECT for straight/custom text
|
|
@@ -2407,9 +2439,9 @@ class Ft {
|
|
|
2407
2439
|
* - Element stroke (StrokeRenderer.ts - only when stroke.enabled = true)
|
|
2408
2440
|
* - Selection box (dashed rectangle in element.render())
|
|
2409
2441
|
*/
|
|
2410
|
-
static renderHoverRingEffect(t, e,
|
|
2411
|
-
t.save(), t.translate(e.x *
|
|
2412
|
-
const n = e.fontSize,
|
|
2442
|
+
static renderHoverRingEffect(t, e, s) {
|
|
2443
|
+
t.save(), t.translate(e.x * s, e.y * s), s !== 1 && t.scale(s, s);
|
|
2444
|
+
const n = e.fontSize, o = e.fontFamily, i = e.bold || !1, a = e.italic || !1, r = e.textAlign || "center", l = te(n, o, i, a), h = n * (e.lineHeight ?? 1.2), c = e.letterSpacing ?? 0, d = 4 / s, f = 4 / s, b = document.createElement("canvas");
|
|
2413
2445
|
b.width = t.canvas.width, b.height = t.canvas.height;
|
|
2414
2446
|
const u = b.getContext("2d");
|
|
2415
2447
|
if (!u) {
|
|
@@ -2419,18 +2451,18 @@ class Ft {
|
|
|
2419
2451
|
u.setTransform(t.getTransform()), u.textBaseline = "alphabetic", u.lineJoin = "round";
|
|
2420
2452
|
const p = e.getRichText ? e.getRichText() : null;
|
|
2421
2453
|
if (p) {
|
|
2422
|
-
const g =
|
|
2454
|
+
const g = ee(p), y = [], S = [];
|
|
2423
2455
|
g.forEach((T) => {
|
|
2424
2456
|
if (e.transformType === "custom" && e.transformData) {
|
|
2425
|
-
const R = e.transformData.width - pt * 2, C =
|
|
2457
|
+
const R = e.transformData.width - pt * 2, C = ne(T, R, {
|
|
2426
2458
|
fontSize: n,
|
|
2427
|
-
fontFamily:
|
|
2459
|
+
fontFamily: o,
|
|
2428
2460
|
bold: i,
|
|
2429
2461
|
italic: a,
|
|
2430
2462
|
letterSpacing: e.letterSpacing
|
|
2431
2463
|
});
|
|
2432
|
-
C.forEach((
|
|
2433
|
-
y.push(
|
|
2464
|
+
C.forEach((x, I) => {
|
|
2465
|
+
y.push(x), S.push({
|
|
2434
2466
|
isParagraphStart: I === 0,
|
|
2435
2467
|
isParagraphEnd: I === C.length - 1
|
|
2436
2468
|
});
|
|
@@ -2446,20 +2478,20 @@ class Ft {
|
|
|
2446
2478
|
const w = -m / 2;
|
|
2447
2479
|
y.forEach((T, R) => {
|
|
2448
2480
|
var N, j;
|
|
2449
|
-
const C = S[R].isParagraphStart,
|
|
2481
|
+
const C = S[R].isParagraphStart, x = S[R].isParagraphEnd;
|
|
2450
2482
|
let I = 0;
|
|
2451
|
-
const
|
|
2483
|
+
const M = T.map((H) => H.text).join(""), P = ((N = M.match(/^ +/)) == null ? void 0 : N[0].length) || 0, k = ((j = M.match(/ +$/)) == null ? void 0 : j[0].length) || 0;
|
|
2452
2484
|
let B = 0;
|
|
2453
2485
|
T.forEach((H) => {
|
|
2454
|
-
const z = H.style.fontSize !== void 0 ? H.style.fontSize : n, K = H.style.fontFamily !== void 0 ? H.style.fontFamily :
|
|
2486
|
+
const z = H.style.fontSize !== void 0 ? H.style.fontSize : n, K = H.style.fontFamily !== void 0 ? H.style.fontFamily : o, Q = H.style.bold !== void 0 ? H.style.bold : i, L = H.style.italic !== void 0 ? H.style.italic : a;
|
|
2455
2487
|
let A = H.text;
|
|
2456
2488
|
const O = B, G = B + H.text.length;
|
|
2457
2489
|
if (!C && P > 0 && O < P) {
|
|
2458
2490
|
const E = Math.min(P - O, H.text.length);
|
|
2459
2491
|
A = A.substring(E);
|
|
2460
2492
|
}
|
|
2461
|
-
if (!
|
|
2462
|
-
const E =
|
|
2493
|
+
if (!x && k > 0) {
|
|
2494
|
+
const E = M.length - k;
|
|
2463
2495
|
if (G > E) {
|
|
2464
2496
|
const _ = !C && O < P ? Math.min(P - O, H.text.length) : 0, U = Math.max(0, E - O - _);
|
|
2465
2497
|
A = A.substring(0, U);
|
|
@@ -2476,7 +2508,7 @@ class Ft {
|
|
|
2476
2508
|
r === "center" ? F = -I / 2 : r === "right" ? F = W !== void 0 ? W / 2 - I : -I : F = W !== void 0 ? -W / 2 : 0;
|
|
2477
2509
|
const D = w + l.ascent + R * h;
|
|
2478
2510
|
B = 0, T.forEach((H) => {
|
|
2479
|
-
const z = H.style.fontSize !== void 0 ? H.style.fontSize : n, K = H.style.fontFamily !== void 0 ? H.style.fontFamily :
|
|
2511
|
+
const z = H.style.fontSize !== void 0 ? H.style.fontSize : n, K = H.style.fontFamily !== void 0 ? H.style.fontFamily : o;
|
|
2480
2512
|
H.style.color !== void 0 ? H.style.color : e.color;
|
|
2481
2513
|
const Q = H.style.bold !== void 0 ? H.style.bold : i, L = H.style.italic !== void 0 ? H.style.italic : a;
|
|
2482
2514
|
let A = H.text;
|
|
@@ -2485,8 +2517,8 @@ class Ft {
|
|
|
2485
2517
|
const E = Math.min(P - O, H.text.length);
|
|
2486
2518
|
A = A.substring(E);
|
|
2487
2519
|
}
|
|
2488
|
-
if (!
|
|
2489
|
-
const E =
|
|
2520
|
+
if (!x && k > 0) {
|
|
2521
|
+
const E = M.length - k;
|
|
2490
2522
|
if (G > E) {
|
|
2491
2523
|
const _ = !C && O < P ? Math.min(P - O, H.text.length) : 0, U = Math.max(0, E - O - _);
|
|
2492
2524
|
A = A.substring(0, U);
|
|
@@ -2499,36 +2531,36 @@ class Ft {
|
|
|
2499
2531
|
});
|
|
2500
2532
|
});
|
|
2501
2533
|
} else {
|
|
2502
|
-
t.font = Lt(n,
|
|
2534
|
+
t.font = Lt(n, o, i, a), u.font = t.font, u.textAlign = r;
|
|
2503
2535
|
let g, y;
|
|
2504
2536
|
if (e.transformType === "custom" && e.transformData) {
|
|
2505
|
-
const C = e.transformData.width - pt * 2, { lines:
|
|
2537
|
+
const C = e.transformData.width - pt * 2, { lines: x } = me(
|
|
2506
2538
|
e.text,
|
|
2507
2539
|
C,
|
|
2508
2540
|
n,
|
|
2509
|
-
|
|
2541
|
+
o,
|
|
2510
2542
|
i,
|
|
2511
2543
|
a,
|
|
2512
2544
|
void 0,
|
|
2513
2545
|
!0,
|
|
2514
2546
|
{ letterSpacing: c, lineHeight: e.lineHeight }
|
|
2515
2547
|
);
|
|
2516
|
-
g =
|
|
2548
|
+
g = x;
|
|
2517
2549
|
} else {
|
|
2518
2550
|
g = e.text.split(`
|
|
2519
2551
|
`);
|
|
2520
2552
|
const C = e.text.includes(`
|
|
2521
2553
|
`);
|
|
2522
|
-
g =
|
|
2554
|
+
g = ke(g, C);
|
|
2523
2555
|
}
|
|
2524
2556
|
g.length === 0 ? y = 0 : g.length === 1 ? y = l.height : y = (g.length - 1) * h + l.height;
|
|
2525
2557
|
const S = -y / 2, m = e.text.includes(`
|
|
2526
2558
|
`), w = e.transformType === "custom" && e.transformData ? e.transformData.width : 0, T = -w / 2;
|
|
2527
2559
|
let R = T + pt;
|
|
2528
|
-
r === "center" ? R = T + w / 2 : r === "right" && (R = T + w - pt), g.forEach((C,
|
|
2529
|
-
const I = S + l.ascent +
|
|
2560
|
+
r === "center" ? R = T + w / 2 : r === "right" && (R = T + w - pt), g.forEach((C, x) => {
|
|
2561
|
+
const I = S + l.ascent + x * h, M = m || x === 0, P = m || x === g.length - 1;
|
|
2530
2562
|
let k = C;
|
|
2531
|
-
|
|
2563
|
+
M || (k = k.replace(/^ +/, "")), P || (k = k.replace(/ +$/, "")), u.globalCompositeOperation = "source-over", u.strokeStyle = t.strokeStyle, u.globalAlpha = Math.min(t.globalAlpha * 1.6, 0.8), u.lineWidth = (f + d) * 2, u.lineJoin = "round", Pt(u, k, R, I, c), u.globalCompositeOperation = "destination-out", u.globalAlpha = 1, u.lineWidth = f * 2, Pt(u, k, R, I, c), Nt(u, k, R, I, c);
|
|
2532
2564
|
});
|
|
2533
2565
|
}
|
|
2534
2566
|
t.setTransform(1, 0, 0, 1, 0, 0), t.drawImage(b, 0, 0), t.restore();
|
|
@@ -2544,31 +2576,31 @@ class Ft {
|
|
|
2544
2576
|
* - Element stroke (StrokeRenderer.ts - only when stroke.enabled = true)
|
|
2545
2577
|
* - Selection box (dashed outline shown by each transform's render() method)
|
|
2546
2578
|
*/
|
|
2547
|
-
static renderTransformHoverRingEffect(t, e,
|
|
2548
|
-
t.save(), t.translate(e.x *
|
|
2549
|
-
const n = 4 /
|
|
2579
|
+
static renderTransformHoverRingEffect(t, e, s) {
|
|
2580
|
+
t.save(), t.translate(e.x * s, e.y * s), s !== 1 && t.scale(s, s), t.rotate(-e.rotation * Math.PI / 180);
|
|
2581
|
+
const n = 4 / s, o = 4 / s, i = document.createElement("canvas");
|
|
2550
2582
|
i.width = t.canvas.width, i.height = t.canvas.height;
|
|
2551
2583
|
const a = i.getContext("2d");
|
|
2552
2584
|
if (!a) {
|
|
2553
2585
|
t.restore();
|
|
2554
2586
|
return;
|
|
2555
2587
|
}
|
|
2556
|
-
a.setTransform(t.getTransform()), this.renderTransformWithHoverEffect(a, e, n,
|
|
2588
|
+
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();
|
|
2557
2589
|
}
|
|
2558
2590
|
/**
|
|
2559
2591
|
* Helper to render text along a transform path with hover effect
|
|
2560
2592
|
*/
|
|
2561
|
-
static renderTransformWithHoverEffect(t, e,
|
|
2593
|
+
static renderTransformWithHoverEffect(t, e, s, n, o) {
|
|
2562
2594
|
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";
|
|
2563
2595
|
if (t.font = `${d} ${c} ${a}px ${r}`, t.textAlign = "center", t.textBaseline = "middle", i.transformType === "lean") {
|
|
2564
2596
|
const y = -i.transformData.leanAmount * Math.PI / 4;
|
|
2565
|
-
t.transform(1, 0, Math.tan(y), 1, 0, 0), t.globalCompositeOperation = "source-over", t.strokeStyle =
|
|
2597
|
+
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);
|
|
2566
2598
|
return;
|
|
2567
2599
|
}
|
|
2568
2600
|
const f = i.text.split(""), b = f.map((g) => t.measureText(g).width), u = this.calculateCharPositions(e, f, b), p = (g) => {
|
|
2569
2601
|
t.translate(g.x, g.y), g.angle && t.rotate(g.angle), g.skewY && t.transform(1, g.skewY, 0, 1, 0, 0);
|
|
2570
2602
|
};
|
|
2571
|
-
t.globalCompositeOperation = "source-over", t.strokeStyle =
|
|
2603
|
+
t.globalCompositeOperation = "source-over", t.strokeStyle = o, t.globalAlpha = 0.8, t.lineWidth = (n + s) * 2, t.lineJoin = "round", u.forEach((g, y) => {
|
|
2572
2604
|
t.save(), p(g), t.strokeText(f[y], 0, 0), t.restore();
|
|
2573
2605
|
}), t.globalCompositeOperation = "destination-out", t.globalAlpha = 1, t.lineWidth = n * 2, u.forEach((g, y) => {
|
|
2574
2606
|
t.save(), p(g), t.strokeText(f[y], 0, 0), t.fillText(f[y], 0, 0), t.restore();
|
|
@@ -2579,25 +2611,25 @@ class Ft {
|
|
|
2579
2611
|
*
|
|
2580
2612
|
* Also used by EditModeRenderer for cursor positioning on transformed text.
|
|
2581
2613
|
*/
|
|
2582
|
-
static calculateCharPositions(t, e,
|
|
2583
|
-
const n = t.transformType,
|
|
2584
|
-
return n === "circle" ? this.calculateCirclePositions(
|
|
2614
|
+
static calculateCharPositions(t, e, s) {
|
|
2615
|
+
const n = t.transformType, o = t.transformData;
|
|
2616
|
+
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 }));
|
|
2585
2617
|
}
|
|
2586
2618
|
/**
|
|
2587
2619
|
* Calculate positions for circle transform
|
|
2588
2620
|
*/
|
|
2589
|
-
static calculateCirclePositions(t, e,
|
|
2590
|
-
const n = [],
|
|
2621
|
+
static calculateCirclePositions(t, e, s) {
|
|
2622
|
+
const n = [], o = s.reduce((a, r) => a + r, 0), i = t.radius * t.scale;
|
|
2591
2623
|
if (t.reverse) {
|
|
2592
|
-
let a = Math.PI / 2 +
|
|
2624
|
+
let a = Math.PI / 2 + o / (2 * i);
|
|
2593
2625
|
e.forEach((r, l) => {
|
|
2594
|
-
const c =
|
|
2626
|
+
const c = s[l] / i, d = Math.cos(a - c / 2) * i, f = Math.sin(a - c / 2) * i, b = a - c / 2 - Math.PI / 2;
|
|
2595
2627
|
n.push({ x: d, y: f, angle: b }), a -= c;
|
|
2596
2628
|
});
|
|
2597
2629
|
} else {
|
|
2598
|
-
let a = -Math.PI / 2 -
|
|
2630
|
+
let a = -Math.PI / 2 - o / (2 * i);
|
|
2599
2631
|
e.forEach((r, l) => {
|
|
2600
|
-
const c =
|
|
2632
|
+
const c = s[l] / i, d = Math.cos(a + c / 2) * i, f = Math.sin(a + c / 2) * i, b = a + c / 2 + Math.PI / 2;
|
|
2601
2633
|
n.push({ x: d, y: f, angle: b }), a += c;
|
|
2602
2634
|
});
|
|
2603
2635
|
}
|
|
@@ -2606,57 +2638,57 @@ class Ft {
|
|
|
2606
2638
|
/**
|
|
2607
2639
|
* Calculate positions for wave transform
|
|
2608
2640
|
*/
|
|
2609
|
-
static calculateWavePositions(t, e,
|
|
2610
|
-
const
|
|
2611
|
-
let a = -
|
|
2641
|
+
static calculateWavePositions(t, e, s, n) {
|
|
2642
|
+
const o = [];
|
|
2643
|
+
let a = -s.reduce((r, l) => r + l, 0) / 2;
|
|
2612
2644
|
return e.forEach((r, l) => {
|
|
2613
|
-
const h =
|
|
2614
|
-
|
|
2615
|
-
}),
|
|
2645
|
+
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), b = n.amplitude * n.frequency * Math.PI * Math.cos(n.frequency * Math.PI * d);
|
|
2646
|
+
o.push({ x: c, y: f, angle: 0, skewY: b * Te }), a += h;
|
|
2647
|
+
}), o;
|
|
2616
2648
|
}
|
|
2617
2649
|
/**
|
|
2618
2650
|
* Calculate positions for arch transform
|
|
2619
2651
|
*/
|
|
2620
|
-
static calculateArchPositions(t, e,
|
|
2621
|
-
const
|
|
2652
|
+
static calculateArchPositions(t, e, s, n) {
|
|
2653
|
+
const o = [], i = s.reduce((l, h) => l + h, 0), a = n.width / 2;
|
|
2622
2654
|
let r = -i / 2;
|
|
2623
2655
|
return e.forEach((l, h) => {
|
|
2624
|
-
const c =
|
|
2625
|
-
|
|
2626
|
-
}),
|
|
2656
|
+
const c = s[h], d = r + c / 2, f = d / a, b = (Math.pow(f, 2) - 1) * n.archHeight * t.fontSize, u = 2 * f * n.archHeight;
|
|
2657
|
+
o.push({ x: d, y: b, angle: 0, skewY: u * 0.3 }), r += c;
|
|
2658
|
+
}), o;
|
|
2627
2659
|
}
|
|
2628
2660
|
/**
|
|
2629
2661
|
* Calculate positions for lean transform
|
|
2630
2662
|
*/
|
|
2631
2663
|
static calculateLeanPositions(t, e) {
|
|
2632
|
-
const
|
|
2633
|
-
let
|
|
2664
|
+
const s = [];
|
|
2665
|
+
let o = -e.reduce((i, a) => i + a, 0) / 2;
|
|
2634
2666
|
return t.forEach((i, a) => {
|
|
2635
|
-
const r = e[a], l =
|
|
2636
|
-
|
|
2637
|
-
}),
|
|
2667
|
+
const r = e[a], l = o + r / 2;
|
|
2668
|
+
s.push({ x: l, y: 0, angle: 0 }), o += r;
|
|
2669
|
+
}), s;
|
|
2638
2670
|
}
|
|
2639
2671
|
/**
|
|
2640
2672
|
* Calculate positions for ascend transform
|
|
2641
2673
|
*/
|
|
2642
|
-
static calculateAscendPositions(t, e,
|
|
2643
|
-
const
|
|
2674
|
+
static calculateAscendPositions(t, e, s, n) {
|
|
2675
|
+
const o = [], i = s.reduce((h, c) => h + c, 0), a = n.ascendAngle * Math.PI / 180, r = Math.tan(a);
|
|
2644
2676
|
let l = -i / 2;
|
|
2645
2677
|
return e.forEach((h, c) => {
|
|
2646
|
-
const d =
|
|
2647
|
-
|
|
2648
|
-
}),
|
|
2678
|
+
const d = s[c], f = l + d / 2, b = f * r;
|
|
2679
|
+
o.push({ x: f, y: b, angle: 0, skewY: r * 1 }), l += d;
|
|
2680
|
+
}), o;
|
|
2649
2681
|
}
|
|
2650
2682
|
/**
|
|
2651
2683
|
* Calculate positions for flag transform
|
|
2652
2684
|
*/
|
|
2653
|
-
static calculateFlagPositions(t, e,
|
|
2654
|
-
const
|
|
2655
|
-
let a = -
|
|
2685
|
+
static calculateFlagPositions(t, e, s, n) {
|
|
2686
|
+
const o = [];
|
|
2687
|
+
let a = -s.reduce((r, l) => r + l, 0) / 2;
|
|
2656
2688
|
return e.forEach((r, l) => {
|
|
2657
|
-
const h =
|
|
2658
|
-
|
|
2659
|
-
}),
|
|
2689
|
+
const h = s[l], c = a + h / 2, d = c / (n.width / 2), f = Math.abs(d), b = n.amplitude * f, u = b * t.fontSize * Math.sin(n.frequency * Math.PI * d), p = b * n.frequency * Math.PI * Math.cos(n.frequency * Math.PI * d), g = n.amplitude * Math.sign(d) * Math.sin(n.frequency * Math.PI * d), y = p + g;
|
|
2690
|
+
o.push({ x: c, y: u, angle: 0, skewY: y * 0.3 }), a += h;
|
|
2691
|
+
}), o;
|
|
2660
2692
|
}
|
|
2661
2693
|
}
|
|
2662
2694
|
class Rt {
|
|
@@ -2664,41 +2696,41 @@ class Rt {
|
|
|
2664
2696
|
* Render snap guides layer
|
|
2665
2697
|
*/
|
|
2666
2698
|
static renderSnapGuidesLayer(t, e = []) {
|
|
2667
|
-
e.length !== 0 && (t.save(), t.strokeStyle = nt(t.canvas), t.lineWidth = ct.canvas.snapGuideWidth, t.setLineDash(ct.canvas.snapGuideDash), e.forEach((
|
|
2668
|
-
t.beginPath(),
|
|
2699
|
+
e.length !== 0 && (t.save(), t.strokeStyle = nt(t.canvas), t.lineWidth = ct.canvas.snapGuideWidth, t.setLineDash(ct.canvas.snapGuideDash), e.forEach((s) => {
|
|
2700
|
+
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();
|
|
2669
2701
|
}), t.restore());
|
|
2670
2702
|
}
|
|
2671
2703
|
/**
|
|
2672
2704
|
* Render spacing indicators layer
|
|
2673
2705
|
*/
|
|
2674
2706
|
static renderSpacingIndicatorsLayer(t, e = []) {
|
|
2675
|
-
e.length !== 0 && (t.save(), t.setLineDash([]), e.forEach((
|
|
2707
|
+
e.length !== 0 && (t.save(), t.setLineDash([]), e.forEach((s) => {
|
|
2676
2708
|
const n = Kt(t.canvas);
|
|
2677
|
-
if (t.strokeStyle = n, t.fillStyle = n, t.lineWidth = ct.canvas.spacingIndicatorWidth, t.beginPath(),
|
|
2678
|
-
const
|
|
2679
|
-
t.moveTo(
|
|
2709
|
+
if (t.strokeStyle = n, t.fillStyle = n, t.lineWidth = ct.canvas.spacingIndicatorWidth, t.beginPath(), s.type === "horizontal") {
|
|
2710
|
+
const o = s.x1 ?? 0, i = s.x2 ?? 0, a = s.y ?? 0;
|
|
2711
|
+
t.moveTo(o, a), t.lineTo(i, a), t.stroke();
|
|
2680
2712
|
const r = 6;
|
|
2681
|
-
t.beginPath(), t.moveTo(
|
|
2682
|
-
const l =
|
|
2683
|
-
this.renderDistanceLabel(t, l, h,
|
|
2684
|
-
} else if (
|
|
2685
|
-
const
|
|
2686
|
-
t.moveTo(
|
|
2713
|
+
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();
|
|
2714
|
+
const l = s.labelX, h = s.labelY;
|
|
2715
|
+
this.renderDistanceLabel(t, l, h, s.distance);
|
|
2716
|
+
} else if (s.type === "vertical") {
|
|
2717
|
+
const o = s.x ?? 0, i = s.y1 ?? 0, a = s.y2 ?? 0;
|
|
2718
|
+
t.moveTo(o, i), t.lineTo(o, a), t.stroke();
|
|
2687
2719
|
const r = 6;
|
|
2688
|
-
t.beginPath(), t.moveTo(
|
|
2689
|
-
const l =
|
|
2690
|
-
this.renderDistanceLabel(t, l, h,
|
|
2720
|
+
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();
|
|
2721
|
+
const l = s.labelX, h = s.labelY;
|
|
2722
|
+
this.renderDistanceLabel(t, l, h, s.distance);
|
|
2691
2723
|
}
|
|
2692
2724
|
}), t.restore());
|
|
2693
2725
|
}
|
|
2694
2726
|
/**
|
|
2695
2727
|
* Render a distance label with background
|
|
2696
2728
|
*/
|
|
2697
|
-
static renderDistanceLabel(t, e,
|
|
2698
|
-
const
|
|
2729
|
+
static renderDistanceLabel(t, e, s, n) {
|
|
2730
|
+
const o = `${n}`;
|
|
2699
2731
|
t.font = `600 ${ct.canvas.spacingLabelFontSize}px ${ct.canvas.spacingLabelFontFamily}`;
|
|
2700
|
-
const a = t.measureText(
|
|
2701
|
-
t.fillStyle = Kt(t.canvas), t.beginPath(), t.roundRect(e - h / 2,
|
|
2732
|
+
const a = t.measureText(o).width, r = ct.canvas.spacingLabelFontSize, l = 4, h = a + l * 2, c = r + l * 2;
|
|
2733
|
+
t.fillStyle = Kt(t.canvas), t.beginPath(), t.roundRect(e - h / 2, s - c / 2, h, c, we), t.fill(), t.fillStyle = ve, t.textAlign = "center", t.textBaseline = "middle", t.fillText(o, e, s);
|
|
2702
2734
|
}
|
|
2703
2735
|
}
|
|
2704
2736
|
class Vt {
|
|
@@ -2706,53 +2738,53 @@ class Vt {
|
|
|
2706
2738
|
* Render edit mode features: cursor and text selection highlight
|
|
2707
2739
|
* This renders on the main canvas at world coordinates (same as the element)
|
|
2708
2740
|
*/
|
|
2709
|
-
static renderEditModeLayer(t, e,
|
|
2741
|
+
static renderEditModeLayer(t, e, s, n) {
|
|
2710
2742
|
if (!e || e.transformType === "image" || e.transformType === "group") return;
|
|
2711
|
-
const
|
|
2743
|
+
const o = e, { cursorPosition: i, selectionStart: a, selectionEnd: r, editText: l, editRichText: h, cursorOpacity: c, isTouchDevice: d, selectionHandlePositionsRef: f } = s, b = n || 1, u = o.transformType;
|
|
2712
2744
|
if (u === "circle" || u === "wave" || u === "arch" || u === "lean" || u === "ascend" || u === "flag") {
|
|
2713
|
-
this.renderTransformEditModeLayer(t,
|
|
2745
|
+
this.renderTransformEditModeLayer(t, o, s, b);
|
|
2714
2746
|
return;
|
|
2715
2747
|
}
|
|
2716
|
-
const p =
|
|
2717
|
-
t.save(), t.translate(
|
|
2718
|
-
const C =
|
|
2719
|
-
let
|
|
2720
|
-
if (h &&
|
|
2721
|
-
const L =
|
|
2748
|
+
const p = o.fontSize || 24, g = o.fontFamily || "Arial", y = o.bold || !1, S = o.italic || !1, m = o.underline || !1, w = o.strikethrough || !1, T = o.textAlign || "center", R = o.letterSpacing ?? 0;
|
|
2749
|
+
t.save(), t.translate(o.x, o.y), t.rotate(-o.rotation * Math.PI / 180);
|
|
2750
|
+
const C = te(p, g, y, S), x = C.height, I = p * (o.lineHeight ?? 1.2);
|
|
2751
|
+
let M, P, k;
|
|
2752
|
+
if (h && o.transformType === "custom" && o.transformData.width) {
|
|
2753
|
+
const L = o.transformData.width - pt * 2;
|
|
2722
2754
|
k = L;
|
|
2723
|
-
const A =
|
|
2724
|
-
|
|
2725
|
-
const G =
|
|
2726
|
-
fontSize:
|
|
2727
|
-
fontFamily:
|
|
2728
|
-
bold:
|
|
2729
|
-
italic:
|
|
2730
|
-
letterSpacing:
|
|
2755
|
+
const A = ee(h);
|
|
2756
|
+
M = [], P = [], A.forEach((O) => {
|
|
2757
|
+
const G = ne(O, L, {
|
|
2758
|
+
fontSize: o.fontSize,
|
|
2759
|
+
fontFamily: o.fontFamily,
|
|
2760
|
+
bold: o.bold,
|
|
2761
|
+
italic: o.italic,
|
|
2762
|
+
letterSpacing: o.letterSpacing
|
|
2731
2763
|
});
|
|
2732
2764
|
G.forEach((E, _) => {
|
|
2733
|
-
|
|
2765
|
+
M.push(E), P.push({
|
|
2734
2766
|
isParagraphStart: _ === 0,
|
|
2735
2767
|
isParagraphEnd: _ === G.length - 1
|
|
2736
2768
|
});
|
|
2737
2769
|
});
|
|
2738
2770
|
});
|
|
2739
2771
|
} else
|
|
2740
|
-
|
|
2772
|
+
M = l.split(`
|
|
2741
2773
|
`).map((A) => [
|
|
2742
2774
|
{
|
|
2743
2775
|
text: A,
|
|
2744
2776
|
style: { fontSize: p, fontFamily: g, bold: y, italic: S }
|
|
2745
2777
|
}
|
|
2746
|
-
]), P =
|
|
2778
|
+
]), P = M.map(() => ({
|
|
2747
2779
|
isParagraphStart: !0,
|
|
2748
2780
|
// Each line is its own paragraph
|
|
2749
2781
|
isParagraphEnd: !0
|
|
2750
2782
|
}));
|
|
2751
|
-
const B =
|
|
2752
|
-
let W = -B / 2, F = 0, D = W, N =
|
|
2783
|
+
const B = M.length > 1 ? C.height + (M.length - 1) * I : C.height;
|
|
2784
|
+
let W = -B / 2, F = 0, D = W, N = x;
|
|
2753
2785
|
const j = [];
|
|
2754
2786
|
let H = 0;
|
|
2755
|
-
|
|
2787
|
+
M.forEach((L, A) => {
|
|
2756
2788
|
var _, U;
|
|
2757
2789
|
const O = P[A].isParagraphStart, G = P[A].isParagraphEnd, E = [];
|
|
2758
2790
|
L.forEach((ot) => {
|
|
@@ -2770,7 +2802,7 @@ class Vt {
|
|
|
2770
2802
|
});
|
|
2771
2803
|
});
|
|
2772
2804
|
{
|
|
2773
|
-
const ot = A === 0, et = A ===
|
|
2805
|
+
const ot = A === 0, et = A === M.length - 1, lt = E.map((V) => V.char).join(""), Y = ((_ = lt.match(/^ +/)) == null ? void 0 : _[0].length) || 0, ht = ((U = lt.match(/ +$/)) == null ? void 0 : U[0].length) || 0;
|
|
2774
2806
|
let it = 0;
|
|
2775
2807
|
for (let V = 0; V < E.length; V++)
|
|
2776
2808
|
!ot && V < Y || !et && V >= E.length - ht || (it += E[V].width);
|
|
@@ -2788,36 +2820,36 @@ class Vt {
|
|
|
2788
2820
|
}, st += q.width;
|
|
2789
2821
|
}
|
|
2790
2822
|
if (E.length > 0) {
|
|
2791
|
-
const V = E[0].index, q = E[E.length - 1].index, ut = A <
|
|
2823
|
+
const V = E[0].index, q = E[E.length - 1].index, ut = A < M.length - 1 && q + 1 === H ? q : q + 1;
|
|
2792
2824
|
if (i >= V && i <= ut)
|
|
2793
2825
|
if (i === V)
|
|
2794
|
-
F = Z, D = W, N =
|
|
2826
|
+
F = Z, D = W, N = x;
|
|
2795
2827
|
else {
|
|
2796
2828
|
let yt = 0;
|
|
2797
2829
|
for (let rt = 0; rt < E.length && E[rt].index < i; rt++) {
|
|
2798
2830
|
const dt = E[rt], bt = dt.char === " ";
|
|
2799
2831
|
let St = !0;
|
|
2800
2832
|
if (bt) {
|
|
2801
|
-
const kt = rt < Y, X = rt >= E.length - ht, vt = !O && Y > 0,
|
|
2802
|
-
St = !(kt && vt || X &&
|
|
2833
|
+
const kt = rt < Y, X = rt >= E.length - ht, vt = !O && Y > 0, Mt = !G && ht > 0;
|
|
2834
|
+
St = !(kt && vt || X && Mt);
|
|
2803
2835
|
}
|
|
2804
2836
|
St && (yt += dt.width);
|
|
2805
2837
|
}
|
|
2806
|
-
F = Z + yt, D = W, N =
|
|
2838
|
+
F = Z + yt, D = W, N = x;
|
|
2807
2839
|
}
|
|
2808
2840
|
}
|
|
2809
|
-
A <
|
|
2841
|
+
A < M.length - 1 && (W += I);
|
|
2810
2842
|
}
|
|
2811
2843
|
});
|
|
2812
2844
|
const z = a !== r;
|
|
2813
2845
|
let K = null, Q = null;
|
|
2814
2846
|
if (z) {
|
|
2815
2847
|
const L = Math.min(a, r), A = Math.max(a, r);
|
|
2816
|
-
t.save(), t.fillStyle =
|
|
2848
|
+
t.save(), t.fillStyle = Me(t.canvas);
|
|
2817
2849
|
let O = 0, G = -B / 2;
|
|
2818
|
-
if (
|
|
2850
|
+
if (M.forEach((E, _) => {
|
|
2819
2851
|
var ht, it;
|
|
2820
|
-
const U = P[_].isParagraphStart, ot = P[_].isParagraphEnd, et = _ === 0, lt = _ ===
|
|
2852
|
+
const U = P[_].isParagraphStart, ot = P[_].isParagraphEnd, et = _ === 0, lt = _ === M.length - 1, Y = [];
|
|
2821
2853
|
if (E.forEach((Z) => {
|
|
2822
2854
|
Array.from(Z.text).forEach((st) => {
|
|
2823
2855
|
const V = Z.style || {}, q = V.fontSize !== void 0 ? V.fontSize : p, at = V.fontFamily !== void 0 ? V.fontFamily : g, J = V.bold !== void 0 ? V.bold : y, ut = V.italic !== void 0 ? V.italic : S, yt = V.letterSpacing !== void 0 ? V.letterSpacing : R;
|
|
@@ -2840,33 +2872,33 @@ class Vt {
|
|
|
2840
2872
|
const yt = Math.max(L, Z), rt = Math.min(A, st + 1);
|
|
2841
2873
|
let dt = 0;
|
|
2842
2874
|
for (let X = 0; X < Y.length && Y[X].index < yt; X++) {
|
|
2843
|
-
const vt = Y[X],
|
|
2844
|
-
!(
|
|
2875
|
+
const vt = Y[X], Mt = X < q, Ht = X >= Y.length - at, It = !U && q > 0, Bt = !ot && at > 0;
|
|
2876
|
+
!(Mt && It || Ht && Bt) && (dt += vt.width);
|
|
2845
2877
|
}
|
|
2846
2878
|
let bt = 0;
|
|
2847
2879
|
for (let X = 0; X < Y.length && Y[X].index < rt; X++) {
|
|
2848
|
-
const vt = Y[X],
|
|
2849
|
-
!(
|
|
2880
|
+
const vt = Y[X], Mt = X < q, Ht = X >= Y.length - at, It = !U && q > 0, Bt = !ot && at > 0;
|
|
2881
|
+
!(Mt && It || Ht && Bt) && (bt += vt.width);
|
|
2850
2882
|
}
|
|
2851
2883
|
const St = ut + dt, kt = bt - dt;
|
|
2852
|
-
t.fillRect(St, G, kt,
|
|
2884
|
+
t.fillRect(St, G, kt, x), K === null && (K = { x: St, y: G }), Q = { x: St + kt, y: G + x }, t.restore();
|
|
2853
2885
|
}
|
|
2854
2886
|
}
|
|
2855
|
-
_ <
|
|
2887
|
+
_ < M.length - 1 && (G += I);
|
|
2856
2888
|
}), t.restore(), h) {
|
|
2857
2889
|
t.save();
|
|
2858
|
-
const E =
|
|
2859
|
-
|
|
2890
|
+
const E = o.transformType === "custom" ? o.transformData : null, _ = E != null && E.width ? E.width - pt * 2 : void 0;
|
|
2891
|
+
Pe(t, h, {
|
|
2860
2892
|
fontSize: p,
|
|
2861
2893
|
fontFamily: g,
|
|
2862
|
-
color:
|
|
2894
|
+
color: o.color || "#000000",
|
|
2863
2895
|
bold: y,
|
|
2864
2896
|
italic: S,
|
|
2865
2897
|
underline: m,
|
|
2866
2898
|
strikethrough: w,
|
|
2867
2899
|
textAlign: T,
|
|
2868
|
-
letterSpacing:
|
|
2869
|
-
lineHeight:
|
|
2900
|
+
letterSpacing: o.letterSpacing,
|
|
2901
|
+
lineHeight: o.lineHeight
|
|
2870
2902
|
}, _), t.restore();
|
|
2871
2903
|
}
|
|
2872
2904
|
}
|
|
@@ -2876,7 +2908,7 @@ class Vt {
|
|
|
2876
2908
|
const E = nt(t.canvas);
|
|
2877
2909
|
t.fillStyle = E, t.strokeStyle = E, t.lineWidth = G, t.lineCap = "round";
|
|
2878
2910
|
const _ = { x: L.x, y: L.y - O }, U = { x: A.x, y: A.y + O };
|
|
2879
|
-
t.beginPath(), t.moveTo(L.x, L.y), t.lineTo(L.x, L.y +
|
|
2911
|
+
t.beginPath(), t.moveTo(L.x, L.y), t.lineTo(L.x, L.y + x), t.stroke(), t.beginPath(), t.arc(_.x, _.y, O, 0, Math.PI * 2), t.fill(), t.strokeStyle = "white", t.lineWidth = 2 / b, t.stroke(), t.strokeStyle = E, t.lineWidth = G, t.beginPath(), t.moveTo(A.x, A.y - x), t.lineTo(A.x, A.y), t.stroke(), t.beginPath(), t.arc(U.x, U.y, O, 0, Math.PI * 2), t.fill(), t.strokeStyle = "white", t.lineWidth = 2 / b, t.stroke(), t.restore(), f && (f.current = {
|
|
2880
2912
|
start: {
|
|
2881
2913
|
center: _,
|
|
2882
2914
|
textEdge: L
|
|
@@ -2895,15 +2927,15 @@ class Vt {
|
|
|
2895
2927
|
* Render edit mode features for transformed text (circle, wave, arch, etc.)
|
|
2896
2928
|
* Renders cursor along the transform path
|
|
2897
2929
|
*/
|
|
2898
|
-
static renderTransformEditModeLayer(t, e,
|
|
2899
|
-
const { cursorPosition:
|
|
2930
|
+
static renderTransformEditModeLayer(t, e, s, n = 1) {
|
|
2931
|
+
const { cursorPosition: o, cursorOpacity: i } = s, a = e.fontSize || 24, r = e.fontFamily || "Arial", l = e.bold || !1, h = e.italic || !1;
|
|
2900
2932
|
t.save(), t.translate(e.x, e.y), t.rotate(-e.rotation * Math.PI / 180);
|
|
2901
2933
|
const c = l ? "bold" : "normal", d = h ? "italic" : "normal";
|
|
2902
2934
|
t.font = `${d} ${c} ${a}px ${r}`;
|
|
2903
2935
|
const f = Array.from(e.text), b = f.map((p) => t.measureText(p).width), u = Ft.calculateCharPositions(e, f, b);
|
|
2904
|
-
if (
|
|
2936
|
+
if (o >= 0 && o <= f.length && i > 0) {
|
|
2905
2937
|
let p;
|
|
2906
|
-
if (
|
|
2938
|
+
if (o === 0)
|
|
2907
2939
|
if (u.length > 0) {
|
|
2908
2940
|
const y = u[0], S = b[0];
|
|
2909
2941
|
p = {
|
|
@@ -2913,7 +2945,7 @@ class Vt {
|
|
|
2913
2945
|
};
|
|
2914
2946
|
} else
|
|
2915
2947
|
p = { x: 0, y: 0, angle: 0 };
|
|
2916
|
-
else if (
|
|
2948
|
+
else if (o >= u.length) {
|
|
2917
2949
|
const y = u[u.length - 1], S = b[b.length - 1];
|
|
2918
2950
|
p = {
|
|
2919
2951
|
x: y.x + Math.cos(y.angle) * (S / 2),
|
|
@@ -2921,7 +2953,7 @@ class Vt {
|
|
|
2921
2953
|
angle: y.angle
|
|
2922
2954
|
};
|
|
2923
2955
|
} else {
|
|
2924
|
-
const y = u[
|
|
2956
|
+
const y = u[o], S = b[o];
|
|
2925
2957
|
p = {
|
|
2926
2958
|
x: y.x - Math.cos(y.angle) * (S / 2),
|
|
2927
2959
|
y: y.y - Math.sin(y.angle) * (S / 2),
|
|
@@ -2938,27 +2970,27 @@ class Vt {
|
|
|
2938
2970
|
* Render crop box layer (for images in crop mode)
|
|
2939
2971
|
* Shows both image resize handles and crop handles
|
|
2940
2972
|
*/
|
|
2941
|
-
static renderCropBoxLayer(t, e,
|
|
2942
|
-
if (!(e instanceof
|
|
2943
|
-
const
|
|
2973
|
+
static renderCropBoxLayer(t, e, s, n = 1) {
|
|
2974
|
+
if (!(e instanceof xe) || !e.isCropping) return;
|
|
2975
|
+
const o = e, i = o.getCropBoxBounds();
|
|
2944
2976
|
if (!i) return;
|
|
2945
|
-
const a = 4 / n, r = 2 / n, l =
|
|
2977
|
+
const a = 4 / n, r = 2 / n, l = Re / n, h = Ce / n, c = 1 / n;
|
|
2946
2978
|
t.save(), t.translate(e.x * n, e.y * n), t.rotate(gt.toRadians(e.rotation));
|
|
2947
|
-
const d =
|
|
2979
|
+
const d = o.transformData.flipHorizontal ? -1 : 1, f = o.transformData.flipVertical ? -1 : 1;
|
|
2948
2980
|
t.scale(d * n, f * n);
|
|
2949
|
-
const b =
|
|
2981
|
+
const b = o.transformData.width * o.transformData.cropWidth, u = o.transformData.height * o.transformData.cropHeight, p = o.transformData.width / 2 - (o.transformData.cropX * o.transformData.width + b / 2), g = o.transformData.height / 2 - (o.transformData.cropY * o.transformData.height + u / 2), y = o.transformData.width / 2, S = o.transformData.height / 2, m = {
|
|
2950
2982
|
x: p - y,
|
|
2951
2983
|
y: g - S,
|
|
2952
|
-
width:
|
|
2953
|
-
height:
|
|
2984
|
+
width: o.transformData.width,
|
|
2985
|
+
height: o.transformData.height
|
|
2954
2986
|
};
|
|
2955
2987
|
t.fillStyle = "rgba(0, 0, 0, 0.5)", i.y > m.y && t.fillRect(m.x, m.y, m.width, i.y - m.y);
|
|
2956
2988
|
const w = i.y + i.height, T = m.y + m.height;
|
|
2957
2989
|
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);
|
|
2958
2990
|
const R = i.x + i.width, C = m.x + m.width;
|
|
2959
2991
|
R < C && t.fillRect(R, i.y, C - R, i.height), t.strokeStyle = nt(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;
|
|
2960
|
-
const
|
|
2961
|
-
t.beginPath(), t.moveTo(i.x +
|
|
2992
|
+
const x = i.width / 3;
|
|
2993
|
+
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();
|
|
2962
2994
|
const I = i.height / 3;
|
|
2963
2995
|
if (t.beginPath(), t.moveTo(i.x, i.y + I), t.lineTo(i.x + i.width, i.y + I), t.moveTo(i.x, i.y + 2 * I), t.lineTo(i.x + i.width, i.y + 2 * I), t.stroke(), [
|
|
2964
2996
|
{ x: i.x, y: i.y },
|
|
@@ -2985,10 +3017,10 @@ class Vt {
|
|
|
2985
3017
|
k.orientation === "horizontal" ? (B = h, W = a) : (B = a, W = h);
|
|
2986
3018
|
const F = k.x - B / 2, D = k.y - W / 2;
|
|
2987
3019
|
t.fillStyle = "#fff", t.fillRect(F, D, B, W), t.strokeStyle = "#bbb", t.lineWidth = c, t.strokeRect(F, D, B, W);
|
|
2988
|
-
}), t.restore(),
|
|
2989
|
-
const k =
|
|
3020
|
+
}), t.restore(), s && s.resizeHandles) {
|
|
3021
|
+
const k = s.resizeHandles.filter(
|
|
2990
3022
|
(D) => D.anchor === "top-left" || D.anchor === "top-right" || D.anchor === "bottom-left" || D.anchor === "bottom-right"
|
|
2991
|
-
), B =
|
|
3023
|
+
), B = o.getCropBoxWorldCorners(), W = 6, F = 20;
|
|
2992
3024
|
k.forEach((D) => {
|
|
2993
3025
|
let N = !1;
|
|
2994
3026
|
if (B)
|
|
@@ -3004,8 +3036,8 @@ class Vt {
|
|
|
3004
3036
|
}
|
|
3005
3037
|
}
|
|
3006
3038
|
}
|
|
3007
|
-
|
|
3008
|
-
const
|
|
3039
|
+
Ie();
|
|
3040
|
+
const qe = Qt("CanvasRenderer"), $ = class $ {
|
|
3009
3041
|
/**
|
|
3010
3042
|
* Get a pooled offscreen canvas for clipping content, only recreating
|
|
3011
3043
|
* when dimensions change. Eliminates per-frame canvas allocation.
|
|
@@ -3024,12 +3056,12 @@ const Ke = Jt("CanvasRenderer"), $ = class $ {
|
|
|
3024
3056
|
* Safely render an element, catching errors so one element's failure
|
|
3025
3057
|
* doesn't crash the entire canvas render loop.
|
|
3026
3058
|
*/
|
|
3027
|
-
static safeRender(t, e,
|
|
3059
|
+
static safeRender(t, e, s, n) {
|
|
3028
3060
|
try {
|
|
3029
|
-
e.render(t,
|
|
3030
|
-
} catch (
|
|
3031
|
-
const i =
|
|
3032
|
-
|
|
3061
|
+
e.render(t, s, n);
|
|
3062
|
+
} catch (o) {
|
|
3063
|
+
const i = o instanceof Error ? o : new Error(String(o));
|
|
3064
|
+
qe.error(`Failed to render element ${e.id}:`, i), $.onRenderError && $.onRenderError({
|
|
3033
3065
|
category: "render",
|
|
3034
3066
|
message: `Failed to render element: ${i.message}`,
|
|
3035
3067
|
originalError: i,
|
|
@@ -3045,8 +3077,8 @@ const Ke = Jt("CanvasRenderer"), $ = class $ {
|
|
|
3045
3077
|
* Helper function to render an element (using actual element instance, not config)
|
|
3046
3078
|
* Used by knockout rendering system
|
|
3047
3079
|
*/
|
|
3048
|
-
static renderElement(t, e,
|
|
3049
|
-
|
|
3080
|
+
static renderElement(t, e, s = !0) {
|
|
3081
|
+
s && (t.save(), t.globalAlpha = tt), e.render(t, !1, !1), s && t.restore();
|
|
3050
3082
|
}
|
|
3051
3083
|
/**
|
|
3052
3084
|
* Apply artboard clip path to the context, respecting clipShape.
|
|
@@ -3054,22 +3086,22 @@ const Ke = Jt("CanvasRenderer"), $ = class $ {
|
|
|
3054
3086
|
* Caller must call ctx.beginPath() before this if needed.
|
|
3055
3087
|
*/
|
|
3056
3088
|
static applyArtboardClipPath(t, e) {
|
|
3057
|
-
const { x:
|
|
3089
|
+
const { x: s, y: n, width: o, height: i, clipShape: a } = e, r = e.borderRadius || 0;
|
|
3058
3090
|
if (t.beginPath(), !a || a === "rectangle")
|
|
3059
|
-
r > 0 ? t.roundRect(
|
|
3091
|
+
r > 0 ? t.roundRect(s, n, o, i, r) : t.rect(s, n, o, i);
|
|
3060
3092
|
else if (a === "circle") {
|
|
3061
|
-
const l =
|
|
3093
|
+
const l = s + o / 2, h = n + i / 2, c = Math.min(o, i) / 2;
|
|
3062
3094
|
t.arc(l, h, c, 0, Math.PI * 2);
|
|
3063
3095
|
} else if (typeof a == "object" && a.type === "rounded") {
|
|
3064
|
-
const l = Math.min(a.radius, Math.min(
|
|
3065
|
-
t.roundRect(
|
|
3096
|
+
const l = Math.min(a.radius, Math.min(o, i) / 2);
|
|
3097
|
+
t.roundRect(s, n, o, i, l);
|
|
3066
3098
|
} else if (typeof a == "object" && a.type === "path")
|
|
3067
3099
|
try {
|
|
3068
3100
|
const l = new Path2D(a.d);
|
|
3069
|
-
t.translate(
|
|
3101
|
+
t.translate(s, n), t.clip(l), t.translate(-s, -n);
|
|
3070
3102
|
return;
|
|
3071
3103
|
} catch {
|
|
3072
|
-
t.rect(
|
|
3104
|
+
t.rect(s, n, o, i);
|
|
3073
3105
|
}
|
|
3074
3106
|
else if (typeof a == "object" && a.type === "composite-path")
|
|
3075
3107
|
try {
|
|
@@ -3077,15 +3109,15 @@ const Ke = Jt("CanvasRenderer"), $ = class $ {
|
|
|
3077
3109
|
for (const h of a.pieces) {
|
|
3078
3110
|
const c = new Path2D(h.d), d = h.rotation ?? 0, f = new DOMMatrix();
|
|
3079
3111
|
if (f.translateSelf(h.x, h.y), d !== 0) {
|
|
3080
|
-
const b = (h.baseWidth ?? 0) / 2, u = (h.baseHeight ?? 0) / 2,
|
|
3081
|
-
f.translateSelf(
|
|
3112
|
+
const b = (h.baseWidth ?? 0) / 2, u = (h.baseHeight ?? 0) / 2, { width: p, height: g } = Zt(h.baseWidth ?? 0, h.baseHeight ?? 0, d);
|
|
3113
|
+
f.translateSelf(p / 2, g / 2), f.rotateSelf(d), f.translateSelf(-b, -u);
|
|
3082
3114
|
}
|
|
3083
3115
|
l.addPath(c, f);
|
|
3084
3116
|
}
|
|
3085
|
-
t.translate(
|
|
3117
|
+
t.translate(s, n), t.clip(l), t.translate(-s, -n);
|
|
3086
3118
|
return;
|
|
3087
3119
|
} catch {
|
|
3088
|
-
t.rect(
|
|
3120
|
+
t.rect(s, n, o, i);
|
|
3089
3121
|
}
|
|
3090
3122
|
t.clip();
|
|
3091
3123
|
}
|
|
@@ -3093,25 +3125,25 @@ const Ke = Jt("CanvasRenderer"), $ = class $ {
|
|
|
3093
3125
|
* Render an element with overflow dimming - parts outside the artboard render at 30% opacity
|
|
3094
3126
|
* Uses two-pass rendering: first at 30% opacity (overflow), then clipped to artboard at 100% (inside)
|
|
3095
3127
|
*/
|
|
3096
|
-
static renderElementWithOverflowDimming(t, e,
|
|
3097
|
-
const a = t.getTransform(), r =
|
|
3128
|
+
static renderElementWithOverflowDimming(t, e, s, n, o, i) {
|
|
3129
|
+
const a = t.getTransform(), r = s.borderRadius || 0;
|
|
3098
3130
|
t.save(), t.globalAlpha = 0.3 * (i ? tt : 1), t.filter = "blur(4px)", t.beginPath();
|
|
3099
|
-
const h = t.getTransform().inverse(), c = t.canvas.width, d = t.canvas.height, f = new DOMPoint(0, 0).matrixTransform(h), b = new DOMPoint(c, d).matrixTransform(h), u = Math.max(b.x - f.x, b.y - f.y), p = f.x - u, g = f.y - u, y = b.x + u, S = b.y + u, m = typeof
|
|
3131
|
+
const h = t.getTransform().inverse(), c = t.canvas.width, d = t.canvas.height, f = new DOMPoint(0, 0).matrixTransform(h), b = new DOMPoint(c, d).matrixTransform(h), u = Math.max(b.x - f.x, b.y - f.y), p = f.x - u, g = f.y - u, y = b.x + u, S = b.y + u, m = typeof s.clipShape == "object" && s.clipShape !== null && s.clipShape.type === "composite-path" ? s.clipShape : null;
|
|
3100
3132
|
if (m) {
|
|
3101
3133
|
const w = new Path2D();
|
|
3102
3134
|
w.rect(p, g, y - p, S - g);
|
|
3103
3135
|
for (const T of m.pieces) {
|
|
3104
|
-
const R = new Path2D(T.d), C = T.rotation ?? 0,
|
|
3105
|
-
if (
|
|
3106
|
-
const I = (T.baseWidth ?? 0) / 2,
|
|
3107
|
-
|
|
3136
|
+
const R = new Path2D(T.d), C = T.rotation ?? 0, x = new DOMMatrix();
|
|
3137
|
+
if (x.translateSelf(s.x + T.x, s.y + T.y), C !== 0) {
|
|
3138
|
+
const I = (T.baseWidth ?? 0) / 2, M = (T.baseHeight ?? 0) / 2, { width: P, height: k } = Zt(T.baseWidth ?? 0, T.baseHeight ?? 0, C);
|
|
3139
|
+
x.translateSelf(P / 2, k / 2), x.rotateSelf(C), x.translateSelf(-I, -M);
|
|
3108
3140
|
}
|
|
3109
|
-
w.addPath(R,
|
|
3141
|
+
w.addPath(R, x);
|
|
3110
3142
|
}
|
|
3111
3143
|
t.clip(w, "evenodd");
|
|
3112
3144
|
} else
|
|
3113
|
-
t.rect(p, g, y - p, S - g), r > 0 ? t.roundRect(
|
|
3114
|
-
e.render(t, !1, !1), t.restore(), t.save(), this.applyArtboardClipPath(t,
|
|
3145
|
+
t.rect(p, g, y - p, S - g), 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");
|
|
3146
|
+
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);
|
|
3115
3147
|
}
|
|
3116
3148
|
/**
|
|
3117
3149
|
* Render all elements layer
|
|
@@ -3122,15 +3154,15 @@ const Ke = Jt("CanvasRenderer"), $ = class $ {
|
|
|
3122
3154
|
* a coloured halo rather than useful UX. Selected/hovered elements fall through to the
|
|
3123
3155
|
* clipped-only branch which respects `clipShape` correctly.
|
|
3124
3156
|
*/
|
|
3125
|
-
static renderElementsLayer(t, e,
|
|
3126
|
-
const c =
|
|
3157
|
+
static renderElementsLayer(t, e, s, n, o, i, a, r = !0, l = !1, h = !1) {
|
|
3158
|
+
const c = o != null && o.getMode() === "drag", d = o == null ? void 0 : o._activeChildContext;
|
|
3127
3159
|
e !== $._cachedElementsRef && ($._cachedElementConfigs = e.map((g) => g.toJSON()), $._cachedElementMap = new Map(e.map((g) => [g.id, g])), $._cachedElementsRef = e);
|
|
3128
3160
|
const f = $._cachedElementConfigs, b = $._cachedElementMap, u = $._knockoutRenderedIds;
|
|
3129
3161
|
u.clear(), e.forEach((g, y) => {
|
|
3130
3162
|
var S, m, w;
|
|
3131
3163
|
if (g.blendMode === "knockout" || g.blendMode === "clip") {
|
|
3132
|
-
const T = f[y], R = g.blendMode === "knockout" ? "destination-out" : "destination-in", C = ((S = T.knockoutParts) == null ? void 0 : S.scope) || "group",
|
|
3133
|
-
I && (C === "artboard" ||
|
|
3164
|
+
const T = f[y], R = g.blendMode === "knockout" ? "destination-out" : "destination-in", C = ((S = T.knockoutParts) == null ? void 0 : S.scope) || "group", x = f.findIndex((k) => k.id === T.id), I = ((m = T.knockoutParts) == null ? void 0 : m.fill) || ((w = T.knockoutParts) == null ? void 0 : w.stroke), M = C === "artboard" && x !== -1 ? f.slice(0, x) : [];
|
|
3165
|
+
I && (C === "artboard" || M.length > 0) && (M.forEach((k) => k.id && u.add(k.id)), Ae(
|
|
3134
3166
|
t,
|
|
3135
3167
|
T,
|
|
3136
3168
|
f,
|
|
@@ -3147,18 +3179,18 @@ const Ke = Jt("CanvasRenderer"), $ = class $ {
|
|
|
3147
3179
|
t,
|
|
3148
3180
|
e,
|
|
3149
3181
|
u,
|
|
3150
|
-
|
|
3182
|
+
s,
|
|
3151
3183
|
n,
|
|
3152
3184
|
c,
|
|
3153
3185
|
d,
|
|
3154
3186
|
f,
|
|
3155
3187
|
r
|
|
3156
3188
|
) : e.forEach((g) => {
|
|
3157
|
-
var
|
|
3189
|
+
var x, I;
|
|
3158
3190
|
if (u.has(g.id) || g.visible === !1) return;
|
|
3159
|
-
const y = g.id ===
|
|
3191
|
+
const y = g.id === s, S = (n == null ? void 0 : n.type) === "element" && ((x = n == null ? void 0 : n.data) == null ? void 0 : x.id) === g.id, m = c && d && _t(g) && g.id === s, w = y && !m, T = f[e.indexOf(g)], R = ((I = T == null ? void 0 : T.distressEffect) == null ? void 0 : I.enabled) && T.distressEffect.style === "custom" && T.distressEffect.textureUrl, C = (M) => {
|
|
3160
3192
|
if (T && T.masks && T.masks.length > 0)
|
|
3161
|
-
At(
|
|
3193
|
+
At(M, T, (P) => {
|
|
3162
3194
|
const k = (B) => {
|
|
3163
3195
|
r && (B.save(), B.globalAlpha = tt), this.safeRender(B, g, w, S), r && B.restore();
|
|
3164
3196
|
};
|
|
@@ -3170,15 +3202,15 @@ const Ke = Jt("CanvasRenderer"), $ = class $ {
|
|
|
3170
3202
|
});
|
|
3171
3203
|
else if (R) {
|
|
3172
3204
|
const P = g.getVisualBoundingBox();
|
|
3173
|
-
$t(
|
|
3205
|
+
$t(M, T.distressEffect, P, (k) => {
|
|
3174
3206
|
r && (k.save(), k.globalAlpha = tt), this.safeRender(k, g, w, S), r && k.restore();
|
|
3175
3207
|
});
|
|
3176
|
-
} else l && !h && a && w ? this.renderElementWithOverflowDimming(
|
|
3208
|
+
} else l && !h && a && w ? this.renderElementWithOverflowDimming(M, g, a, w, S, r) : l && a ? (M.save(), this.applyArtboardClipPath(M, a), r && (M.globalAlpha = tt), this.safeRender(M, g, w, S), M.restore()) : (r && (M.save(), M.globalAlpha = tt), this.safeRender(M, g, w, S), r && M.restore());
|
|
3177
3209
|
};
|
|
3178
3210
|
Dt(
|
|
3179
3211
|
t,
|
|
3180
3212
|
T,
|
|
3181
|
-
(
|
|
3213
|
+
(M) => C(M)
|
|
3182
3214
|
);
|
|
3183
3215
|
});
|
|
3184
3216
|
}
|
|
@@ -3186,13 +3218,13 @@ const Ke = Jt("CanvasRenderer"), $ = class $ {
|
|
|
3186
3218
|
* Render elements with clipping mask support at artboard level
|
|
3187
3219
|
* Elements with isClipping=true clip all elements below them
|
|
3188
3220
|
*/
|
|
3189
|
-
static _renderWithClipping(t, e,
|
|
3221
|
+
static _renderWithClipping(t, e, s, n, o, i, a, r, l = !0) {
|
|
3190
3222
|
var g;
|
|
3191
3223
|
const h = t.canvas, c = h.width, d = h.height, f = t.getTransform(), b = [];
|
|
3192
3224
|
let u = [], p = [];
|
|
3193
3225
|
for (let y = 0; y < e.length; y++) {
|
|
3194
3226
|
const S = e[y], m = r[y];
|
|
3195
|
-
|
|
3227
|
+
s.has(S.id) || S.visible !== !1 && (S.isClipping ? u.length > 0 ? (b.push({
|
|
3196
3228
|
content: u,
|
|
3197
3229
|
mask: S,
|
|
3198
3230
|
contentConfigs: p,
|
|
@@ -3210,10 +3242,10 @@ const Ke = Jt("CanvasRenderer"), $ = class $ {
|
|
|
3210
3242
|
if (!y.mask)
|
|
3211
3243
|
y.content.forEach((S, m) => {
|
|
3212
3244
|
var I;
|
|
3213
|
-
const w = S.id === n, T = (
|
|
3214
|
-
Dt(t,
|
|
3215
|
-
const P =
|
|
3216
|
-
|
|
3245
|
+
const w = S.id === n, T = (o == null ? void 0 : o.type) === "element" && ((I = o == null ? void 0 : o.data) == null ? void 0 : I.id) === S.id, R = i && a && _t(S) && S.id === n, C = w && !R, x = y.contentConfigs[m];
|
|
3246
|
+
Dt(t, x, (M) => {
|
|
3247
|
+
const P = M;
|
|
3248
|
+
x && x.masks && x.masks.length > 0 ? At(P, x, (k) => {
|
|
3217
3249
|
l && (k.save(), k.globalAlpha = tt), S.render(k, C, T), l && k.restore();
|
|
3218
3250
|
}) : (l && (P.save(), P.globalAlpha = tt), S.render(P, C, T), l && P.restore());
|
|
3219
3251
|
});
|
|
@@ -3221,22 +3253,22 @@ const Ke = Jt("CanvasRenderer"), $ = class $ {
|
|
|
3221
3253
|
else {
|
|
3222
3254
|
const S = this._getContentCanvas(c, d), m = S.getContext("2d");
|
|
3223
3255
|
if (!m) continue;
|
|
3224
|
-
m.setTransform(1, 0, 0, 1, 0, 0), m.clearRect(0, 0, c, d), m.globalCompositeOperation = "source-over", m.setTransform(f), y.content.forEach((
|
|
3256
|
+
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, I) => {
|
|
3225
3257
|
var F;
|
|
3226
|
-
const
|
|
3258
|
+
const M = x.id === n, P = (o == null ? void 0 : o.type) === "element" && ((F = o == null ? void 0 : o.data) == null ? void 0 : F.id) === x.id, k = i && a && _t(x) && x.id === n, B = M && !k, W = y.contentConfigs[I];
|
|
3227
3259
|
Dt(m, W, (D) => {
|
|
3228
3260
|
const N = D;
|
|
3229
3261
|
W && W.masks && W.masks.length > 0 ? At(N, W, (j) => {
|
|
3230
|
-
l && (j.save(), j.globalAlpha = tt),
|
|
3231
|
-
}) : (l && (N.save(), N.globalAlpha = tt),
|
|
3262
|
+
l && (j.save(), j.globalAlpha = tt), x.render(j, B, P), l && j.restore();
|
|
3263
|
+
}) : (l && (N.save(), N.globalAlpha = tt), x.render(N, B, P), l && N.restore());
|
|
3232
3264
|
});
|
|
3233
3265
|
});
|
|
3234
3266
|
const w = this._getMaskCanvas(c, d), T = w.getContext("2d");
|
|
3235
3267
|
if (!T) continue;
|
|
3236
3268
|
T.setTransform(1, 0, 0, 1, 0, 0), T.clearRect(0, 0, c, d), T.globalCompositeOperation = "source-over", T.setTransform(f);
|
|
3237
|
-
const R = y.mask.id === n, C = (
|
|
3238
|
-
y.maskConfig && y.maskConfig.masks && y.maskConfig.masks.length > 0 ? At(T, y.maskConfig, (
|
|
3239
|
-
l && (
|
|
3269
|
+
const R = y.mask.id === n, C = (o == null ? void 0 : o.type) === "element" && ((g = o == null ? void 0 : o.data) == null ? void 0 : g.id) === y.mask.id;
|
|
3270
|
+
y.maskConfig && y.maskConfig.masks && y.maskConfig.masks.length > 0 ? At(T, y.maskConfig, (x) => {
|
|
3271
|
+
l && (x.save(), x.globalAlpha = tt), y.mask.render(x, R, C), l && x.restore();
|
|
3240
3272
|
}) : (l && (T.save(), T.globalAlpha = tt), y.mask.render(T, R, C), 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();
|
|
3241
3273
|
}
|
|
3242
3274
|
}
|
|
@@ -3261,34 +3293,34 @@ const Ke = Jt("CanvasRenderer"), $ = class $ {
|
|
|
3261
3293
|
* Render a distance label with background
|
|
3262
3294
|
* @see InteractionFeedbackRenderer.renderDistanceLabel
|
|
3263
3295
|
*/
|
|
3264
|
-
static renderDistanceLabel(t, e,
|
|
3265
|
-
Rt.renderDistanceLabel(t, e,
|
|
3296
|
+
static renderDistanceLabel(t, e, s, n) {
|
|
3297
|
+
Rt.renderDistanceLabel(t, e, s, n);
|
|
3266
3298
|
}
|
|
3267
3299
|
/**
|
|
3268
3300
|
* Render selection box layer
|
|
3269
3301
|
* @see SelectionRenderer.renderSelectionLayer
|
|
3270
3302
|
*/
|
|
3271
|
-
static renderSelectionLayer(t, e,
|
|
3272
|
-
wt.renderSelectionLayer(t, e,
|
|
3303
|
+
static renderSelectionLayer(t, e, s, n = 1) {
|
|
3304
|
+
wt.renderSelectionLayer(t, e, s, n);
|
|
3273
3305
|
}
|
|
3274
3306
|
/**
|
|
3275
3307
|
* Render position and size info below the selected element
|
|
3276
3308
|
* @see SelectionRenderer.renderPositionSizeInfo
|
|
3277
3309
|
*/
|
|
3278
|
-
static renderPositionSizeInfo(t, e,
|
|
3279
|
-
wt.renderPositionSizeInfo(t, e,
|
|
3310
|
+
static renderPositionSizeInfo(t, e, s, n, o = 1) {
|
|
3311
|
+
wt.renderPositionSizeInfo(t, e, s, n, o);
|
|
3280
3312
|
}
|
|
3281
3313
|
/**
|
|
3282
3314
|
* Render transform handles layer
|
|
3283
3315
|
* @see SelectionRenderer.renderHandlesLayer
|
|
3284
3316
|
*/
|
|
3285
|
-
static renderHandlesLayer(t, e,
|
|
3317
|
+
static renderHandlesLayer(t, e, s, n, o, i, a, r = 1, l = !0) {
|
|
3286
3318
|
wt.renderHandlesLayer(
|
|
3287
3319
|
t,
|
|
3288
3320
|
e,
|
|
3289
|
-
o,
|
|
3290
|
-
n,
|
|
3291
3321
|
s,
|
|
3322
|
+
n,
|
|
3323
|
+
o,
|
|
3292
3324
|
i,
|
|
3293
3325
|
a,
|
|
3294
3326
|
r,
|
|
@@ -3299,15 +3331,15 @@ const Ke = Jt("CanvasRenderer"), $ = class $ {
|
|
|
3299
3331
|
* Render hover highlights layer with fade-in animation
|
|
3300
3332
|
* @see HoverRenderer.renderHoverLayer
|
|
3301
3333
|
*/
|
|
3302
|
-
static renderHoverLayer(t, e,
|
|
3303
|
-
Ft.renderHoverLayer(t, e,
|
|
3334
|
+
static renderHoverLayer(t, e, s, n = !1, o = 1, i) {
|
|
3335
|
+
Ft.renderHoverLayer(t, e, s, n, o, i);
|
|
3304
3336
|
}
|
|
3305
3337
|
/**
|
|
3306
3338
|
* Render crop box layer (for images in crop mode)
|
|
3307
3339
|
* @see EditModeRenderer.renderCropBoxLayer
|
|
3308
3340
|
*/
|
|
3309
|
-
static renderCropBoxLayer(t, e,
|
|
3310
|
-
Vt.renderCropBoxLayer(t, e,
|
|
3341
|
+
static renderCropBoxLayer(t, e, s, n = 1) {
|
|
3342
|
+
Vt.renderCropBoxLayer(t, e, s, n);
|
|
3311
3343
|
}
|
|
3312
3344
|
// =========================================================================
|
|
3313
3345
|
// Main Render Orchestration
|
|
@@ -3319,7 +3351,7 @@ const Ke = Jt("CanvasRenderer"), $ = class $ {
|
|
|
3319
3351
|
static render({
|
|
3320
3352
|
ctx: t,
|
|
3321
3353
|
elements: e,
|
|
3322
|
-
selectedId:
|
|
3354
|
+
selectedId: s,
|
|
3323
3355
|
selectedElement: n,
|
|
3324
3356
|
// Chrome-related fields (transformHandles, currentRotation,
|
|
3325
3357
|
// isRotating, hideHandles, isAltKeyPressed, showRotationHandle)
|
|
@@ -3328,7 +3360,7 @@ const Ke = Jt("CanvasRenderer"), $ = class $ {
|
|
|
3328
3360
|
// consumed here — single-selection chrome is now drawn by
|
|
3329
3361
|
// `renderInteractionChromeLayer` after piece guides. See that
|
|
3330
3362
|
// method for the actual chrome rendering.
|
|
3331
|
-
hoverState:
|
|
3363
|
+
hoverState: o,
|
|
3332
3364
|
isEditing: i,
|
|
3333
3365
|
stateMachine: a,
|
|
3334
3366
|
snapGuides: r = [],
|
|
@@ -3347,18 +3379,18 @@ const Ke = Jt("CanvasRenderer"), $ = class $ {
|
|
|
3347
3379
|
if (this.renderElementsLayer(
|
|
3348
3380
|
t,
|
|
3349
3381
|
e,
|
|
3350
|
-
o,
|
|
3351
3382
|
s,
|
|
3383
|
+
o,
|
|
3352
3384
|
a ?? void 0,
|
|
3353
3385
|
h,
|
|
3354
3386
|
c,
|
|
3355
3387
|
d,
|
|
3356
3388
|
u,
|
|
3357
3389
|
p
|
|
3358
|
-
), g != null && g.enabled && c &&
|
|
3390
|
+
), g != null && g.enabled && c && Ee(t, g, c, h), y != null && y.enabled && c && He(t, y, c, h), i && S && n && Vt.renderEditModeLayer(t, n, S, f), f !== 1) {
|
|
3359
3391
|
t.save();
|
|
3360
|
-
const R = t.getTransform().a / f, C = b.x * f * R,
|
|
3361
|
-
t.setTransform(R, 0, 0, R, C,
|
|
3392
|
+
const R = t.getTransform().a / f, C = b.x * f * R, x = b.y * f * R;
|
|
3393
|
+
t.setTransform(R, 0, 0, R, C, x);
|
|
3362
3394
|
}
|
|
3363
3395
|
const m = r.map((T) => ({
|
|
3364
3396
|
...T,
|
|
@@ -3396,9 +3428,9 @@ const Ke = Jt("CanvasRenderer"), $ = class $ {
|
|
|
3396
3428
|
static renderInteractionChromeLayer({
|
|
3397
3429
|
ctx: t,
|
|
3398
3430
|
selectedElement: e,
|
|
3399
|
-
transformHandles:
|
|
3431
|
+
transformHandles: s,
|
|
3400
3432
|
stateMachine: n,
|
|
3401
|
-
currentRotation:
|
|
3433
|
+
currentRotation: o,
|
|
3402
3434
|
isRotating: i,
|
|
3403
3435
|
hoverState: a,
|
|
3404
3436
|
selectedId: r,
|
|
@@ -3416,13 +3448,13 @@ const Ke = Jt("CanvasRenderer"), $ = class $ {
|
|
|
3416
3448
|
const S = t.getTransform().a / u, m = p.x * u * S, w = p.y * u * S;
|
|
3417
3449
|
t.setTransform(S, 0, 0, S, m, w);
|
|
3418
3450
|
}
|
|
3419
|
-
if (e &&
|
|
3420
|
-
|
|
3421
|
-
else if (!l && n && wt.renderSelectionLayer(t, e, n, u),
|
|
3451
|
+
if (e && Be(e) && e.isCropping)
|
|
3452
|
+
s && Vt.renderCropBoxLayer(t, e, s, u);
|
|
3453
|
+
else if (!l && n && wt.renderSelectionLayer(t, e, n, u), s && n && wt.renderPositionSizeInfo(t, e, s, n, u), !l && s && n && wt.renderHandlesLayer(
|
|
3422
3454
|
t,
|
|
3423
3455
|
e,
|
|
3424
|
-
o,
|
|
3425
3456
|
s,
|
|
3457
|
+
o,
|
|
3426
3458
|
i,
|
|
3427
3459
|
a,
|
|
3428
3460
|
n,
|
|
@@ -3440,20 +3472,23 @@ const Ke = Jt("CanvasRenderer"), $ = class $ {
|
|
|
3440
3472
|
}
|
|
3441
3473
|
};
|
|
3442
3474
|
$._contentCanvas = null, $._contentCanvasSize = { width: 0, height: 0 }, $._maskCanvas = null, $._maskCanvasSize = { width: 0, height: 0 }, $._cachedElementsRef = null, $._cachedElementConfigs = null, $._cachedElementMap = null, $._knockoutRenderedIds = /* @__PURE__ */ new Set(), $.onRenderError = null;
|
|
3443
|
-
let
|
|
3475
|
+
let Jt = $;
|
|
3444
3476
|
export {
|
|
3445
|
-
|
|
3446
|
-
|
|
3447
|
-
|
|
3448
|
-
|
|
3449
|
-
|
|
3450
|
-
|
|
3451
|
-
|
|
3452
|
-
|
|
3453
|
-
|
|
3454
|
-
|
|
3455
|
-
|
|
3477
|
+
an as A,
|
|
3478
|
+
Jt as C,
|
|
3479
|
+
on as I,
|
|
3480
|
+
Ke as R,
|
|
3481
|
+
rn as S,
|
|
3482
|
+
nn as T,
|
|
3483
|
+
oe as a,
|
|
3484
|
+
hn as b,
|
|
3485
|
+
tn as c,
|
|
3486
|
+
Qe as d,
|
|
3487
|
+
Ye as e,
|
|
3488
|
+
sn as f,
|
|
3456
3489
|
jt as g,
|
|
3457
|
-
|
|
3490
|
+
ie as n,
|
|
3491
|
+
ln as p,
|
|
3492
|
+
en as r
|
|
3458
3493
|
};
|
|
3459
|
-
//# sourceMappingURL=CanvasRenderer-
|
|
3494
|
+
//# sourceMappingURL=CanvasRenderer-COO5UXtZ.js.map
|