dingbatch 0.1.0 → 0.2.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/boomerang-s5naDBuf.d.ts +39 -0
- package/dist/chunk-5A7FSZ3T.js +1626 -0
- package/dist/chunk-5A7FSZ3T.js.map +1 -0
- package/dist/index.d.ts +229 -29
- package/dist/index.js +65 -3
- package/dist/react/index.d.ts +1 -1
- package/dist/react/index.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-IAFZ3FNR.js +0 -531
- package/dist/chunk-IAFZ3FNR.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,7 +1,69 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
arrow,
|
|
3
|
+
atomic,
|
|
4
|
+
bird,
|
|
5
|
+
blob,
|
|
6
|
+
boomerang,
|
|
7
|
+
bowtie,
|
|
8
|
+
cat,
|
|
9
|
+
chevron,
|
|
10
|
+
circle,
|
|
11
|
+
cross,
|
|
12
|
+
cursor,
|
|
13
|
+
diamond,
|
|
14
|
+
dog,
|
|
15
|
+
fish,
|
|
16
|
+
flower,
|
|
17
|
+
hexagon,
|
|
18
|
+
kidney,
|
|
19
|
+
leaf,
|
|
20
|
+
moon,
|
|
21
|
+
octagon,
|
|
22
|
+
oval,
|
|
23
|
+
pentagon,
|
|
24
|
+
polygon,
|
|
25
|
+
rectangle,
|
|
26
|
+
rocket,
|
|
27
|
+
semicircle,
|
|
28
|
+
spiral,
|
|
29
|
+
star,
|
|
30
|
+
starburst,
|
|
31
|
+
sun,
|
|
32
|
+
swallowtail,
|
|
33
|
+
triangle
|
|
34
|
+
} from "./chunk-5A7FSZ3T.js";
|
|
4
35
|
export {
|
|
5
|
-
|
|
36
|
+
arrow,
|
|
37
|
+
atomic,
|
|
38
|
+
bird,
|
|
39
|
+
blob,
|
|
40
|
+
boomerang,
|
|
41
|
+
bowtie,
|
|
42
|
+
cat,
|
|
43
|
+
chevron,
|
|
44
|
+
circle,
|
|
45
|
+
cross,
|
|
46
|
+
cursor,
|
|
47
|
+
diamond,
|
|
48
|
+
dog,
|
|
49
|
+
fish,
|
|
50
|
+
flower,
|
|
51
|
+
hexagon,
|
|
52
|
+
kidney,
|
|
53
|
+
leaf,
|
|
54
|
+
moon,
|
|
55
|
+
octagon,
|
|
56
|
+
oval,
|
|
57
|
+
pentagon,
|
|
58
|
+
polygon,
|
|
59
|
+
rectangle,
|
|
60
|
+
rocket,
|
|
61
|
+
semicircle,
|
|
62
|
+
spiral,
|
|
63
|
+
star,
|
|
64
|
+
starburst,
|
|
65
|
+
sun,
|
|
66
|
+
swallowtail,
|
|
67
|
+
triangle
|
|
6
68
|
};
|
|
7
69
|
//# sourceMappingURL=index.js.map
|
package/dist/react/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
2
|
import { CSSProperties } from 'react';
|
|
3
|
-
import { DingbatResult, BoomerangParams } from '../
|
|
3
|
+
import { D as DingbatResult, B as BoomerangParams } from '../boomerang-s5naDBuf.js';
|
|
4
4
|
|
|
5
5
|
interface DingbatProps {
|
|
6
6
|
/** Shape result from a dingbatch generator */
|
package/dist/react/index.js
CHANGED
package/package.json
CHANGED
package/dist/chunk-IAFZ3FNR.js
DELETED
|
@@ -1,531 +0,0 @@
|
|
|
1
|
-
// src/generators/utils/svg.ts
|
|
2
|
-
function wrapPath(path, width, height) {
|
|
3
|
-
return `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${width} ${height}" width="${width}" height="${height}"><path d="${path}" fill="currentColor"/></svg>`;
|
|
4
|
-
}
|
|
5
|
-
function addSvgFields(result) {
|
|
6
|
-
const viewBox = `0 0 ${result.width} ${result.height}`;
|
|
7
|
-
const svg = wrapPath(result.path, result.width, result.height);
|
|
8
|
-
return { ...result, viewBox, svg };
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
// src/presets/boomerang.ts
|
|
12
|
-
var crescent = {
|
|
13
|
-
style: "crescent",
|
|
14
|
-
armLength: 50,
|
|
15
|
-
bendAngle: 160,
|
|
16
|
-
thickness: 35,
|
|
17
|
-
taper: 0.5,
|
|
18
|
-
tipRoundness: 0.2,
|
|
19
|
-
armCurvature: 0,
|
|
20
|
-
bendSharpness: 0
|
|
21
|
-
};
|
|
22
|
-
var fatMoon = {
|
|
23
|
-
style: "crescent",
|
|
24
|
-
armLength: 45,
|
|
25
|
-
bendAngle: 180,
|
|
26
|
-
thickness: 50,
|
|
27
|
-
taper: 0.3,
|
|
28
|
-
tipRoundness: 0.6,
|
|
29
|
-
armCurvature: 0,
|
|
30
|
-
bendSharpness: 0
|
|
31
|
-
};
|
|
32
|
-
var sharpChevron = {
|
|
33
|
-
style: "chevron",
|
|
34
|
-
armLength: 55,
|
|
35
|
-
bendAngle: 60,
|
|
36
|
-
thickness: 40,
|
|
37
|
-
taper: 1,
|
|
38
|
-
tipRoundness: 0,
|
|
39
|
-
armCurvature: 0,
|
|
40
|
-
bendSharpness: 0
|
|
41
|
-
};
|
|
42
|
-
var thinArc = {
|
|
43
|
-
style: "crescent",
|
|
44
|
-
armLength: 60,
|
|
45
|
-
bendAngle: 140,
|
|
46
|
-
thickness: 20,
|
|
47
|
-
taper: 0.7,
|
|
48
|
-
tipRoundness: 0.1,
|
|
49
|
-
armCurvature: 0,
|
|
50
|
-
bendSharpness: 0
|
|
51
|
-
};
|
|
52
|
-
var horseshoe = {
|
|
53
|
-
style: "horseshoe",
|
|
54
|
-
armLength: 80,
|
|
55
|
-
bendAngle: 50,
|
|
56
|
-
thickness: 18,
|
|
57
|
-
taper: 0.2,
|
|
58
|
-
tipRoundness: 0.3,
|
|
59
|
-
armCurvature: 0.4,
|
|
60
|
-
bendSharpness: 0
|
|
61
|
-
};
|
|
62
|
-
|
|
63
|
-
// src/generators/curved/boomerang.ts
|
|
64
|
-
function boomerangBase(params) {
|
|
65
|
-
const style = params.style || "classic";
|
|
66
|
-
switch (style) {
|
|
67
|
-
case "crescent":
|
|
68
|
-
return generateCrescent(params);
|
|
69
|
-
case "horseshoe":
|
|
70
|
-
return generateHorseshoe(params);
|
|
71
|
-
case "chevron":
|
|
72
|
-
return generateChevron(params);
|
|
73
|
-
case "classic":
|
|
74
|
-
default:
|
|
75
|
-
return generateClassic(params);
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
var boomerang = Object.assign(boomerangBase, {
|
|
79
|
-
crescent: (overrides) => boomerangBase({ ...crescent, ...overrides }),
|
|
80
|
-
fatMoon: (overrides) => boomerangBase({ ...fatMoon, ...overrides }),
|
|
81
|
-
sharpChevron: (overrides) => boomerangBase({ ...sharpChevron, ...overrides }),
|
|
82
|
-
thinArc: (overrides) => boomerangBase({ ...thinArc, ...overrides }),
|
|
83
|
-
horseshoe: (overrides) => boomerangBase({ ...horseshoe, ...overrides })
|
|
84
|
-
});
|
|
85
|
-
function generateClassic(params) {
|
|
86
|
-
const {
|
|
87
|
-
armLength,
|
|
88
|
-
bendAngle,
|
|
89
|
-
armCurvature,
|
|
90
|
-
bendSharpness,
|
|
91
|
-
thickness,
|
|
92
|
-
taper,
|
|
93
|
-
tipRoundness,
|
|
94
|
-
armBalance = 1,
|
|
95
|
-
thicknessBalance = 0,
|
|
96
|
-
rotation = 0
|
|
97
|
-
} = params;
|
|
98
|
-
const clampedBendAngle = Math.max(30, Math.min(180, bendAngle));
|
|
99
|
-
const clampedArmCurvature = Math.max(0, Math.min(1, armCurvature));
|
|
100
|
-
const clampedBendSharpness = Math.max(0, Math.min(1, bendSharpness));
|
|
101
|
-
const clampedTaper = Math.max(0, Math.min(1, taper));
|
|
102
|
-
const clampedTipRoundness = Math.max(0, Math.min(1, tipRoundness));
|
|
103
|
-
const clampedArmBalance = Math.max(0.5, Math.min(2, armBalance));
|
|
104
|
-
const clampedThicknessBalance = Math.max(-1, Math.min(1, thicknessBalance));
|
|
105
|
-
const arm1Length = armLength * (2 / (1 + clampedArmBalance));
|
|
106
|
-
const arm2Length = armLength * (2 * clampedArmBalance / (1 + clampedArmBalance));
|
|
107
|
-
const halfAngle = clampedBendAngle / 2 * Math.PI / 180;
|
|
108
|
-
const arm1Dir = { x: -Math.sin(halfAngle), y: -Math.cos(halfAngle) };
|
|
109
|
-
const arm2Dir = { x: Math.sin(halfAngle), y: -Math.cos(halfAngle) };
|
|
110
|
-
const tip1 = { x: arm1Dir.x * arm1Length, y: arm1Dir.y * arm1Length };
|
|
111
|
-
const tip2 = { x: arm2Dir.x * arm2Length, y: arm2Dir.y * arm2Length };
|
|
112
|
-
const bendPoint = { x: 0, y: 0 };
|
|
113
|
-
const numSamples = 20;
|
|
114
|
-
const arm1Spine = generateArmSpine(tip1, bendPoint, arm1Dir, arm1Length, clampedArmCurvature, numSamples);
|
|
115
|
-
const arm2Spine = generateArmSpine(bendPoint, tip2, arm2Dir, arm2Length, clampedArmCurvature, numSamples);
|
|
116
|
-
const minThickness = thickness * clampedTaper;
|
|
117
|
-
function getThicknessAlongArm(t, isArm1) {
|
|
118
|
-
const tipFade = Math.sin(t * Math.PI / 2);
|
|
119
|
-
const baseThickness = minThickness + (thickness - minThickness) * tipFade;
|
|
120
|
-
const balanceFactor = isArm1 ? 1 - clampedThicknessBalance * 0.3 : 1 + clampedThicknessBalance * 0.3;
|
|
121
|
-
return baseThickness * balanceFactor;
|
|
122
|
-
}
|
|
123
|
-
const arm1Outer = [];
|
|
124
|
-
const arm1Inner = [];
|
|
125
|
-
const arm2Outer = [];
|
|
126
|
-
const arm2Inner = [];
|
|
127
|
-
for (let i = 0; i < arm1Spine.length; i++) {
|
|
128
|
-
const t = i / (arm1Spine.length - 1);
|
|
129
|
-
const point = arm1Spine[i];
|
|
130
|
-
const tangent = getSpineTangent(arm1Spine, i);
|
|
131
|
-
const normal = { x: -tangent.y, y: tangent.x };
|
|
132
|
-
const halfThick = getThicknessAlongArm(t, true) / 2;
|
|
133
|
-
arm1Outer.push({ x: point.x + normal.x * halfThick, y: point.y + normal.y * halfThick });
|
|
134
|
-
arm1Inner.push({ x: point.x - normal.x * halfThick, y: point.y - normal.y * halfThick });
|
|
135
|
-
}
|
|
136
|
-
for (let i = 0; i < arm2Spine.length; i++) {
|
|
137
|
-
const t = 1 - i / (arm2Spine.length - 1);
|
|
138
|
-
const point = arm2Spine[i];
|
|
139
|
-
const tangent = getSpineTangent(arm2Spine, i);
|
|
140
|
-
const normal = { x: -tangent.y, y: tangent.x };
|
|
141
|
-
const halfThick = getThicknessAlongArm(t, false) / 2;
|
|
142
|
-
arm2Outer.push({ x: point.x + normal.x * halfThick, y: point.y + normal.y * halfThick });
|
|
143
|
-
arm2Inner.push({ x: point.x - normal.x * halfThick, y: point.y - normal.y * halfThick });
|
|
144
|
-
}
|
|
145
|
-
const pathParts = [];
|
|
146
|
-
pathParts.push(`M ${arm1Outer[0].x.toFixed(2)},${arm1Outer[0].y.toFixed(2)}`);
|
|
147
|
-
const tip1Curve = clampedTipRoundness * thickness * 0.3;
|
|
148
|
-
pathParts.push(`Q ${(tip1.x + arm1Dir.x * tip1Curve).toFixed(2)},${(tip1.y + arm1Dir.y * tip1Curve).toFixed(2)} ${arm1Inner[0].x.toFixed(2)},${arm1Inner[0].y.toFixed(2)}`);
|
|
149
|
-
pathParts.push(smoothCurveThroughPoints(arm1Inner));
|
|
150
|
-
const bendInner2 = arm2Inner[0];
|
|
151
|
-
if (clampedBendSharpness < 0.3) {
|
|
152
|
-
pathParts.push(`L ${bendInner2.x.toFixed(2)},${bendInner2.y.toFixed(2)}`);
|
|
153
|
-
} else {
|
|
154
|
-
const bendInnerOffset = thickness * 0.2 * clampedBendSharpness;
|
|
155
|
-
const bendInnerCtrl = { x: 0, y: bendInnerOffset };
|
|
156
|
-
pathParts.push(`Q ${bendInnerCtrl.x.toFixed(2)},${bendInnerCtrl.y.toFixed(2)} ${bendInner2.x.toFixed(2)},${bendInner2.y.toFixed(2)}`);
|
|
157
|
-
}
|
|
158
|
-
pathParts.push(smoothCurveThroughPoints(arm2Inner));
|
|
159
|
-
const tip2Curve = clampedTipRoundness * thickness * 0.3;
|
|
160
|
-
pathParts.push(`Q ${(tip2.x + arm2Dir.x * tip2Curve).toFixed(2)},${(tip2.y + arm2Dir.y * tip2Curve).toFixed(2)} ${arm2Outer[arm2Outer.length - 1].x.toFixed(2)},${arm2Outer[arm2Outer.length - 1].y.toFixed(2)}`);
|
|
161
|
-
const arm2OuterReversed = [...arm2Outer].reverse();
|
|
162
|
-
pathParts.push(smoothCurveThroughPoints(arm2OuterReversed));
|
|
163
|
-
const bendOuter1 = arm1Outer[arm1Outer.length - 1];
|
|
164
|
-
if (clampedBendSharpness < 0.3) {
|
|
165
|
-
pathParts.push(`L ${bendOuter1.x.toFixed(2)},${bendOuter1.y.toFixed(2)}`);
|
|
166
|
-
} else {
|
|
167
|
-
const bendOuterOffset = -thickness * 0.4 * clampedBendSharpness;
|
|
168
|
-
const bendOuterCtrl = { x: 0, y: bendOuterOffset };
|
|
169
|
-
pathParts.push(`Q ${bendOuterCtrl.x.toFixed(2)},${bendOuterCtrl.y.toFixed(2)} ${bendOuter1.x.toFixed(2)},${bendOuter1.y.toFixed(2)}`);
|
|
170
|
-
}
|
|
171
|
-
const arm1OuterReversed = [...arm1Outer].reverse();
|
|
172
|
-
pathParts.push(smoothCurveThroughPoints(arm1OuterReversed));
|
|
173
|
-
pathParts.push("Z");
|
|
174
|
-
let path = pathParts.join(" ");
|
|
175
|
-
const allPoints = [...arm1Outer, ...arm1Inner, ...arm2Outer, ...arm2Inner];
|
|
176
|
-
let minX = Math.min(...allPoints.map((p) => p.x));
|
|
177
|
-
let maxX = Math.max(...allPoints.map((p) => p.x));
|
|
178
|
-
let minY = Math.min(...allPoints.map((p) => p.y));
|
|
179
|
-
let maxY = Math.max(...allPoints.map((p) => p.y));
|
|
180
|
-
const padding = thickness * 0.3 * clampedTipRoundness;
|
|
181
|
-
minX -= padding;
|
|
182
|
-
maxX += padding;
|
|
183
|
-
minY -= padding;
|
|
184
|
-
const width = maxX - minX;
|
|
185
|
-
const height = maxY - minY;
|
|
186
|
-
path = normalizePath(path, minX, minY);
|
|
187
|
-
if (rotation !== 0) {
|
|
188
|
-
path = rotatePath(path, rotation, width, height);
|
|
189
|
-
}
|
|
190
|
-
return addSvgFields({ path, width, height, centerX: width / 2, centerY: height / 2 });
|
|
191
|
-
}
|
|
192
|
-
function generateCrescent(params) {
|
|
193
|
-
const {
|
|
194
|
-
armLength,
|
|
195
|
-
// Used as arc radius
|
|
196
|
-
bendAngle,
|
|
197
|
-
// Used as arc span (degrees, 30-300)
|
|
198
|
-
thickness,
|
|
199
|
-
taper,
|
|
200
|
-
tipRoundness,
|
|
201
|
-
armBalance = 1,
|
|
202
|
-
// Asymmetric arc thickness along length
|
|
203
|
-
rotation = 0
|
|
204
|
-
} = params;
|
|
205
|
-
const radius = Math.max(20, armLength);
|
|
206
|
-
const arcSpan = Math.max(30, Math.min(300, bendAngle)) * Math.PI / 180;
|
|
207
|
-
const clampedTaper = Math.max(0, Math.min(1, taper));
|
|
208
|
-
const clampedTipRoundness = Math.max(0, Math.min(1, tipRoundness));
|
|
209
|
-
const clampedArmBalance = Math.max(0.5, Math.min(2, armBalance));
|
|
210
|
-
const numSamples = 30;
|
|
211
|
-
const startAngle = -arcSpan / 2;
|
|
212
|
-
const endAngle = arcSpan / 2;
|
|
213
|
-
const spine = [];
|
|
214
|
-
for (let i = 0; i <= numSamples; i++) {
|
|
215
|
-
const t = i / numSamples;
|
|
216
|
-
const angle = startAngle + (endAngle - startAngle) * t;
|
|
217
|
-
spine.push({
|
|
218
|
-
x: Math.sin(angle) * radius,
|
|
219
|
-
y: -Math.cos(angle) * radius + radius
|
|
220
|
-
// Shift so bottom of arc is at y=0
|
|
221
|
-
});
|
|
222
|
-
}
|
|
223
|
-
const minThickness = thickness * clampedTaper;
|
|
224
|
-
function getThicknessAtT(t) {
|
|
225
|
-
const balanceShift = (t - 0.5) * (clampedArmBalance - 1) * 0.5;
|
|
226
|
-
const adjustedT = Math.max(0, Math.min(1, t + balanceShift));
|
|
227
|
-
const adjustedDist = Math.min(adjustedT, 1 - adjustedT) * 2;
|
|
228
|
-
const adjustedFactor = Math.sin(adjustedDist * Math.PI / 2);
|
|
229
|
-
return minThickness + (thickness - minThickness) * adjustedFactor;
|
|
230
|
-
}
|
|
231
|
-
const outer = [];
|
|
232
|
-
const inner = [];
|
|
233
|
-
for (let i = 0; i < spine.length; i++) {
|
|
234
|
-
const t = i / (spine.length - 1);
|
|
235
|
-
const point = spine[i];
|
|
236
|
-
const tangent = getSpineTangent(spine, i);
|
|
237
|
-
const normal = { x: -tangent.y, y: tangent.x };
|
|
238
|
-
const halfThick = getThicknessAtT(t) / 2;
|
|
239
|
-
outer.push({ x: point.x + normal.x * halfThick, y: point.y + normal.y * halfThick });
|
|
240
|
-
inner.push({ x: point.x - normal.x * halfThick, y: point.y - normal.y * halfThick });
|
|
241
|
-
}
|
|
242
|
-
const pathParts = [];
|
|
243
|
-
pathParts.push(`M ${outer[0].x.toFixed(2)},${outer[0].y.toFixed(2)}`);
|
|
244
|
-
const startTipCurve = clampedTipRoundness * thickness * 0.4;
|
|
245
|
-
const startTangent = getSpineTangent(spine, 0);
|
|
246
|
-
pathParts.push(`Q ${(spine[0].x - startTangent.x * startTipCurve).toFixed(2)},${(spine[0].y - startTangent.y * startTipCurve).toFixed(2)} ${inner[0].x.toFixed(2)},${inner[0].y.toFixed(2)}`);
|
|
247
|
-
pathParts.push(smoothCurveThroughPoints(inner));
|
|
248
|
-
const endTipCurve = clampedTipRoundness * thickness * 0.4;
|
|
249
|
-
const endTangent = getSpineTangent(spine, spine.length - 1);
|
|
250
|
-
pathParts.push(`Q ${(spine[spine.length - 1].x + endTangent.x * endTipCurve).toFixed(2)},${(spine[spine.length - 1].y + endTangent.y * endTipCurve).toFixed(2)} ${outer[outer.length - 1].x.toFixed(2)},${outer[outer.length - 1].y.toFixed(2)}`);
|
|
251
|
-
const outerReversed = [...outer].reverse();
|
|
252
|
-
pathParts.push(smoothCurveThroughPoints(outerReversed));
|
|
253
|
-
pathParts.push("Z");
|
|
254
|
-
let path = pathParts.join(" ");
|
|
255
|
-
const allPoints = [...outer, ...inner];
|
|
256
|
-
let minX = Math.min(...allPoints.map((p) => p.x));
|
|
257
|
-
let maxX = Math.max(...allPoints.map((p) => p.x));
|
|
258
|
-
let minY = Math.min(...allPoints.map((p) => p.y));
|
|
259
|
-
let maxY = Math.max(...allPoints.map((p) => p.y));
|
|
260
|
-
const padding = thickness * 0.3 * clampedTipRoundness;
|
|
261
|
-
minX -= padding;
|
|
262
|
-
maxX += padding;
|
|
263
|
-
minY -= padding;
|
|
264
|
-
maxY += padding;
|
|
265
|
-
const width = maxX - minX;
|
|
266
|
-
const height = maxY - minY;
|
|
267
|
-
path = normalizePath(path, minX, minY);
|
|
268
|
-
if (rotation !== 0) {
|
|
269
|
-
path = rotatePath(path, rotation, width, height);
|
|
270
|
-
}
|
|
271
|
-
return addSvgFields({ path, width, height, centerX: width / 2, centerY: height / 2 });
|
|
272
|
-
}
|
|
273
|
-
function generateHorseshoe(params) {
|
|
274
|
-
const {
|
|
275
|
-
armLength,
|
|
276
|
-
// Length of the vertical arms
|
|
277
|
-
bendAngle,
|
|
278
|
-
// Spacing between arms (width at top)
|
|
279
|
-
armCurvature,
|
|
280
|
-
// How curved the bottom connection is
|
|
281
|
-
thickness,
|
|
282
|
-
taper,
|
|
283
|
-
tipRoundness,
|
|
284
|
-
armBalance = 1,
|
|
285
|
-
// Asymmetric arm lengths
|
|
286
|
-
rotation = 0
|
|
287
|
-
} = params;
|
|
288
|
-
const spacing = Math.max(20, bendAngle);
|
|
289
|
-
const clampedArmCurvature = Math.max(0, Math.min(1, armCurvature));
|
|
290
|
-
const clampedTaper = Math.max(0, Math.min(1, taper));
|
|
291
|
-
const clampedTipRoundness = Math.max(0, Math.min(1, tipRoundness));
|
|
292
|
-
const clampedArmBalance = Math.max(0.5, Math.min(2, armBalance));
|
|
293
|
-
const arm1Len = armLength * (2 / (1 + clampedArmBalance));
|
|
294
|
-
const arm2Len = armLength * (2 * clampedArmBalance / (1 + clampedArmBalance));
|
|
295
|
-
const halfSpacing = spacing / 2;
|
|
296
|
-
const halfThick = thickness / 2;
|
|
297
|
-
const tipThick = thickness * clampedTaper / 2;
|
|
298
|
-
const leftOuterX = -halfSpacing - halfThick;
|
|
299
|
-
const leftInnerX = -halfSpacing + halfThick;
|
|
300
|
-
const rightInnerX = halfSpacing - halfThick;
|
|
301
|
-
const rightOuterX = halfSpacing + halfThick;
|
|
302
|
-
const leftTopY = 0;
|
|
303
|
-
const leftBottomY = arm1Len;
|
|
304
|
-
const rightBottomY = arm2Len;
|
|
305
|
-
const rightTopY = 0;
|
|
306
|
-
const bottomY = Math.max(arm1Len, arm2Len);
|
|
307
|
-
const curveDepth = halfSpacing * clampedArmCurvature;
|
|
308
|
-
const pathParts = [];
|
|
309
|
-
const leftTipOuterX = -halfSpacing - tipThick;
|
|
310
|
-
const leftTipInnerX = -halfSpacing + tipThick;
|
|
311
|
-
const rightTipInnerX = halfSpacing - tipThick;
|
|
312
|
-
const rightTipOuterX = halfSpacing + tipThick;
|
|
313
|
-
pathParts.push(`M ${leftTipOuterX.toFixed(2)},${leftTopY.toFixed(2)}`);
|
|
314
|
-
if (clampedTipRoundness > 0) {
|
|
315
|
-
const tipCurve = clampedTipRoundness * thickness * 0.3;
|
|
316
|
-
pathParts.push(`Q ${(-halfSpacing).toFixed(2)},${(leftTopY - tipCurve).toFixed(2)} ${leftTipInnerX.toFixed(2)},${leftTopY.toFixed(2)}`);
|
|
317
|
-
} else {
|
|
318
|
-
pathParts.push(`L ${leftTipInnerX.toFixed(2)},${leftTopY.toFixed(2)}`);
|
|
319
|
-
}
|
|
320
|
-
pathParts.push(`L ${leftInnerX.toFixed(2)},${leftBottomY.toFixed(2)}`);
|
|
321
|
-
if (clampedArmCurvature > 0.1) {
|
|
322
|
-
const innerCtrlY = bottomY + curveDepth;
|
|
323
|
-
pathParts.push(`Q ${0},${innerCtrlY.toFixed(2)} ${rightInnerX.toFixed(2)},${rightBottomY.toFixed(2)}`);
|
|
324
|
-
} else {
|
|
325
|
-
pathParts.push(`L ${rightInnerX.toFixed(2)},${rightBottomY.toFixed(2)}`);
|
|
326
|
-
}
|
|
327
|
-
pathParts.push(`L ${rightTipInnerX.toFixed(2)},${rightTopY.toFixed(2)}`);
|
|
328
|
-
if (clampedTipRoundness > 0) {
|
|
329
|
-
const tipCurve = clampedTipRoundness * thickness * 0.3;
|
|
330
|
-
pathParts.push(`Q ${halfSpacing.toFixed(2)},${(rightTopY - tipCurve).toFixed(2)} ${rightTipOuterX.toFixed(2)},${rightTopY.toFixed(2)}`);
|
|
331
|
-
} else {
|
|
332
|
-
pathParts.push(`L ${rightTipOuterX.toFixed(2)},${rightTopY.toFixed(2)}`);
|
|
333
|
-
}
|
|
334
|
-
pathParts.push(`L ${rightOuterX.toFixed(2)},${rightBottomY.toFixed(2)}`);
|
|
335
|
-
if (clampedArmCurvature > 0.1) {
|
|
336
|
-
const outerCtrlY = bottomY + curveDepth + thickness;
|
|
337
|
-
pathParts.push(`Q ${0},${outerCtrlY.toFixed(2)} ${leftOuterX.toFixed(2)},${leftBottomY.toFixed(2)}`);
|
|
338
|
-
} else {
|
|
339
|
-
pathParts.push(`L ${leftOuterX.toFixed(2)},${leftBottomY.toFixed(2)}`);
|
|
340
|
-
}
|
|
341
|
-
pathParts.push(`L ${leftTipOuterX.toFixed(2)},${leftTopY.toFixed(2)}`);
|
|
342
|
-
pathParts.push("Z");
|
|
343
|
-
let path = pathParts.join(" ");
|
|
344
|
-
const padding = thickness * 0.3;
|
|
345
|
-
let minX = leftOuterX - padding;
|
|
346
|
-
let maxX = rightOuterX + padding;
|
|
347
|
-
let minY = -padding - clampedTipRoundness * thickness * 0.3;
|
|
348
|
-
let maxY = bottomY + curveDepth + thickness + padding;
|
|
349
|
-
const width = maxX - minX;
|
|
350
|
-
const height = maxY - minY;
|
|
351
|
-
path = normalizePath(path, minX, minY);
|
|
352
|
-
if (rotation !== 0) {
|
|
353
|
-
path = rotatePath(path, rotation, width, height);
|
|
354
|
-
}
|
|
355
|
-
return addSvgFields({ path, width, height, centerX: width / 2, centerY: height / 2 });
|
|
356
|
-
}
|
|
357
|
-
function generateChevron(params) {
|
|
358
|
-
const {
|
|
359
|
-
armLength,
|
|
360
|
-
// Length of the arms
|
|
361
|
-
bendAngle,
|
|
362
|
-
// Angle of the V (smaller = sharper point)
|
|
363
|
-
thickness,
|
|
364
|
-
// Controls arm width (proportional)
|
|
365
|
-
taper = 0,
|
|
366
|
-
// 0 = V with cutout, 1 = solid triangle (no cutout)
|
|
367
|
-
tipRoundness = 0,
|
|
368
|
-
// Roundness at the tip
|
|
369
|
-
armBalance = 1,
|
|
370
|
-
// Asymmetric arm lengths
|
|
371
|
-
rotation = 0
|
|
372
|
-
} = params;
|
|
373
|
-
const clampedBendAngle = Math.max(20, Math.min(160, bendAngle));
|
|
374
|
-
const clampedTaper = Math.max(0, Math.min(1, taper));
|
|
375
|
-
const clampedTipRoundness = Math.max(0, Math.min(1, tipRoundness));
|
|
376
|
-
const clampedArmBalance = Math.max(0.5, Math.min(2, armBalance));
|
|
377
|
-
const armWidth = Math.max(armLength * 0.15, thickness * 0.5);
|
|
378
|
-
const cutoutDepth = armLength * 0.6 * (1 - clampedTaper);
|
|
379
|
-
const arm1Len = armLength * (2 / (1 + clampedArmBalance));
|
|
380
|
-
const arm2Len = armLength * (2 * clampedArmBalance / (1 + clampedArmBalance));
|
|
381
|
-
const halfAngle = clampedBendAngle / 2 * Math.PI / 180;
|
|
382
|
-
const tip = { x: 0, y: 0 };
|
|
383
|
-
const arm1End = { x: -Math.sin(halfAngle) * arm1Len, y: -Math.cos(halfAngle) * arm1Len };
|
|
384
|
-
const arm2End = { x: Math.sin(halfAngle) * arm2Len, y: -Math.cos(halfAngle) * arm2Len };
|
|
385
|
-
const arm1Perp = { x: -Math.cos(halfAngle), y: Math.sin(halfAngle) };
|
|
386
|
-
const arm2Perp = { x: Math.cos(halfAngle), y: Math.sin(halfAngle) };
|
|
387
|
-
const arm1OuterCorner = {
|
|
388
|
-
x: arm1End.x + arm1Perp.x * armWidth / 2,
|
|
389
|
-
y: arm1End.y + arm1Perp.y * armWidth / 2
|
|
390
|
-
};
|
|
391
|
-
const arm1InnerCorner = {
|
|
392
|
-
x: arm1End.x - arm1Perp.x * armWidth / 2,
|
|
393
|
-
y: arm1End.y - arm1Perp.y * armWidth / 2
|
|
394
|
-
};
|
|
395
|
-
const arm2OuterCorner = {
|
|
396
|
-
x: arm2End.x + arm2Perp.x * armWidth / 2,
|
|
397
|
-
y: arm2End.y + arm2Perp.y * armWidth / 2
|
|
398
|
-
};
|
|
399
|
-
const arm2InnerCorner = {
|
|
400
|
-
x: arm2End.x - arm2Perp.x * armWidth / 2,
|
|
401
|
-
y: arm2End.y - arm2Perp.y * armWidth / 2
|
|
402
|
-
};
|
|
403
|
-
const innerTip = {
|
|
404
|
-
x: 0,
|
|
405
|
-
y: -cutoutDepth
|
|
406
|
-
};
|
|
407
|
-
const pathParts = [];
|
|
408
|
-
if (clampedTipRoundness > 0) {
|
|
409
|
-
const roundAmount = clampedTipRoundness * armWidth * 0.3;
|
|
410
|
-
const tipStart = {
|
|
411
|
-
x: tip.x + arm1Perp.x * roundAmount,
|
|
412
|
-
y: tip.y + arm1Perp.y * roundAmount - roundAmount * 0.5
|
|
413
|
-
};
|
|
414
|
-
pathParts.push(`M ${tipStart.x.toFixed(2)},${tipStart.y.toFixed(2)}`);
|
|
415
|
-
const tipEnd = {
|
|
416
|
-
x: tip.x + arm2Perp.x * roundAmount,
|
|
417
|
-
y: tip.y + arm2Perp.y * roundAmount - roundAmount * 0.5
|
|
418
|
-
};
|
|
419
|
-
pathParts.push(`Q ${tip.x.toFixed(2)},${tip.y.toFixed(2)} ${tipEnd.x.toFixed(2)},${tipEnd.y.toFixed(2)}`);
|
|
420
|
-
} else {
|
|
421
|
-
pathParts.push(`M ${tip.x.toFixed(2)},${tip.y.toFixed(2)}`);
|
|
422
|
-
}
|
|
423
|
-
pathParts.push(`L ${arm2OuterCorner.x.toFixed(2)},${arm2OuterCorner.y.toFixed(2)}`);
|
|
424
|
-
pathParts.push(`L ${arm2InnerCorner.x.toFixed(2)},${arm2InnerCorner.y.toFixed(2)}`);
|
|
425
|
-
if (cutoutDepth > 5 && clampedTaper < 0.9) {
|
|
426
|
-
pathParts.push(`L ${innerTip.x.toFixed(2)},${innerTip.y.toFixed(2)}`);
|
|
427
|
-
}
|
|
428
|
-
pathParts.push(`L ${arm1InnerCorner.x.toFixed(2)},${arm1InnerCorner.y.toFixed(2)}`);
|
|
429
|
-
pathParts.push(`L ${arm1OuterCorner.x.toFixed(2)},${arm1OuterCorner.y.toFixed(2)}`);
|
|
430
|
-
pathParts.push("Z");
|
|
431
|
-
let path = pathParts.join(" ");
|
|
432
|
-
const allPoints = [tip, arm1End, arm2End, arm1OuterCorner, arm1InnerCorner, arm2OuterCorner, arm2InnerCorner];
|
|
433
|
-
if (cutoutDepth > 5 && clampedTaper < 0.9) {
|
|
434
|
-
allPoints.push(innerTip);
|
|
435
|
-
}
|
|
436
|
-
let minX = Math.min(...allPoints.map((p) => p.x));
|
|
437
|
-
let maxX = Math.max(...allPoints.map((p) => p.x));
|
|
438
|
-
let minY = Math.min(...allPoints.map((p) => p.y));
|
|
439
|
-
let maxY = Math.max(...allPoints.map((p) => p.y));
|
|
440
|
-
const padding = armWidth * 0.2;
|
|
441
|
-
minX -= padding;
|
|
442
|
-
maxX += padding;
|
|
443
|
-
minY -= padding;
|
|
444
|
-
maxY += padding;
|
|
445
|
-
const width = maxX - minX;
|
|
446
|
-
const height = maxY - minY;
|
|
447
|
-
path = normalizePath(path, minX, minY);
|
|
448
|
-
if (rotation !== 0) {
|
|
449
|
-
path = rotatePath(path, rotation, width, height);
|
|
450
|
-
}
|
|
451
|
-
return addSvgFields({ path, width, height, centerX: width / 2, centerY: height / 2 });
|
|
452
|
-
}
|
|
453
|
-
function generateArmSpine(start, end, direction, length, curvature, numSamples) {
|
|
454
|
-
const points = [];
|
|
455
|
-
const perpDir = { x: direction.y, y: -direction.x };
|
|
456
|
-
const bowAmount = length * 0.4 * curvature;
|
|
457
|
-
const midPoint = { x: (start.x + end.x) / 2, y: (start.y + end.y) / 2 };
|
|
458
|
-
const controlPoint = {
|
|
459
|
-
x: midPoint.x + perpDir.x * bowAmount,
|
|
460
|
-
y: midPoint.y + perpDir.y * bowAmount
|
|
461
|
-
};
|
|
462
|
-
for (let i = 0; i <= numSamples; i++) {
|
|
463
|
-
const t = i / numSamples;
|
|
464
|
-
if (curvature < 0.1) {
|
|
465
|
-
points.push({
|
|
466
|
-
x: start.x + (end.x - start.x) * t,
|
|
467
|
-
y: start.y + (end.y - start.y) * t
|
|
468
|
-
});
|
|
469
|
-
} else {
|
|
470
|
-
const mt = 1 - t;
|
|
471
|
-
points.push({
|
|
472
|
-
x: mt * mt * start.x + 2 * mt * t * controlPoint.x + t * t * end.x,
|
|
473
|
-
y: mt * mt * start.y + 2 * mt * t * controlPoint.y + t * t * end.y
|
|
474
|
-
});
|
|
475
|
-
}
|
|
476
|
-
}
|
|
477
|
-
return points;
|
|
478
|
-
}
|
|
479
|
-
function getSpineTangent(spine, index) {
|
|
480
|
-
const prev = spine[Math.max(0, index - 1)];
|
|
481
|
-
const next = spine[Math.min(spine.length - 1, index + 1)];
|
|
482
|
-
const dx = next.x - prev.x;
|
|
483
|
-
const dy = next.y - prev.y;
|
|
484
|
-
const len = Math.sqrt(dx * dx + dy * dy);
|
|
485
|
-
return len > 0 ? { x: dx / len, y: dy / len } : { x: 1, y: 0 };
|
|
486
|
-
}
|
|
487
|
-
function smoothCurveThroughPoints(points) {
|
|
488
|
-
if (points.length < 2) return "";
|
|
489
|
-
const parts = [];
|
|
490
|
-
const tension = 0.3;
|
|
491
|
-
for (let i = 0; i < points.length - 1; i++) {
|
|
492
|
-
const p0 = points[Math.max(0, i - 1)];
|
|
493
|
-
const p1 = points[i];
|
|
494
|
-
const p2 = points[i + 1];
|
|
495
|
-
const p3 = points[Math.min(points.length - 1, i + 2)];
|
|
496
|
-
const cp1x = p1.x + (p2.x - p0.x) * tension;
|
|
497
|
-
const cp1y = p1.y + (p2.y - p0.y) * tension;
|
|
498
|
-
const cp2x = p2.x - (p3.x - p1.x) * tension;
|
|
499
|
-
const cp2y = p2.y - (p3.y - p1.y) * tension;
|
|
500
|
-
parts.push(`C ${cp1x.toFixed(2)},${cp1y.toFixed(2)} ${cp2x.toFixed(2)},${cp2y.toFixed(2)} ${p2.x.toFixed(2)},${p2.y.toFixed(2)}`);
|
|
501
|
-
}
|
|
502
|
-
return parts.join(" ");
|
|
503
|
-
}
|
|
504
|
-
function normalizePath(path, minX, minY) {
|
|
505
|
-
return path.replace(
|
|
506
|
-
/([-\d.]+),([-\d.]+)/g,
|
|
507
|
-
(_, x, y) => `${(parseFloat(x) - minX).toFixed(2)},${(parseFloat(y) - minY).toFixed(2)}`
|
|
508
|
-
);
|
|
509
|
-
}
|
|
510
|
-
function rotatePath(path, rotation, width, height) {
|
|
511
|
-
const rad = rotation * Math.PI / 180;
|
|
512
|
-
const cos = Math.cos(rad);
|
|
513
|
-
const sin = Math.sin(rad);
|
|
514
|
-
const cx = width / 2;
|
|
515
|
-
const cy = height / 2;
|
|
516
|
-
return path.replace(
|
|
517
|
-
/([-\d.]+),([-\d.]+)/g,
|
|
518
|
-
(_, xStr, yStr) => {
|
|
519
|
-
const x = parseFloat(xStr) - cx;
|
|
520
|
-
const y = parseFloat(yStr) - cy;
|
|
521
|
-
const rx = x * cos - y * sin + cx;
|
|
522
|
-
const ry = x * sin + y * cos + cy;
|
|
523
|
-
return `${rx.toFixed(2)},${ry.toFixed(2)}`;
|
|
524
|
-
}
|
|
525
|
-
);
|
|
526
|
-
}
|
|
527
|
-
|
|
528
|
-
export {
|
|
529
|
-
boomerang
|
|
530
|
-
};
|
|
531
|
-
//# sourceMappingURL=chunk-IAFZ3FNR.js.map
|