@snowcone-app/canvas 0.28.0 → 0.29.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-B_3GISlW.js → CanvasRenderer-_lFoIoz5.js} +1083 -1071
- package/dist/CanvasRenderer-_lFoIoz5.js.map +1 -0
- package/dist/{CanvasStateV1-kL09wsAn.js → CanvasStateV1-BMxr6xb8.js} +7 -4
- package/dist/{CanvasStateV1-kL09wsAn.js.map → CanvasStateV1-BMxr6xb8.js.map} +1 -1
- package/dist/{ContextualToolbars-C69oYLdw.js → ContextualToolbars-0jWvnQgp.js} +1718 -1656
- package/dist/ContextualToolbars-0jWvnQgp.js.map +1 -0
- package/dist/{EditorCanvasImpl-CrI9C_xM.js → EditorCanvasImpl-BNz8TPFs.js} +8 -8
- package/dist/{EditorCanvasImpl-CrI9C_xM.js.map → EditorCanvasImpl-BNz8TPFs.js.map} +1 -1
- package/dist/{ExportManager-J2xK86uq.js → ExportManager-B8Td7uR5.js} +1043 -964
- package/dist/ExportManager-B8Td7uR5.js.map +1 -0
- package/dist/{FontAnalyzer-PE6nysqE.js → FontAnalyzer-D4Sg-P6_.js} +1234 -1172
- package/dist/FontAnalyzer-D4Sg-P6_.js.map +1 -0
- package/dist/{ImagePanel-CmQCxBGm.js → ImagePanel-CN2Bu3hf.js} +6 -6
- package/dist/{ImagePanel-CmQCxBGm.js.map → ImagePanel-CN2Bu3hf.js.map} +1 -1
- package/dist/{SnowconeCanvas-CQiFVR0X.js → SnowconeCanvas-CR_LdRFP.js} +27 -27
- package/dist/{SnowconeCanvas-CQiFVR0X.js.map → SnowconeCanvas-CR_LdRFP.js.map} +1 -1
- package/dist/{UnifiedFontService-BJzoqfBF.js → UnifiedFontService-CgYnYTj7.js} +7 -7
- package/dist/{UnifiedFontService-BJzoqfBF.js.map → UnifiedFontService-CgYnYTj7.js.map} +1 -1
- package/dist/advanced.mjs +14 -14
- package/dist/components/toolbars/SecondaryPanels.d.ts +11 -0
- package/dist/core/TextElement.d.ts +13 -0
- package/dist/core/TextMetrics.d.ts +17 -3
- package/dist/core/rich-text-layout.d.ts +2 -0
- package/dist/core/text-spacing.d.ts +74 -0
- package/dist/{custom-icons-BWiUGqD6.js → custom-icons-B5TRC1Ed.js} +2 -2
- package/dist/{custom-icons-BWiUGqD6.js.map → custom-icons-B5TRC1Ed.js.map} +1 -1
- package/dist/{design-builder-bquxIHct.js → design-builder-COj0zkxu.js} +2 -2
- package/dist/{design-builder-bquxIHct.js.map → design-builder-COj0zkxu.js.map} +1 -1
- package/dist/{editorErrors-8uDRMhow.js → editorErrors-CCvoKj_P.js} +2 -2
- package/dist/{editorErrors-8uDRMhow.js.map → editorErrors-CCvoKj_P.js.map} +1 -1
- package/dist/{embed-L3oRIgsj.js → embed-BTRtoktw.js} +10 -10
- package/dist/{embed-L3oRIgsj.js.map → embed-BTRtoktw.js.map} +1 -1
- package/dist/embed.mjs +6 -6
- package/dist/{guards-BlbhM5MX.js → guards-uQtEQJbs.js} +2 -2
- package/dist/{guards-BlbhM5MX.js.map → guards-uQtEQJbs.js.map} +1 -1
- package/dist/hooks/useTextToolbar.d.ts +8 -0
- package/dist/index.mjs +8 -8
- package/dist/internals.mjs +5 -5
- package/dist/rendering/renderer-types.d.ts +4 -0
- package/dist/rendering/rich-text-renderer.d.ts +4 -0
- package/dist/rendering/text-renderer.d.ts +4 -1
- package/dist/state/CanvasStateV1.d.ts +3 -0
- package/dist/{template-fields-ai7vnW8g.js → template-fields-BLRp84Ny.js} +6 -6
- package/dist/{template-fields-ai7vnW8g.js.map → template-fields-BLRp84Ny.js.map} +1 -1
- package/dist/testing.mjs +4 -4
- package/dist/types/index.d.ts +26 -0
- package/dist/{usePieceGuideBundle-CMe5br2a.js → usePieceGuideBundle-CTQszfKA.js} +2 -2
- package/dist/{usePieceGuideBundle-CMe5br2a.js.map → usePieceGuideBundle-CTQszfKA.js.map} +1 -1
- package/dist/utils/featureApplied.d.ts +6 -0
- package/dist/{validation-B8kIYutI.js → validation-eCebhplp.js} +1940 -1935
- package/dist/validation-eCebhplp.js.map +1 -0
- package/dist/workers/export-worker.bundle.string.d.ts +1 -1
- package/example/package.json +1 -1
- package/package.json +1 -1
- package/dist/CanvasRenderer-B_3GISlW.js.map +0 -1
- package/dist/ContextualToolbars-C69oYLdw.js.map +0 -1
- package/dist/ExportManager-J2xK86uq.js.map +0 -1
- package/dist/FontAnalyzer-PE6nysqE.js.map +0 -1
- package/dist/validation-B8kIYutI.js.map +0 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { X as
|
|
2
|
-
import { T as
|
|
3
|
-
import { i as
|
|
4
|
-
const
|
|
1
|
+
import { X as oe, Y as ie, au as nt, Z as Ft, aH as ae, aF as re, ay as Ot, aE as le, ax as gt, aI as he, aJ as Yt, aK as ce, aL as de, c as Zt, aM as fe, aN as ge, aO as ue, aP as pe, a4 as Jt, a0 as Qt, a8 as pt, a1 as te, a2 as Lt, a9 as Gt, a7 as Pt, aa as Xt, a5 as ye, ab as be, aQ as Nt, aR as Se, aS as me, aT as Te, I as we, aU as ve, aV as Me, aW as tt } from "./FontAnalyzer-D4Sg-P6_.js";
|
|
2
|
+
import { T as Wt, a as xe, u as Ce, K as Re, z as At, L as Kt, M as ke, N as Pe, O as Ae } from "./ExportManager-B8Td7uR5.js";
|
|
3
|
+
import { i as Dt, a as Ee } from "./guards-uQtEQJbs.js";
|
|
4
|
+
const ct = {
|
|
5
5
|
// Canvas-specific
|
|
6
6
|
canvas: {
|
|
7
7
|
snapThreshold: 8,
|
|
@@ -15,30 +15,30 @@ const rt = {
|
|
|
15
15
|
spacingLabelFontSize: 11,
|
|
16
16
|
spacingLabelFontFamily: "-apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif"
|
|
17
17
|
}
|
|
18
|
-
},
|
|
19
|
-
function
|
|
20
|
-
return
|
|
18
|
+
}, He = 2, Rt = 6, Ie = 16, Be = 5, Le = 5, ee = 0.5;
|
|
19
|
+
function $t(v) {
|
|
20
|
+
return He / v;
|
|
21
21
|
}
|
|
22
|
-
function
|
|
23
|
-
return
|
|
22
|
+
function qe(v) {
|
|
23
|
+
return Rt / v;
|
|
24
24
|
}
|
|
25
|
-
function
|
|
26
|
-
return
|
|
25
|
+
function We(v) {
|
|
26
|
+
return Ie / v;
|
|
27
27
|
}
|
|
28
|
-
function
|
|
29
|
-
return [
|
|
28
|
+
function Ue(v) {
|
|
29
|
+
return [Be / v, Le / v];
|
|
30
30
|
}
|
|
31
|
-
function
|
|
31
|
+
function De(v, t, e, o) {
|
|
32
32
|
v.save();
|
|
33
|
-
const n =
|
|
33
|
+
const n = ee / o;
|
|
34
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
|
-
v.save(), v.fillStyle = "#fff", v.strokeStyle = n, v.lineWidth =
|
|
36
|
+
function Ze(v, t, e, o = 1, n = "#3b82f6", s = !1) {
|
|
37
|
+
const i = We(o);
|
|
38
|
+
v.save(), v.fillStyle = "#fff", v.strokeStyle = n, v.lineWidth = s ? $t(o) * 1.25 : $t(o), v.beginPath(), v.arc(t, e, i, 0, Math.PI * 2), v.fill(), v.stroke(), De(v, t, e, o), v.restore();
|
|
39
39
|
}
|
|
40
|
-
const
|
|
41
|
-
class
|
|
40
|
+
const jt = Rt * 2;
|
|
41
|
+
class Je {
|
|
42
42
|
constructor() {
|
|
43
43
|
this.resizeHandles = [], this.rotationHandle = null, this.elementRotation = 0, this.rotationAnchor = { x: 0, y: 0 };
|
|
44
44
|
}
|
|
@@ -48,18 +48,18 @@ class je {
|
|
|
48
48
|
* @param zoom - Current zoom level (used to maintain consistent rotation handle distance in screen space)
|
|
49
49
|
*/
|
|
50
50
|
update(t, e = 1) {
|
|
51
|
-
const n = "isCropping" in t && t.isCropping ? t.getBoundingBox() : t.getVisualBoundingBox(),
|
|
52
|
-
this.elementRotation = t.rotation, this.rotationAnchor =
|
|
53
|
-
const a =
|
|
51
|
+
const n = "isCropping" in t && t.isCropping ? t.getBoundingBox() : t.getVisualBoundingBox(), s = t.getRotationAnchor(), i = t.getEnabledAnchors();
|
|
52
|
+
this.elementRotation = t.rotation, this.rotationAnchor = s;
|
|
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 = oe(r, t.rotation, s), 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 = ie(
|
|
60
60
|
r,
|
|
61
61
|
t.rotation,
|
|
62
|
-
|
|
62
|
+
s,
|
|
63
63
|
e
|
|
64
64
|
);
|
|
65
65
|
}
|
|
@@ -67,68 +67,68 @@ class je {
|
|
|
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, o = 0, n = !1, s = !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, s, l), h && e && this.rotationHandle && n && this.renderRotationTooltip(t, this.rotationHandle, o, 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, o = !1, n = !1, s = 1) {
|
|
83
83
|
t.save();
|
|
84
|
-
const i = e.x *
|
|
84
|
+
const i = e.x * s, a = e.y * s;
|
|
85
85
|
if (e.anchor.includes("middle")) {
|
|
86
86
|
const l = e.anchor === "middle-top" || e.anchor === "middle-bottom";
|
|
87
87
|
t.translate(i, a), t.rotate(-this.elementRotation * Math.PI / 180), l && t.rotate(Math.PI / 2), t.translate(-i, -a);
|
|
88
|
-
const h =
|
|
89
|
-
t.fillStyle = "#fff", t.strokeStyle =
|
|
88
|
+
const h = jt * 0.6, c = jt * 1.4, d = h / 2, f = i - h / 2, b = a - c / 2;
|
|
89
|
+
t.fillStyle = "#fff", t.strokeStyle = nt(t.canvas), t.lineWidth = o || 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 =
|
|
91
|
+
t.fillStyle = "#fff", t.strokeStyle = nt(t.canvas), t.lineWidth = o || n ? 2.5 : 2, t.beginPath(), t.arc(i, a, Rt, 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, o = !1, n = 1) {
|
|
99
99
|
t.save();
|
|
100
|
-
const
|
|
101
|
-
t.fillStyle = "#fff", t.strokeStyle =
|
|
102
|
-
const r =
|
|
103
|
-
t.translate(
|
|
100
|
+
const s = e.x * n, i = e.y * n, a = Rt * 2.67;
|
|
101
|
+
t.fillStyle = "#fff", t.strokeStyle = nt(t.canvas), t.lineWidth = o ? 2.5 : 2, t.beginPath(), t.arc(s, i, a, 0, Math.PI * 2), t.fill(), t.stroke();
|
|
102
|
+
const r = ee;
|
|
103
|
+
t.translate(s, 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, o, 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 s = `${Math.round(o)}°`, i = s.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(s, 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 (
|
|
121
|
-
return
|
|
117
|
+
hitTestResize(t, e, o = 1) {
|
|
118
|
+
const n = re / o;
|
|
119
|
+
for (const s of this.resizeHandles)
|
|
120
|
+
if (Ft(t, e, s.x, s.y, n))
|
|
121
|
+
return s;
|
|
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, o = 1) {
|
|
129
129
|
if (!this.rotationHandle) return !1;
|
|
130
|
-
const n = (
|
|
131
|
-
return
|
|
130
|
+
const n = (Rt * 2.67 + 2) / o;
|
|
131
|
+
return Ft(t, e, this.rotationHandle.x, this.rotationHandle.y, n);
|
|
132
132
|
}
|
|
133
133
|
/**
|
|
134
134
|
* Get rotation handle position (for React-based rendering)
|
|
@@ -142,37 +142,37 @@ class je {
|
|
|
142
142
|
* @param rotation - Element rotation in degrees
|
|
143
143
|
*/
|
|
144
144
|
getCursor(t, e) {
|
|
145
|
-
const
|
|
146
|
-
return
|
|
145
|
+
const o = t.anchor.includes("middle") ? "edge" : "corner";
|
|
146
|
+
return ae(
|
|
147
147
|
t.x,
|
|
148
148
|
t.y,
|
|
149
149
|
this.rotationAnchor.x,
|
|
150
150
|
this.rotationAnchor.y,
|
|
151
|
-
|
|
151
|
+
o,
|
|
152
152
|
e,
|
|
153
153
|
t.anchor
|
|
154
154
|
);
|
|
155
155
|
}
|
|
156
156
|
}
|
|
157
|
-
const
|
|
158
|
-
function
|
|
157
|
+
const _e = 15;
|
|
158
|
+
function ze(v, t) {
|
|
159
159
|
return Math.abs(v) >= Math.abs(t) ? "x" : "y";
|
|
160
160
|
}
|
|
161
|
-
function
|
|
162
|
-
return e != null && e.shift ?
|
|
161
|
+
function Ve(v, t, e) {
|
|
162
|
+
return e != null && e.shift ? ze(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 Fe(v, t = _e) {
|
|
165
|
+
let o = (Math.round(v / t) * t % 360 + 360) % 360;
|
|
166
|
+
return o > 180 && (o -= 360), o === 0 ? 0 : o;
|
|
167
167
|
}
|
|
168
|
-
function
|
|
168
|
+
function Oe({
|
|
169
169
|
anchor: v,
|
|
170
170
|
startVisualWidth: t,
|
|
171
171
|
startVisualHeight: e,
|
|
172
|
-
newVisualWidth:
|
|
172
|
+
newVisualWidth: o,
|
|
173
173
|
newVisualHeight: n
|
|
174
174
|
}) {
|
|
175
|
-
const
|
|
175
|
+
const s = t !== 0 ? t : 1, i = e !== 0 ? e : 1, a = o / s, r = n / i;
|
|
176
176
|
let l;
|
|
177
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,
|
|
@@ -180,83 +180,83 @@ function _e({
|
|
|
180
180
|
newVisualHeight: e * l
|
|
181
181
|
};
|
|
182
182
|
}
|
|
183
|
-
class
|
|
183
|
+
class Ye {
|
|
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: o,
|
|
191
191
|
dy: n,
|
|
192
|
-
startData:
|
|
192
|
+
startData: s,
|
|
193
193
|
snapSystem: i,
|
|
194
194
|
modifiers: a
|
|
195
195
|
}) {
|
|
196
|
-
var
|
|
197
|
-
const l = new
|
|
198
|
-
let
|
|
199
|
-
e.anchor.includes("right") ?
|
|
196
|
+
var F, W, q, J, E;
|
|
197
|
+
const l = new Ot(t).worldDeltaToLocal(o, n), h = l.dx, c = l.dy, d = s.visualWidth ?? s.width ?? 0, f = s.visualHeight ?? s.height ?? 0, b = s.width ?? 0, u = s.height ?? 0;
|
|
198
|
+
let p = d, g = f;
|
|
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
|
|
203
|
+
const z = Oe({
|
|
204
204
|
anchor: e.anchor,
|
|
205
205
|
startVisualWidth: d,
|
|
206
206
|
startVisualHeight: f,
|
|
207
|
-
newVisualWidth:
|
|
208
|
-
newVisualHeight:
|
|
207
|
+
newVisualWidth: p,
|
|
208
|
+
newVisualHeight: g
|
|
209
209
|
});
|
|
210
|
-
S =
|
|
210
|
+
S = z.scale, p = z.newVisualWidth, g = z.newVisualHeight;
|
|
211
211
|
}
|
|
212
212
|
let m, w;
|
|
213
213
|
if (S !== null)
|
|
214
|
-
m =
|
|
214
|
+
m = b * S, w = u * S;
|
|
215
215
|
else if (e.anchor === "middle-left" || e.anchor === "middle-right") {
|
|
216
|
-
const
|
|
217
|
-
m =
|
|
216
|
+
const z = p - d;
|
|
217
|
+
m = b + z, w = u;
|
|
218
218
|
} else if (e.anchor === "middle-top" || e.anchor === "middle-bottom") {
|
|
219
|
-
const
|
|
220
|
-
m =
|
|
219
|
+
const z = g - f;
|
|
220
|
+
m = b, w = u + z;
|
|
221
221
|
} else {
|
|
222
|
-
const
|
|
223
|
-
m =
|
|
222
|
+
const z = p / d, N = g / f;
|
|
223
|
+
m = b * z, w = u * N;
|
|
224
224
|
}
|
|
225
|
-
const T =
|
|
225
|
+
const T = p, C = g;
|
|
226
226
|
let R = !1;
|
|
227
227
|
if (i && t.transformType === "image") {
|
|
228
|
-
const
|
|
229
|
-
if (
|
|
230
|
-
const
|
|
231
|
-
if (!!
|
|
232
|
-
const
|
|
233
|
-
(
|
|
228
|
+
const z = e.anchor ?? "", N = z === "top-left" || z === "top-right" || z === "bottom-left" || z === "bottom-right", Q = z.startsWith("crop-");
|
|
229
|
+
if (N && !Q) {
|
|
230
|
+
const B = (F = i.activeSnaps) == null ? void 0 : F.x, k = (W = i.activeSnaps) == null ? void 0 : W.y;
|
|
231
|
+
if (!!B || !!k) {
|
|
232
|
+
const G = [B, k].find(
|
|
233
|
+
(P) => typeof P == "object" && P !== null && "frozenWidth" in P
|
|
234
234
|
);
|
|
235
|
-
if (
|
|
236
|
-
const
|
|
237
|
-
let
|
|
238
|
-
|
|
239
|
-
const
|
|
240
|
-
|
|
235
|
+
if (G) {
|
|
236
|
+
const P = t, _ = s.transformData, j = G.frozenWidth ?? ((q = P.transformData) == null ? void 0 : q.width) ?? b, ot = P.imageAspectRatio || (_ != null && _.width && (_ != null && _.height) ? _.width / _.height : null);
|
|
237
|
+
let et = G.frozenHeight;
|
|
238
|
+
et == null && (ot && ot !== 0 ? et = j / ot : (J = P.transformData) != null && J.height ? et = P.transformData.height : et = u);
|
|
239
|
+
const lt = b !== 0 ? j / b : 1, Y = u !== 0 ? et / u : 1;
|
|
240
|
+
p = d * lt, g = f * Y, m = j, w = et, R = !0;
|
|
241
241
|
}
|
|
242
242
|
}
|
|
243
243
|
}
|
|
244
244
|
}
|
|
245
245
|
m = Math.max(50, m), w = Math.max(40, w);
|
|
246
|
-
const x = t.clone(),
|
|
247
|
-
if (!e.anchor.includes("middle") && ((
|
|
248
|
-
const
|
|
249
|
-
x.stroke = { ...x.stroke, width:
|
|
246
|
+
const x = t.clone(), H = x.resize(e.anchor, m, w, s);
|
|
247
|
+
if (!e.anchor.includes("middle") && ((E = x.stroke) != null && E.enabled) && s.strokeWidth !== void 0 && s.strokeWidth > 0) {
|
|
248
|
+
const z = s.width ?? 1, N = s.height ?? 1, Q = Math.sqrt(m / z * (w / N)), B = Math.max(1, Math.round(s.strokeWidth * Q * 10) / 10);
|
|
249
|
+
x.stroke = { ...x.stroke, width: B };
|
|
250
250
|
}
|
|
251
|
-
const A = R ||
|
|
252
|
-
if (
|
|
253
|
-
const
|
|
251
|
+
const A = R || H === !1, I = e.anchor.includes("top") || e.anchor.includes("bottom"), L = "isCropping" in x && x.isCropping, D = "isGroup" in x && x.isGroup;
|
|
252
|
+
if (I && !L && !D) {
|
|
253
|
+
const z = t.getRotationAnchor(), N = this._calculateFixedCornerOffset({
|
|
254
254
|
element: t,
|
|
255
255
|
updatedElement: x,
|
|
256
256
|
handle: e,
|
|
257
|
-
rotationAnchor:
|
|
257
|
+
rotationAnchor: z
|
|
258
258
|
});
|
|
259
|
-
x.x +=
|
|
259
|
+
x.x += N.x, x.y += N.y;
|
|
260
260
|
}
|
|
261
261
|
return {
|
|
262
262
|
element: x,
|
|
@@ -273,27 +273,27 @@ class ze {
|
|
|
273
273
|
static _calculateFixedCornerOffset({
|
|
274
274
|
element: t,
|
|
275
275
|
updatedElement: e,
|
|
276
|
-
handle:
|
|
276
|
+
handle: o,
|
|
277
277
|
rotationAnchor: n
|
|
278
278
|
}) {
|
|
279
|
-
const
|
|
279
|
+
const s = new Ot(t), { cos: i, sin: a } = s.getRenderingCosSin(), r = t.getVisualBoundingBox(), l = e.getVisualBoundingBox(), h = n, c = e.getRotationAnchor(), d = this._getFixedLocalCoords(o.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, C = this._getFixedLocalCoords(o.anchor, l.width, l.height), R = C.x, x = C.y, H = l.x - c.x, M = l.y - c.y, A = H + R, I = M + x, L = A * i - I * a, D = A * a + I * i, F = c.x + L, W = c.y + D;
|
|
280
280
|
return {
|
|
281
|
-
x: w -
|
|
282
|
-
y: T -
|
|
281
|
+
x: w - F,
|
|
282
|
+
y: T - W
|
|
283
283
|
};
|
|
284
284
|
}
|
|
285
285
|
/**
|
|
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, o) {
|
|
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 = o;
|
|
294
294
|
break;
|
|
295
295
|
case "top-right":
|
|
296
|
-
n.x = 0, n.y =
|
|
296
|
+
n.x = 0, n.y = o;
|
|
297
297
|
break;
|
|
298
298
|
case "bottom-left":
|
|
299
299
|
n.x = e, n.y = 0;
|
|
@@ -302,13 +302,13 @@ class ze {
|
|
|
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 = o / 2;
|
|
306
306
|
break;
|
|
307
307
|
case "middle-right":
|
|
308
|
-
n.x = 0, n.y =
|
|
308
|
+
n.x = 0, n.y = o / 2;
|
|
309
309
|
break;
|
|
310
310
|
case "middle-top":
|
|
311
|
-
n.x = e / 2, n.y =
|
|
311
|
+
n.x = e / 2, n.y = o;
|
|
312
312
|
break;
|
|
313
313
|
case "middle-bottom":
|
|
314
314
|
n.x = e / 2, n.y = 0;
|
|
@@ -317,7 +317,7 @@ class ze {
|
|
|
317
317
|
return n;
|
|
318
318
|
}
|
|
319
319
|
}
|
|
320
|
-
class
|
|
320
|
+
class Ge {
|
|
321
321
|
constructor() {
|
|
322
322
|
this.hooks = {
|
|
323
323
|
beforeResize: [],
|
|
@@ -341,8 +341,8 @@ class Ve {
|
|
|
341
341
|
*/
|
|
342
342
|
removeHook(t, e) {
|
|
343
343
|
if (!this.hooks[t]) return;
|
|
344
|
-
const
|
|
345
|
-
|
|
344
|
+
const o = this.hooks[t].indexOf(e);
|
|
345
|
+
o !== -1 && this.hooks[t].splice(o, 1);
|
|
346
346
|
}
|
|
347
347
|
/**
|
|
348
348
|
* Clear all hooks at a stage
|
|
@@ -362,9 +362,9 @@ class Ve {
|
|
|
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((o, n) => {
|
|
366
|
+
const s = n(o);
|
|
367
|
+
return s !== void 0 ? s : o;
|
|
368
368
|
}, e) : e;
|
|
369
369
|
}
|
|
370
370
|
/**
|
|
@@ -372,24 +372,24 @@ class Ve {
|
|
|
372
372
|
*/
|
|
373
373
|
executeResize(t) {
|
|
374
374
|
const e = this.runHooks("beforeResize", t);
|
|
375
|
-
let
|
|
375
|
+
let o = Ye.calculateResize({
|
|
376
376
|
...e,
|
|
377
377
|
snapSystem: t.snapSystem,
|
|
378
378
|
modifiers: t.modifiers
|
|
379
379
|
});
|
|
380
|
-
return
|
|
380
|
+
return o.handle = t.handle, o.startData = t.startData, o = this.runHooks("afterResize", o), o;
|
|
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 o = this.runHooks("beforePositionUpdate", { position: t, element: e });
|
|
388
|
+
return this.runHooks("afterPositionUpdate", o).position;
|
|
389
389
|
}
|
|
390
390
|
}
|
|
391
|
-
const
|
|
392
|
-
class
|
|
391
|
+
const Qe = new Ge();
|
|
392
|
+
class tn {
|
|
393
393
|
constructor(t = null) {
|
|
394
394
|
this.state = "IDLE", this.context = {
|
|
395
395
|
mode: null,
|
|
@@ -433,14 +433,14 @@ class Ue {
|
|
|
433
433
|
/**
|
|
434
434
|
* Start drag operation
|
|
435
435
|
*/
|
|
436
|
-
startDrag(t, e,
|
|
436
|
+
startDrag(t, e, o, n = null) {
|
|
437
437
|
this.state = "DRAGGING";
|
|
438
|
-
const
|
|
439
|
-
let i =
|
|
438
|
+
const s = t.getTransformStartData();
|
|
439
|
+
let i = s;
|
|
440
440
|
if (n === "crop-image-drag" && t.transformData) {
|
|
441
441
|
const a = t.transformData;
|
|
442
442
|
i = {
|
|
443
|
-
...
|
|
443
|
+
...s,
|
|
444
444
|
cropX: a.cropX,
|
|
445
445
|
cropY: a.cropY,
|
|
446
446
|
cropWidth: a.cropWidth,
|
|
@@ -452,7 +452,7 @@ class Ue {
|
|
|
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: o,
|
|
456
456
|
startData: i,
|
|
457
457
|
activeHandle: null,
|
|
458
458
|
element: t
|
|
@@ -481,13 +481,13 @@ class Ue {
|
|
|
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, o = null, n) {
|
|
485
485
|
if (this.state !== "DRAGGING")
|
|
486
486
|
throw new Error("Cannot update drag: not in DRAGGING state");
|
|
487
|
-
const
|
|
487
|
+
const s = t - this.context.startX, i = e - this.context.startY, { dx: a, dy: r, lockedAxis: l } = Ve(s, 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, o);
|
|
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 Ue {
|
|
|
495
495
|
/**
|
|
496
496
|
* Start resize operation
|
|
497
497
|
*/
|
|
498
|
-
startResize(t, e,
|
|
498
|
+
startResize(t, e, o, n, s, 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: o,
|
|
504
504
|
startY: n,
|
|
505
505
|
startData: {
|
|
506
506
|
...a,
|
|
@@ -508,8 +508,8 @@ class Ue {
|
|
|
508
508
|
visualY: i.y,
|
|
509
509
|
visualWidth: i.width,
|
|
510
510
|
visualHeight: i.height,
|
|
511
|
-
bboxX:
|
|
512
|
-
bboxY:
|
|
511
|
+
bboxX: s.x,
|
|
512
|
+
bboxY: s.y
|
|
513
513
|
},
|
|
514
514
|
activeHandle: e,
|
|
515
515
|
element: r
|
|
@@ -523,8 +523,8 @@ class Ue {
|
|
|
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 o = t - this.context.startX, n = e - this.context.startY;
|
|
527
|
+
return { dx: o, dy: n };
|
|
528
528
|
}
|
|
529
529
|
/**
|
|
530
530
|
* Adjust the resize start position to account for snap corrections
|
|
@@ -556,16 +556,16 @@ class Ue {
|
|
|
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, o) {
|
|
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(), s = t.getVisualBoundingBox(), i = t.getTransformStartData();
|
|
563
|
+
this.context.startX = e, this.context.startY = o, this.context.startData = {
|
|
564
564
|
...i,
|
|
565
|
-
visualX:
|
|
566
|
-
visualY:
|
|
567
|
-
visualWidth:
|
|
568
|
-
visualHeight:
|
|
565
|
+
visualX: s.x,
|
|
566
|
+
visualY: s.y,
|
|
567
|
+
visualWidth: s.width,
|
|
568
|
+
visualHeight: s.height,
|
|
569
569
|
bboxX: n.x,
|
|
570
570
|
bboxY: n.y
|
|
571
571
|
};
|
|
@@ -573,14 +573,14 @@ class Ue {
|
|
|
573
573
|
/**
|
|
574
574
|
* Start rotation operation
|
|
575
575
|
*/
|
|
576
|
-
startRotate(t, e,
|
|
576
|
+
startRotate(t, e, o, n, s) {
|
|
577
577
|
this.state = "ROTATING", this.context = {
|
|
578
578
|
mode: "rotate",
|
|
579
579
|
startX: e,
|
|
580
|
-
startY:
|
|
580
|
+
startY: o,
|
|
581
581
|
startData: {
|
|
582
582
|
startAngle: n,
|
|
583
|
-
currentRotation:
|
|
583
|
+
currentRotation: s,
|
|
584
584
|
elementData: t.getTransformStartData()
|
|
585
585
|
},
|
|
586
586
|
activeHandle: null,
|
|
@@ -597,12 +597,12 @@ class Ue {
|
|
|
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, o, n, s) {
|
|
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 = (le(o, 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), s != null && s.shift ? Fe(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 Ue {
|
|
|
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, o) {
|
|
628
628
|
this.state = "PINCHING";
|
|
629
629
|
const n = {
|
|
630
|
-
x: (e.x +
|
|
631
|
-
y: (e.y +
|
|
632
|
-
},
|
|
630
|
+
x: (e.x + o.x) / 2,
|
|
631
|
+
y: (e.y + o.y) / 2
|
|
632
|
+
}, s = o.x - e.x, i = o.y - e.y, a = Math.hypot(s, i), r = Math.atan2(i, s), l = {
|
|
633
633
|
elementData: t.getTransformStartData(),
|
|
634
634
|
startCentroid: n,
|
|
635
635
|
startDistance: a,
|
|
@@ -660,14 +660,14 @@ class Ue {
|
|
|
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 o = this.context.startData, n = {
|
|
664
664
|
x: (t.x + e.x) / 2,
|
|
665
665
|
y: (t.y + e.y) / 2
|
|
666
|
-
},
|
|
666
|
+
}, s = e.x - t.x, i = e.y - t.y, a = Math.hypot(s, i), r = Math.atan2(i, s), l = Math.max(o.startDistance, 1e-4), h = a / l, c = Math.max(h, 0.05), d = r - o.startAngle;
|
|
667
667
|
return {
|
|
668
668
|
scale: c,
|
|
669
669
|
rotationDelta: d,
|
|
670
|
-
startCentroid:
|
|
670
|
+
startCentroid: o.startCentroid,
|
|
671
671
|
currentCentroid: n
|
|
672
672
|
};
|
|
673
673
|
}
|
|
@@ -716,7 +716,7 @@ class Ue {
|
|
|
716
716
|
return this.context.mode;
|
|
717
717
|
}
|
|
718
718
|
}
|
|
719
|
-
class
|
|
719
|
+
class mt {
|
|
720
720
|
/**
|
|
721
721
|
* Resolve rotation anchor with clear precedence:
|
|
722
722
|
* 1. Transform's getRotationAnchor() if overridden
|
|
@@ -736,7 +736,7 @@ class bt {
|
|
|
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(), o = {
|
|
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 bt {
|
|
|
753
753
|
rotation: this.resolve(t)
|
|
754
754
|
};
|
|
755
755
|
if (t.rotation !== 0) {
|
|
756
|
-
const n =
|
|
757
|
-
Object.keys(
|
|
756
|
+
const n = o.rotation, s = gt.toRadiansInverse(t.rotation);
|
|
757
|
+
Object.keys(o).forEach((i) => {
|
|
758
758
|
if (i === "rotation") return;
|
|
759
|
-
const a =
|
|
760
|
-
|
|
759
|
+
const a = o[i], r = a.x - n.x, l = a.y - n.y, h = r * Math.cos(s) - l * Math.sin(s), c = r * Math.sin(s) + l * Math.cos(s);
|
|
760
|
+
o[i] = {
|
|
761
761
|
x: n.x + h,
|
|
762
762
|
y: n.y + c
|
|
763
763
|
};
|
|
764
764
|
});
|
|
765
765
|
}
|
|
766
|
-
return
|
|
766
|
+
return o;
|
|
767
767
|
}
|
|
768
768
|
/**
|
|
769
769
|
* Get edge lines for an element (for edge-to-edge snapping)
|
|
@@ -817,14 +817,14 @@ class bt {
|
|
|
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(), o = {
|
|
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), s = 1e-3;
|
|
824
|
+
return Math.abs(n.x - o.x) > s || Math.abs(n.y - o.y) > s;
|
|
825
825
|
}
|
|
826
826
|
}
|
|
827
|
-
class
|
|
827
|
+
class qt {
|
|
828
828
|
constructor(t) {
|
|
829
829
|
this.cellSize = t, this.cells = /* @__PURE__ */ new Map(), this.idIndex = /* @__PURE__ */ new Map();
|
|
830
830
|
}
|
|
@@ -835,8 +835,8 @@ class Nt {
|
|
|
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 o = this.cells.get(e);
|
|
839
|
+
o || (o = /* @__PURE__ */ new Set(), this.cells.set(e, o)), o.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 Nt {
|
|
|
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 o of e) {
|
|
848
|
+
const n = this.cells.get(o);
|
|
849
849
|
if (n) {
|
|
850
|
-
for (const
|
|
851
|
-
|
|
852
|
-
n.size === 0 && this.cells.delete(
|
|
850
|
+
for (const s of n)
|
|
851
|
+
s.id === t && n.delete(s);
|
|
852
|
+
n.size === 0 && this.cells.delete(o);
|
|
853
853
|
}
|
|
854
854
|
}
|
|
855
855
|
this.idIndex.delete(t);
|
|
@@ -862,19 +862,19 @@ class Nt {
|
|
|
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, o, n) {
|
|
866
|
+
const s = [], i = Math.floor((t - o) / this.cellSize), a = Math.floor((t + o) / this.cellSize), r = Math.floor((e - o) / this.cellSize), l = Math.floor((e + o) / 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);
|
|
870
870
|
if (f)
|
|
871
|
-
for (const
|
|
872
|
-
if (n !== void 0 &&
|
|
873
|
-
const
|
|
874
|
-
|
|
871
|
+
for (const b of f) {
|
|
872
|
+
if (n !== void 0 && b.id === n) continue;
|
|
873
|
+
const u = b.x - t, p = b.y - e;
|
|
874
|
+
u * u + p * p <= o * o && s.push(b);
|
|
875
875
|
}
|
|
876
876
|
}
|
|
877
|
-
return
|
|
877
|
+
return s;
|
|
878
878
|
}
|
|
879
879
|
/**
|
|
880
880
|
* Query all items whose coordinate on `axis` is within `radius` of the
|
|
@@ -888,26 +888,26 @@ class Nt {
|
|
|
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, o, n) {
|
|
892
|
+
const s = [];
|
|
893
893
|
if (t === "x") {
|
|
894
|
-
const i = Math.floor((e -
|
|
894
|
+
const i = Math.floor((e - o) / this.cellSize), a = Math.floor((e + o) / 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) <= o && s.push(d);
|
|
900
900
|
}
|
|
901
901
|
} else {
|
|
902
|
-
const i = Math.floor((e -
|
|
902
|
+
const i = Math.floor((e - o) / this.cellSize), a = Math.floor((e + o) / 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) <= o && s.push(d);
|
|
908
908
|
}
|
|
909
909
|
}
|
|
910
|
-
return
|
|
910
|
+
return s;
|
|
911
911
|
}
|
|
912
912
|
/** Rebuild from a full list of items (clears existing data first) */
|
|
913
913
|
rebuild(t) {
|
|
@@ -920,32 +920,32 @@ class Nt {
|
|
|
920
920
|
return `${Math.floor(t / this.cellSize)},${Math.floor(e / this.cellSize)}`;
|
|
921
921
|
}
|
|
922
922
|
}
|
|
923
|
-
function
|
|
923
|
+
function ft(v) {
|
|
924
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
|
|
928
|
+
function Tt(v) {
|
|
929
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
|
|
933
|
+
function xt(v, t) {
|
|
934
934
|
const e = v.transformData;
|
|
935
935
|
return e && "width" in e ? (e.width = t, !0) : !1;
|
|
936
936
|
}
|
|
937
|
-
function
|
|
937
|
+
function Et(v, t) {
|
|
938
938
|
const e = v.transformData;
|
|
939
939
|
return e && "height" in e ? (e.height = t, !0) : !1;
|
|
940
940
|
}
|
|
941
|
-
class
|
|
941
|
+
class en {
|
|
942
942
|
constructor(t = {}) {
|
|
943
|
-
this._extraSnapRects = [], this.snapThreshold = t.snapThreshold ||
|
|
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,
|
|
945
945
|
// { snapTo: number, anchorKey: string, frozenFontSize: number, frozenWidth: number, frozenPosition: {x, y}, isPositionBasedSnap: boolean }
|
|
946
946
|
y: null
|
|
947
947
|
// { snapTo: number, anchorKey: string, frozenFontSize: number, frozenWidth: number, frozenPosition: {x, y}, isPositionBasedSnap: boolean }
|
|
948
|
-
}, this.stickyThreshold = t.stickyThreshold || 15, this._spatialGrid = new
|
|
948
|
+
}, this.stickyThreshold = t.stickyThreshold || 15, this._spatialGrid = new qt(Math.max(this.snapThreshold * 2, 16)), this._anchorMetadata = /* @__PURE__ */ new Map();
|
|
949
949
|
}
|
|
950
950
|
/**
|
|
951
951
|
* Enable or disable snapping
|
|
@@ -957,7 +957,7 @@ class Ze {
|
|
|
957
957
|
* Set snap threshold in pixels
|
|
958
958
|
*/
|
|
959
959
|
setSnapThreshold(t) {
|
|
960
|
-
this.snapThreshold = t, this._spatialGrid = new
|
|
960
|
+
this.snapThreshold = t, this._spatialGrid = new qt(Math.max(t * 2, 16));
|
|
961
961
|
}
|
|
962
962
|
/**
|
|
963
963
|
* Get current snap guides for rendering
|
|
@@ -996,31 +996,31 @@ class Ze {
|
|
|
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 o = mt.getSnapAnchors(e);
|
|
1000
|
+
for (const [n, s] of Object.entries(o)) {
|
|
1001
1001
|
const i = `${e.id}:${n}`, a = {
|
|
1002
|
-
x:
|
|
1003
|
-
y:
|
|
1002
|
+
x: s.x,
|
|
1003
|
+
y: s.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: s
|
|
1010
1010
|
});
|
|
1011
1011
|
}
|
|
1012
1012
|
}
|
|
1013
1013
|
for (const e of this._extraSnapRects) {
|
|
1014
|
-
const
|
|
1014
|
+
const o = e.x + e.width / 2, n = e.y + e.height / 2, s = 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: s, 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: s, y: i },
|
|
1019
|
+
topCenter: { x: o, y: e.y },
|
|
1020
|
+
rightCenter: { x: s, y: n },
|
|
1021
|
+
bottomCenter: { x: o, y: i },
|
|
1022
1022
|
leftCenter: { x: e.x, y: n },
|
|
1023
|
-
center: { x:
|
|
1023
|
+
center: { x: o, 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,27 +1040,27 @@ class Ze {
|
|
|
1040
1040
|
/**
|
|
1041
1041
|
* Snap a position during drag operation
|
|
1042
1042
|
*/
|
|
1043
|
-
snapPosition(t, e,
|
|
1044
|
-
if (!this.enabled || !
|
|
1043
|
+
snapPosition(t, e, o) {
|
|
1044
|
+
if (!this.enabled || !o)
|
|
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 s = mt.getSnapAnchors(n), i = o.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(s)) {
|
|
1053
1053
|
const m = this._spatialGrid.queryNearAxis("x", S.x, this.snapThreshold);
|
|
1054
1054
|
for (const T of m) {
|
|
1055
1055
|
const C = this._anchorMetadata.get(T.id);
|
|
1056
1056
|
if (!C) continue;
|
|
1057
|
-
const R = C.point, x = C.anchorKey,
|
|
1058
|
-
if (
|
|
1057
|
+
const R = C.point, x = C.anchorKey, H = Math.abs(S.x - R.x);
|
|
1058
|
+
if (H < this.snapThreshold) {
|
|
1059
1059
|
const M = {
|
|
1060
1060
|
snapTo: R.x,
|
|
1061
1061
|
offset: S.x - t.x,
|
|
1062
1062
|
// How far anchor is from element position
|
|
1063
|
-
distance:
|
|
1063
|
+
distance: H,
|
|
1064
1064
|
guide: {
|
|
1065
1065
|
type: "vertical",
|
|
1066
1066
|
x: R.x,
|
|
@@ -1070,19 +1070,19 @@ class Ze {
|
|
|
1070
1070
|
otherKey: x
|
|
1071
1071
|
}
|
|
1072
1072
|
};
|
|
1073
|
-
c.push(M),
|
|
1073
|
+
c.push(M), H < l && (l = H, 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 C = this._anchorMetadata.get(T.id);
|
|
1079
1079
|
if (!C) continue;
|
|
1080
|
-
const R = C.point, x = C.anchorKey,
|
|
1081
|
-
if (
|
|
1080
|
+
const R = C.point, x = C.anchorKey, H = Math.abs(S.y - R.y);
|
|
1081
|
+
if (H < this.snapThreshold) {
|
|
1082
1082
|
const M = {
|
|
1083
1083
|
snapTo: R.y,
|
|
1084
1084
|
offset: S.y - t.y,
|
|
1085
|
-
distance:
|
|
1085
|
+
distance: H,
|
|
1086
1086
|
guide: {
|
|
1087
1087
|
type: "horizontal",
|
|
1088
1088
|
y: R.y,
|
|
@@ -1092,41 +1092,41 @@ class Ze {
|
|
|
1092
1092
|
otherKey: x
|
|
1093
1093
|
}
|
|
1094
1094
|
};
|
|
1095
|
-
d.push(M),
|
|
1095
|
+
d.push(M), H < h && (h = H, r = M);
|
|
1096
1096
|
}
|
|
1097
1097
|
}
|
|
1098
1098
|
}
|
|
1099
|
-
let
|
|
1100
|
-
a && (
|
|
1101
|
-
const
|
|
1099
|
+
let b = t.x, u = t.y;
|
|
1100
|
+
a && (b = a.snapTo - a.offset), r && (u = r.snapTo - r.offset);
|
|
1101
|
+
const p = /* @__PURE__ */ new Map(), g = /* @__PURE__ */ new Map();
|
|
1102
1102
|
for (const y of c) {
|
|
1103
|
-
const S =
|
|
1104
|
-
(!S || y.distance < S.distance) &&
|
|
1103
|
+
const S = p.get(y.snapTo);
|
|
1104
|
+
(!S || y.distance < S.distance) && p.set(y.snapTo, y);
|
|
1105
1105
|
}
|
|
1106
1106
|
for (const y of d) {
|
|
1107
|
-
const S =
|
|
1108
|
-
(!S || y.distance < S.distance) &&
|
|
1107
|
+
const S = g.get(y.snapTo);
|
|
1108
|
+
(!S || y.distance < S.distance) && g.set(y.snapTo, y);
|
|
1109
1109
|
}
|
|
1110
|
-
for (const y of
|
|
1110
|
+
for (const y of p.values())
|
|
1111
1111
|
f.push(y.guide);
|
|
1112
|
-
for (const y of
|
|
1112
|
+
for (const y of g.values())
|
|
1113
1113
|
f.push(y.guide);
|
|
1114
|
-
return this.guides = f, { x:
|
|
1114
|
+
return this.guides = f, { x: b, y: u };
|
|
1115
1115
|
}
|
|
1116
1116
|
/**
|
|
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, o, n, s) {
|
|
1121
|
+
if (!s) 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 =
|
|
1124
|
+
return s.fontSize ?? 0;
|
|
1125
|
+
const r = ft(t) ?? t.width ?? s.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 / s.width;
|
|
1129
|
+
return (s.fontSize ?? 0) * h;
|
|
1130
1130
|
}
|
|
1131
1131
|
/**
|
|
1132
1132
|
* Check if this will be a position-based snap (vs dimension-based)
|
|
@@ -1134,7 +1134,7 @@ class Ze {
|
|
|
1134
1134
|
* Used for text elements where height is derived, not settable
|
|
1135
1135
|
*/
|
|
1136
1136
|
_isPositionBasedSnap(t, e) {
|
|
1137
|
-
return e === "x" ? !1 : e === "y" ? !(
|
|
1137
|
+
return e === "x" ? !1 : e === "y" ? !(Tt(t) !== void 0 || t.height !== void 0 && typeof t.height == "number") : !1;
|
|
1138
1138
|
}
|
|
1139
1139
|
/**
|
|
1140
1140
|
* Determine which snap keys to use based on the resize handle
|
|
@@ -1153,18 +1153,18 @@ class Ze {
|
|
|
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, o, n) {
|
|
1157
|
+
const s = [], i = new Set(n);
|
|
1158
|
+
for (const a of o) {
|
|
1159
1159
|
const r = t[a];
|
|
1160
1160
|
if (!r) continue;
|
|
1161
1161
|
const l = this._spatialGrid.queryNearAxis("x", r.x, this.snapThreshold);
|
|
1162
1162
|
for (const h of l) {
|
|
1163
1163
|
const c = this._anchorMetadata.get(h.id);
|
|
1164
1164
|
if (!c || !i.has(c.anchorKey)) continue;
|
|
1165
|
-
const d = c.point, f = c.anchorKey,
|
|
1166
|
-
|
|
1167
|
-
distance:
|
|
1165
|
+
const d = c.point, f = c.anchorKey, b = Math.abs(r.x - d.x);
|
|
1166
|
+
b < this.snapThreshold && s.push({
|
|
1167
|
+
distance: b,
|
|
1168
1168
|
snapTo: d.x,
|
|
1169
1169
|
currentValue: r.x,
|
|
1170
1170
|
guide: {
|
|
@@ -1178,25 +1178,25 @@ class Ze {
|
|
|
1178
1178
|
});
|
|
1179
1179
|
}
|
|
1180
1180
|
}
|
|
1181
|
-
return
|
|
1181
|
+
return s;
|
|
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, o, n) {
|
|
1189
|
+
const s = [], i = new Set(n);
|
|
1190
|
+
for (const a of o) {
|
|
1191
1191
|
const r = t[a];
|
|
1192
1192
|
if (!r) continue;
|
|
1193
1193
|
const l = this._spatialGrid.queryNearAxis("y", r.y, this.snapThreshold);
|
|
1194
1194
|
for (const h of l) {
|
|
1195
1195
|
const c = this._anchorMetadata.get(h.id);
|
|
1196
1196
|
if (!c || !i.has(c.anchorKey)) continue;
|
|
1197
|
-
const d = c.point, f = c.anchorKey,
|
|
1198
|
-
|
|
1199
|
-
distance:
|
|
1197
|
+
const d = c.point, f = c.anchorKey, b = Math.abs(r.y - d.y);
|
|
1198
|
+
b < this.snapThreshold && s.push({
|
|
1199
|
+
distance: b,
|
|
1200
1200
|
snapTo: d.y,
|
|
1201
1201
|
currentValue: r.y,
|
|
1202
1202
|
guide: {
|
|
@@ -1210,42 +1210,42 @@ class Ze {
|
|
|
1210
1210
|
});
|
|
1211
1211
|
}
|
|
1212
1212
|
}
|
|
1213
|
-
return
|
|
1213
|
+
return s;
|
|
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, o) {
|
|
1219
1219
|
if (!e || !e.anchor) {
|
|
1220
|
-
t.sort((n,
|
|
1220
|
+
t.sort((n, s) => n.distance - s.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
|
+
o === "x" ? e.anchor.includes("left") ? t.sort((n, s) => {
|
|
1224
|
+
const i = n.guide.movingKey.includes("left") ? -1e3 : 0, a = s.guide.movingKey.includes("left") ? -1e3 : 0;
|
|
1225
|
+
return n.distance + i - (s.distance + a);
|
|
1226
|
+
}) : e.anchor.includes("right") ? t.sort((n, s) => {
|
|
1227
|
+
const i = n.guide.movingKey.includes("right") ? -1e3 : 0, a = s.guide.movingKey.includes("right") ? -1e3 : 0;
|
|
1228
|
+
return n.distance + i - (s.distance + a);
|
|
1229
|
+
}) : t.sort((n, s) => n.distance - s.distance) : o === "y" && (e.anchor.includes("top") ? t.sort((n, s) => {
|
|
1230
|
+
const i = n.guide.movingKey.includes("top") ? -1e3 : 0, a = s.guide.movingKey.includes("top") ? -1e3 : 0;
|
|
1231
|
+
return n.distance + i - (s.distance + a);
|
|
1232
|
+
}) : e.anchor.includes("bottom") ? t.sort((n, s) => {
|
|
1233
|
+
const i = n.guide.movingKey.includes("bottom") ? -1e3 : 0, a = s.guide.movingKey.includes("bottom") ? -1e3 : 0;
|
|
1234
|
+
return n.distance + i - (s.distance + a);
|
|
1235
|
+
}) : t.sort((n, s) => n.distance - s.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, o, n, s) {
|
|
1241
|
+
const i = o[e];
|
|
1242
1242
|
if (!i) return null;
|
|
1243
|
-
if (
|
|
1243
|
+
if (s === "x") {
|
|
1244
1244
|
let a = 1 / 0, r = -1 / 0;
|
|
1245
|
-
for (const l of Object.values(
|
|
1245
|
+
for (const l of Object.values(o))
|
|
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
|
-
const h =
|
|
1248
|
+
const h = mt.getSnapAnchors(l);
|
|
1249
1249
|
for (const c of Object.values(h))
|
|
1250
1250
|
Math.abs(c.x - t.snapTo) < 5 && (a = Math.min(a, c.y), r = Math.max(r, c.y));
|
|
1251
1251
|
}
|
|
@@ -1262,12 +1262,12 @@ class Ze {
|
|
|
1262
1262
|
otherKey: "snap"
|
|
1263
1263
|
}
|
|
1264
1264
|
};
|
|
1265
|
-
} else if (
|
|
1265
|
+
} else if (s === "y") {
|
|
1266
1266
|
let a = 1 / 0, r = -1 / 0;
|
|
1267
|
-
for (const l of Object.values(
|
|
1267
|
+
for (const l of Object.values(o))
|
|
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
|
-
const h =
|
|
1270
|
+
const h = mt.getSnapAnchors(l);
|
|
1271
1271
|
for (const c of Object.values(h))
|
|
1272
1272
|
Math.abs(c.y - t.snapTo) < 5 && (a = Math.min(a, c.x), r = Math.max(r, c.x));
|
|
1273
1273
|
}
|
|
@@ -1293,9 +1293,9 @@ class Ze {
|
|
|
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 o = e.getVisualBoundingBox(), n = o.width / o.height;
|
|
1297
|
+
let s = this.stickyThreshold;
|
|
1298
|
+
return t === "x" ? n > 1 && (s = this.stickyThreshold / Math.sqrt(n)) : t === "y" && n < 1 && (s = this.stickyThreshold * Math.sqrt(n)), s;
|
|
1299
1299
|
}
|
|
1300
1300
|
/**
|
|
1301
1301
|
* Calculate what dimensions should be when edge reaches snap point
|
|
@@ -1313,48 +1313,48 @@ class Ze {
|
|
|
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,
|
|
1317
|
-
const i =
|
|
1316
|
+
_calculateFrozenDimensionsAtSnap(t, e, o, n, s) {
|
|
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 + o, h && c && (l = r / c)) : d.includes("left") && (r = i - o, h && c && (l = r / c)) : e === "y" && (d.includes("bottom") ? (l = a + o, h && c && (r = l * c)) : d.includes("top") && (l = a - o, 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, o, n, s, i, a) {
|
|
1327
1327
|
const r = this.activeSnaps[t];
|
|
1328
1328
|
let l = 0, h = null;
|
|
1329
1329
|
if (r) {
|
|
1330
1330
|
const c = e[r.anchorKey];
|
|
1331
1331
|
if (c) {
|
|
1332
|
-
const d = t === "x" ? c.x : c.y, f = Math.abs(d - r.snapTo),
|
|
1333
|
-
if (f <
|
|
1332
|
+
const d = t === "x" ? c.x : c.y, f = Math.abs(d - r.snapTo), b = this._getAdjustedStickyThreshold(t, n);
|
|
1333
|
+
if (f < b) {
|
|
1334
1334
|
if (l = r.snapTo - d, !(t === "y" && r.isPositionBasedSnap)) {
|
|
1335
|
-
const
|
|
1335
|
+
const p = this._calculateFrozenFontSizeAtSnap(
|
|
1336
1336
|
n,
|
|
1337
1337
|
t === "x" ? l : 0,
|
|
1338
1338
|
t === "y" ? l : 0,
|
|
1339
|
-
|
|
1339
|
+
s,
|
|
1340
1340
|
i
|
|
1341
1341
|
);
|
|
1342
|
-
|
|
1342
|
+
p !== r.frozenFontSize && (r.frozenFontSize = p);
|
|
1343
1343
|
}
|
|
1344
1344
|
h = this._createGuideForSnap(r, r.anchorKey, e, a, t);
|
|
1345
1345
|
} else {
|
|
1346
|
-
const
|
|
1347
|
-
if (this.activeSnaps[t] = null,
|
|
1348
|
-
h =
|
|
1349
|
-
const
|
|
1346
|
+
const u = r;
|
|
1347
|
+
if (this.activeSnaps[t] = null, o.length > 0 && o[0].distance < this.snapThreshold) {
|
|
1348
|
+
h = o[0], l = h.snapTo - h.currentValue;
|
|
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
|
+
s,
|
|
1354
1354
|
i
|
|
1355
1355
|
), y = this._isPositionBasedSnap(n, t);
|
|
1356
1356
|
let S;
|
|
1357
|
-
|
|
1357
|
+
p ? S = u.frozenPosition : y ? S = {
|
|
1358
1358
|
x: t === "x" ? n.x + l : n.x,
|
|
1359
1359
|
y: t === "y" ? n.y + l : n.y
|
|
1360
1360
|
} : S = { x: n.x, y: n.y };
|
|
@@ -1363,12 +1363,12 @@ class Ze {
|
|
|
1363
1363
|
t,
|
|
1364
1364
|
l,
|
|
1365
1365
|
h.guide.movingKey,
|
|
1366
|
-
|
|
1366
|
+
s
|
|
1367
1367
|
);
|
|
1368
1368
|
this.activeSnaps[t] = {
|
|
1369
1369
|
snapTo: h.snapTo,
|
|
1370
1370
|
anchorKey: h.guide.movingKey,
|
|
1371
|
-
frozenFontSize:
|
|
1371
|
+
frozenFontSize: g,
|
|
1372
1372
|
frozenWidth: m.frozenWidth,
|
|
1373
1373
|
frozenHeight: m.frozenHeight,
|
|
1374
1374
|
frozenPosition: S,
|
|
@@ -1378,35 +1378,35 @@ class Ze {
|
|
|
1378
1378
|
}
|
|
1379
1379
|
} else
|
|
1380
1380
|
this.activeSnaps[t] = null;
|
|
1381
|
-
} else if (
|
|
1382
|
-
h =
|
|
1381
|
+
} else if (o.length > 0 && o[0].distance < this.snapThreshold) {
|
|
1382
|
+
h = o[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
|
+
s,
|
|
1388
1388
|
i
|
|
1389
|
-
),
|
|
1390
|
-
let
|
|
1391
|
-
d ?
|
|
1389
|
+
), b = this._isPositionBasedSnap(n, t);
|
|
1390
|
+
let u;
|
|
1391
|
+
d ? u = c.frozenPosition : b ? u = {
|
|
1392
1392
|
x: t === "x" ? n.x + l : n.x,
|
|
1393
1393
|
y: t === "y" ? n.y + l : n.y
|
|
1394
|
-
} :
|
|
1395
|
-
const
|
|
1394
|
+
} : u = { x: n.x, y: n.y };
|
|
1395
|
+
const p = this._calculateFrozenDimensionsAtSnap(
|
|
1396
1396
|
n,
|
|
1397
1397
|
t,
|
|
1398
1398
|
l,
|
|
1399
1399
|
h.guide.movingKey,
|
|
1400
|
-
|
|
1400
|
+
s
|
|
1401
1401
|
);
|
|
1402
1402
|
this.activeSnaps[t] = {
|
|
1403
1403
|
snapTo: h.snapTo,
|
|
1404
1404
|
anchorKey: h.guide.movingKey,
|
|
1405
1405
|
frozenFontSize: f,
|
|
1406
|
-
frozenWidth:
|
|
1407
|
-
frozenHeight:
|
|
1408
|
-
frozenPosition:
|
|
1409
|
-
isPositionBasedSnap:
|
|
1406
|
+
frozenWidth: p.frozenWidth,
|
|
1407
|
+
frozenHeight: p.frozenHeight,
|
|
1408
|
+
frozenPosition: u,
|
|
1409
|
+
isPositionBasedSnap: b
|
|
1410
1410
|
};
|
|
1411
1411
|
}
|
|
1412
1412
|
return { snapDelta: l, bestSnap: h };
|
|
@@ -1414,16 +1414,16 @@ class Ze {
|
|
|
1414
1414
|
/**
|
|
1415
1415
|
* Adjust element for right edge resize
|
|
1416
1416
|
*/
|
|
1417
|
-
_adjustElementForRightResize(t, e,
|
|
1418
|
-
const n = t.getVisualBoundingBox(),
|
|
1419
|
-
if (!
|
|
1420
|
-
const i =
|
|
1421
|
-
i !== void 0 ?
|
|
1417
|
+
_adjustElementForRightResize(t, e, o) {
|
|
1418
|
+
const n = t.getVisualBoundingBox(), s = t.transformType === "image";
|
|
1419
|
+
if (!s) {
|
|
1420
|
+
const i = ft(t);
|
|
1421
|
+
i !== void 0 ? xt(t, i + e) : t.width !== void 0 && (t.width += e);
|
|
1422
1422
|
}
|
|
1423
|
-
if (
|
|
1424
|
-
const i =
|
|
1423
|
+
if (o.anchor === "middle-right") {
|
|
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 (!s) {
|
|
1427
1427
|
const a = t.getVisualBoundingBox().x - n.x;
|
|
1428
1428
|
a !== 0 && (t.x -= a);
|
|
1429
1429
|
}
|
|
@@ -1431,16 +1431,16 @@ class Ze {
|
|
|
1431
1431
|
/**
|
|
1432
1432
|
* Adjust element for left edge resize
|
|
1433
1433
|
*/
|
|
1434
|
-
_adjustElementForLeftResize(t, e,
|
|
1435
|
-
const n = t.getVisualBoundingBox(),
|
|
1436
|
-
if (!
|
|
1437
|
-
const i =
|
|
1438
|
-
i !== void 0 ?
|
|
1434
|
+
_adjustElementForLeftResize(t, e, o) {
|
|
1435
|
+
const n = t.getVisualBoundingBox(), s = t.transformType === "image";
|
|
1436
|
+
if (!s) {
|
|
1437
|
+
const i = ft(t);
|
|
1438
|
+
i !== void 0 ? xt(t, i - e) : t.width !== void 0 && (t.width -= e);
|
|
1439
1439
|
}
|
|
1440
|
-
if (
|
|
1441
|
-
const i =
|
|
1440
|
+
if (o.anchor === "middle-left") {
|
|
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, !s) {
|
|
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 Ze {
|
|
|
1448
1448
|
/**
|
|
1449
1449
|
* Adjust element for bottom edge resize
|
|
1450
1450
|
*/
|
|
1451
|
-
_adjustElementForBottomResize(t, e,
|
|
1452
|
-
const n = t.getVisualBoundingBox(),
|
|
1453
|
-
if (!
|
|
1454
|
-
const r =
|
|
1455
|
-
r !== void 0 ?
|
|
1451
|
+
_adjustElementForBottomResize(t, e, o) {
|
|
1452
|
+
const n = t.getVisualBoundingBox(), s = t.transformType === "image";
|
|
1453
|
+
if (!s) {
|
|
1454
|
+
const r = Tt(t);
|
|
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 (
|
|
1459
|
-
const r =
|
|
1458
|
+
if (o.anchor === "middle-bottom") {
|
|
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 (!s && a) {
|
|
1462
1462
|
const r = i.y - n.y;
|
|
1463
1463
|
r !== 0 && (t.y -= r);
|
|
1464
|
-
} else
|
|
1464
|
+
} else s || (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 (!
|
|
1472
|
-
const r =
|
|
1473
|
-
r !== void 0 ?
|
|
1469
|
+
_adjustElementForTopResize(t, e, o) {
|
|
1470
|
+
const n = t.getVisualBoundingBox(), s = t.transformType === "image";
|
|
1471
|
+
if (!s) {
|
|
1472
|
+
const r = Tt(t);
|
|
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 (
|
|
1477
|
-
const r =
|
|
1476
|
+
if (o.anchor === "middle-top") {
|
|
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 = !s && 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,64 +1492,64 @@ class Ze {
|
|
|
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, C, R, x,
|
|
1495
|
+
snapDimensions(t, e, o = null) {
|
|
1496
|
+
var T, C, R, x, H;
|
|
1497
1497
|
if (!this.enabled || !e)
|
|
1498
1498
|
return this.clearGuides(), t;
|
|
1499
|
-
const { element: n } = t,
|
|
1499
|
+
const { element: n } = t, s = 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
1503
|
const M = n.clone();
|
|
1504
1504
|
if (M.transformData) {
|
|
1505
|
-
const A = n.getVisualBoundingBox(),
|
|
1506
|
-
|
|
1505
|
+
const A = n.getVisualBoundingBox(), I = A.width, L = A.height, D = (o == null ? void 0 : o.width) ?? n.width ?? 0, F = (o == null ? void 0 : o.height) ?? n.height ?? 0, W = (o == null ? void 0 : o.visualWidth) ?? I, q = (o == null ? void 0 : o.visualHeight) ?? L, J = t.unfrozenDimensions.width / W, E = t.unfrozenDimensions.height / q;
|
|
1506
|
+
xt(M, D * J), Et(M, F * E);
|
|
1507
1507
|
}
|
|
1508
|
-
i =
|
|
1508
|
+
i = mt.getSnapAnchors(M);
|
|
1509
1509
|
} else
|
|
1510
|
-
i =
|
|
1510
|
+
i = mt.getSnapAnchors(n);
|
|
1511
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
|
|
1515
|
+
const h = this._getSnapKeysForHandle(s), c = this._getTargetSnapKeys(), d = this._findXSnaps(i, l, h, c), f = this._findYSnaps(i, l, h, c);
|
|
1516
|
+
this._prioritizeSnaps(d, s, "x"), this._prioritizeSnaps(f, s, "y");
|
|
1517
|
+
const b = this._processStickySnap("x", i, d, n, s, o, l), u = this._processStickySnap("y", i, f, n, s, o, 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 =
|
|
1520
|
-
if (a && w && (
|
|
1519
|
+
const w = s && (s.anchor === "top-left" || s.anchor === "top-right" || s.anchor === "bottom-left" || s.anchor === "bottom-right");
|
|
1520
|
+
if (a && w && (p !== 0 || g !== 0))
|
|
1521
1521
|
return t;
|
|
1522
|
-
if (
|
|
1523
|
-
const M = n.clone(), A = this.activeSnaps.x || this.activeSnaps.y,
|
|
1524
|
-
if (!
|
|
1525
|
-
if (
|
|
1526
|
-
if (
|
|
1527
|
-
const
|
|
1528
|
-
|
|
1522
|
+
if (p !== 0 || g !== 0) {
|
|
1523
|
+
const M = n.clone(), A = this.activeSnaps.x || this.activeSnaps.y, I = (A == null ? void 0 : A.frozenFontSize) ?? n.fontSize ?? 0, L = (A == null ? void 0 : A.frozenWidth) ?? ft(n) ?? n.width ?? 0, D = (A == null ? void 0 : A.frozenHeight) ?? Tt(n) ?? n.height ?? 0, F = (A == null ? void 0 : A.frozenPosition) ?? { x: n.x, y: n.y }, W = M.isCropping && !String(s.anchor).startsWith("crop-");
|
|
1524
|
+
if (!W)
|
|
1525
|
+
if (s && s.anchor) {
|
|
1526
|
+
if (p !== 0) {
|
|
1527
|
+
const B = (T = this.activeSnaps.x) == null ? void 0 : T.anchorKey, k = B == null ? void 0 : B.toLowerCase();
|
|
1528
|
+
k && k.includes("right") ? this._adjustElementForRightResize(M, p, s) : k && k.includes("left") ? this._adjustElementForLeftResize(M, p, s) : M.x += p;
|
|
1529
1529
|
}
|
|
1530
|
-
if (
|
|
1531
|
-
const
|
|
1532
|
-
|
|
1530
|
+
if (g !== 0) {
|
|
1531
|
+
const B = (C = this.activeSnaps.y) == null ? void 0 : C.anchorKey, k = B == null ? void 0 : B.toLowerCase();
|
|
1532
|
+
k && k.includes("bottom") ? this._adjustElementForBottomResize(M, g, s) : k && k.includes("top") ? this._adjustElementForTopResize(M, g, s) : M.y += g;
|
|
1533
1533
|
}
|
|
1534
1534
|
} else
|
|
1535
|
-
M.x +=
|
|
1536
|
-
M.fontSize !== void 0 && (M.fontSize =
|
|
1537
|
-
const
|
|
1538
|
-
if (
|
|
1539
|
-
if (
|
|
1540
|
-
const
|
|
1541
|
-
let
|
|
1542
|
-
|
|
1543
|
-
const
|
|
1544
|
-
|
|
1535
|
+
M.x += p, M.y += g;
|
|
1536
|
+
M.fontSize !== void 0 && (M.fontSize = I);
|
|
1537
|
+
const q = M.transformType === "image", J = this.activeSnaps.x !== null || this.activeSnaps.y !== null;
|
|
1538
|
+
if (q && J) {
|
|
1539
|
+
if (ft(M) !== void 0) {
|
|
1540
|
+
const B = this.activeSnaps.x || this.activeSnaps.y;
|
|
1541
|
+
let k = L, O = D;
|
|
1542
|
+
B && (k = B.frozenWidth ?? k, O = B.frozenHeight ?? O);
|
|
1543
|
+
const G = ft(n), P = Tt(n), _ = M.imageAspectRatio || (G && P ? G / P : null);
|
|
1544
|
+
_ && _ !== 0 && (O = k / _), xt(M, k), Et(M, O), B && (B.frozenWidth = k, B.frozenHeight = O);
|
|
1545
1545
|
}
|
|
1546
1546
|
} else
|
|
1547
|
-
(((R = this.activeSnaps.y) == null ? void 0 : R.isPositionBasedSnap) || !1) && (
|
|
1548
|
-
const
|
|
1549
|
-
return (
|
|
1547
|
+
(((R = this.activeSnaps.y) == null ? void 0 : R.isPositionBasedSnap) || !1) && (ft(M) !== void 0 ? xt(M, L) : M.width !== void 0 && (M.width = L));
|
|
1548
|
+
const E = s && (s.anchor === "middle-left" || s.anchor === "middle-right"), z = s && (s.anchor === "middle-top" || s.anchor === "middle-bottom"), N = ((x = this.activeSnaps.x) == null ? void 0 : x.isPositionBasedSnap) || !1, Q = ((H = this.activeSnaps.y) == null ? void 0 : H.isPositionBasedSnap) || !1;
|
|
1549
|
+
return (p === 0 || N) && !E && !z && !W && (M.x = F.x), (g === 0 || Q) && !z && !E && !W && (M.y = F.y), {
|
|
1550
1550
|
...t,
|
|
1551
1551
|
element: M,
|
|
1552
|
-
snapAdjustment: { dx:
|
|
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
|
|
1555
1555
|
};
|
|
@@ -1559,16 +1559,16 @@ class Ze {
|
|
|
1559
1559
|
/**
|
|
1560
1560
|
* Snap rotation (for future implementation)
|
|
1561
1561
|
*/
|
|
1562
|
-
snapRotation(t, e,
|
|
1562
|
+
snapRotation(t, e, o) {
|
|
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], s = 5;
|
|
1565
1565
|
for (const i of n)
|
|
1566
|
-
if (
|
|
1566
|
+
if (he(t, i, s))
|
|
1567
1567
|
return i;
|
|
1568
1568
|
return t;
|
|
1569
1569
|
}
|
|
1570
1570
|
}
|
|
1571
|
-
class
|
|
1571
|
+
class nn {
|
|
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,45 +1600,45 @@ class Je {
|
|
|
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, o) {
|
|
1604
|
+
if (!this.enabled || !o)
|
|
1605
1605
|
return t;
|
|
1606
|
-
const n =
|
|
1607
|
-
if (
|
|
1606
|
+
const n = Yt, s = o.filter((p) => p.id !== e.id);
|
|
1607
|
+
if (s.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
|
|
1614
|
-
const
|
|
1615
|
-
return !(a.x + a.width <
|
|
1613
|
+
const b = s.filter((p) => {
|
|
1614
|
+
const g = p.getVisualBoundingBox();
|
|
1615
|
+
return !(a.x + a.width < g.x || a.x > g.x + g.width);
|
|
1616
1616
|
});
|
|
1617
|
-
if (
|
|
1618
|
-
const y =
|
|
1617
|
+
if (b.sort((p, g) => {
|
|
1618
|
+
const y = p.getVisualBoundingBox(), S = g.getVisualBoundingBox();
|
|
1619
1619
|
return y.y - S.y;
|
|
1620
|
-
}),
|
|
1621
|
-
let
|
|
1622
|
-
for (const m of
|
|
1620
|
+
}), b.length >= 1) {
|
|
1621
|
+
let p = null, g = null;
|
|
1622
|
+
for (const m of b) {
|
|
1623
1623
|
const w = m.getVisualBoundingBox();
|
|
1624
|
-
w.y + w.height <= a.y ? (!
|
|
1624
|
+
w.y + w.height <= a.y ? (!p || w.y > p.getVisualBoundingBox().y) && (p = m) : w.y >= a.y + a.height && (!g || w.y < g.getVisualBoundingBox().y) && (g = m);
|
|
1625
1625
|
}
|
|
1626
1626
|
const y = [];
|
|
1627
|
-
for (let m = 0; m <
|
|
1628
|
-
const w =
|
|
1627
|
+
for (let m = 0; m < b.length - 1; m++) {
|
|
1628
|
+
const w = b[m].getVisualBoundingBox(), C = b[m + 1].getVisualBoundingBox().y - (w.y + w.height);
|
|
1629
1629
|
y.push(C);
|
|
1630
1630
|
}
|
|
1631
1631
|
let S = null;
|
|
1632
|
-
if (
|
|
1633
|
-
const m =
|
|
1632
|
+
if (p) {
|
|
1633
|
+
const m = p.getVisualBoundingBox(), w = a.y - (m.y + m.height);
|
|
1634
1634
|
for (const T of y)
|
|
1635
1635
|
if (Math.abs(w - T) <= n) {
|
|
1636
1636
|
S = T;
|
|
1637
1637
|
break;
|
|
1638
1638
|
}
|
|
1639
1639
|
}
|
|
1640
|
-
if (!S &&
|
|
1641
|
-
const w =
|
|
1640
|
+
if (!S && g) {
|
|
1641
|
+
const w = g.getVisualBoundingBox().y - (a.y + a.height);
|
|
1642
1642
|
for (const T of y)
|
|
1643
1643
|
if (Math.abs(w - T) <= n) {
|
|
1644
1644
|
S = T;
|
|
@@ -1646,45 +1646,45 @@ class Je {
|
|
|
1646
1646
|
}
|
|
1647
1647
|
}
|
|
1648
1648
|
if (S !== null && S > 0) {
|
|
1649
|
-
if (
|
|
1650
|
-
const m =
|
|
1649
|
+
if (p) {
|
|
1650
|
+
const m = p.getVisualBoundingBox(), w = a.y - (m.y + m.height);
|
|
1651
1651
|
Math.abs(w - S) <= n && (c = m.y + m.height + S - l, f = !0);
|
|
1652
1652
|
}
|
|
1653
|
-
if (!f &&
|
|
1654
|
-
const m =
|
|
1653
|
+
if (!f && g) {
|
|
1654
|
+
const m = g.getVisualBoundingBox(), w = m.y - (a.y + a.height);
|
|
1655
1655
|
Math.abs(w - S) <= n && (c = m.y - a.height - S - l, f = !0);
|
|
1656
1656
|
}
|
|
1657
1657
|
}
|
|
1658
1658
|
}
|
|
1659
|
-
const
|
|
1660
|
-
const
|
|
1661
|
-
return !(a.y + a.height <
|
|
1659
|
+
const u = s.filter((p) => {
|
|
1660
|
+
const g = p.getVisualBoundingBox();
|
|
1661
|
+
return !(a.y + a.height < g.y || a.y > g.y + g.height);
|
|
1662
1662
|
});
|
|
1663
|
-
if (
|
|
1664
|
-
const y =
|
|
1663
|
+
if (u.sort((p, g) => {
|
|
1664
|
+
const y = p.getVisualBoundingBox(), S = g.getVisualBoundingBox();
|
|
1665
1665
|
return y.x - S.x;
|
|
1666
|
-
}),
|
|
1667
|
-
let
|
|
1668
|
-
for (const m of
|
|
1666
|
+
}), u.length >= 1) {
|
|
1667
|
+
let p = null, g = null;
|
|
1668
|
+
for (const m of u) {
|
|
1669
1669
|
const w = m.getVisualBoundingBox();
|
|
1670
|
-
w.x + w.width <= a.x ? (!
|
|
1670
|
+
w.x + w.width <= a.x ? (!p || w.x > p.getVisualBoundingBox().x) && (p = m) : w.x >= a.x + a.width && (!g || w.x < g.getVisualBoundingBox().x) && (g = m);
|
|
1671
1671
|
}
|
|
1672
1672
|
const y = [];
|
|
1673
|
-
for (let m = 0; m <
|
|
1674
|
-
const w =
|
|
1673
|
+
for (let m = 0; m < u.length - 1; m++) {
|
|
1674
|
+
const w = u[m].getVisualBoundingBox(), C = u[m + 1].getVisualBoundingBox().x - (w.x + w.width);
|
|
1675
1675
|
y.push(C);
|
|
1676
1676
|
}
|
|
1677
1677
|
let S = null;
|
|
1678
|
-
if (
|
|
1679
|
-
const m =
|
|
1678
|
+
if (p) {
|
|
1679
|
+
const m = p.getVisualBoundingBox(), w = a.x - (m.x + m.width);
|
|
1680
1680
|
for (const T of y)
|
|
1681
1681
|
if (Math.abs(w - T) <= n) {
|
|
1682
1682
|
S = T;
|
|
1683
1683
|
break;
|
|
1684
1684
|
}
|
|
1685
1685
|
}
|
|
1686
|
-
if (!S &&
|
|
1687
|
-
const w =
|
|
1686
|
+
if (!S && g) {
|
|
1687
|
+
const w = g.getVisualBoundingBox().x - (a.x + a.width);
|
|
1688
1688
|
for (const T of y)
|
|
1689
1689
|
if (Math.abs(w - T) <= n) {
|
|
1690
1690
|
S = T;
|
|
@@ -1692,12 +1692,12 @@ class Je {
|
|
|
1692
1692
|
}
|
|
1693
1693
|
}
|
|
1694
1694
|
if (S !== null && S > 0) {
|
|
1695
|
-
if (
|
|
1696
|
-
const m =
|
|
1695
|
+
if (p) {
|
|
1696
|
+
const m = p.getVisualBoundingBox(), w = a.x - (m.x + m.width);
|
|
1697
1697
|
Math.abs(w - S) <= n && (h = m.x + m.width + S - r, d = !0);
|
|
1698
1698
|
}
|
|
1699
|
-
if (!d &&
|
|
1700
|
-
const m =
|
|
1699
|
+
if (!d && g) {
|
|
1700
|
+
const m = g.getVisualBoundingBox(), w = m.x - (a.x + a.width);
|
|
1701
1701
|
Math.abs(w - S) <= n && (h = m.x - a.width - S - r, d = !0);
|
|
1702
1702
|
}
|
|
1703
1703
|
}
|
|
@@ -1710,31 +1710,31 @@ class Je {
|
|
|
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, o = !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 s = t.getVisualBoundingBox(), i = [], a = [], r = [], l = [];
|
|
1720
1720
|
for (const c of n) {
|
|
1721
|
-
const d = c.getVisualBoundingBox(), f =
|
|
1722
|
-
f >= this.minDistance && f < this.detectionThreshold &&
|
|
1721
|
+
const d = c.getVisualBoundingBox(), f = s.x - (d.x + d.width), b = d.x - (s.x + s.width), u = s.y - (d.y + d.height), p = d.y - (s.y + s.height), g = !(s.y + s.height < d.y || s.y > d.y + d.height), y = !(s.x + s.width < d.x || s.x > d.x + d.width);
|
|
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 (o) {
|
|
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, s, 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
|
+
s,
|
|
1738
1738
|
a,
|
|
1739
1739
|
"right",
|
|
1740
1740
|
n
|
|
@@ -1742,13 +1742,13 @@ class Je {
|
|
|
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, s, 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
|
+
s,
|
|
1752
1752
|
l,
|
|
1753
1753
|
"bottom",
|
|
1754
1754
|
n
|
|
@@ -1763,9 +1763,9 @@ class Je {
|
|
|
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 o = [], n = t.getVisualBoundingBox(), s = 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 s) {
|
|
1769
1769
|
const h = l.getVisualBoundingBox();
|
|
1770
1770
|
if (Math.min(
|
|
1771
1771
|
Math.abs(n.x - (h.x + h.width)),
|
|
@@ -1778,21 +1778,21 @@ class Je {
|
|
|
1778
1778
|
// bottom
|
|
1779
1779
|
) > i)
|
|
1780
1780
|
continue;
|
|
1781
|
-
let d = 0, f = !1,
|
|
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,
|
|
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 && (o.push({
|
|
1784
1784
|
type: "horizontal",
|
|
1785
1785
|
distance: Math.round(d),
|
|
1786
|
-
x1:
|
|
1787
|
-
x2:
|
|
1788
|
-
y:
|
|
1789
|
-
labelX: (
|
|
1790
|
-
labelY:
|
|
1786
|
+
x1: b,
|
|
1787
|
+
x2: u,
|
|
1788
|
+
y: p,
|
|
1789
|
+
labelX: (b + u) / 2,
|
|
1790
|
+
labelY: p,
|
|
1791
1791
|
isAltHover: !0
|
|
1792
1792
|
}), a++);
|
|
1793
1793
|
let S = 0, m = !1, w = 0, T = 0, C = 0;
|
|
1794
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, C = h.y)) : n.y >= h.y + h.height && (S = n.y - (h.y + h.height), S >= this.minDistance && (m = !0, w = (n.x + n.width / 2 + h.x + h.width / 2) / 2 + x, T = h.y + h.height, C = n.y)), m && (
|
|
1795
|
+
h.y >= n.y + n.height ? (S = h.y - (n.y + n.height), S >= this.minDistance && (m = !0, w = (n.x + n.width / 2 + h.x + h.width / 2) / 2 + x, T = n.y + n.height, C = h.y)) : n.y >= h.y + h.height && (S = n.y - (h.y + h.height), S >= this.minDistance && (m = !0, w = (n.x + n.width / 2 + h.x + h.width / 2) / 2 + x, T = h.y + h.height, C = n.y)), m && (o.push({
|
|
1796
1796
|
type: "vertical",
|
|
1797
1797
|
distance: Math.round(S),
|
|
1798
1798
|
x: w,
|
|
@@ -1803,93 +1803,93 @@ class Je {
|
|
|
1803
1803
|
isAltHover: !0
|
|
1804
1804
|
}), r++);
|
|
1805
1805
|
}
|
|
1806
|
-
return
|
|
1806
|
+
return o;
|
|
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, o, n, s) {
|
|
1813
|
+
const i = [], r = o[0], l = r.distance, h = r.element.getVisualBoundingBox(), c = this.checkIfWouldSnap(e, l, n, s);
|
|
1814
1814
|
if (this.addIndicatorForDirection(i, e, h, l, n, c), n === "left" || n === "right") {
|
|
1815
|
-
const d =
|
|
1815
|
+
const d = s.filter((f) => {
|
|
1816
1816
|
if (f.id === t.id) return !1;
|
|
1817
|
-
const
|
|
1818
|
-
return !(e.y + e.height <
|
|
1817
|
+
const b = f.getVisualBoundingBox();
|
|
1818
|
+
return !(e.y + e.height < b.y || e.y > b.y + b.height);
|
|
1819
1819
|
});
|
|
1820
|
-
if (d.sort((f,
|
|
1821
|
-
const
|
|
1822
|
-
return
|
|
1820
|
+
if (d.sort((f, b) => {
|
|
1821
|
+
const u = f.getVisualBoundingBox(), p = b.getVisualBoundingBox();
|
|
1822
|
+
return u.x - p.x;
|
|
1823
1823
|
}), n === "left")
|
|
1824
1824
|
for (let f = 0; f < d.length - 1; f++) {
|
|
1825
|
-
const
|
|
1825
|
+
const b = d[f], u = d[f + 1], p = b.getVisualBoundingBox(), g = u.getVisualBoundingBox(), y = g.x - (p.x + p.width);
|
|
1826
1826
|
if (Math.abs(y - l) <= 16 && y >= this.minDistance) {
|
|
1827
|
-
const S = Math.max(
|
|
1827
|
+
const S = Math.max(p.y, g.y), m = Math.min(p.y + p.height, g.y + g.height), w = (S + m) / 2;
|
|
1828
1828
|
i.push({
|
|
1829
1829
|
type: "horizontal",
|
|
1830
1830
|
distance: Math.round(y),
|
|
1831
|
-
x1:
|
|
1832
|
-
x2:
|
|
1831
|
+
x1: p.x + p.width,
|
|
1832
|
+
x2: g.x,
|
|
1833
1833
|
y: w,
|
|
1834
|
-
labelX: (
|
|
1834
|
+
labelX: (p.x + p.width + g.x) / 2,
|
|
1835
1835
|
labelY: w
|
|
1836
1836
|
});
|
|
1837
1837
|
}
|
|
1838
1838
|
}
|
|
1839
1839
|
else
|
|
1840
1840
|
for (let f = 0; f < d.length - 1; f++) {
|
|
1841
|
-
const
|
|
1841
|
+
const b = d[f], u = d[f + 1], p = b.getVisualBoundingBox(), g = u.getVisualBoundingBox(), y = g.x - (p.x + p.width);
|
|
1842
1842
|
if (Math.abs(y - l) <= 16 && y >= this.minDistance) {
|
|
1843
|
-
const S = Math.max(
|
|
1843
|
+
const S = Math.max(p.y, g.y), m = Math.min(p.y + p.height, g.y + g.height), w = (S + m) / 2;
|
|
1844
1844
|
i.push({
|
|
1845
1845
|
type: "horizontal",
|
|
1846
1846
|
distance: Math.round(y),
|
|
1847
|
-
x1:
|
|
1848
|
-
x2:
|
|
1847
|
+
x1: p.x + p.width,
|
|
1848
|
+
x2: g.x,
|
|
1849
1849
|
y: w,
|
|
1850
|
-
labelX: (
|
|
1850
|
+
labelX: (p.x + p.width + g.x) / 2,
|
|
1851
1851
|
labelY: w
|
|
1852
1852
|
});
|
|
1853
1853
|
}
|
|
1854
1854
|
}
|
|
1855
1855
|
} else {
|
|
1856
|
-
const d =
|
|
1856
|
+
const d = s.filter((f) => {
|
|
1857
1857
|
if (f.id === t.id) return !1;
|
|
1858
|
-
const
|
|
1859
|
-
return !(e.x + e.width <
|
|
1858
|
+
const b = f.getVisualBoundingBox();
|
|
1859
|
+
return !(e.x + e.width < b.x || e.x > b.x + b.width);
|
|
1860
1860
|
});
|
|
1861
|
-
if (d.sort((f,
|
|
1862
|
-
const
|
|
1863
|
-
return
|
|
1861
|
+
if (d.sort((f, b) => {
|
|
1862
|
+
const u = f.getVisualBoundingBox(), p = b.getVisualBoundingBox();
|
|
1863
|
+
return u.y - p.y;
|
|
1864
1864
|
}), n === "top")
|
|
1865
1865
|
for (let f = 0; f < d.length - 1; f++) {
|
|
1866
|
-
const
|
|
1866
|
+
const b = d[f], u = d[f + 1], p = b.getVisualBoundingBox(), g = u.getVisualBoundingBox(), y = g.y - (p.y + p.height);
|
|
1867
1867
|
if (Math.abs(y - l) <= 16 && y >= this.minDistance) {
|
|
1868
|
-
const S = Math.max(
|
|
1868
|
+
const S = Math.max(p.x, g.x), m = Math.min(p.x + p.width, g.x + g.width), w = (S + m) / 2;
|
|
1869
1869
|
i.push({
|
|
1870
1870
|
type: "vertical",
|
|
1871
1871
|
distance: Math.round(y),
|
|
1872
1872
|
x: w,
|
|
1873
|
-
y1:
|
|
1874
|
-
y2:
|
|
1873
|
+
y1: p.y + p.height,
|
|
1874
|
+
y2: g.y,
|
|
1875
1875
|
labelX: w,
|
|
1876
|
-
labelY: (
|
|
1876
|
+
labelY: (p.y + p.height + g.y) / 2
|
|
1877
1877
|
});
|
|
1878
1878
|
}
|
|
1879
1879
|
}
|
|
1880
1880
|
else
|
|
1881
1881
|
for (let f = 0; f < d.length - 1; f++) {
|
|
1882
|
-
const
|
|
1882
|
+
const b = d[f], u = d[f + 1], p = b.getVisualBoundingBox(), g = u.getVisualBoundingBox(), y = g.y - (p.y + p.height);
|
|
1883
1883
|
if (Math.abs(y - l) <= 16 && y >= this.minDistance) {
|
|
1884
|
-
const S = Math.max(
|
|
1884
|
+
const S = Math.max(p.x, g.x), m = Math.min(p.x + p.width, g.x + g.width), w = (S + m) / 2;
|
|
1885
1885
|
i.push({
|
|
1886
1886
|
type: "vertical",
|
|
1887
1887
|
distance: Math.round(y),
|
|
1888
1888
|
x: w,
|
|
1889
|
-
y1:
|
|
1890
|
-
y2:
|
|
1889
|
+
y1: p.y + p.height,
|
|
1890
|
+
y2: g.y,
|
|
1891
1891
|
labelX: w,
|
|
1892
|
-
labelY: (
|
|
1892
|
+
labelY: (p.y + p.height + g.y) / 2
|
|
1893
1893
|
});
|
|
1894
1894
|
}
|
|
1895
1895
|
}
|
|
@@ -1899,9 +1899,9 @@ class Je {
|
|
|
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, o, n) {
|
|
1903
|
+
const s = Yt;
|
|
1904
|
+
if (o === "top" || o === "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 Je {
|
|
|
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) <= s;
|
|
1922
1922
|
}
|
|
1923
1923
|
}
|
|
1924
1924
|
return !1;
|
|
@@ -1939,7 +1939,7 @@ class Je {
|
|
|
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) <= s;
|
|
1943
1943
|
}
|
|
1944
1944
|
}
|
|
1945
1945
|
return !1;
|
|
@@ -1948,59 +1948,59 @@ class Je {
|
|
|
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, o, n, s, i = !1) {
|
|
1952
|
+
if (s === "left") {
|
|
1953
|
+
const a = Math.max(e.y, o.y), r = Math.min(e.y + e.height, o.y + o.height), l = (a + r) / 2;
|
|
1954
1954
|
t.push({
|
|
1955
1955
|
type: "horizontal",
|
|
1956
1956
|
distance: Math.round(n),
|
|
1957
|
-
x1:
|
|
1957
|
+
x1: o.x + o.width,
|
|
1958
1958
|
x2: e.x,
|
|
1959
1959
|
y: l,
|
|
1960
|
-
labelX: (
|
|
1960
|
+
labelX: (o.x + o.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 (s === "right") {
|
|
1965
|
+
const a = Math.max(e.y, o.y), r = Math.min(e.y + e.height, o.y + o.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: o.x,
|
|
1971
1971
|
y: l,
|
|
1972
|
-
labelX: (e.x + e.width +
|
|
1972
|
+
labelX: (e.x + e.width + o.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 (s === "top") {
|
|
1977
|
+
const a = Math.max(e.x, o.x), r = Math.min(e.x + e.width, o.x + o.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: o.y + o.height,
|
|
1983
1983
|
y2: e.y,
|
|
1984
1984
|
labelX: l,
|
|
1985
|
-
labelY: (
|
|
1985
|
+
labelY: (o.y + o.height + e.y) / 2,
|
|
1986
1986
|
isSnapTarget: i
|
|
1987
1987
|
});
|
|
1988
|
-
} else if (
|
|
1989
|
-
const a = Math.max(e.x,
|
|
1988
|
+
} else if (s === "bottom") {
|
|
1989
|
+
const a = Math.max(e.x, o.x), r = Math.min(e.x + e.width, o.x + o.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: o.y,
|
|
1996
1996
|
labelX: l,
|
|
1997
|
-
labelY: (e.y + e.height +
|
|
1997
|
+
labelY: (e.y + e.height + o.y) / 2,
|
|
1998
1998
|
isSnapTarget: i
|
|
1999
1999
|
});
|
|
2000
2000
|
}
|
|
2001
2001
|
}
|
|
2002
2002
|
}
|
|
2003
|
-
const
|
|
2003
|
+
const _t = Zt("ArtboardRenderer"), Xe = {
|
|
2004
2004
|
showLabel: !0,
|
|
2005
2005
|
showBorder: !0,
|
|
2006
2006
|
borderColor: "",
|
|
@@ -2018,15 +2018,15 @@ const Wt = $t("ArtboardRenderer"), Fe = {
|
|
|
2018
2018
|
borderRadius: 0
|
|
2019
2019
|
// Default to no border radius (sharp corners)
|
|
2020
2020
|
};
|
|
2021
|
-
class
|
|
2021
|
+
class ne {
|
|
2022
2022
|
constructor(t = {}) {
|
|
2023
|
-
this.options = { ...
|
|
2023
|
+
this.options = { ...Xe, ...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, o = !1) {
|
|
2029
|
+
t.save(), this.renderBackground(t, e), this.options.showBorder && this.renderBorder(t, e, o), this.options.showLabel && this.renderLabel(t, e, o), t.restore();
|
|
2030
2030
|
}
|
|
2031
2031
|
/**
|
|
2032
2032
|
* Render artboard background
|
|
@@ -2042,69 +2042,69 @@ class Jt {
|
|
|
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
|
-
|
|
2048
|
-
|
|
2045
|
+
const o = Wt.getTexture(e.backgroundTexture), n = Wt.getTexturePresetColor(e.backgroundTexture);
|
|
2046
|
+
if (t.fillStyle = n, t.fillRect(e.x, e.y, e.width, e.height), !o || !o.complete) {
|
|
2047
|
+
Wt.loadTexture(e.backgroundTexture).catch((s) => {
|
|
2048
|
+
_t.error("Failed to load texture:", s);
|
|
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(o, 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, o, n, s) {
|
|
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, o, n, s), t.clip(), t.fillStyle = a, t.fillRect(e, o, n, s), t.fillStyle = r;
|
|
2060
|
+
for (let l = 0; l < Math.ceil(s / 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, o + 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, o) {
|
|
2069
|
+
const { x: n, y: s, width: i, height: a, clipShape: r } = e, l = this.options.borderColor || ce(), h = this.options.selectedBorderColor || nt();
|
|
2070
|
+
if (t.strokeStyle = o ? h : l, t.lineWidth = o ? 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, s, i, a, c);
|
|
2074
2074
|
} else
|
|
2075
|
-
t.rect(n,
|
|
2075
|
+
t.rect(n, s, i, a);
|
|
2076
2076
|
else if (r === "circle") {
|
|
2077
|
-
const c = n + i / 2, d =
|
|
2077
|
+
const c = n + i / 2, d = s + 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, s, 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, s), t.stroke(c), t.restore();
|
|
2086
2086
|
return;
|
|
2087
2087
|
} catch (c) {
|
|
2088
|
-
|
|
2088
|
+
_t.warn("Invalid SVG path for border, falling back to rectangle:", c), t.rect(n, s, 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, o) {
|
|
2096
|
+
const n = this.options.labelFontSize, s = this.options.labelPadding, i = `${e.name} (${Math.round(e.width)} × ${Math.round(e.height)})`, a = e.x, r = e.y - s;
|
|
2097
2097
|
t.font = `${n}px -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif`;
|
|
2098
|
-
const l = this.options.selectedBorderColor ||
|
|
2099
|
-
t.fillStyle =
|
|
2098
|
+
const l = this.options.selectedBorderColor || nt(), h = this.options.labelColor || de();
|
|
2099
|
+
t.fillStyle = o ? 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, o) {
|
|
2105
2105
|
e.forEach((n) => {
|
|
2106
|
-
const
|
|
2107
|
-
this.render(t, n,
|
|
2106
|
+
const s = n.id === o;
|
|
2107
|
+
this.render(t, n, s);
|
|
2108
2108
|
});
|
|
2109
2109
|
}
|
|
2110
2110
|
/**
|
|
@@ -2120,26 +2120,26 @@ class Jt {
|
|
|
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: o, y: n, width: s, 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(s, i) / 2);
|
|
2127
|
+
this.roundedRect(t, o, n, s, i, r);
|
|
2128
2128
|
} else
|
|
2129
|
-
t.rect(
|
|
2129
|
+
t.rect(o, n, s, i);
|
|
2130
2130
|
else if (a === "circle") {
|
|
2131
|
-
const r =
|
|
2131
|
+
const r = o + s / 2, l = n + i / 2, h = Math.min(s, 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(s, i) / 2);
|
|
2135
|
+
this.roundedRect(t, o, n, s, 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(o, n), t.clip(r), t.translate(-o, -n);
|
|
2140
2140
|
return;
|
|
2141
2141
|
} catch (r) {
|
|
2142
|
-
|
|
2142
|
+
_t.warn("Invalid SVG path, falling back to rectangle:", r), t.rect(o, n, s, i);
|
|
2143
2143
|
}
|
|
2144
2144
|
t.clip();
|
|
2145
2145
|
}
|
|
@@ -2147,8 +2147,8 @@ class Jt {
|
|
|
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, o, n, s, i) {
|
|
2151
|
+
typeof t.roundRect == "function" ? t.roundRect(e, o, n, s, i) : (t.moveTo(e + i, o), t.lineTo(e + n - i, o), t.arcTo(e + n, o, e + n, o + i, i), t.lineTo(e + n, o + s - i), t.arcTo(e + n, o + s, e + n - i, o + s, i), t.lineTo(e + i, o + s), t.arcTo(e, o + s, e, o + s - i, i), t.lineTo(e, o + i), t.arcTo(e, o, e + i, o, i));
|
|
2152
2152
|
}
|
|
2153
2153
|
/**
|
|
2154
2154
|
* Restore after clipping
|
|
@@ -2159,21 +2159,21 @@ class Jt {
|
|
|
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, o, n, s, i = !1) {
|
|
2163
|
+
t.save(), t.setLineDash([5, 5]), t.strokeStyle = i ? "#0066cc" : "#999", t.lineWidth = 1, t.strokeRect(e, o, n, s), 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: s, width: i, height: a } = e, r = [
|
|
2170
|
+
{ x: n, y: s },
|
|
2171
2171
|
// top-left
|
|
2172
|
-
{ x: n + i, y:
|
|
2172
|
+
{ x: n + i, y: s },
|
|
2173
2173
|
// top-right
|
|
2174
|
-
{ x: n, y:
|
|
2174
|
+
{ x: n, y: s + a },
|
|
2175
2175
|
// bottom-left
|
|
2176
|
-
{ x: n + i, y:
|
|
2176
|
+
{ x: n + i, y: s + a }
|
|
2177
2177
|
// bottom-right
|
|
2178
2178
|
];
|
|
2179
2179
|
t.save(), r.forEach((l) => {
|
|
@@ -2198,7 +2198,7 @@ class Jt {
|
|
|
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 ne({
|
|
2202
2202
|
...t,
|
|
2203
2203
|
showPreviewBackground: !1
|
|
2204
2204
|
// CRITICAL: Never show preview in exports
|
|
@@ -2211,15 +2211,15 @@ class Jt {
|
|
|
2211
2211
|
return !!(this.options.showPreviewBackground && t.previewBackgroundColor && t.previewBackgroundColor !== "transparent");
|
|
2212
2212
|
}
|
|
2213
2213
|
}
|
|
2214
|
-
class
|
|
2214
|
+
class wt {
|
|
2215
2215
|
/**
|
|
2216
2216
|
* Render selection box layer
|
|
2217
2217
|
*/
|
|
2218
|
-
static renderSelectionLayer(t, e,
|
|
2219
|
-
if (!e || e.visible === !1 ||
|
|
2218
|
+
static renderSelectionLayer(t, e, o, n = 1) {
|
|
2219
|
+
if (!e || e.visible === !1 || o && o.getMode() === "drag" || "isGroup" in e && e.isGroup) return;
|
|
2220
2220
|
const i = e.getVisualBoundingBox(), a = e.getRotationAnchor();
|
|
2221
|
-
t.save(), t.strokeStyle =
|
|
2222
|
-
const r =
|
|
2221
|
+
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
|
+
const r = ct.canvas.selectionPadding;
|
|
2223
2223
|
t.strokeRect(
|
|
2224
2224
|
(i.x - r) * n,
|
|
2225
2225
|
(i.y - r) * n,
|
|
@@ -2231,48 +2231,48 @@ class mt {
|
|
|
2231
2231
|
* Render position and size info below the selected element
|
|
2232
2232
|
* Only shows dimensions (width x height) while resizing
|
|
2233
2233
|
*/
|
|
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 =
|
|
2234
|
+
static renderPositionSizeInfo(t, e, o, n, s = 1) {
|
|
2235
|
+
if (!e || !(o != null && o.rotationHandle) || (n == null ? void 0 : n.getMode()) !== "resize") return;
|
|
2236
|
+
const i = e.getVisualBoundingBox(), a = Math.round(i.width), r = Math.round(i.height), l = `${a} × ${r}`, h = o.rotationHandle, c = h.x * s, d = h.y * s - 20;
|
|
2237
2237
|
t.save(), t.font = "10px system-ui, -apple-system, sans-serif";
|
|
2238
|
-
const
|
|
2239
|
-
t.shadowColor =
|
|
2240
|
-
c -
|
|
2241
|
-
d -
|
|
2242
|
-
p,
|
|
2238
|
+
const b = t.measureText(l).width + 12, u = 18;
|
|
2239
|
+
t.shadowColor = fe(t.canvas), t.shadowBlur = 4, t.shadowOffsetY = 1, t.fillStyle = ge(t.canvas), t.beginPath(), t.roundRect(
|
|
2240
|
+
c - b / 2,
|
|
2241
|
+
d - u / 2,
|
|
2243
2242
|
b,
|
|
2243
|
+
u,
|
|
2244
2244
|
3
|
|
2245
2245
|
// Smaller border radius
|
|
2246
|
-
), t.fill(), t.shadowColor = "transparent", t.shadowBlur = 0, t.shadowOffsetY = 0, t.fillStyle =
|
|
2246
|
+
), t.fill(), t.shadowColor = "transparent", t.shadowBlur = 0, t.shadowOffsetY = 0, t.fillStyle = ue(t.canvas), t.textAlign = "center", t.textBaseline = "middle", t.fillText(l, c, d + 0.5), t.restore();
|
|
2247
2247
|
}
|
|
2248
2248
|
/**
|
|
2249
2249
|
* Render transform handles layer
|
|
2250
2250
|
*/
|
|
2251
|
-
static renderHandlesLayer(t, e,
|
|
2251
|
+
static renderHandlesLayer(t, e, o, n, s, i, a, r = 1, l = !0) {
|
|
2252
2252
|
if (!e || e.visible === !1 || a.getMode() === "drag") return;
|
|
2253
|
-
const c = i.type === "rotation-handle", d = i.type === "resize-handle" ? i.data : null, f = a.getMode() === "resize",
|
|
2254
|
-
|
|
2253
|
+
const c = i.type === "rotation-handle", d = i.type === "resize-handle" ? i.data : null, f = a.getMode() === "resize", b = f ? a.getActiveHandle() : null;
|
|
2254
|
+
o.render(
|
|
2255
2255
|
t,
|
|
2256
2256
|
l,
|
|
2257
2257
|
n,
|
|
2258
|
-
|
|
2258
|
+
s,
|
|
2259
2259
|
c,
|
|
2260
2260
|
d,
|
|
2261
2261
|
f,
|
|
2262
|
-
|
|
2262
|
+
b,
|
|
2263
2263
|
r,
|
|
2264
2264
|
!0
|
|
2265
2265
|
// Render rotation handle on canvas (not React)
|
|
2266
2266
|
);
|
|
2267
2267
|
}
|
|
2268
2268
|
}
|
|
2269
|
-
class
|
|
2269
|
+
class Vt {
|
|
2270
2270
|
/**
|
|
2271
2271
|
* Render hover highlights layer with fade-in animation
|
|
2272
2272
|
* Outlines the actual element shape instead of a rectangular border
|
|
2273
2273
|
*/
|
|
2274
|
-
static renderHoverLayer(t, e,
|
|
2275
|
-
if (e.type !== "element" || !e.data || e.data.id ===
|
|
2274
|
+
static renderHoverLayer(t, e, o, n = !1, s = 1, i) {
|
|
2275
|
+
if (e.type !== "element" || !e.data || e.data.id === o) return;
|
|
2276
2276
|
const a = e.data;
|
|
2277
2277
|
t.save();
|
|
2278
2278
|
const r = 150, l = 0.5;
|
|
@@ -2281,82 +2281,82 @@ class _t {
|
|
|
2281
2281
|
const c = performance.now() - e.startTime;
|
|
2282
2282
|
h = Math.min(c / r, 1) * l;
|
|
2283
2283
|
}
|
|
2284
|
-
t.strokeStyle =
|
|
2284
|
+
t.strokeStyle = pe(t.canvas), t.globalAlpha = h, t.lineWidth = 3, this.renderElementOutline(t, a, s, i), t.restore();
|
|
2285
2285
|
}
|
|
2286
2286
|
/**
|
|
2287
2287
|
* Render outline for a specific element type
|
|
2288
2288
|
*/
|
|
2289
|
-
static renderElementOutline(t, e,
|
|
2290
|
-
const
|
|
2291
|
-
t.translate(
|
|
2289
|
+
static renderElementOutline(t, e, o = 1, n) {
|
|
2290
|
+
const s = e.getRotationAnchor();
|
|
2291
|
+
t.translate(s.x * o, s.y * o), t.rotate(gt.toRadians(e.rotation)), t.translate(-s.x * o, -s.y * o), e.transformType === "shape" ? this.renderShapeOutline(t, e, o) : e.transformType === "image" ? this.renderImageOutline(t, e, o) : e.transformType === "group" ? this.renderGroupOutline(t, e, o) : this.renderTextOutline(t, e, o, n);
|
|
2292
2292
|
}
|
|
2293
2293
|
/**
|
|
2294
2294
|
* Render outline for shape elements (star, rectangle, circle, etc.)
|
|
2295
2295
|
* Creates a ring effect with a gap between the element and the stroke
|
|
2296
2296
|
*/
|
|
2297
|
-
static renderShapeOutline(t, e,
|
|
2298
|
-
const n = e.transformData,
|
|
2299
|
-
switch (t.save(), t.translate(e.x *
|
|
2297
|
+
static renderShapeOutline(t, e, o) {
|
|
2298
|
+
const n = e.transformData, s = n.width * o, i = n.height * o, a = 2, l = a + a / 2;
|
|
2299
|
+
switch (t.save(), t.translate(e.x * o, e.y * o), t.beginPath(), n.shapeType) {
|
|
2300
2300
|
case "rectangle": {
|
|
2301
|
-
const h = n.borderRadius || 0, c = -(
|
|
2301
|
+
const h = n.borderRadius || 0, c = -(s + l * 2) / 2, d = -(i + l * 2) / 2, f = s + l * 2, b = i + l * 2;
|
|
2302
2302
|
if (h > 0) {
|
|
2303
|
-
const
|
|
2304
|
-
t.roundRect(c, d, f,
|
|
2303
|
+
const u = Math.min(h / 100 * Math.min(f, b), f / 2, b / 2);
|
|
2304
|
+
t.roundRect(c, d, f, b, u);
|
|
2305
2305
|
} else
|
|
2306
|
-
t.rect(c, d, f,
|
|
2306
|
+
t.rect(c, d, f, b);
|
|
2307
2307
|
break;
|
|
2308
2308
|
}
|
|
2309
2309
|
case "circle": {
|
|
2310
|
-
const h = Math.min(
|
|
2310
|
+
const h = Math.min(s, i) / 2 + l;
|
|
2311
2311
|
t.arc(0, 0, h, 0, Math.PI * 2);
|
|
2312
2312
|
break;
|
|
2313
2313
|
}
|
|
2314
2314
|
case "ellipse": {
|
|
2315
|
-
const h = (n.radiusX ??
|
|
2315
|
+
const h = (n.radiusX ?? s / 2) + l, c = (n.radiusY ?? i / 2) + l;
|
|
2316
2316
|
t.ellipse(0, 0, h, c, 0, 0, Math.PI * 2);
|
|
2317
2317
|
break;
|
|
2318
2318
|
}
|
|
2319
2319
|
case "triangle": {
|
|
2320
|
-
const h =
|
|
2320
|
+
const h = s / 2, c = i / 2, d = [
|
|
2321
2321
|
{ x: 0, y: -c },
|
|
2322
2322
|
// top
|
|
2323
2323
|
{ x: h, y: c },
|
|
2324
2324
|
// bottom-right
|
|
2325
2325
|
{ x: -h, y: c }
|
|
2326
2326
|
// bottom-left
|
|
2327
|
-
], f = d.map((
|
|
2328
|
-
const
|
|
2327
|
+
], f = d.map((u, p) => {
|
|
2328
|
+
const g = d[(p + 1) % 3], y = g.x - u.x, S = g.y - u.y, m = Math.sqrt(y * y + S * S);
|
|
2329
2329
|
return { x: S / m, y: -y / m };
|
|
2330
|
-
}),
|
|
2331
|
-
const
|
|
2330
|
+
}), b = d.map((u, p) => {
|
|
2331
|
+
const g = f[(p + 2) % 3], y = f[p], S = g.x + y.x, m = g.y + y.y, w = Math.sqrt(S * S + m * m), T = (S * g.x + m * g.y) / w, C = l / T;
|
|
2332
2332
|
return {
|
|
2333
|
-
x:
|
|
2334
|
-
y:
|
|
2333
|
+
x: u.x + S / w * C,
|
|
2334
|
+
y: u.y + m / w * C
|
|
2335
2335
|
};
|
|
2336
2336
|
});
|
|
2337
|
-
t.moveTo(
|
|
2337
|
+
t.moveTo(b[0].x, b[0].y), t.lineTo(b[1].x, b[1].y), t.lineTo(b[2].x, b[2].y), t.closePath();
|
|
2338
2338
|
break;
|
|
2339
2339
|
}
|
|
2340
2340
|
case "star": {
|
|
2341
|
-
const h = n.points ?? 5, c = n.innerRadius ?? 0.4, d = Math.min(
|
|
2342
|
-
for (let
|
|
2343
|
-
const
|
|
2344
|
-
|
|
2341
|
+
const h = n.points ?? 5, c = n.innerRadius ?? 0.4, d = Math.min(s, i) / 2 + l, f = d * c;
|
|
2342
|
+
for (let b = 0; b < h * 2; b++) {
|
|
2343
|
+
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
|
+
b === 0 ? t.moveTo(g, y) : t.lineTo(g, y);
|
|
2345
2345
|
}
|
|
2346
2346
|
t.closePath();
|
|
2347
2347
|
break;
|
|
2348
2348
|
}
|
|
2349
2349
|
case "polygon": {
|
|
2350
|
-
const h = n.sides ?? 5, c = Math.min(
|
|
2350
|
+
const h = n.sides ?? 5, c = Math.min(s, i) / 2 + l;
|
|
2351
2351
|
for (let d = 0; d < h; d++) {
|
|
2352
|
-
const f = d * 2 * Math.PI / h - Math.PI / 2,
|
|
2353
|
-
d === 0 ? t.moveTo(
|
|
2352
|
+
const f = d * 2 * Math.PI / h - Math.PI / 2, b = c * Math.cos(f), u = c * Math.sin(f);
|
|
2353
|
+
d === 0 ? t.moveTo(b, u) : t.lineTo(b, u);
|
|
2354
2354
|
}
|
|
2355
2355
|
t.closePath();
|
|
2356
2356
|
break;
|
|
2357
2357
|
}
|
|
2358
2358
|
case "line": {
|
|
2359
|
-
const h =
|
|
2359
|
+
const h = s / 2 + l;
|
|
2360
2360
|
t.moveTo(-h, 0), t.lineTo(h, 0);
|
|
2361
2361
|
break;
|
|
2362
2362
|
}
|
|
@@ -2367,24 +2367,24 @@ class _t {
|
|
|
2367
2367
|
* Render outline for image elements
|
|
2368
2368
|
* Creates a ring effect with a gap between the element and the stroke
|
|
2369
2369
|
*/
|
|
2370
|
-
static renderImageOutline(t, e,
|
|
2371
|
-
var
|
|
2372
|
-
const n = e.getVisualBoundingBox(),
|
|
2373
|
-
t.save(), t.translate(e.x *
|
|
2374
|
-
const c = -(
|
|
2370
|
+
static renderImageOutline(t, e, o) {
|
|
2371
|
+
var u;
|
|
2372
|
+
const n = e.getVisualBoundingBox(), s = n.width * o, i = n.height * o, a = ((u = e.transformData) == null ? void 0 : u.borderRadius) || 0, r = 2, h = r + r / 2;
|
|
2373
|
+
t.save(), t.translate(e.x * o, e.y * o);
|
|
2374
|
+
const c = -(s + h * 2) / 2, d = -(i + h * 2) / 2, f = s + h * 2, b = i + h * 2;
|
|
2375
2375
|
if (t.beginPath(), a > 0) {
|
|
2376
|
-
const
|
|
2377
|
-
t.roundRect(c, d, f,
|
|
2376
|
+
const p = Math.min(a / 100 * Math.min(f, b), f / 2, b / 2);
|
|
2377
|
+
t.roundRect(c, d, f, b, p);
|
|
2378
2378
|
} else
|
|
2379
|
-
t.rect(c, d, f,
|
|
2379
|
+
t.rect(c, d, f, b);
|
|
2380
2380
|
t.stroke(), t.restore();
|
|
2381
2381
|
}
|
|
2382
2382
|
/**
|
|
2383
2383
|
* Render outline for group elements
|
|
2384
2384
|
* Creates a ring effect with a gap between the element and the stroke
|
|
2385
2385
|
*/
|
|
2386
|
-
static renderGroupOutline(t, e,
|
|
2387
|
-
const n = e.getVisualBoundingBox(),
|
|
2386
|
+
static renderGroupOutline(t, e, o) {
|
|
2387
|
+
const n = e.getVisualBoundingBox(), s = 2, a = s + s / 2, r = n.x * o - a, l = n.y * o - a, h = n.width * o + a * 2, c = n.height * o + a * 2;
|
|
2388
2388
|
t.save(), t.setLineDash([5, 5]), t.beginPath(), t.roundRect(r, l, h, c, 8), t.stroke(), t.restore();
|
|
2389
2389
|
}
|
|
2390
2390
|
/**
|
|
@@ -2392,9 +2392,9 @@ class _t {
|
|
|
2392
2392
|
* Creates a ring effect with a gap between text and stroke (ring behind text fill)
|
|
2393
2393
|
* Supports all transform types: custom, circle, wave, arch, etc.
|
|
2394
2394
|
*/
|
|
2395
|
-
static renderTextOutline(t, e,
|
|
2396
|
-
const
|
|
2397
|
-
|
|
2395
|
+
static renderTextOutline(t, e, o, n) {
|
|
2396
|
+
const s = e.transformType;
|
|
2397
|
+
s === "circle" || s === "wave" || s === "arch" || s === "lean" || s === "ascend" || s === "flag" ? this.renderTransformHoverRingEffect(t, e, o) : this.renderHoverRingEffect(t, e, o);
|
|
2398
2398
|
}
|
|
2399
2399
|
/**
|
|
2400
2400
|
* HOVER RING EFFECT for straight/custom text
|
|
@@ -2407,122 +2407,131 @@ class _t {
|
|
|
2407
2407
|
* - Element stroke (StrokeRenderer.ts - only when stroke.enabled = true)
|
|
2408
2408
|
* - Selection box (dashed rectangle in element.render())
|
|
2409
2409
|
*/
|
|
2410
|
-
static renderHoverRingEffect(t, e,
|
|
2411
|
-
t.save(), t.translate(e.x *
|
|
2412
|
-
const n = e.fontSize,
|
|
2413
|
-
|
|
2414
|
-
const
|
|
2415
|
-
if (!
|
|
2410
|
+
static renderHoverRingEffect(t, e, o) {
|
|
2411
|
+
t.save(), t.translate(e.x * o, e.y * o), o !== 1 && t.scale(o, o);
|
|
2412
|
+
const n = e.fontSize, s = e.fontFamily, i = e.bold || !1, a = e.italic || !1, r = e.textAlign || "center", l = Jt(n, s, i, a), h = n * (e.lineHeight ?? 1.2), c = e.letterSpacing ?? 0, d = 4 / o, f = 4 / o, b = document.createElement("canvas");
|
|
2413
|
+
b.width = t.canvas.width, b.height = t.canvas.height;
|
|
2414
|
+
const u = b.getContext("2d");
|
|
2415
|
+
if (!u) {
|
|
2416
2416
|
t.restore();
|
|
2417
2417
|
return;
|
|
2418
2418
|
}
|
|
2419
|
-
|
|
2420
|
-
const
|
|
2421
|
-
if (
|
|
2422
|
-
const g =
|
|
2423
|
-
g.forEach((
|
|
2419
|
+
u.setTransform(t.getTransform()), u.textBaseline = "alphabetic", u.lineJoin = "round";
|
|
2420
|
+
const p = e.getRichText ? e.getRichText() : null;
|
|
2421
|
+
if (p) {
|
|
2422
|
+
const g = Qt(p), y = [], S = [];
|
|
2423
|
+
g.forEach((T) => {
|
|
2424
2424
|
if (e.transformType === "custom" && e.transformData) {
|
|
2425
|
-
const
|
|
2425
|
+
const C = e.transformData.width - pt * 2, R = te(T, C, {
|
|
2426
2426
|
fontSize: n,
|
|
2427
|
-
fontFamily:
|
|
2427
|
+
fontFamily: s,
|
|
2428
2428
|
bold: i,
|
|
2429
|
-
italic: a
|
|
2429
|
+
italic: a,
|
|
2430
|
+
letterSpacing: e.letterSpacing
|
|
2430
2431
|
});
|
|
2431
|
-
|
|
2432
|
-
|
|
2433
|
-
isParagraphStart:
|
|
2434
|
-
isParagraphEnd:
|
|
2432
|
+
R.forEach((x, H) => {
|
|
2433
|
+
y.push(x), S.push({
|
|
2434
|
+
isParagraphStart: H === 0,
|
|
2435
|
+
isParagraphEnd: H === R.length - 1
|
|
2435
2436
|
});
|
|
2436
2437
|
});
|
|
2437
2438
|
} else
|
|
2438
|
-
|
|
2439
|
+
y.push(T), S.push({
|
|
2439
2440
|
isParagraphStart: !0,
|
|
2440
2441
|
isParagraphEnd: !0
|
|
2441
2442
|
});
|
|
2442
2443
|
});
|
|
2443
|
-
let
|
|
2444
|
-
|
|
2445
|
-
const
|
|
2446
|
-
|
|
2447
|
-
var
|
|
2448
|
-
const
|
|
2449
|
-
let
|
|
2450
|
-
const
|
|
2451
|
-
let
|
|
2452
|
-
|
|
2453
|
-
const
|
|
2444
|
+
let m;
|
|
2445
|
+
y.length === 0 ? m = 0 : y.length === 1 ? m = l.height : m = (y.length - 1) * h + l.height;
|
|
2446
|
+
const w = -m / 2;
|
|
2447
|
+
y.forEach((T, C) => {
|
|
2448
|
+
var q, J;
|
|
2449
|
+
const R = S[C].isParagraphStart, x = S[C].isParagraphEnd;
|
|
2450
|
+
let H = 0;
|
|
2451
|
+
const M = T.map((E) => E.text).join(""), A = ((q = M.match(/^ +/)) == null ? void 0 : q[0].length) || 0, I = ((J = M.match(/ +$/)) == null ? void 0 : J[0].length) || 0;
|
|
2452
|
+
let L = 0;
|
|
2453
|
+
T.forEach((E) => {
|
|
2454
|
+
const z = E.style.fontSize !== void 0 ? E.style.fontSize : n, N = E.style.fontFamily !== void 0 ? E.style.fontFamily : s, Q = E.style.bold !== void 0 ? E.style.bold : i, B = E.style.italic !== void 0 ? E.style.italic : a;
|
|
2454
2455
|
let k = E.text;
|
|
2455
|
-
const
|
|
2456
|
-
if (!
|
|
2457
|
-
const
|
|
2458
|
-
k = k.substring(
|
|
2456
|
+
const O = L, G = L + E.text.length;
|
|
2457
|
+
if (!R && A > 0 && O < A) {
|
|
2458
|
+
const P = Math.min(A - O, E.text.length);
|
|
2459
|
+
k = k.substring(P);
|
|
2459
2460
|
}
|
|
2460
|
-
if (!
|
|
2461
|
-
const
|
|
2462
|
-
if (
|
|
2463
|
-
const
|
|
2464
|
-
k = k.substring(0,
|
|
2461
|
+
if (!x && I > 0) {
|
|
2462
|
+
const P = M.length - I;
|
|
2463
|
+
if (G > P) {
|
|
2464
|
+
const _ = !R && O < A ? Math.min(A - O, E.text.length) : 0, j = Math.max(0, P - O - _);
|
|
2465
|
+
k = k.substring(0, j);
|
|
2465
2466
|
}
|
|
2466
2467
|
}
|
|
2467
|
-
k.length > 0
|
|
2468
|
+
if (k.length > 0) {
|
|
2469
|
+
const P = E.style.letterSpacing !== void 0 ? E.style.letterSpacing : c;
|
|
2470
|
+
t.save(), t.font = Lt(z, N, Q, B), H += Gt(t.measureText(k).width, k, P), t.restore();
|
|
2471
|
+
}
|
|
2472
|
+
L += E.text.length;
|
|
2468
2473
|
});
|
|
2469
|
-
const
|
|
2470
|
-
let
|
|
2471
|
-
r === "center" ?
|
|
2472
|
-
const
|
|
2473
|
-
|
|
2474
|
-
const
|
|
2474
|
+
const D = e.transformType === "custom" && e.transformData ? e.transformData.width - pt * 2 : void 0;
|
|
2475
|
+
let F;
|
|
2476
|
+
r === "center" ? F = -H / 2 : r === "right" ? F = D !== void 0 ? D / 2 - H : -H : F = D !== void 0 ? -D / 2 : 0;
|
|
2477
|
+
const W = w + l.ascent + C * h;
|
|
2478
|
+
L = 0, T.forEach((E) => {
|
|
2479
|
+
const z = E.style.fontSize !== void 0 ? E.style.fontSize : n, N = E.style.fontFamily !== void 0 ? E.style.fontFamily : s;
|
|
2475
2480
|
E.style.color !== void 0 ? E.style.color : e.color;
|
|
2476
|
-
const
|
|
2481
|
+
const Q = E.style.bold !== void 0 ? E.style.bold : i, B = E.style.italic !== void 0 ? E.style.italic : a;
|
|
2477
2482
|
let k = E.text;
|
|
2478
|
-
const
|
|
2479
|
-
if (!
|
|
2480
|
-
const
|
|
2481
|
-
k = k.substring(
|
|
2483
|
+
const O = L, G = L + E.text.length;
|
|
2484
|
+
if (!R && A > 0 && O < A) {
|
|
2485
|
+
const P = Math.min(A - O, E.text.length);
|
|
2486
|
+
k = k.substring(P);
|
|
2482
2487
|
}
|
|
2483
|
-
if (!
|
|
2484
|
-
const
|
|
2485
|
-
if (
|
|
2486
|
-
const
|
|
2487
|
-
k = k.substring(0,
|
|
2488
|
+
if (!x && I > 0) {
|
|
2489
|
+
const P = M.length - I;
|
|
2490
|
+
if (G > P) {
|
|
2491
|
+
const _ = !R && O < A ? Math.min(A - O, E.text.length) : 0, j = Math.max(0, P - O - _);
|
|
2492
|
+
k = k.substring(0, j);
|
|
2488
2493
|
}
|
|
2489
2494
|
}
|
|
2490
|
-
|
|
2495
|
+
if (L += E.text.length, k.length > 0) {
|
|
2496
|
+
const P = E.style.letterSpacing !== void 0 ? E.style.letterSpacing : c;
|
|
2497
|
+
u.font = Lt(z, N, Q, B), u.textAlign = "left", u.globalCompositeOperation = "source-over", u.strokeStyle = t.strokeStyle, u.globalAlpha = Math.min(t.globalAlpha * 1.6, 0.8), u.lineWidth = (f + d) * 2, Pt(u, k, F, W, P), u.globalCompositeOperation = "destination-out", u.globalAlpha = 1, u.lineWidth = f * 2, Pt(u, k, F, W, P), Xt(u, k, F, W, P), F += Gt(u.measureText(k).width, k, P);
|
|
2498
|
+
}
|
|
2491
2499
|
});
|
|
2492
2500
|
});
|
|
2493
2501
|
} else {
|
|
2494
|
-
t.font =
|
|
2495
|
-
let g,
|
|
2502
|
+
t.font = Lt(n, s, i, a), u.font = t.font, u.textAlign = r;
|
|
2503
|
+
let g, y;
|
|
2496
2504
|
if (e.transformType === "custom" && e.transformData) {
|
|
2497
|
-
const
|
|
2505
|
+
const R = e.transformData.width - pt * 2, { lines: x } = ye(
|
|
2498
2506
|
e.text,
|
|
2499
|
-
|
|
2507
|
+
R,
|
|
2500
2508
|
n,
|
|
2501
|
-
|
|
2509
|
+
s,
|
|
2502
2510
|
i,
|
|
2503
2511
|
a,
|
|
2504
2512
|
void 0,
|
|
2505
|
-
!0
|
|
2513
|
+
!0,
|
|
2514
|
+
{ letterSpacing: c, lineHeight: e.lineHeight }
|
|
2506
2515
|
);
|
|
2507
|
-
g =
|
|
2516
|
+
g = x;
|
|
2508
2517
|
} else {
|
|
2509
2518
|
g = e.text.split(`
|
|
2510
2519
|
`);
|
|
2511
|
-
const
|
|
2520
|
+
const R = e.text.includes(`
|
|
2512
2521
|
`);
|
|
2513
|
-
g =
|
|
2522
|
+
g = xe(g, R);
|
|
2514
2523
|
}
|
|
2515
|
-
g.length === 0 ?
|
|
2516
|
-
const
|
|
2517
|
-
`),
|
|
2518
|
-
let
|
|
2519
|
-
r === "center" ?
|
|
2520
|
-
const
|
|
2521
|
-
let
|
|
2522
|
-
|
|
2524
|
+
g.length === 0 ? y = 0 : g.length === 1 ? y = l.height : y = (g.length - 1) * h + l.height;
|
|
2525
|
+
const S = -y / 2, m = e.text.includes(`
|
|
2526
|
+
`), w = e.transformType === "custom" && e.transformData ? e.transformData.width : 0, T = -w / 2;
|
|
2527
|
+
let C = T + pt;
|
|
2528
|
+
r === "center" ? C = T + w / 2 : r === "right" && (C = T + w - pt), g.forEach((R, x) => {
|
|
2529
|
+
const H = S + l.ascent + x * h, M = m || x === 0, A = m || x === g.length - 1;
|
|
2530
|
+
let I = R;
|
|
2531
|
+
M || (I = I.replace(/^ +/, "")), A || (I = I.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, I, C, H, c), u.globalCompositeOperation = "destination-out", u.globalAlpha = 1, u.lineWidth = f * 2, Pt(u, I, C, H, c), Xt(u, I, C, H, c);
|
|
2523
2532
|
});
|
|
2524
2533
|
}
|
|
2525
|
-
t.setTransform(1, 0, 0, 1, 0, 0), t.drawImage(
|
|
2534
|
+
t.setTransform(1, 0, 0, 1, 0, 0), t.drawImage(b, 0, 0), t.restore();
|
|
2526
2535
|
}
|
|
2527
2536
|
/**
|
|
2528
2537
|
* HOVER RING EFFECT for transformed text (circle, wave, arch, lean, ascend, flag)
|
|
@@ -2535,34 +2544,34 @@ class _t {
|
|
|
2535
2544
|
* - Element stroke (StrokeRenderer.ts - only when stroke.enabled = true)
|
|
2536
2545
|
* - Selection box (dashed outline shown by each transform's render() method)
|
|
2537
2546
|
*/
|
|
2538
|
-
static renderTransformHoverRingEffect(t, e,
|
|
2539
|
-
t.save(), t.translate(e.x *
|
|
2540
|
-
const n = 4 /
|
|
2547
|
+
static renderTransformHoverRingEffect(t, e, o) {
|
|
2548
|
+
t.save(), t.translate(e.x * o, e.y * o), o !== 1 && t.scale(o, o), t.rotate(-e.rotation * Math.PI / 180);
|
|
2549
|
+
const n = 4 / o, s = 4 / o, i = document.createElement("canvas");
|
|
2541
2550
|
i.width = t.canvas.width, i.height = t.canvas.height;
|
|
2542
2551
|
const a = i.getContext("2d");
|
|
2543
2552
|
if (!a) {
|
|
2544
2553
|
t.restore();
|
|
2545
2554
|
return;
|
|
2546
2555
|
}
|
|
2547
|
-
a.setTransform(t.getTransform()), this.renderTransformWithHoverEffect(a, e, n,
|
|
2556
|
+
a.setTransform(t.getTransform()), this.renderTransformWithHoverEffect(a, e, n, s, t.strokeStyle), t.setTransform(1, 0, 0, 1, 0, 0), t.drawImage(i, 0, 0), t.restore();
|
|
2548
2557
|
}
|
|
2549
2558
|
/**
|
|
2550
2559
|
* Helper to render text along a transform path with hover effect
|
|
2551
2560
|
*/
|
|
2552
|
-
static renderTransformWithHoverEffect(t, e,
|
|
2561
|
+
static renderTransformWithHoverEffect(t, e, o, n, s) {
|
|
2553
2562
|
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";
|
|
2554
2563
|
if (t.font = `${d} ${c} ${a}px ${r}`, t.textAlign = "center", t.textBaseline = "middle", i.transformType === "lean") {
|
|
2555
2564
|
const y = -i.transformData.leanAmount * Math.PI / 4;
|
|
2556
|
-
t.transform(1, 0, Math.tan(y), 1, 0, 0), t.globalCompositeOperation = "source-over", t.strokeStyle =
|
|
2565
|
+
t.transform(1, 0, Math.tan(y), 1, 0, 0), t.globalCompositeOperation = "source-over", t.strokeStyle = s, t.globalAlpha = 0.8, t.lineWidth = (n + o) * 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);
|
|
2557
2566
|
return;
|
|
2558
2567
|
}
|
|
2559
|
-
const f = i.text.split(""),
|
|
2560
|
-
t.translate(
|
|
2568
|
+
const f = i.text.split(""), b = f.map((g) => t.measureText(g).width), u = this.calculateCharPositions(e, f, b), p = (g) => {
|
|
2569
|
+
t.translate(g.x, g.y), g.angle && t.rotate(g.angle), g.skewY && t.transform(1, g.skewY, 0, 1, 0, 0);
|
|
2561
2570
|
};
|
|
2562
|
-
t.globalCompositeOperation = "source-over", t.strokeStyle =
|
|
2563
|
-
t.save(), g
|
|
2564
|
-
}), t.globalCompositeOperation = "destination-out", t.globalAlpha = 1, t.lineWidth = n * 2,
|
|
2565
|
-
t.save(), g
|
|
2571
|
+
t.globalCompositeOperation = "source-over", t.strokeStyle = s, t.globalAlpha = 0.8, t.lineWidth = (n + o) * 2, t.lineJoin = "round", u.forEach((g, y) => {
|
|
2572
|
+
t.save(), p(g), t.strokeText(f[y], 0, 0), t.restore();
|
|
2573
|
+
}), t.globalCompositeOperation = "destination-out", t.globalAlpha = 1, t.lineWidth = n * 2, u.forEach((g, y) => {
|
|
2574
|
+
t.save(), p(g), t.strokeText(f[y], 0, 0), t.fillText(f[y], 0, 0), t.restore();
|
|
2566
2575
|
});
|
|
2567
2576
|
}
|
|
2568
2577
|
/**
|
|
@@ -2570,26 +2579,26 @@ class _t {
|
|
|
2570
2579
|
*
|
|
2571
2580
|
* Also used by EditModeRenderer for cursor positioning on transformed text.
|
|
2572
2581
|
*/
|
|
2573
|
-
static calculateCharPositions(t, e,
|
|
2574
|
-
const n = t.transformType,
|
|
2575
|
-
return n === "circle" ? this.calculateCirclePositions(
|
|
2582
|
+
static calculateCharPositions(t, e, o) {
|
|
2583
|
+
const n = t.transformType, s = t.transformData;
|
|
2584
|
+
return n === "circle" ? this.calculateCirclePositions(s, e, o) : n === "wave" ? this.calculateWavePositions(t, e, o, s) : n === "arch" ? this.calculateArchPositions(t, e, o, s) : n === "lean" ? this.calculateLeanPositions(e, o) : n === "ascend" ? this.calculateAscendPositions(t, e, o, s) : n === "flag" ? this.calculateFlagPositions(t, e, o, s) : e.map(() => ({ x: 0, y: 0, angle: 0 }));
|
|
2576
2585
|
}
|
|
2577
2586
|
/**
|
|
2578
2587
|
* Calculate positions for circle transform
|
|
2579
2588
|
*/
|
|
2580
|
-
static calculateCirclePositions(t, e,
|
|
2581
|
-
const n = [],
|
|
2589
|
+
static calculateCirclePositions(t, e, o) {
|
|
2590
|
+
const n = [], s = o.reduce((a, r) => a + r, 0), i = t.radius * t.scale;
|
|
2582
2591
|
if (t.reverse) {
|
|
2583
|
-
let a = Math.PI / 2 +
|
|
2592
|
+
let a = Math.PI / 2 + s / (2 * i);
|
|
2584
2593
|
e.forEach((r, l) => {
|
|
2585
|
-
const c =
|
|
2586
|
-
n.push({ x: d, y: f, angle:
|
|
2594
|
+
const c = o[l] / i, d = Math.cos(a - c / 2) * i, f = Math.sin(a - c / 2) * i, b = a - c / 2 - Math.PI / 2;
|
|
2595
|
+
n.push({ x: d, y: f, angle: b }), a -= c;
|
|
2587
2596
|
});
|
|
2588
2597
|
} else {
|
|
2589
|
-
let a = -Math.PI / 2 -
|
|
2598
|
+
let a = -Math.PI / 2 - s / (2 * i);
|
|
2590
2599
|
e.forEach((r, l) => {
|
|
2591
|
-
const c =
|
|
2592
|
-
n.push({ x: d, y: f, angle:
|
|
2600
|
+
const c = o[l] / i, d = Math.cos(a + c / 2) * i, f = Math.sin(a + c / 2) * i, b = a + c / 2 + Math.PI / 2;
|
|
2601
|
+
n.push({ x: d, y: f, angle: b }), a += c;
|
|
2593
2602
|
});
|
|
2594
2603
|
}
|
|
2595
2604
|
return n;
|
|
@@ -2597,328 +2606,331 @@ class _t {
|
|
|
2597
2606
|
/**
|
|
2598
2607
|
* Calculate positions for wave transform
|
|
2599
2608
|
*/
|
|
2600
|
-
static calculateWavePositions(t, e,
|
|
2601
|
-
const
|
|
2602
|
-
let a = -
|
|
2609
|
+
static calculateWavePositions(t, e, o, n) {
|
|
2610
|
+
const s = [];
|
|
2611
|
+
let a = -o.reduce((r, l) => r + l, 0) / 2;
|
|
2603
2612
|
return e.forEach((r, l) => {
|
|
2604
|
-
const h =
|
|
2605
|
-
|
|
2606
|
-
}),
|
|
2613
|
+
const h = o[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);
|
|
2614
|
+
s.push({ x: c, y: f, angle: 0, skewY: b * be }), a += h;
|
|
2615
|
+
}), s;
|
|
2607
2616
|
}
|
|
2608
2617
|
/**
|
|
2609
2618
|
* Calculate positions for arch transform
|
|
2610
2619
|
*/
|
|
2611
|
-
static calculateArchPositions(t, e,
|
|
2612
|
-
const
|
|
2620
|
+
static calculateArchPositions(t, e, o, n) {
|
|
2621
|
+
const s = [], i = o.reduce((l, h) => l + h, 0), a = n.width / 2;
|
|
2613
2622
|
let r = -i / 2;
|
|
2614
2623
|
return e.forEach((l, h) => {
|
|
2615
|
-
const c =
|
|
2616
|
-
|
|
2617
|
-
}),
|
|
2624
|
+
const c = o[h], d = r + c / 2, f = d / a, b = (Math.pow(f, 2) - 1) * n.archHeight * t.fontSize, u = 2 * f * n.archHeight;
|
|
2625
|
+
s.push({ x: d, y: b, angle: 0, skewY: u * 0.3 }), r += c;
|
|
2626
|
+
}), s;
|
|
2618
2627
|
}
|
|
2619
2628
|
/**
|
|
2620
2629
|
* Calculate positions for lean transform
|
|
2621
2630
|
*/
|
|
2622
2631
|
static calculateLeanPositions(t, e) {
|
|
2623
|
-
const
|
|
2624
|
-
let
|
|
2632
|
+
const o = [];
|
|
2633
|
+
let s = -e.reduce((i, a) => i + a, 0) / 2;
|
|
2625
2634
|
return t.forEach((i, a) => {
|
|
2626
|
-
const r = e[a], l =
|
|
2627
|
-
|
|
2628
|
-
}),
|
|
2635
|
+
const r = e[a], l = s + r / 2;
|
|
2636
|
+
o.push({ x: l, y: 0, angle: 0 }), s += r;
|
|
2637
|
+
}), o;
|
|
2629
2638
|
}
|
|
2630
2639
|
/**
|
|
2631
2640
|
* Calculate positions for ascend transform
|
|
2632
2641
|
*/
|
|
2633
|
-
static calculateAscendPositions(t, e,
|
|
2634
|
-
const
|
|
2642
|
+
static calculateAscendPositions(t, e, o, n) {
|
|
2643
|
+
const s = [], i = o.reduce((h, c) => h + c, 0), a = n.ascendAngle * Math.PI / 180, r = Math.tan(a);
|
|
2635
2644
|
let l = -i / 2;
|
|
2636
2645
|
return e.forEach((h, c) => {
|
|
2637
|
-
const d =
|
|
2638
|
-
|
|
2639
|
-
}),
|
|
2646
|
+
const d = o[c], f = l + d / 2, b = f * r;
|
|
2647
|
+
s.push({ x: f, y: b, angle: 0, skewY: r * 1 }), l += d;
|
|
2648
|
+
}), s;
|
|
2640
2649
|
}
|
|
2641
2650
|
/**
|
|
2642
2651
|
* Calculate positions for flag transform
|
|
2643
2652
|
*/
|
|
2644
|
-
static calculateFlagPositions(t, e,
|
|
2645
|
-
const
|
|
2646
|
-
let a = -
|
|
2653
|
+
static calculateFlagPositions(t, e, o, n) {
|
|
2654
|
+
const s = [];
|
|
2655
|
+
let a = -o.reduce((r, l) => r + l, 0) / 2;
|
|
2647
2656
|
return e.forEach((r, l) => {
|
|
2648
|
-
const h =
|
|
2649
|
-
|
|
2650
|
-
}),
|
|
2657
|
+
const h = o[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;
|
|
2658
|
+
s.push({ x: c, y: u, angle: 0, skewY: y * 0.3 }), a += h;
|
|
2659
|
+
}), s;
|
|
2651
2660
|
}
|
|
2652
2661
|
}
|
|
2653
|
-
class
|
|
2662
|
+
class Ct {
|
|
2654
2663
|
/**
|
|
2655
2664
|
* Render snap guides layer
|
|
2656
2665
|
*/
|
|
2657
2666
|
static renderSnapGuidesLayer(t, e = []) {
|
|
2658
|
-
e.length !== 0 && (t.save(), t.strokeStyle =
|
|
2659
|
-
t.beginPath(),
|
|
2667
|
+
e.length !== 0 && (t.save(), t.strokeStyle = nt(t.canvas), t.lineWidth = ct.canvas.snapGuideWidth, t.setLineDash(ct.canvas.snapGuideDash), e.forEach((o) => {
|
|
2668
|
+
t.beginPath(), o.type === "vertical" ? (t.moveTo(o.x ?? 0, o.y1 ?? 0), t.lineTo(o.x ?? 0, o.y2 ?? 0)) : o.type === "horizontal" ? (t.moveTo(o.x1 ?? 0, o.y ?? 0), t.lineTo(o.x2 ?? 0, o.y ?? 0)) : (t.moveTo(o.x1 ?? 0, o.y1 ?? 0), t.lineTo(o.x2 ?? 0, o.y2 ?? 0)), t.stroke();
|
|
2660
2669
|
}), t.restore());
|
|
2661
2670
|
}
|
|
2662
2671
|
/**
|
|
2663
2672
|
* Render spacing indicators layer
|
|
2664
2673
|
*/
|
|
2665
2674
|
static renderSpacingIndicatorsLayer(t, e = []) {
|
|
2666
|
-
e.length !== 0 && (t.save(), t.setLineDash([]), e.forEach((
|
|
2667
|
-
const n =
|
|
2668
|
-
if (t.strokeStyle = n, t.fillStyle = n, t.lineWidth =
|
|
2669
|
-
const
|
|
2670
|
-
t.moveTo(
|
|
2675
|
+
e.length !== 0 && (t.save(), t.setLineDash([]), e.forEach((o) => {
|
|
2676
|
+
const n = Nt(t.canvas);
|
|
2677
|
+
if (t.strokeStyle = n, t.fillStyle = n, t.lineWidth = ct.canvas.spacingIndicatorWidth, t.beginPath(), o.type === "horizontal") {
|
|
2678
|
+
const s = o.x1 ?? 0, i = o.x2 ?? 0, a = o.y ?? 0;
|
|
2679
|
+
t.moveTo(s, a), t.lineTo(i, a), t.stroke();
|
|
2671
2680
|
const r = 6;
|
|
2672
|
-
t.beginPath(), t.moveTo(
|
|
2673
|
-
const l =
|
|
2674
|
-
this.renderDistanceLabel(t, l, h,
|
|
2675
|
-
} else if (
|
|
2676
|
-
const
|
|
2677
|
-
t.moveTo(
|
|
2681
|
+
t.beginPath(), t.moveTo(s, a - r), t.lineTo(s, a + r), t.stroke(), t.beginPath(), t.moveTo(i, a - r), t.lineTo(i, a + r), t.stroke();
|
|
2682
|
+
const l = o.labelX, h = o.labelY;
|
|
2683
|
+
this.renderDistanceLabel(t, l, h, o.distance);
|
|
2684
|
+
} else if (o.type === "vertical") {
|
|
2685
|
+
const s = o.x ?? 0, i = o.y1 ?? 0, a = o.y2 ?? 0;
|
|
2686
|
+
t.moveTo(s, i), t.lineTo(s, a), t.stroke();
|
|
2678
2687
|
const r = 6;
|
|
2679
|
-
t.beginPath(), t.moveTo(
|
|
2680
|
-
const l =
|
|
2681
|
-
this.renderDistanceLabel(t, l, h,
|
|
2688
|
+
t.beginPath(), t.moveTo(s - r, i), t.lineTo(s + r, i), t.stroke(), t.beginPath(), t.moveTo(s - r, a), t.lineTo(s + r, a), t.stroke();
|
|
2689
|
+
const l = o.labelX, h = o.labelY;
|
|
2690
|
+
this.renderDistanceLabel(t, l, h, o.distance);
|
|
2682
2691
|
}
|
|
2683
2692
|
}), t.restore());
|
|
2684
2693
|
}
|
|
2685
2694
|
/**
|
|
2686
2695
|
* Render a distance label with background
|
|
2687
2696
|
*/
|
|
2688
|
-
static renderDistanceLabel(t, e,
|
|
2689
|
-
const
|
|
2690
|
-
t.font = `600 ${
|
|
2691
|
-
const a = t.measureText(
|
|
2692
|
-
t.fillStyle =
|
|
2697
|
+
static renderDistanceLabel(t, e, o, n) {
|
|
2698
|
+
const s = `${n}`;
|
|
2699
|
+
t.font = `600 ${ct.canvas.spacingLabelFontSize}px ${ct.canvas.spacingLabelFontFamily}`;
|
|
2700
|
+
const a = t.measureText(s).width, r = ct.canvas.spacingLabelFontSize, l = 4, h = a + l * 2, c = r + l * 2;
|
|
2701
|
+
t.fillStyle = Nt(t.canvas), t.beginPath(), t.roundRect(e - h / 2, o - c / 2, h, c, Se), t.fill(), t.fillStyle = me, t.textAlign = "center", t.textBaseline = "middle", t.fillText(s, e, o);
|
|
2693
2702
|
}
|
|
2694
2703
|
}
|
|
2695
|
-
class
|
|
2704
|
+
class zt {
|
|
2696
2705
|
/**
|
|
2697
2706
|
* Render edit mode features: cursor and text selection highlight
|
|
2698
2707
|
* This renders on the main canvas at world coordinates (same as the element)
|
|
2699
2708
|
*/
|
|
2700
|
-
static renderEditModeLayer(t, e,
|
|
2709
|
+
static renderEditModeLayer(t, e, o, n) {
|
|
2701
2710
|
if (!e || e.transformType === "image" || e.transformType === "group") return;
|
|
2702
|
-
const
|
|
2703
|
-
if (
|
|
2704
|
-
this.renderTransformEditModeLayer(t,
|
|
2711
|
+
const s = e, { cursorPosition: i, selectionStart: a, selectionEnd: r, editText: l, editRichText: h, cursorOpacity: c, isTouchDevice: d, selectionHandlePositionsRef: f } = o, b = n || 1, u = s.transformType;
|
|
2712
|
+
if (u === "circle" || u === "wave" || u === "arch" || u === "lean" || u === "ascend" || u === "flag") {
|
|
2713
|
+
this.renderTransformEditModeLayer(t, s, o, b);
|
|
2705
2714
|
return;
|
|
2706
2715
|
}
|
|
2707
|
-
const
|
|
2708
|
-
t.save(), t.translate(
|
|
2709
|
-
const
|
|
2710
|
-
let
|
|
2711
|
-
if (h &&
|
|
2712
|
-
const
|
|
2713
|
-
|
|
2714
|
-
const k =
|
|
2715
|
-
|
|
2716
|
-
const
|
|
2717
|
-
fontSize:
|
|
2718
|
-
fontFamily:
|
|
2719
|
-
bold:
|
|
2720
|
-
italic:
|
|
2716
|
+
const p = s.fontSize || 24, g = s.fontFamily || "Arial", y = s.bold || !1, S = s.italic || !1, m = s.underline || !1, w = s.strikethrough || !1, T = s.textAlign || "center", C = s.letterSpacing ?? 0;
|
|
2717
|
+
t.save(), t.translate(s.x, s.y), t.rotate(-s.rotation * Math.PI / 180);
|
|
2718
|
+
const R = Jt(p, g, y, S), x = R.height, H = p * (s.lineHeight ?? 1.2);
|
|
2719
|
+
let M, A, I;
|
|
2720
|
+
if (h && s.transformType === "custom" && s.transformData.width) {
|
|
2721
|
+
const B = s.transformData.width - pt * 2;
|
|
2722
|
+
I = B;
|
|
2723
|
+
const k = Qt(h);
|
|
2724
|
+
M = [], A = [], k.forEach((O) => {
|
|
2725
|
+
const G = te(O, B, {
|
|
2726
|
+
fontSize: s.fontSize,
|
|
2727
|
+
fontFamily: s.fontFamily,
|
|
2728
|
+
bold: s.bold,
|
|
2729
|
+
italic: s.italic,
|
|
2730
|
+
letterSpacing: s.letterSpacing
|
|
2721
2731
|
});
|
|
2722
|
-
|
|
2723
|
-
|
|
2724
|
-
isParagraphStart:
|
|
2725
|
-
isParagraphEnd:
|
|
2732
|
+
G.forEach((P, _) => {
|
|
2733
|
+
M.push(P), A.push({
|
|
2734
|
+
isParagraphStart: _ === 0,
|
|
2735
|
+
isParagraphEnd: _ === G.length - 1
|
|
2726
2736
|
});
|
|
2727
2737
|
});
|
|
2728
2738
|
});
|
|
2729
2739
|
} else
|
|
2730
|
-
|
|
2740
|
+
M = l.split(`
|
|
2731
2741
|
`).map((k) => [
|
|
2732
2742
|
{
|
|
2733
2743
|
text: k,
|
|
2734
|
-
style: { fontSize:
|
|
2744
|
+
style: { fontSize: p, fontFamily: g, bold: y, italic: S }
|
|
2735
2745
|
}
|
|
2736
|
-
]),
|
|
2746
|
+
]), A = M.map(() => ({
|
|
2737
2747
|
isParagraphStart: !0,
|
|
2738
2748
|
// Each line is its own paragraph
|
|
2739
2749
|
isParagraphEnd: !0
|
|
2740
2750
|
}));
|
|
2741
|
-
const
|
|
2742
|
-
let
|
|
2743
|
-
const
|
|
2751
|
+
const L = M.length > 1 ? R.height + (M.length - 1) * H : R.height;
|
|
2752
|
+
let D = -L / 2, F = 0, W = D, q = x;
|
|
2753
|
+
const J = [];
|
|
2744
2754
|
let E = 0;
|
|
2745
|
-
|
|
2746
|
-
var
|
|
2747
|
-
const
|
|
2748
|
-
|
|
2749
|
-
Array.from(
|
|
2750
|
-
let
|
|
2755
|
+
M.forEach((B, k) => {
|
|
2756
|
+
var _, j;
|
|
2757
|
+
const O = A[k].isParagraphStart, G = A[k].isParagraphEnd, P = [];
|
|
2758
|
+
B.forEach((ot) => {
|
|
2759
|
+
Array.from(ot.text).forEach((lt) => {
|
|
2760
|
+
let Y = p, ht = g, it = y, U = S, st = C;
|
|
2751
2761
|
if (h && E < l.length) {
|
|
2752
|
-
const
|
|
2753
|
-
|
|
2762
|
+
const Z = h.getStyleAt(E);
|
|
2763
|
+
Y = Z.fontSize || p, ht = Z.fontFamily || g, it = Z.bold !== void 0 ? Z.bold : y, U = Z.italic !== void 0 ? Z.italic : S, st = Z.letterSpacing !== void 0 ? Z.letterSpacing : C;
|
|
2754
2764
|
}
|
|
2755
2765
|
t.save();
|
|
2756
|
-
const
|
|
2757
|
-
t.font = `${
|
|
2758
|
-
const
|
|
2759
|
-
t.restore(),
|
|
2766
|
+
const V = it ? "bold" : "normal", $ = U ? "italic" : "normal";
|
|
2767
|
+
t.font = `${$} ${V} ${Y}px "${ht}", Arial, sans-serif`;
|
|
2768
|
+
const at = t.measureText(lt).width + st;
|
|
2769
|
+
t.restore(), P.push({ char: lt, width: at, fontSize: Y, index: E }), E++;
|
|
2760
2770
|
});
|
|
2761
2771
|
});
|
|
2762
2772
|
{
|
|
2763
|
-
const
|
|
2764
|
-
let
|
|
2765
|
-
for (let V = 0; V <
|
|
2766
|
-
!
|
|
2767
|
-
let
|
|
2768
|
-
T === "center" ?
|
|
2769
|
-
let
|
|
2770
|
-
for (let V = 0; V <
|
|
2771
|
-
const
|
|
2772
|
-
|
|
2773
|
-
x:
|
|
2774
|
-
y:
|
|
2775
|
-
width:
|
|
2773
|
+
const ot = k === 0, et = k === M.length - 1, lt = P.map((V) => V.char).join(""), Y = ((_ = lt.match(/^ +/)) == null ? void 0 : _[0].length) || 0, ht = ((j = lt.match(/ +$/)) == null ? void 0 : j[0].length) || 0;
|
|
2774
|
+
let it = 0;
|
|
2775
|
+
for (let V = 0; V < P.length; V++)
|
|
2776
|
+
!ot && V < Y || !et && V >= P.length - ht || (it += P[V].width);
|
|
2777
|
+
let U;
|
|
2778
|
+
T === "center" ? U = -it / 2 : T === "right" ? U = I !== void 0 ? I / 2 - it : -it : U = I !== void 0 ? -I / 2 : 0;
|
|
2779
|
+
let st = U;
|
|
2780
|
+
for (let V = 0; V < P.length; V++) {
|
|
2781
|
+
const $ = P[V];
|
|
2782
|
+
J[$.index] = {
|
|
2783
|
+
x: st,
|
|
2784
|
+
y: D,
|
|
2785
|
+
width: $.width,
|
|
2776
2786
|
// All characters keep their width for cursor navigation
|
|
2777
|
-
height:
|
|
2778
|
-
},
|
|
2787
|
+
height: $.fontSize
|
|
2788
|
+
}, st += $.width;
|
|
2779
2789
|
}
|
|
2780
|
-
if (
|
|
2781
|
-
const V =
|
|
2782
|
-
if (i >= V && i <=
|
|
2790
|
+
if (P.length > 0) {
|
|
2791
|
+
const V = P[0].index, $ = P[P.length - 1].index, ut = k < M.length - 1 && $ + 1 === E ? $ : $ + 1;
|
|
2792
|
+
if (i >= V && i <= ut)
|
|
2783
2793
|
if (i === V)
|
|
2784
|
-
|
|
2794
|
+
F = U, W = D, q = x;
|
|
2785
2795
|
else {
|
|
2786
|
-
let
|
|
2787
|
-
for (let
|
|
2788
|
-
const
|
|
2789
|
-
let
|
|
2790
|
-
if (
|
|
2791
|
-
const
|
|
2792
|
-
|
|
2796
|
+
let yt = 0;
|
|
2797
|
+
for (let rt = 0; rt < P.length && P[rt].index < i; rt++) {
|
|
2798
|
+
const dt = P[rt], bt = dt.char === " ";
|
|
2799
|
+
let St = !0;
|
|
2800
|
+
if (bt) {
|
|
2801
|
+
const kt = rt < Y, X = rt >= P.length - ht, vt = !O && Y > 0, Mt = !G && ht > 0;
|
|
2802
|
+
St = !(kt && vt || X && Mt);
|
|
2793
2803
|
}
|
|
2794
|
-
|
|
2804
|
+
St && (yt += dt.width);
|
|
2795
2805
|
}
|
|
2796
|
-
|
|
2806
|
+
F = U + yt, W = D, q = x;
|
|
2797
2807
|
}
|
|
2798
2808
|
}
|
|
2799
|
-
k <
|
|
2809
|
+
k < M.length - 1 && (D += H);
|
|
2800
2810
|
}
|
|
2801
2811
|
});
|
|
2802
|
-
const
|
|
2803
|
-
let
|
|
2804
|
-
if (
|
|
2805
|
-
const
|
|
2806
|
-
t.save(), t.fillStyle =
|
|
2807
|
-
let
|
|
2808
|
-
if (
|
|
2809
|
-
var
|
|
2810
|
-
const
|
|
2811
|
-
if (
|
|
2812
|
-
Array.from(
|
|
2813
|
-
const V =
|
|
2812
|
+
const z = a !== r;
|
|
2813
|
+
let N = null, Q = null;
|
|
2814
|
+
if (z) {
|
|
2815
|
+
const B = Math.min(a, r), k = Math.max(a, r);
|
|
2816
|
+
t.save(), t.fillStyle = Te(t.canvas);
|
|
2817
|
+
let O = 0, G = -L / 2;
|
|
2818
|
+
if (M.forEach((P, _) => {
|
|
2819
|
+
var ht, it;
|
|
2820
|
+
const j = A[_].isParagraphStart, ot = A[_].isParagraphEnd, et = _ === 0, lt = _ === M.length - 1, Y = [];
|
|
2821
|
+
if (P.forEach((U) => {
|
|
2822
|
+
Array.from(U.text).forEach((st) => {
|
|
2823
|
+
const V = U.style || {}, $ = V.fontSize !== void 0 ? V.fontSize : p, at = V.fontFamily !== void 0 ? V.fontFamily : g, Z = V.bold !== void 0 ? V.bold : y, ut = V.italic !== void 0 ? V.italic : S, yt = V.letterSpacing !== void 0 ? V.letterSpacing : C;
|
|
2814
2824
|
t.save();
|
|
2815
|
-
const
|
|
2816
|
-
t.font = `${
|
|
2817
|
-
const
|
|
2818
|
-
t.restore(),
|
|
2825
|
+
const rt = Z ? "bold" : "normal", dt = ut ? "italic" : "normal";
|
|
2826
|
+
t.font = `${dt} ${rt} ${$}px "${at}", Arial, sans-serif`;
|
|
2827
|
+
const bt = t.measureText(st).width + yt;
|
|
2828
|
+
t.restore(), Y.push({ char: st, index: O, width: bt, style: V }), O++;
|
|
2819
2829
|
});
|
|
2820
|
-
}),
|
|
2821
|
-
const
|
|
2822
|
-
if (k >
|
|
2830
|
+
}), Y.length > 0) {
|
|
2831
|
+
const U = Y[0].index, st = Y[Y.length - 1].index;
|
|
2832
|
+
if (k > U && B <= st) {
|
|
2823
2833
|
t.save();
|
|
2824
|
-
const V =
|
|
2834
|
+
const V = Y.map((X) => X.char).join(""), $ = ((ht = V.match(/^ +/)) == null ? void 0 : ht[0].length) || 0, at = ((it = V.match(/ +$/)) == null ? void 0 : it[0].length) || 0;
|
|
2835
|
+
let Z = 0;
|
|
2836
|
+
for (let X = 0; X < Y.length; X++)
|
|
2837
|
+
!et && X < $ || !lt && X >= Y.length - at || (Z += Y[X].width);
|
|
2825
2838
|
let ut = 0;
|
|
2826
|
-
|
|
2827
|
-
|
|
2828
|
-
let
|
|
2829
|
-
|
|
2830
|
-
|
|
2831
|
-
|
|
2832
|
-
for (let N = 0; N < F.length && F[N].index < pt; N++) {
|
|
2833
|
-
const Tt = F[N], wt = N < q, At = N >= F.length - J, Et = !G && q > 0, It = !st && J > 0;
|
|
2834
|
-
!(wt && Et || At && It) && (ht += Tt.width);
|
|
2839
|
+
T === "center" ? ut = -Z / 2 : T === "right" && (ut = -Z);
|
|
2840
|
+
const yt = Math.max(B, U), rt = Math.min(k, st + 1);
|
|
2841
|
+
let dt = 0;
|
|
2842
|
+
for (let X = 0; X < Y.length && Y[X].index < yt; X++) {
|
|
2843
|
+
const vt = Y[X], Mt = X < $, Ht = X >= Y.length - at, It = !j && $ > 0, Bt = !ot && at > 0;
|
|
2844
|
+
!(Mt && It || Ht && Bt) && (dt += vt.width);
|
|
2835
2845
|
}
|
|
2836
|
-
let
|
|
2837
|
-
for (let
|
|
2838
|
-
const
|
|
2839
|
-
!(
|
|
2846
|
+
let bt = 0;
|
|
2847
|
+
for (let X = 0; X < Y.length && Y[X].index < rt; X++) {
|
|
2848
|
+
const vt = Y[X], Mt = X < $, Ht = X >= Y.length - at, It = !j && $ > 0, Bt = !ot && at > 0;
|
|
2849
|
+
!(Mt && It || Ht && Bt) && (bt += vt.width);
|
|
2840
2850
|
}
|
|
2841
|
-
const
|
|
2842
|
-
t.fillRect(
|
|
2851
|
+
const St = ut + dt, kt = bt - dt;
|
|
2852
|
+
t.fillRect(St, G, kt, x), N === null && (N = { x: St, y: G }), Q = { x: St + kt, y: G + x }, t.restore();
|
|
2843
2853
|
}
|
|
2844
2854
|
}
|
|
2845
|
-
|
|
2855
|
+
_ < M.length - 1 && (G += H);
|
|
2846
2856
|
}), t.restore(), h) {
|
|
2847
2857
|
t.save();
|
|
2848
|
-
const
|
|
2849
|
-
|
|
2850
|
-
fontSize:
|
|
2851
|
-
fontFamily:
|
|
2852
|
-
color:
|
|
2858
|
+
const P = s.transformType === "custom" ? s.transformData : null, _ = P != null && P.width ? P.width - pt * 2 : void 0;
|
|
2859
|
+
Ce(t, h, {
|
|
2860
|
+
fontSize: p,
|
|
2861
|
+
fontFamily: g,
|
|
2862
|
+
color: s.color || "#000000",
|
|
2853
2863
|
bold: y,
|
|
2854
2864
|
italic: S,
|
|
2855
2865
|
underline: m,
|
|
2856
2866
|
strikethrough: w,
|
|
2857
|
-
textAlign: T
|
|
2858
|
-
|
|
2867
|
+
textAlign: T,
|
|
2868
|
+
letterSpacing: s.letterSpacing,
|
|
2869
|
+
lineHeight: s.lineHeight
|
|
2870
|
+
}, _), t.restore();
|
|
2859
2871
|
}
|
|
2860
2872
|
}
|
|
2861
|
-
if (
|
|
2862
|
-
const
|
|
2873
|
+
if (z && d && N && Q) {
|
|
2874
|
+
const B = N, k = Q, O = 6 / b, G = 2 / b;
|
|
2863
2875
|
t.save();
|
|
2864
|
-
const
|
|
2865
|
-
t.fillStyle =
|
|
2866
|
-
const
|
|
2867
|
-
t.beginPath(), t.moveTo(
|
|
2876
|
+
const P = nt(t.canvas);
|
|
2877
|
+
t.fillStyle = P, t.strokeStyle = P, t.lineWidth = G, t.lineCap = "round";
|
|
2878
|
+
const _ = { x: B.x, y: B.y - O }, j = { x: k.x, y: k.y + O };
|
|
2879
|
+
t.beginPath(), t.moveTo(B.x, B.y), t.lineTo(B.x, B.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 = P, t.lineWidth = G, t.beginPath(), t.moveTo(k.x, k.y - x), t.lineTo(k.x, k.y), t.stroke(), t.beginPath(), t.arc(j.x, j.y, O, 0, Math.PI * 2), t.fill(), t.strokeStyle = "white", t.lineWidth = 2 / b, t.stroke(), t.restore(), f && (f.current = {
|
|
2868
2880
|
start: {
|
|
2869
|
-
center:
|
|
2870
|
-
textEdge:
|
|
2881
|
+
center: _,
|
|
2882
|
+
textEdge: B
|
|
2871
2883
|
// Original selection edge (top-left of selection on first line)
|
|
2872
2884
|
},
|
|
2873
2885
|
end: {
|
|
2874
|
-
center:
|
|
2886
|
+
center: j,
|
|
2875
2887
|
textEdge: k
|
|
2876
2888
|
// Original selection edge (bottom-right of selection on last line)
|
|
2877
2889
|
}
|
|
2878
2890
|
});
|
|
2879
2891
|
} else f && (f.current = { start: null, end: null });
|
|
2880
|
-
!
|
|
2892
|
+
!z && c > 0 && (t.save(), t.globalAlpha = c, t.strokeStyle = nt(t.canvas), t.lineWidth = 3 / b, t.lineCap = "round", t.beginPath(), t.moveTo(F, W), t.lineTo(F, W + q), t.stroke(), t.restore()), t.restore();
|
|
2881
2893
|
}
|
|
2882
2894
|
/**
|
|
2883
2895
|
* Render edit mode features for transformed text (circle, wave, arch, etc.)
|
|
2884
2896
|
* Renders cursor along the transform path
|
|
2885
2897
|
*/
|
|
2886
|
-
static renderTransformEditModeLayer(t, e,
|
|
2887
|
-
const { cursorPosition:
|
|
2898
|
+
static renderTransformEditModeLayer(t, e, o, n = 1) {
|
|
2899
|
+
const { cursorPosition: s, cursorOpacity: i } = o, a = e.fontSize || 24, r = e.fontFamily || "Arial", l = e.bold || !1, h = e.italic || !1;
|
|
2888
2900
|
t.save(), t.translate(e.x, e.y), t.rotate(-e.rotation * Math.PI / 180);
|
|
2889
2901
|
const c = l ? "bold" : "normal", d = h ? "italic" : "normal";
|
|
2890
2902
|
t.font = `${d} ${c} ${a}px ${r}`;
|
|
2891
|
-
const f = Array.from(e.text),
|
|
2892
|
-
if (
|
|
2893
|
-
let
|
|
2894
|
-
if (
|
|
2895
|
-
if (
|
|
2896
|
-
const y =
|
|
2897
|
-
|
|
2903
|
+
const f = Array.from(e.text), b = f.map((p) => t.measureText(p).width), u = Vt.calculateCharPositions(e, f, b);
|
|
2904
|
+
if (s >= 0 && s <= f.length && i > 0) {
|
|
2905
|
+
let p;
|
|
2906
|
+
if (s === 0)
|
|
2907
|
+
if (u.length > 0) {
|
|
2908
|
+
const y = u[0], S = b[0];
|
|
2909
|
+
p = {
|
|
2898
2910
|
x: y.x - Math.cos(y.angle) * (S / 2),
|
|
2899
2911
|
y: y.y - Math.sin(y.angle) * (S / 2),
|
|
2900
2912
|
angle: y.angle
|
|
2901
2913
|
};
|
|
2902
2914
|
} else
|
|
2903
|
-
|
|
2904
|
-
else if (
|
|
2905
|
-
const y =
|
|
2906
|
-
|
|
2915
|
+
p = { x: 0, y: 0, angle: 0 };
|
|
2916
|
+
else if (s >= u.length) {
|
|
2917
|
+
const y = u[u.length - 1], S = b[b.length - 1];
|
|
2918
|
+
p = {
|
|
2907
2919
|
x: y.x + Math.cos(y.angle) * (S / 2),
|
|
2908
2920
|
y: y.y + Math.sin(y.angle) * (S / 2),
|
|
2909
2921
|
angle: y.angle
|
|
2910
2922
|
};
|
|
2911
2923
|
} else {
|
|
2912
|
-
const y =
|
|
2913
|
-
|
|
2924
|
+
const y = u[s], S = b[s];
|
|
2925
|
+
p = {
|
|
2914
2926
|
x: y.x - Math.cos(y.angle) * (S / 2),
|
|
2915
2927
|
y: y.y - Math.sin(y.angle) * (S / 2),
|
|
2916
2928
|
angle: y.angle
|
|
2917
2929
|
};
|
|
2918
2930
|
}
|
|
2919
|
-
t.save(), t.translate(
|
|
2920
|
-
const
|
|
2921
|
-
t.beginPath(), t.moveTo(0, -
|
|
2931
|
+
t.save(), t.translate(p.x, p.y), t.rotate(p.angle), t.globalAlpha = i, t.strokeStyle = nt(t.canvas), t.lineWidth = 2 / n;
|
|
2932
|
+
const g = a * 1.2;
|
|
2933
|
+
t.beginPath(), t.moveTo(0, -g / 2), t.lineTo(0, g / 2), t.stroke(), t.restore();
|
|
2922
2934
|
}
|
|
2923
2935
|
t.restore();
|
|
2924
2936
|
}
|
|
@@ -2926,29 +2938,29 @@ class Dt {
|
|
|
2926
2938
|
* Render crop box layer (for images in crop mode)
|
|
2927
2939
|
* Shows both image resize handles and crop handles
|
|
2928
2940
|
*/
|
|
2929
|
-
static renderCropBoxLayer(t, e,
|
|
2930
|
-
if (!(e instanceof
|
|
2931
|
-
const
|
|
2941
|
+
static renderCropBoxLayer(t, e, o, n = 1) {
|
|
2942
|
+
if (!(e instanceof we) || !e.isCropping) return;
|
|
2943
|
+
const s = e, i = s.getCropBoxBounds();
|
|
2932
2944
|
if (!i) return;
|
|
2933
|
-
const a = 4 / n, r = 2 / n, l =
|
|
2934
|
-
t.save(), t.translate(e.x * n, e.y * n), t.rotate(
|
|
2935
|
-
const d =
|
|
2945
|
+
const a = 4 / n, r = 2 / n, l = ve / n, h = Me / n, c = 1 / n;
|
|
2946
|
+
t.save(), t.translate(e.x * n, e.y * n), t.rotate(gt.toRadians(e.rotation));
|
|
2947
|
+
const d = s.transformData.flipHorizontal ? -1 : 1, f = s.transformData.flipVertical ? -1 : 1;
|
|
2936
2948
|
t.scale(d * n, f * n);
|
|
2937
|
-
const
|
|
2938
|
-
x:
|
|
2939
|
-
y:
|
|
2940
|
-
width:
|
|
2941
|
-
height:
|
|
2949
|
+
const b = s.transformData.width * s.transformData.cropWidth, u = s.transformData.height * s.transformData.cropHeight, p = s.transformData.width / 2 - (s.transformData.cropX * s.transformData.width + b / 2), g = s.transformData.height / 2 - (s.transformData.cropY * s.transformData.height + u / 2), y = s.transformData.width / 2, S = s.transformData.height / 2, m = {
|
|
2950
|
+
x: p - y,
|
|
2951
|
+
y: g - S,
|
|
2952
|
+
width: s.transformData.width,
|
|
2953
|
+
height: s.transformData.height
|
|
2942
2954
|
};
|
|
2943
2955
|
t.fillStyle = "rgba(0, 0, 0, 0.5)", i.y > m.y && t.fillRect(m.x, m.y, m.width, i.y - m.y);
|
|
2944
2956
|
const w = i.y + i.height, T = m.y + m.height;
|
|
2945
2957
|
w < T && t.fillRect(m.x, w, m.width, T - w), i.x > m.x && t.fillRect(m.x, i.y, i.x - m.x, i.height);
|
|
2946
2958
|
const C = i.x + i.width, R = m.x + m.width;
|
|
2947
|
-
C < R && t.fillRect(C, i.y, R - C, i.height), t.strokeStyle =
|
|
2959
|
+
C < R && t.fillRect(C, i.y, R - C, 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;
|
|
2948
2960
|
const x = i.width / 3;
|
|
2949
2961
|
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();
|
|
2950
|
-
const
|
|
2951
|
-
if (t.beginPath(), t.moveTo(i.x, i.y +
|
|
2962
|
+
const H = i.height / 3;
|
|
2963
|
+
if (t.beginPath(), t.moveTo(i.x, i.y + H), t.lineTo(i.x + i.width, i.y + H), t.moveTo(i.x, i.y + 2 * H), t.lineTo(i.x + i.width, i.y + 2 * H), t.stroke(), [
|
|
2952
2964
|
{ x: i.x, y: i.y },
|
|
2953
2965
|
// top-left
|
|
2954
2966
|
{ x: i.x + i.width, y: i.y },
|
|
@@ -2957,8 +2969,8 @@ class Dt {
|
|
|
2957
2969
|
// bottom-right
|
|
2958
2970
|
{ x: i.x, y: i.y + i.height }
|
|
2959
2971
|
// bottom-left
|
|
2960
|
-
].forEach((
|
|
2961
|
-
t.beginPath(), t.arc(
|
|
2972
|
+
].forEach((I) => {
|
|
2973
|
+
t.beginPath(), t.arc(I.x, I.y, l + 1 / n, 0, Math.PI * 2), t.fillStyle = "#bbb", t.fill(), t.beginPath(), t.arc(I.x, I.y, l, 0, Math.PI * 2), t.fillStyle = "#fff", t.fill();
|
|
2962
2974
|
}), [
|
|
2963
2975
|
{ x: i.x + i.width / 2, y: i.y, orientation: "horizontal" },
|
|
2964
2976
|
// top
|
|
@@ -2968,32 +2980,32 @@ class Dt {
|
|
|
2968
2980
|
// left
|
|
2969
2981
|
{ x: i.x + i.width, y: i.y + i.height / 2, orientation: "vertical" }
|
|
2970
2982
|
// right
|
|
2971
|
-
].forEach((
|
|
2972
|
-
let L,
|
|
2973
|
-
|
|
2974
|
-
const
|
|
2975
|
-
t.fillStyle = "#fff", t.fillRect(
|
|
2976
|
-
}), t.restore(),
|
|
2977
|
-
const
|
|
2978
|
-
(
|
|
2979
|
-
), L =
|
|
2980
|
-
|
|
2981
|
-
let
|
|
2983
|
+
].forEach((I) => {
|
|
2984
|
+
let L, D;
|
|
2985
|
+
I.orientation === "horizontal" ? (L = h, D = a) : (L = a, D = h);
|
|
2986
|
+
const F = I.x - L / 2, W = I.y - D / 2;
|
|
2987
|
+
t.fillStyle = "#fff", t.fillRect(F, W, L, D), t.strokeStyle = "#bbb", t.lineWidth = c, t.strokeRect(F, W, L, D);
|
|
2988
|
+
}), t.restore(), o && o.resizeHandles) {
|
|
2989
|
+
const I = o.resizeHandles.filter(
|
|
2990
|
+
(W) => W.anchor === "top-left" || W.anchor === "top-right" || W.anchor === "bottom-left" || W.anchor === "bottom-right"
|
|
2991
|
+
), L = s.getCropBoxWorldCorners(), D = 6, F = 20;
|
|
2992
|
+
I.forEach((W) => {
|
|
2993
|
+
let q = !1;
|
|
2982
2994
|
if (L)
|
|
2983
|
-
for (const
|
|
2984
|
-
const
|
|
2985
|
-
if (Math.sqrt(
|
|
2986
|
-
|
|
2995
|
+
for (const J of L) {
|
|
2996
|
+
const E = W.x - J.x, z = W.y - J.y;
|
|
2997
|
+
if (Math.sqrt(E * E + z * z) < F) {
|
|
2998
|
+
q = !0;
|
|
2987
2999
|
break;
|
|
2988
3000
|
}
|
|
2989
3001
|
}
|
|
2990
|
-
|
|
3002
|
+
q || (t.save(), t.globalAlpha = 1, t.beginPath(), t.arc(W.x * n, W.y * n, D, 0, 2 * Math.PI), t.fillStyle = "#fff", t.fill(), t.strokeStyle = nt(t.canvas), t.lineWidth = 2, t.stroke(), t.restore());
|
|
2991
3003
|
});
|
|
2992
3004
|
}
|
|
2993
3005
|
}
|
|
2994
3006
|
}
|
|
2995
|
-
|
|
2996
|
-
const
|
|
3007
|
+
Ae();
|
|
3008
|
+
const Ne = Zt("CanvasRenderer"), K = class K {
|
|
2997
3009
|
/**
|
|
2998
3010
|
* Get a pooled offscreen canvas for clipping content, only recreating
|
|
2999
3011
|
* when dimensions change. Eliminates per-frame canvas allocation.
|
|
@@ -3012,12 +3024,12 @@ const Oe = $t("CanvasRenderer"), K = class K {
|
|
|
3012
3024
|
* Safely render an element, catching errors so one element's failure
|
|
3013
3025
|
* doesn't crash the entire canvas render loop.
|
|
3014
3026
|
*/
|
|
3015
|
-
static safeRender(t, e,
|
|
3027
|
+
static safeRender(t, e, o, n) {
|
|
3016
3028
|
try {
|
|
3017
|
-
e.render(t,
|
|
3018
|
-
} catch (
|
|
3019
|
-
const i =
|
|
3020
|
-
|
|
3029
|
+
e.render(t, o, n);
|
|
3030
|
+
} catch (s) {
|
|
3031
|
+
const i = s instanceof Error ? s : new Error(String(s));
|
|
3032
|
+
Ne.error(`Failed to render element ${e.id}:`, i), K.onRenderError && K.onRenderError({
|
|
3021
3033
|
category: "render",
|
|
3022
3034
|
message: `Failed to render element: ${i.message}`,
|
|
3023
3035
|
originalError: i,
|
|
@@ -3033,8 +3045,8 @@ const Oe = $t("CanvasRenderer"), K = class K {
|
|
|
3033
3045
|
* Helper function to render an element (using actual element instance, not config)
|
|
3034
3046
|
* Used by knockout rendering system
|
|
3035
3047
|
*/
|
|
3036
|
-
static renderElement(t, e,
|
|
3037
|
-
|
|
3048
|
+
static renderElement(t, e, o = !0) {
|
|
3049
|
+
o && (t.save(), t.globalAlpha = tt), e.render(t, !1, !1), o && t.restore();
|
|
3038
3050
|
}
|
|
3039
3051
|
/**
|
|
3040
3052
|
* Apply artboard clip path to the context, respecting clipShape.
|
|
@@ -3042,22 +3054,22 @@ const Oe = $t("CanvasRenderer"), K = class K {
|
|
|
3042
3054
|
* Caller must call ctx.beginPath() before this if needed.
|
|
3043
3055
|
*/
|
|
3044
3056
|
static applyArtboardClipPath(t, e) {
|
|
3045
|
-
const { x:
|
|
3057
|
+
const { x: o, y: n, width: s, height: i, clipShape: a } = e, r = e.borderRadius || 0;
|
|
3046
3058
|
if (t.beginPath(), !a || a === "rectangle")
|
|
3047
|
-
r > 0 ? t.roundRect(
|
|
3059
|
+
r > 0 ? t.roundRect(o, n, s, i, r) : t.rect(o, n, s, i);
|
|
3048
3060
|
else if (a === "circle") {
|
|
3049
|
-
const l =
|
|
3061
|
+
const l = o + s / 2, h = n + i / 2, c = Math.min(s, i) / 2;
|
|
3050
3062
|
t.arc(l, h, c, 0, Math.PI * 2);
|
|
3051
3063
|
} else if (typeof a == "object" && a.type === "rounded") {
|
|
3052
|
-
const l = Math.min(a.radius, Math.min(
|
|
3053
|
-
t.roundRect(
|
|
3064
|
+
const l = Math.min(a.radius, Math.min(s, i) / 2);
|
|
3065
|
+
t.roundRect(o, n, s, i, l);
|
|
3054
3066
|
} else if (typeof a == "object" && a.type === "path")
|
|
3055
3067
|
try {
|
|
3056
3068
|
const l = new Path2D(a.d);
|
|
3057
|
-
t.translate(
|
|
3069
|
+
t.translate(o, n), t.clip(l), t.translate(-o, -n);
|
|
3058
3070
|
return;
|
|
3059
3071
|
} catch {
|
|
3060
|
-
t.rect(
|
|
3072
|
+
t.rect(o, n, s, i);
|
|
3061
3073
|
}
|
|
3062
3074
|
else if (typeof a == "object" && a.type === "composite-path")
|
|
3063
3075
|
try {
|
|
@@ -3065,15 +3077,15 @@ const Oe = $t("CanvasRenderer"), K = class K {
|
|
|
3065
3077
|
for (const h of a.pieces) {
|
|
3066
3078
|
const c = new Path2D(h.d), d = h.rotation ?? 0, f = new DOMMatrix();
|
|
3067
3079
|
if (f.translateSelf(h.x, h.y), d !== 0) {
|
|
3068
|
-
const
|
|
3069
|
-
f.translateSelf(
|
|
3080
|
+
const b = (h.baseWidth ?? 0) / 2, u = (h.baseHeight ?? 0) / 2, p = d === 90 || d === 270, g = p ? h.baseHeight ?? 0 : h.baseWidth ?? 0, y = p ? h.baseWidth ?? 0 : h.baseHeight ?? 0;
|
|
3081
|
+
f.translateSelf(g / 2, y / 2), f.rotateSelf(d), f.translateSelf(-b, -u);
|
|
3070
3082
|
}
|
|
3071
3083
|
l.addPath(c, f);
|
|
3072
3084
|
}
|
|
3073
|
-
t.translate(
|
|
3085
|
+
t.translate(o, n), t.clip(l), t.translate(-o, -n);
|
|
3074
3086
|
return;
|
|
3075
3087
|
} catch {
|
|
3076
|
-
t.rect(
|
|
3088
|
+
t.rect(o, n, s, i);
|
|
3077
3089
|
}
|
|
3078
3090
|
t.clip();
|
|
3079
3091
|
}
|
|
@@ -3081,25 +3093,25 @@ const Oe = $t("CanvasRenderer"), K = class K {
|
|
|
3081
3093
|
* Render an element with overflow dimming - parts outside the artboard render at 30% opacity
|
|
3082
3094
|
* Uses two-pass rendering: first at 30% opacity (overflow), then clipped to artboard at 100% (inside)
|
|
3083
3095
|
*/
|
|
3084
|
-
static renderElementWithOverflowDimming(t, e,
|
|
3085
|
-
const a = t.getTransform(), r =
|
|
3096
|
+
static renderElementWithOverflowDimming(t, e, o, n, s, i) {
|
|
3097
|
+
const a = t.getTransform(), r = o.borderRadius || 0;
|
|
3086
3098
|
t.save(), t.globalAlpha = 0.3 * (i ? tt : 1), t.filter = "blur(4px)", t.beginPath();
|
|
3087
|
-
const h = t.getTransform().inverse(), c = t.canvas.width, d = t.canvas.height, f = new DOMPoint(0, 0).matrixTransform(h),
|
|
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 o.clipShape == "object" && o.clipShape !== null && o.clipShape.type === "composite-path" ? o.clipShape : null;
|
|
3088
3100
|
if (m) {
|
|
3089
3101
|
const w = new Path2D();
|
|
3090
|
-
w.rect(
|
|
3102
|
+
w.rect(p, g, y - p, S - g);
|
|
3091
3103
|
for (const T of m.pieces) {
|
|
3092
3104
|
const C = new Path2D(T.d), R = T.rotation ?? 0, x = new DOMMatrix();
|
|
3093
|
-
if (x.translateSelf(
|
|
3094
|
-
const
|
|
3095
|
-
x.translateSelf(
|
|
3105
|
+
if (x.translateSelf(o.x + T.x, o.y + T.y), R !== 0) {
|
|
3106
|
+
const H = (T.baseWidth ?? 0) / 2, M = (T.baseHeight ?? 0) / 2, A = R === 90 || R === 270, I = A ? T.baseHeight ?? 0 : T.baseWidth ?? 0, L = A ? T.baseWidth ?? 0 : T.baseHeight ?? 0;
|
|
3107
|
+
x.translateSelf(I / 2, L / 2), x.rotateSelf(R), x.translateSelf(-H, -M);
|
|
3096
3108
|
}
|
|
3097
3109
|
w.addPath(C, x);
|
|
3098
3110
|
}
|
|
3099
3111
|
t.clip(w, "evenodd");
|
|
3100
3112
|
} else
|
|
3101
|
-
t.rect(
|
|
3102
|
-
e.render(t, !1, !1), t.restore(), t.save(), this.applyArtboardClipPath(t,
|
|
3113
|
+
t.rect(p, g, y - p, S - g), r > 0 ? t.roundRect(o.x, o.y, o.width, o.height, r) : t.rect(o.x, o.y, o.width, o.height), t.clip("evenodd");
|
|
3114
|
+
e.render(t, !1, !1), t.restore(), t.save(), this.applyArtboardClipPath(t, o), i && (t.globalAlpha = tt), e.render(t, n, s), t.restore(), t.setTransform(a);
|
|
3103
3115
|
}
|
|
3104
3116
|
/**
|
|
3105
3117
|
* Render all elements layer
|
|
@@ -3110,108 +3122,108 @@ const Oe = $t("CanvasRenderer"), K = class K {
|
|
|
3110
3122
|
* a coloured halo rather than useful UX. Selected/hovered elements fall through to the
|
|
3111
3123
|
* clipped-only branch which respects `clipShape` correctly.
|
|
3112
3124
|
*/
|
|
3113
|
-
static renderElementsLayer(t, e,
|
|
3114
|
-
const c =
|
|
3115
|
-
e !== K._cachedElementsRef && (K._cachedElementConfigs = e.map((
|
|
3116
|
-
const f = K._cachedElementConfigs,
|
|
3117
|
-
|
|
3125
|
+
static renderElementsLayer(t, e, o, n, s, i, a, r = !0, l = !1, h = !1) {
|
|
3126
|
+
const c = s != null && s.getMode() === "drag", d = s == null ? void 0 : s._activeChildContext;
|
|
3127
|
+
e !== K._cachedElementsRef && (K._cachedElementConfigs = e.map((g) => g.toJSON()), K._cachedElementMap = new Map(e.map((g) => [g.id, g])), K._cachedElementsRef = e);
|
|
3128
|
+
const f = K._cachedElementConfigs, b = K._cachedElementMap, u = K._knockoutRenderedIds;
|
|
3129
|
+
u.clear(), e.forEach((g, y) => {
|
|
3118
3130
|
var S, m, w;
|
|
3119
|
-
if (
|
|
3120
|
-
const T = f[y], C =
|
|
3121
|
-
|
|
3131
|
+
if (g.blendMode === "knockout" || g.blendMode === "clip") {
|
|
3132
|
+
const T = f[y], C = g.blendMode === "knockout" ? "destination-out" : "destination-in", R = ((S = T.knockoutParts) == null ? void 0 : S.scope) || "group", x = f.findIndex((I) => I.id === T.id), H = ((m = T.knockoutParts) == null ? void 0 : m.fill) || ((w = T.knockoutParts) == null ? void 0 : w.stroke), M = R === "artboard" && x !== -1 ? f.slice(0, x) : [];
|
|
3133
|
+
H && (R === "artboard" || M.length > 0) && (M.forEach((I) => I.id && u.add(I.id)), Re(
|
|
3122
3134
|
t,
|
|
3123
3135
|
T,
|
|
3124
3136
|
f,
|
|
3125
|
-
(
|
|
3126
|
-
const
|
|
3127
|
-
|
|
3137
|
+
(I, L) => {
|
|
3138
|
+
const D = L.id && b.get(L.id);
|
|
3139
|
+
D && this.renderElement(I, D, r);
|
|
3128
3140
|
},
|
|
3129
3141
|
i,
|
|
3130
3142
|
a,
|
|
3131
3143
|
C
|
|
3132
|
-
),
|
|
3144
|
+
), u.add(g.id));
|
|
3133
3145
|
}
|
|
3134
|
-
}), e.some((
|
|
3146
|
+
}), e.some((g) => !u.has(g.id) && g.isClipping) ? this._renderWithClipping(
|
|
3135
3147
|
t,
|
|
3136
3148
|
e,
|
|
3137
|
-
|
|
3138
|
-
|
|
3149
|
+
u,
|
|
3150
|
+
o,
|
|
3139
3151
|
n,
|
|
3140
3152
|
c,
|
|
3141
3153
|
d,
|
|
3142
3154
|
f,
|
|
3143
3155
|
r
|
|
3144
|
-
) : e.forEach((
|
|
3156
|
+
) : e.forEach((g) => {
|
|
3145
3157
|
var R, x;
|
|
3146
|
-
if (
|
|
3147
|
-
const y =
|
|
3158
|
+
if (u.has(g.id) || g.visible === !1) return;
|
|
3159
|
+
const y = g.id === o, S = (n == null ? void 0 : n.type) === "element" && ((R = n == null ? void 0 : n.data) == null ? void 0 : R.id) === g.id, m = c && d && Dt(g) && g.id === o, w = y && !m, T = f[e.indexOf(g)], C = ((x = T == null ? void 0 : T.distressEffect) == null ? void 0 : x.enabled) && T.distressEffect.style === "custom" && T.distressEffect.textureUrl;
|
|
3148
3160
|
if (T && T.masks && T.masks.length > 0)
|
|
3149
|
-
|
|
3161
|
+
At(t, T, (H) => {
|
|
3150
3162
|
const M = (A) => {
|
|
3151
|
-
r && (A.save(), A.globalAlpha = tt), this.safeRender(A,
|
|
3163
|
+
r && (A.save(), A.globalAlpha = tt), this.safeRender(A, g, w, S), r && A.restore();
|
|
3152
3164
|
};
|
|
3153
3165
|
if (C) {
|
|
3154
|
-
const A =
|
|
3155
|
-
|
|
3166
|
+
const A = g.getVisualBoundingBox();
|
|
3167
|
+
Kt(H, T.distressEffect, A, M);
|
|
3156
3168
|
} else
|
|
3157
|
-
M(
|
|
3169
|
+
M(H);
|
|
3158
3170
|
});
|
|
3159
3171
|
else if (C) {
|
|
3160
|
-
const
|
|
3161
|
-
|
|
3162
|
-
r && (M.save(), M.globalAlpha = tt), this.safeRender(M,
|
|
3172
|
+
const H = g.getVisualBoundingBox();
|
|
3173
|
+
Kt(t, T.distressEffect, H, (M) => {
|
|
3174
|
+
r && (M.save(), M.globalAlpha = tt), this.safeRender(M, g, w, S), r && M.restore();
|
|
3163
3175
|
});
|
|
3164
|
-
} else l && !h && a && w ? this.renderElementWithOverflowDimming(t,
|
|
3176
|
+
} else l && !h && a && w ? this.renderElementWithOverflowDimming(t, g, a, w, S, r) : l && a ? (t.save(), this.applyArtboardClipPath(t, a), r && (t.globalAlpha = tt), this.safeRender(t, g, w, S), t.restore()) : (r && (t.save(), t.globalAlpha = tt), this.safeRender(t, g, w, S), r && t.restore());
|
|
3165
3177
|
});
|
|
3166
3178
|
}
|
|
3167
3179
|
/**
|
|
3168
3180
|
* Render elements with clipping mask support at artboard level
|
|
3169
3181
|
* Elements with isClipping=true clip all elements below them
|
|
3170
3182
|
*/
|
|
3171
|
-
static _renderWithClipping(t, e,
|
|
3172
|
-
var
|
|
3173
|
-
const h = t.canvas, c = h.width, d = h.height, f = t.getTransform(),
|
|
3174
|
-
let
|
|
3183
|
+
static _renderWithClipping(t, e, o, n, s, i, a, r, l = !0) {
|
|
3184
|
+
var g;
|
|
3185
|
+
const h = t.canvas, c = h.width, d = h.height, f = t.getTransform(), b = [];
|
|
3186
|
+
let u = [], p = [];
|
|
3175
3187
|
for (let y = 0; y < e.length; y++) {
|
|
3176
3188
|
const S = e[y], m = r[y];
|
|
3177
|
-
|
|
3178
|
-
content:
|
|
3189
|
+
o.has(S.id) || S.visible !== !1 && (S.isClipping ? u.length > 0 ? (b.push({
|
|
3190
|
+
content: u,
|
|
3179
3191
|
mask: S,
|
|
3180
|
-
contentConfigs:
|
|
3192
|
+
contentConfigs: p,
|
|
3181
3193
|
maskConfig: m
|
|
3182
|
-
}),
|
|
3194
|
+
}), u = [], p = []) : b.push({
|
|
3183
3195
|
content: [S],
|
|
3184
3196
|
contentConfigs: [m]
|
|
3185
|
-
}) : (
|
|
3197
|
+
}) : (u.push(S), p.push(m)));
|
|
3186
3198
|
}
|
|
3187
|
-
|
|
3188
|
-
content:
|
|
3189
|
-
contentConfigs:
|
|
3199
|
+
u.length > 0 && b.push({
|
|
3200
|
+
content: u,
|
|
3201
|
+
contentConfigs: p
|
|
3190
3202
|
});
|
|
3191
|
-
for (const y of
|
|
3203
|
+
for (const y of b)
|
|
3192
3204
|
if (!y.mask)
|
|
3193
3205
|
y.content.forEach((S, m) => {
|
|
3194
|
-
var
|
|
3195
|
-
const w = S.id === n, T = (
|
|
3196
|
-
x && x.masks && x.masks.length > 0 ?
|
|
3206
|
+
var H;
|
|
3207
|
+
const w = S.id === n, T = (s == null ? void 0 : s.type) === "element" && ((H = s == null ? void 0 : s.data) == null ? void 0 : H.id) === S.id, C = i && a && Dt(S) && S.id === n, R = w && !C, x = y.contentConfigs[m];
|
|
3208
|
+
x && x.masks && x.masks.length > 0 ? At(t, x, (M) => {
|
|
3197
3209
|
l && (M.save(), M.globalAlpha = tt), S.render(M, R, T), l && M.restore();
|
|
3198
3210
|
}) : (l && (t.save(), t.globalAlpha = tt), S.render(t, R, T), l && t.restore());
|
|
3199
3211
|
});
|
|
3200
3212
|
else {
|
|
3201
3213
|
const S = this._getContentCanvas(c, d), m = S.getContext("2d");
|
|
3202
3214
|
if (!m) continue;
|
|
3203
|
-
m.setTransform(1, 0, 0, 1, 0, 0), m.clearRect(0, 0, c, d), m.globalCompositeOperation = "source-over", m.setTransform(f), y.content.forEach((x,
|
|
3204
|
-
var
|
|
3205
|
-
const M = x.id === n, A = (
|
|
3206
|
-
|
|
3207
|
-
l && (
|
|
3215
|
+
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, H) => {
|
|
3216
|
+
var F;
|
|
3217
|
+
const M = x.id === n, A = (s == null ? void 0 : s.type) === "element" && ((F = s == null ? void 0 : s.data) == null ? void 0 : F.id) === x.id, I = i && a && Dt(x) && x.id === n, L = M && !I, D = y.contentConfigs[H];
|
|
3218
|
+
D && D.masks && D.masks.length > 0 ? At(m, D, (W) => {
|
|
3219
|
+
l && (W.save(), W.globalAlpha = tt), x.render(W, L, A), l && W.restore();
|
|
3208
3220
|
}) : (l && (m.save(), m.globalAlpha = tt), x.render(m, L, A), l && m.restore());
|
|
3209
3221
|
});
|
|
3210
3222
|
const w = this._getMaskCanvas(c, d), T = w.getContext("2d");
|
|
3211
3223
|
if (!T) continue;
|
|
3212
3224
|
T.setTransform(1, 0, 0, 1, 0, 0), T.clearRect(0, 0, c, d), T.globalCompositeOperation = "source-over", T.setTransform(f);
|
|
3213
|
-
const C = y.mask.id === n, R = (
|
|
3214
|
-
y.maskConfig && y.maskConfig.masks && y.maskConfig.masks.length > 0 ?
|
|
3225
|
+
const C = y.mask.id === n, R = (s == null ? void 0 : s.type) === "element" && ((g = s == null ? void 0 : s.data) == null ? void 0 : g.id) === y.mask.id;
|
|
3226
|
+
y.maskConfig && y.maskConfig.masks && y.maskConfig.masks.length > 0 ? At(T, y.maskConfig, (x) => {
|
|
3215
3227
|
l && (x.save(), x.globalAlpha = tt), y.mask.render(x, C, R), l && x.restore();
|
|
3216
3228
|
}) : (l && (T.save(), T.globalAlpha = tt), y.mask.render(T, C, R), l && T.restore()), m.globalCompositeOperation = "destination-in", m.setTransform(1, 0, 0, 1, 0, 0), m.drawImage(w, 0, 0), t.save(), t.setTransform(1, 0, 0, 1, 0, 0), t.drawImage(S, 0, 0), t.restore();
|
|
3217
3229
|
}
|
|
@@ -3224,47 +3236,47 @@ const Oe = $t("CanvasRenderer"), K = class K {
|
|
|
3224
3236
|
* @see InteractionFeedbackRenderer.renderSnapGuidesLayer
|
|
3225
3237
|
*/
|
|
3226
3238
|
static renderSnapGuidesLayer(t, e = []) {
|
|
3227
|
-
|
|
3239
|
+
Ct.renderSnapGuidesLayer(t, e);
|
|
3228
3240
|
}
|
|
3229
3241
|
/**
|
|
3230
3242
|
* Render spacing indicators layer
|
|
3231
3243
|
* @see InteractionFeedbackRenderer.renderSpacingIndicatorsLayer
|
|
3232
3244
|
*/
|
|
3233
3245
|
static renderSpacingIndicatorsLayer(t, e = []) {
|
|
3234
|
-
|
|
3246
|
+
Ct.renderSpacingIndicatorsLayer(t, e);
|
|
3235
3247
|
}
|
|
3236
3248
|
/**
|
|
3237
3249
|
* Render a distance label with background
|
|
3238
3250
|
* @see InteractionFeedbackRenderer.renderDistanceLabel
|
|
3239
3251
|
*/
|
|
3240
|
-
static renderDistanceLabel(t, e,
|
|
3241
|
-
|
|
3252
|
+
static renderDistanceLabel(t, e, o, n) {
|
|
3253
|
+
Ct.renderDistanceLabel(t, e, o, n);
|
|
3242
3254
|
}
|
|
3243
3255
|
/**
|
|
3244
3256
|
* Render selection box layer
|
|
3245
3257
|
* @see SelectionRenderer.renderSelectionLayer
|
|
3246
3258
|
*/
|
|
3247
|
-
static renderSelectionLayer(t, e,
|
|
3248
|
-
|
|
3259
|
+
static renderSelectionLayer(t, e, o, n = 1) {
|
|
3260
|
+
wt.renderSelectionLayer(t, e, o, n);
|
|
3249
3261
|
}
|
|
3250
3262
|
/**
|
|
3251
3263
|
* Render position and size info below the selected element
|
|
3252
3264
|
* @see SelectionRenderer.renderPositionSizeInfo
|
|
3253
3265
|
*/
|
|
3254
|
-
static renderPositionSizeInfo(t, e,
|
|
3255
|
-
|
|
3266
|
+
static renderPositionSizeInfo(t, e, o, n, s = 1) {
|
|
3267
|
+
wt.renderPositionSizeInfo(t, e, o, n, s);
|
|
3256
3268
|
}
|
|
3257
3269
|
/**
|
|
3258
3270
|
* Render transform handles layer
|
|
3259
3271
|
* @see SelectionRenderer.renderHandlesLayer
|
|
3260
3272
|
*/
|
|
3261
|
-
static renderHandlesLayer(t, e,
|
|
3262
|
-
|
|
3273
|
+
static renderHandlesLayer(t, e, o, n, s, i, a, r = 1, l = !0) {
|
|
3274
|
+
wt.renderHandlesLayer(
|
|
3263
3275
|
t,
|
|
3264
3276
|
e,
|
|
3265
|
-
s,
|
|
3266
|
-
n,
|
|
3267
3277
|
o,
|
|
3278
|
+
n,
|
|
3279
|
+
s,
|
|
3268
3280
|
i,
|
|
3269
3281
|
a,
|
|
3270
3282
|
r,
|
|
@@ -3275,15 +3287,15 @@ const Oe = $t("CanvasRenderer"), K = class K {
|
|
|
3275
3287
|
* Render hover highlights layer with fade-in animation
|
|
3276
3288
|
* @see HoverRenderer.renderHoverLayer
|
|
3277
3289
|
*/
|
|
3278
|
-
static renderHoverLayer(t, e,
|
|
3279
|
-
|
|
3290
|
+
static renderHoverLayer(t, e, o, n = !1, s = 1, i) {
|
|
3291
|
+
Vt.renderHoverLayer(t, e, o, n, s, i);
|
|
3280
3292
|
}
|
|
3281
3293
|
/**
|
|
3282
3294
|
* Render crop box layer (for images in crop mode)
|
|
3283
3295
|
* @see EditModeRenderer.renderCropBoxLayer
|
|
3284
3296
|
*/
|
|
3285
|
-
static renderCropBoxLayer(t, e,
|
|
3286
|
-
|
|
3297
|
+
static renderCropBoxLayer(t, e, o, n = 1) {
|
|
3298
|
+
zt.renderCropBoxLayer(t, e, o, n);
|
|
3287
3299
|
}
|
|
3288
3300
|
// =========================================================================
|
|
3289
3301
|
// Main Render Orchestration
|
|
@@ -3295,7 +3307,7 @@ const Oe = $t("CanvasRenderer"), K = class K {
|
|
|
3295
3307
|
static render({
|
|
3296
3308
|
ctx: t,
|
|
3297
3309
|
elements: e,
|
|
3298
|
-
selectedId:
|
|
3310
|
+
selectedId: o,
|
|
3299
3311
|
selectedElement: n,
|
|
3300
3312
|
// Chrome-related fields (transformHandles, currentRotation,
|
|
3301
3313
|
// isRotating, hideHandles, isAltKeyPressed, showRotationHandle)
|
|
@@ -3304,7 +3316,7 @@ const Oe = $t("CanvasRenderer"), K = class K {
|
|
|
3304
3316
|
// consumed here — single-selection chrome is now drawn by
|
|
3305
3317
|
// `renderInteractionChromeLayer` after piece guides. See that
|
|
3306
3318
|
// method for the actual chrome rendering.
|
|
3307
|
-
hoverState:
|
|
3319
|
+
hoverState: s,
|
|
3308
3320
|
isEditing: i,
|
|
3309
3321
|
stateMachine: a,
|
|
3310
3322
|
snapGuides: r = [],
|
|
@@ -3313,27 +3325,27 @@ const Oe = $t("CanvasRenderer"), K = class K {
|
|
|
3313
3325
|
artboard: c,
|
|
3314
3326
|
isPreview: d = !0,
|
|
3315
3327
|
zoom: f = 1,
|
|
3316
|
-
paddingOffset:
|
|
3317
|
-
showOverflowDimmed:
|
|
3318
|
-
suppressOverflowDim:
|
|
3319
|
-
distressTexture:
|
|
3328
|
+
paddingOffset: b = { x: 0, y: 0 },
|
|
3329
|
+
showOverflowDimmed: u = !1,
|
|
3330
|
+
suppressOverflowDim: p = !1,
|
|
3331
|
+
distressTexture: g,
|
|
3320
3332
|
imageMask: y,
|
|
3321
3333
|
editModeData: S
|
|
3322
3334
|
}) {
|
|
3323
3335
|
if (this.renderElementsLayer(
|
|
3324
3336
|
t,
|
|
3325
3337
|
e,
|
|
3326
|
-
s,
|
|
3327
3338
|
o,
|
|
3339
|
+
s,
|
|
3328
3340
|
a ?? void 0,
|
|
3329
3341
|
h,
|
|
3330
3342
|
c,
|
|
3331
3343
|
d,
|
|
3332
|
-
|
|
3333
|
-
|
|
3334
|
-
),
|
|
3344
|
+
u,
|
|
3345
|
+
p
|
|
3346
|
+
), g != null && g.enabled && c && ke(t, g, c, h), y != null && y.enabled && c && Pe(t, y, c, h), i && S && n && zt.renderEditModeLayer(t, n, S, f), f !== 1) {
|
|
3335
3347
|
t.save();
|
|
3336
|
-
const C = t.getTransform().a / f, R =
|
|
3348
|
+
const C = t.getTransform().a / f, R = b.x * f * C, x = b.y * f * C;
|
|
3337
3349
|
t.setTransform(C, 0, 0, C, R, x);
|
|
3338
3350
|
}
|
|
3339
3351
|
const m = r.map((T) => ({
|
|
@@ -3355,7 +3367,7 @@ const Oe = $t("CanvasRenderer"), K = class K {
|
|
|
3355
3367
|
labelX: T.labelX * f,
|
|
3356
3368
|
labelY: T.labelY * f
|
|
3357
3369
|
}));
|
|
3358
|
-
|
|
3370
|
+
Ct.renderSnapGuidesLayer(t, m), Ct.renderSpacingIndicatorsLayer(t, w), f !== 1 && t.restore();
|
|
3359
3371
|
}
|
|
3360
3372
|
/**
|
|
3361
3373
|
* Single-selection interaction chrome: bbox, handles, position/size
|
|
@@ -3372,9 +3384,9 @@ const Oe = $t("CanvasRenderer"), K = class K {
|
|
|
3372
3384
|
static renderInteractionChromeLayer({
|
|
3373
3385
|
ctx: t,
|
|
3374
3386
|
selectedElement: e,
|
|
3375
|
-
transformHandles:
|
|
3387
|
+
transformHandles: o,
|
|
3376
3388
|
stateMachine: n,
|
|
3377
|
-
currentRotation:
|
|
3389
|
+
currentRotation: s,
|
|
3378
3390
|
isRotating: i,
|
|
3379
3391
|
hoverState: a,
|
|
3380
3392
|
selectedId: r,
|
|
@@ -3383,53 +3395,53 @@ const Oe = $t("CanvasRenderer"), K = class K {
|
|
|
3383
3395
|
isAltKeyPressed: c = !1,
|
|
3384
3396
|
artboardBackgroundColor: d,
|
|
3385
3397
|
hoverClipArtboard: f,
|
|
3386
|
-
showRotationHandle:
|
|
3387
|
-
zoom:
|
|
3388
|
-
paddingOffset:
|
|
3398
|
+
showRotationHandle: b = !0,
|
|
3399
|
+
zoom: u = 1,
|
|
3400
|
+
paddingOffset: p = { x: 0, y: 0 }
|
|
3389
3401
|
}) {
|
|
3390
|
-
if (
|
|
3402
|
+
if (u !== 1) {
|
|
3391
3403
|
t.save();
|
|
3392
|
-
const S = t.getTransform().a /
|
|
3404
|
+
const S = t.getTransform().a / u, m = p.x * u * S, w = p.y * u * S;
|
|
3393
3405
|
t.setTransform(S, 0, 0, S, m, w);
|
|
3394
3406
|
}
|
|
3395
|
-
if (e &&
|
|
3396
|
-
|
|
3397
|
-
else if (!l && n &&
|
|
3407
|
+
if (e && Ee(e) && e.isCropping)
|
|
3408
|
+
o && zt.renderCropBoxLayer(t, e, o, u);
|
|
3409
|
+
else if (!l && n && wt.renderSelectionLayer(t, e, n, u), o && n && wt.renderPositionSizeInfo(t, e, o, n, u), !l && o && n && wt.renderHandlesLayer(
|
|
3398
3410
|
t,
|
|
3399
3411
|
e,
|
|
3400
|
-
s,
|
|
3401
3412
|
o,
|
|
3413
|
+
s,
|
|
3402
3414
|
i,
|
|
3403
3415
|
a,
|
|
3404
3416
|
n,
|
|
3405
|
-
|
|
3406
|
-
|
|
3417
|
+
u,
|
|
3418
|
+
b
|
|
3407
3419
|
), !h) {
|
|
3408
3420
|
if (f) {
|
|
3409
3421
|
t.save();
|
|
3410
|
-
const y = f, S = y.x *
|
|
3422
|
+
const y = f, S = y.x * u, m = y.y * u, w = y.width * u, T = y.height * u, C = (y.borderRadius ?? 0) * u;
|
|
3411
3423
|
t.beginPath(), C > 0 ? t.roundRect(S, m, w, T, C) : t.rect(S, m, w, T), t.clip();
|
|
3412
3424
|
}
|
|
3413
|
-
|
|
3425
|
+
Vt.renderHoverLayer(t, a, r, c, u, d), f && t.restore();
|
|
3414
3426
|
}
|
|
3415
|
-
|
|
3427
|
+
u !== 1 && t.restore();
|
|
3416
3428
|
}
|
|
3417
3429
|
};
|
|
3418
3430
|
K._contentCanvas = null, K._contentCanvasSize = { width: 0, height: 0 }, K._maskCanvas = null, K._maskCanvasSize = { width: 0, height: 0 }, K._cachedElementsRef = null, K._cachedElementConfigs = null, K._cachedElementMap = null, K._knockoutRenderedIds = /* @__PURE__ */ new Set(), K.onRenderError = null;
|
|
3419
|
-
let
|
|
3431
|
+
let Ut = K;
|
|
3420
3432
|
export {
|
|
3421
|
-
|
|
3422
|
-
|
|
3423
|
-
|
|
3424
|
-
|
|
3425
|
-
|
|
3426
|
-
|
|
3427
|
-
|
|
3428
|
-
|
|
3429
|
-
|
|
3430
|
-
|
|
3431
|
-
|
|
3432
|
-
|
|
3433
|
-
|
|
3433
|
+
en as A,
|
|
3434
|
+
Ut as C,
|
|
3435
|
+
tn as I,
|
|
3436
|
+
Ge as R,
|
|
3437
|
+
nn as S,
|
|
3438
|
+
Je as T,
|
|
3439
|
+
ne as a,
|
|
3440
|
+
Ue as b,
|
|
3441
|
+
qe as c,
|
|
3442
|
+
Ve as d,
|
|
3443
|
+
Qe as e,
|
|
3444
|
+
$t as g,
|
|
3445
|
+
Ze as r
|
|
3434
3446
|
};
|
|
3435
|
-
//# sourceMappingURL=CanvasRenderer-
|
|
3447
|
+
//# sourceMappingURL=CanvasRenderer-_lFoIoz5.js.map
|