typography-toolkit 1.3.0 → 1.4.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.
|
@@ -1,202 +1,218 @@
|
|
|
1
|
-
class
|
|
2
|
-
update(
|
|
3
|
-
const
|
|
1
|
+
class y {
|
|
2
|
+
update(t, n, i, a = {}) {
|
|
3
|
+
const e = a.speed || 1, l = a.amplitude || 20, s = n * 0.2, h = (i * 10 * e + s * 5) % l - l / 2;
|
|
4
4
|
return {
|
|
5
|
-
...
|
|
6
|
-
y:
|
|
5
|
+
...t,
|
|
6
|
+
y: h
|
|
7
7
|
};
|
|
8
8
|
}
|
|
9
9
|
}
|
|
10
|
-
class
|
|
11
|
-
update(
|
|
12
|
-
const
|
|
10
|
+
class w {
|
|
11
|
+
update(t, n, i, a = {}) {
|
|
12
|
+
const e = a.speed || 1, l = a.amplitude || 4, s = n * 0.2, c = Math.sin(i * 0.5 * e + s) * l;
|
|
13
13
|
return {
|
|
14
|
-
...
|
|
15
|
-
x:
|
|
14
|
+
...t,
|
|
15
|
+
x: c
|
|
16
16
|
};
|
|
17
17
|
}
|
|
18
18
|
}
|
|
19
|
-
class
|
|
19
|
+
class C {
|
|
20
20
|
constructor() {
|
|
21
|
-
this.
|
|
21
|
+
this.letterStates = /* @__PURE__ */ new Map();
|
|
22
22
|
}
|
|
23
|
-
update(
|
|
24
|
-
const
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
23
|
+
update(t, n, i, a = {}) {
|
|
24
|
+
const e = a.amplitude || 3, l = a.speed || 1;
|
|
25
|
+
let s = this.letterStates.get(n);
|
|
26
|
+
s || (s = {
|
|
27
|
+
lastUpdate: i,
|
|
28
|
+
glitchX: 0,
|
|
29
|
+
glitchY: 0,
|
|
30
|
+
glitchRot: 0
|
|
31
|
+
}, this.letterStates.set(n, s));
|
|
32
|
+
const c = 0.1 / l;
|
|
33
|
+
return i - s.lastUpdate > c && (s.glitchX = (Math.random() - 0.5) * e, s.glitchY = (Math.random() - 0.5) * (e * 0.67), s.glitchRot = (Math.random() - 0.5) * e, s.lastUpdate = i), {
|
|
34
|
+
...t,
|
|
35
|
+
x: s.glitchX,
|
|
36
|
+
y: s.glitchY,
|
|
37
|
+
rotation: s.glitchRot
|
|
30
38
|
};
|
|
31
39
|
}
|
|
32
40
|
}
|
|
33
|
-
class
|
|
34
|
-
update(
|
|
35
|
-
const
|
|
41
|
+
class M {
|
|
42
|
+
update(t, n, i, a = {}) {
|
|
43
|
+
const e = a.speed || 1, l = a.amplitude || 15, s = n * 0.2, h = -((i * 8 * e + s * 4) % l - l / 2);
|
|
36
44
|
return {
|
|
37
|
-
...
|
|
38
|
-
y:
|
|
45
|
+
...t,
|
|
46
|
+
y: h
|
|
39
47
|
};
|
|
40
48
|
}
|
|
41
49
|
}
|
|
42
|
-
function
|
|
43
|
-
const { x:
|
|
44
|
-
|
|
50
|
+
function v(o, t) {
|
|
51
|
+
const { x: n, y: i, rotation: a, scale: e, opacity: l } = t;
|
|
52
|
+
o.style.transform = `translate(${n}px, ${i}px) rotate(${a}deg) scale(${e})`, o.style.opacity = l.toString();
|
|
45
53
|
}
|
|
46
|
-
function
|
|
47
|
-
if (!
|
|
54
|
+
function F(o, t, n, i, a, e) {
|
|
55
|
+
if (!e.enabled)
|
|
48
56
|
return {
|
|
49
57
|
state: { x: 0, y: 0, rotation: 0, scale: 1, opacity: 1 },
|
|
50
58
|
applied: !1
|
|
51
59
|
};
|
|
52
|
-
const l =
|
|
53
|
-
if (
|
|
60
|
+
const l = e.radius || 80, s = e.strength || 1, c = e.behaviors || ["fall-away", "split-apart", "explode"], h = n - o, d = i - t, m = Math.sqrt(h * h + d * d);
|
|
61
|
+
if (m >= l)
|
|
54
62
|
return {
|
|
55
63
|
state: { x: 0, y: 0, rotation: 0, scale: 1, opacity: 1 },
|
|
56
64
|
applied: !1
|
|
57
65
|
};
|
|
58
|
-
const
|
|
59
|
-
let
|
|
60
|
-
switch (
|
|
66
|
+
const r = (1 - m / l) * s, f = Math.atan2(d, h), k = c[a % c.length];
|
|
67
|
+
let p;
|
|
68
|
+
switch (k) {
|
|
61
69
|
case "fall-away":
|
|
62
|
-
const A = Math.cos(
|
|
63
|
-
|
|
70
|
+
const A = Math.cos(f) * r * 20, T = Math.sin(f) * r * 40 + r * 30;
|
|
71
|
+
p = {
|
|
64
72
|
x: A,
|
|
65
|
-
y:
|
|
66
|
-
rotation:
|
|
73
|
+
y: T,
|
|
74
|
+
rotation: r * 15,
|
|
67
75
|
scale: 1,
|
|
68
|
-
opacity: 1 -
|
|
76
|
+
opacity: 1 - r * 0.6
|
|
69
77
|
};
|
|
70
78
|
break;
|
|
71
79
|
case "split-apart":
|
|
72
|
-
const
|
|
73
|
-
|
|
74
|
-
x:
|
|
75
|
-
y: (Math.random() - 0.5) *
|
|
76
|
-
rotation:
|
|
80
|
+
const g = a % 2 === 0 ? 1 : -1;
|
|
81
|
+
p = {
|
|
82
|
+
x: g * r * 50,
|
|
83
|
+
y: (Math.random() - 0.5) * r * 10,
|
|
84
|
+
rotation: r * 10 * g,
|
|
77
85
|
scale: 1,
|
|
78
|
-
opacity: 1 -
|
|
86
|
+
opacity: 1 - r * 0.6
|
|
79
87
|
};
|
|
80
88
|
break;
|
|
81
89
|
case "explode":
|
|
82
|
-
const
|
|
83
|
-
|
|
84
|
-
x: Math.cos(
|
|
85
|
-
y: Math.sin(
|
|
86
|
-
rotation:
|
|
87
|
-
scale: 1 +
|
|
88
|
-
opacity: 1 -
|
|
90
|
+
const x = f + (Math.random() - 0.5) * 0.5;
|
|
91
|
+
p = {
|
|
92
|
+
x: Math.cos(x) * r * 40,
|
|
93
|
+
y: Math.sin(x) * r * 40,
|
|
94
|
+
rotation: r * 30,
|
|
95
|
+
scale: 1 + r * 0.4,
|
|
96
|
+
opacity: 1 - r * 0.6
|
|
89
97
|
};
|
|
90
98
|
break;
|
|
91
99
|
default:
|
|
92
|
-
|
|
100
|
+
p = { x: 0, y: 0, rotation: 0, scale: 1, opacity: 1 };
|
|
93
101
|
}
|
|
94
102
|
return {
|
|
95
|
-
state:
|
|
103
|
+
state: p,
|
|
96
104
|
applied: !0
|
|
97
105
|
};
|
|
98
106
|
}
|
|
99
|
-
class
|
|
100
|
-
constructor(
|
|
101
|
-
var
|
|
102
|
-
if (this.letters = [], this.animationSpeedMultiplier = 1, this.animationFrame = null, this.mouseX = 0, this.mouseY = 0, this.mouseMoveHandler = null, this.startTime = Date.now(), this.isDestroyed = !1, this.container =
|
|
103
|
-
this.textContainer.style.setProperty(
|
|
104
|
-
}),
|
|
105
|
-
let
|
|
106
|
-
if (
|
|
107
|
+
class S {
|
|
108
|
+
constructor(t) {
|
|
109
|
+
var n;
|
|
110
|
+
if (this.letters = [], this.animationSpeedMultiplier = 1, this.animationFrame = null, this.mouseX = 0, this.mouseY = 0, this.mouseMoveHandler = null, this.startTime = Date.now(), this.isDestroyed = !1, this.animationInstances = /* @__PURE__ */ new Map(), this.container = t.container, this.animationTypes = t.animations || ["falling", "splitting", "glitching", "floating"], this.cycle = t.cycle !== !1, this.speed = t.speed || 1, this.amplitude = t.amplitude || 1, this.animationEasing = t.animationEasing || "linear", this.disintegration = t.disintegration || { enabled: !1 }, this.style = t.style || {}, this.fadeOut = t.fadeOut || 0, this.callbacks = t.callbacks, t.animationSpeed !== void 0 && (this.animationSpeedMultiplier = this.parseAnimationSpeed(t.animationSpeed)), this.textContainer = document.createElement("div"), this.textContainer.style.position = "absolute", this.textContainer.style.pointerEvents = "none", this.textContainer.style.zIndex = "1", t.containerClass && (this.textContainer.className = t.containerClass), t.containerStyle && Object.entries(t.containerStyle).forEach(([i, a]) => {
|
|
111
|
+
this.textContainer.style.setProperty(i, a);
|
|
112
|
+
}), t.position) {
|
|
113
|
+
let i = t.position.x, a = t.position.y;
|
|
114
|
+
if (t.position.constrainToViewport) {
|
|
107
115
|
this.container.getBoundingClientRect();
|
|
108
|
-
const
|
|
109
|
-
|
|
116
|
+
const e = window.innerWidth, l = window.innerHeight, s = t.text.length * 20;
|
|
117
|
+
i !== void 0 && (i = Math.max(0, Math.min(i, e - s))), a !== void 0 && (a = Math.max(0, Math.min(a, l - 50)));
|
|
110
118
|
}
|
|
111
|
-
|
|
119
|
+
i !== void 0 && (this.textContainer.style.left = `${i}px`), a !== void 0 && (this.textContainer.style.top = `${a}px`);
|
|
112
120
|
}
|
|
113
|
-
this.createLetters(
|
|
121
|
+
this.createLetters(t.text), this.setupMouseTracking(), this.startAnimation(), (n = this.callbacks) != null && n.onCreate && this.callbacks.onCreate(this.textContainer), this.fadeOut > 0 && setTimeout(() => this.destroy(), this.fadeOut);
|
|
114
122
|
}
|
|
115
|
-
createLetters(
|
|
116
|
-
|
|
117
|
-
if (
|
|
118
|
-
const
|
|
119
|
-
this.textContainer.appendChild(
|
|
123
|
+
createLetters(t) {
|
|
124
|
+
t.toUpperCase().split("").forEach((i, a) => {
|
|
125
|
+
if (i === " ") {
|
|
126
|
+
const s = document.createTextNode(" ");
|
|
127
|
+
this.textContainer.appendChild(s);
|
|
120
128
|
return;
|
|
121
129
|
}
|
|
122
|
-
const
|
|
123
|
-
|
|
124
|
-
const l =
|
|
130
|
+
const e = document.createElement("span");
|
|
131
|
+
e.className = "animated-letter", e.textContent = i, e.dataset.index = a.toString(), e.dataset.char = i, this.applyStyle(e), e.style.display = "inline-block", e.style.position = "relative", e.style.transition = "transform 0.1s ease-out", this.textContainer.appendChild(e);
|
|
132
|
+
const l = e.getBoundingClientRect();
|
|
125
133
|
this.letters.push({
|
|
126
|
-
element:
|
|
127
|
-
index:
|
|
128
|
-
char:
|
|
134
|
+
element: e,
|
|
135
|
+
index: a,
|
|
136
|
+
char: i,
|
|
129
137
|
baseX: l.left,
|
|
130
138
|
baseY: l.top
|
|
131
139
|
});
|
|
132
140
|
}), this.container.appendChild(this.textContainer);
|
|
133
141
|
}
|
|
134
|
-
applyStyle(
|
|
135
|
-
this.style.fontFamily && (
|
|
142
|
+
applyStyle(t) {
|
|
143
|
+
this.style.fontFamily && (t.style.fontFamily = this.style.fontFamily), this.style.fontSize && (t.style.fontSize = `${this.style.fontSize}px`), this.style.color && (t.style.color = this.style.color), this.style.fontWeight && (t.style.fontWeight = this.style.fontWeight), this.style.textShadow && (t.style.textShadow = this.style.textShadow), this.style.letterSpacing && (t.style.letterSpacing = this.style.letterSpacing), this.style.textTransform && (t.style.textTransform = this.style.textTransform);
|
|
136
144
|
}
|
|
137
145
|
setupMouseTracking() {
|
|
138
|
-
this.disintegration.enabled && (this.mouseMoveHandler = (
|
|
139
|
-
this.mouseX =
|
|
146
|
+
this.disintegration.enabled && (this.mouseMoveHandler = (t) => {
|
|
147
|
+
this.mouseX = t.clientX, this.mouseY = t.clientY;
|
|
140
148
|
}, document.addEventListener("mousemove", this.mouseMoveHandler));
|
|
141
149
|
}
|
|
142
150
|
startAnimation() {
|
|
143
|
-
const
|
|
151
|
+
const t = () => {
|
|
144
152
|
if (this.isDestroyed) return;
|
|
145
|
-
const
|
|
146
|
-
this.letters.forEach((
|
|
147
|
-
var
|
|
148
|
-
const
|
|
153
|
+
const n = (Date.now() - this.startTime) * 1e-3;
|
|
154
|
+
this.letters.forEach((i, a) => {
|
|
155
|
+
var d;
|
|
156
|
+
const e = i.element.getBoundingClientRect(), l = e.left + e.width / 2, s = e.top + e.height / 2, c = F(
|
|
149
157
|
l,
|
|
150
|
-
|
|
158
|
+
s,
|
|
151
159
|
this.mouseX,
|
|
152
160
|
this.mouseY,
|
|
153
|
-
|
|
161
|
+
a,
|
|
154
162
|
this.disintegration
|
|
155
163
|
);
|
|
156
|
-
let
|
|
157
|
-
if (
|
|
158
|
-
|
|
164
|
+
let h;
|
|
165
|
+
if (c.applied)
|
|
166
|
+
h = c.state, (d = this.callbacks) != null && d.onDisintegrate && this.callbacks.onDisintegrate(a);
|
|
159
167
|
else {
|
|
160
|
-
const
|
|
161
|
-
|
|
168
|
+
const m = this.getAnimationType(a);
|
|
169
|
+
h = this.getAnimation(m).update(
|
|
162
170
|
{ x: 0, y: 0, rotation: 0, scale: 1, opacity: 1 },
|
|
163
|
-
|
|
164
|
-
|
|
171
|
+
a,
|
|
172
|
+
n,
|
|
165
173
|
{
|
|
166
174
|
speed: this.speed * this.animationSpeedMultiplier,
|
|
167
|
-
amplitude: this.amplitude * (
|
|
175
|
+
amplitude: this.amplitude * (m === "falling" || m === "floating" ? 20 : 4)
|
|
168
176
|
}
|
|
169
177
|
);
|
|
170
178
|
}
|
|
171
|
-
|
|
172
|
-
}), this.animationFrame = requestAnimationFrame(
|
|
179
|
+
v(i.element, h);
|
|
180
|
+
}), this.animationFrame = requestAnimationFrame(t);
|
|
173
181
|
};
|
|
174
|
-
this.animationFrame = requestAnimationFrame(
|
|
182
|
+
this.animationFrame = requestAnimationFrame(t);
|
|
175
183
|
}
|
|
176
|
-
getAnimationType(
|
|
177
|
-
return this.cycle ? this.animationTypes[
|
|
184
|
+
getAnimationType(t) {
|
|
185
|
+
return this.cycle ? this.animationTypes[t % this.animationTypes.length] : this.animationTypes[0];
|
|
178
186
|
}
|
|
179
|
-
getAnimation(
|
|
180
|
-
|
|
187
|
+
getAnimation(t) {
|
|
188
|
+
if (this.animationInstances.has(t))
|
|
189
|
+
return this.animationInstances.get(t);
|
|
190
|
+
let n;
|
|
191
|
+
switch (t) {
|
|
181
192
|
case "falling":
|
|
182
|
-
|
|
193
|
+
n = new y();
|
|
194
|
+
break;
|
|
183
195
|
case "splitting":
|
|
184
|
-
|
|
196
|
+
n = new w();
|
|
197
|
+
break;
|
|
185
198
|
case "glitching":
|
|
186
|
-
|
|
199
|
+
n = new C();
|
|
200
|
+
break;
|
|
187
201
|
case "floating":
|
|
188
|
-
|
|
202
|
+
n = new M();
|
|
203
|
+
break;
|
|
189
204
|
default:
|
|
190
|
-
|
|
205
|
+
n = new y();
|
|
191
206
|
}
|
|
207
|
+
return this.animationInstances.set(t, n), n;
|
|
192
208
|
}
|
|
193
209
|
/**
|
|
194
210
|
* Parse animation speed preset or numeric value to a multiplier
|
|
195
211
|
*/
|
|
196
|
-
parseAnimationSpeed(
|
|
197
|
-
if (typeof
|
|
198
|
-
return
|
|
199
|
-
switch (
|
|
212
|
+
parseAnimationSpeed(t) {
|
|
213
|
+
if (typeof t == "number")
|
|
214
|
+
return t;
|
|
215
|
+
switch (t) {
|
|
200
216
|
case "slow":
|
|
201
217
|
return 0.5;
|
|
202
218
|
case "normal":
|
|
@@ -216,8 +232,8 @@ class v {
|
|
|
216
232
|
/**
|
|
217
233
|
* Set the animation speed multiplier (supports numeric values and presets)
|
|
218
234
|
*/
|
|
219
|
-
setAnimationSpeed(
|
|
220
|
-
this.animationSpeedMultiplier = this.parseAnimationSpeed(
|
|
235
|
+
setAnimationSpeed(t) {
|
|
236
|
+
this.animationSpeedMultiplier = this.parseAnimationSpeed(t);
|
|
221
237
|
}
|
|
222
238
|
/**
|
|
223
239
|
* Get the current animation easing function
|
|
@@ -228,15 +244,15 @@ class v {
|
|
|
228
244
|
/**
|
|
229
245
|
* Set the animation easing function
|
|
230
246
|
*/
|
|
231
|
-
setAnimationEasing(
|
|
232
|
-
this.animationEasing =
|
|
247
|
+
setAnimationEasing(t) {
|
|
248
|
+
this.animationEasing = t;
|
|
233
249
|
}
|
|
234
250
|
/**
|
|
235
251
|
* Destroy the animated text instance
|
|
236
252
|
*/
|
|
237
253
|
destroy() {
|
|
238
|
-
var
|
|
239
|
-
this.isDestroyed || (this.isDestroyed = !0, this.animationFrame !== null && cancelAnimationFrame(this.animationFrame), this.mouseMoveHandler && document.removeEventListener("mousemove", this.mouseMoveHandler), (
|
|
254
|
+
var t;
|
|
255
|
+
this.isDestroyed || (this.isDestroyed = !0, this.animationFrame !== null && cancelAnimationFrame(this.animationFrame), this.mouseMoveHandler && document.removeEventListener("mousemove", this.mouseMoveHandler), this.animationInstances.clear(), (t = this.callbacks) != null && t.onDestroy && this.callbacks.onDestroy(), this.textContainer.style.transition = "opacity 3s ease", this.textContainer.style.opacity = "0", setTimeout(() => {
|
|
240
256
|
this.textContainer.parentNode && this.textContainer.parentNode.removeChild(this.textContainer);
|
|
241
257
|
}, 3e3));
|
|
242
258
|
}
|
|
@@ -247,362 +263,37 @@ class v {
|
|
|
247
263
|
return this.textContainer;
|
|
248
264
|
}
|
|
249
265
|
}
|
|
250
|
-
const
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
"imperfect",
|
|
257
|
-
"uneven",
|
|
258
|
-
"scratchy"
|
|
259
|
-
], R = ["subtle", "moderate", "intense"], k = [
|
|
260
|
-
// Hand-drawn / Handwriting
|
|
261
|
-
{
|
|
262
|
-
name: "Hand-drawn Casual",
|
|
263
|
-
googleFontsName: "Caveat",
|
|
264
|
-
categories: ["hand-drawn", "handwriting", "casual", "sketchy", "informal"],
|
|
265
|
-
description: "Casual handwritten style, friendly and approachable",
|
|
266
|
-
artistic: !1
|
|
267
|
-
},
|
|
268
|
-
{
|
|
269
|
-
name: "Hand-drawn Playful",
|
|
270
|
-
googleFontsName: "Finger Paint",
|
|
271
|
-
categories: ["hand-drawn", "playful", "childlike", "casual", "sketchy"],
|
|
272
|
-
description: "Bold hand-drawn style, playful and energetic",
|
|
273
|
-
artistic: !0
|
|
274
|
-
},
|
|
275
|
-
{
|
|
276
|
-
name: "Hand-drawn Script",
|
|
277
|
-
googleFontsName: "Dancing Script",
|
|
278
|
-
categories: ["hand-drawn", "script", "elegant", "flowing", "cursive"],
|
|
279
|
-
description: "Elegant flowing script, graceful and organic",
|
|
280
|
-
artistic: !1
|
|
281
|
-
},
|
|
282
|
-
// Gothic / Medieval
|
|
283
|
-
{
|
|
284
|
-
name: "Gothic Blackletter",
|
|
285
|
-
googleFontsName: "UnifrakturMaguntia",
|
|
286
|
-
categories: ["gothic", "medieval", "blackletter", "ornate", "historical"],
|
|
287
|
-
description: "Medieval blackletter style, ornate and historical",
|
|
288
|
-
artistic: !0
|
|
289
|
-
},
|
|
290
|
-
{
|
|
291
|
-
name: "Gothic Horror",
|
|
292
|
-
googleFontsName: "Creepster",
|
|
293
|
-
categories: ["gothic", "horror", "creepy", "dripping", "display", "striking", "intense"],
|
|
294
|
-
description: "Horror-style font with dripping effects, very striking",
|
|
295
|
-
artistic: !0
|
|
296
|
-
},
|
|
297
|
-
{
|
|
298
|
-
name: "Gothic Bold",
|
|
299
|
-
googleFontsName: "Eater",
|
|
300
|
-
categories: ["gothic", "bold", "aggressive", "display", "striking"],
|
|
301
|
-
description: "Bold aggressive display font, powerful impact",
|
|
302
|
-
artistic: !0
|
|
303
|
-
},
|
|
304
|
-
// Futuristic / Sci-fi
|
|
305
|
-
{
|
|
306
|
-
name: "Futuristic Digital",
|
|
307
|
-
googleFontsName: "Orbitron",
|
|
308
|
-
categories: ["futuristic", "sci-fi", "digital", "tech", "modern", "geometric"],
|
|
309
|
-
description: "Futuristic geometric font, tech-forward and modern",
|
|
310
|
-
artistic: !0
|
|
311
|
-
},
|
|
312
|
-
{
|
|
313
|
-
name: "Futuristic Display",
|
|
314
|
-
googleFontsName: "Bungee",
|
|
315
|
-
categories: ["futuristic", "display", "bold", "condensed", "striking"],
|
|
316
|
-
description: "Bold condensed display font, high impact",
|
|
317
|
-
artistic: !0
|
|
318
|
-
},
|
|
319
|
-
{
|
|
320
|
-
name: "Futuristic Outline",
|
|
321
|
-
googleFontsName: "Bungee Shade",
|
|
322
|
-
categories: ["futuristic", "outline", "display", "bold", "striking"],
|
|
323
|
-
description: "Outlined version of Bungee, bold and striking",
|
|
324
|
-
artistic: !0
|
|
325
|
-
},
|
|
326
|
-
// Retro / Vintage
|
|
327
|
-
{
|
|
328
|
-
name: "Retro Terminal",
|
|
329
|
-
googleFontsName: "VT323",
|
|
330
|
-
categories: ["retro", "terminal", "monospace", "pixel", "80s", "tech"],
|
|
331
|
-
description: "Retro terminal font, pixelated and nostalgic",
|
|
332
|
-
artistic: !0
|
|
333
|
-
},
|
|
334
|
-
{
|
|
335
|
-
name: "Retro Pixel",
|
|
336
|
-
googleFontsName: "Press Start 2P",
|
|
337
|
-
categories: ["retro", "pixel", "8-bit", "arcade", "nostalgic", "display"],
|
|
338
|
-
description: "8-bit pixel font, classic arcade style",
|
|
339
|
-
artistic: !0
|
|
340
|
-
},
|
|
341
|
-
{
|
|
342
|
-
name: "Retro Display",
|
|
343
|
-
googleFontsName: "Frijole",
|
|
344
|
-
categories: ["retro", "playful", "rounded", "display", "casual"],
|
|
345
|
-
description: "Playful rounded retro font, fun and casual",
|
|
346
|
-
artistic: !0
|
|
347
|
-
},
|
|
348
|
-
// Decorative / Ornate
|
|
349
|
-
{
|
|
350
|
-
name: "Decorative Ornate",
|
|
351
|
-
googleFontsName: "Fascinate",
|
|
352
|
-
categories: ["decorative", "ornate", "display", "striking", "elaborate"],
|
|
353
|
-
description: "Highly decorative display font, ornate and elaborate",
|
|
354
|
-
artistic: !0
|
|
355
|
-
},
|
|
356
|
-
{
|
|
357
|
-
name: "Decorative Outline",
|
|
358
|
-
googleFontsName: "Fascinate Inline",
|
|
359
|
-
categories: ["decorative", "outline", "display", "ornate", "striking"],
|
|
360
|
-
description: "Outlined decorative font, ornate and striking",
|
|
361
|
-
artistic: !0
|
|
362
|
-
},
|
|
363
|
-
{
|
|
364
|
-
name: "Decorative Script",
|
|
365
|
-
googleFontsName: "Fredericka the Great",
|
|
366
|
-
categories: ["decorative", "script", "ornate", "elegant", "display"],
|
|
367
|
-
description: "Elegant decorative script, ornate and sophisticated",
|
|
368
|
-
artistic: !0
|
|
369
|
-
},
|
|
370
|
-
// Creepy / Horror
|
|
371
|
-
{
|
|
372
|
-
name: "Horror Dripping",
|
|
373
|
-
googleFontsName: "Nosifer",
|
|
374
|
-
categories: ["horror", "creepy", "dripping", "blood", "striking", "display", "intense"],
|
|
375
|
-
description: "Creepy font with blood-dripping effects, very striking",
|
|
376
|
-
artistic: !0
|
|
377
|
-
},
|
|
378
|
-
// Tech / Monospace
|
|
379
|
-
{
|
|
380
|
-
name: "Tech Monospace",
|
|
381
|
-
googleFontsName: "Share Tech Mono",
|
|
382
|
-
categories: ["tech", "monospace", "terminal", "code", "modern"],
|
|
383
|
-
description: "Clean tech monospace font, modern and readable",
|
|
384
|
-
artistic: !1
|
|
385
|
-
},
|
|
386
|
-
{
|
|
387
|
-
name: "Tech Display",
|
|
388
|
-
googleFontsName: "Rajdhani",
|
|
389
|
-
categories: ["tech", "modern", "geometric", "sans-serif", "futuristic"],
|
|
390
|
-
description: "Modern geometric tech font, clean and futuristic",
|
|
391
|
-
artistic: !1
|
|
392
|
-
},
|
|
393
|
-
// Organic / Natural
|
|
394
|
-
{
|
|
395
|
-
name: "Organic Flowing",
|
|
396
|
-
googleFontsName: "Dancing Script",
|
|
397
|
-
categories: ["organic", "flowing", "natural", "script", "elegant"],
|
|
398
|
-
description: "Flowing organic script, natural and elegant",
|
|
399
|
-
artistic: !1
|
|
400
|
-
},
|
|
401
|
-
// Modern / Clean
|
|
402
|
-
{
|
|
403
|
-
name: "Modern Sans",
|
|
404
|
-
googleFontsName: "Roboto",
|
|
405
|
-
categories: ["modern", "clean", "sans-serif", "readable", "professional"],
|
|
406
|
-
description: "Clean modern sans-serif, professional and readable",
|
|
407
|
-
artistic: !1
|
|
408
|
-
},
|
|
409
|
-
{
|
|
410
|
-
name: "Modern Serif",
|
|
411
|
-
googleFontsName: "Playfair Display",
|
|
412
|
-
categories: ["modern", "serif", "elegant", "sophisticated", "readable"],
|
|
413
|
-
description: "Elegant modern serif, sophisticated and readable",
|
|
414
|
-
artistic: !1
|
|
415
|
-
},
|
|
416
|
-
// Bold / Display
|
|
417
|
-
{
|
|
418
|
-
name: "Bold Condensed",
|
|
419
|
-
googleFontsName: "Bungee",
|
|
420
|
-
categories: ["bold", "condensed", "display", "striking", "impact"],
|
|
421
|
-
description: "Bold condensed display font, high impact",
|
|
422
|
-
artistic: !0
|
|
423
|
-
},
|
|
424
|
-
{
|
|
425
|
-
name: "Bold Aggressive",
|
|
426
|
-
googleFontsName: "Eater",
|
|
427
|
-
categories: ["bold", "aggressive", "display", "striking", "powerful"],
|
|
428
|
-
description: "Bold aggressive display font, powerful and striking",
|
|
429
|
-
artistic: !0
|
|
430
|
-
},
|
|
431
|
-
// Subtle Unsettling / Organic Imperfect
|
|
432
|
-
{
|
|
433
|
-
name: "Handwritten Thin",
|
|
434
|
-
googleFontsName: "Amatic SC",
|
|
435
|
-
categories: ["hand-drawn", "uneven", "organic", "unsettling", "subtle", "scratchy"],
|
|
436
|
-
description: "Thin hand-drawn letters with subtle irregularity, organic feel",
|
|
437
|
-
artistic: !0
|
|
438
|
-
},
|
|
439
|
-
{
|
|
440
|
-
name: "Rough Handwriting",
|
|
441
|
-
googleFontsName: "Rock Salt",
|
|
442
|
-
categories: ["hand-drawn", "scratchy", "weathered", "rough", "unsettling", "moderate"],
|
|
443
|
-
description: "Rough, weathered handwriting with natural imperfection",
|
|
444
|
-
artistic: !0
|
|
445
|
-
},
|
|
446
|
-
{
|
|
447
|
-
name: "Typewriter Degraded",
|
|
448
|
-
googleFontsName: "Special Elite",
|
|
449
|
-
categories: ["typewriter", "decayed", "weathered", "imperfect", "unsettling", "moderate"],
|
|
450
|
-
description: "Degraded typewriter font, vintage with imperfection",
|
|
451
|
-
artistic: !0
|
|
452
|
-
},
|
|
453
|
-
{
|
|
454
|
-
name: "Casual Handwriting",
|
|
455
|
-
googleFontsName: "Handlee",
|
|
456
|
-
categories: ["hand-drawn", "casual", "imperfect", "organic", "subtle"],
|
|
457
|
-
description: "Casual handwriting with subtle imperfection",
|
|
458
|
-
artistic: !1
|
|
459
|
-
},
|
|
460
|
-
{
|
|
461
|
-
name: "Childlike Organic",
|
|
462
|
-
googleFontsName: "Indie Flower",
|
|
463
|
-
categories: ["hand-drawn", "childlike", "organic", "imperfect", "eerie", "subtle"],
|
|
464
|
-
description: "Childlike handwriting, can feel innocent or eerie depending on context",
|
|
465
|
-
artistic: !1
|
|
466
|
-
},
|
|
467
|
-
{
|
|
468
|
-
name: "Scratchy Personal",
|
|
469
|
-
googleFontsName: "Shadows Into Light",
|
|
470
|
-
categories: ["hand-drawn", "scratchy", "personal", "unsettling", "uneven", "moderate"],
|
|
471
|
-
description: "Scratchy personal handwriting with unsettling quality",
|
|
472
|
-
artistic: !0
|
|
473
|
-
},
|
|
474
|
-
{
|
|
475
|
-
name: "Hurried Scratchy",
|
|
476
|
-
googleFontsName: "Reenie Beanie",
|
|
477
|
-
categories: ["hand-drawn", "scratchy", "hurried", "uneven", "unsettling", "moderate"],
|
|
478
|
-
description: "Hurried scratchy handwriting with nervous energy",
|
|
479
|
-
artistic: !0
|
|
480
|
-
},
|
|
481
|
-
{
|
|
482
|
-
name: "Architectural Irregular",
|
|
483
|
-
googleFontsName: "Architects Daughter",
|
|
484
|
-
categories: ["hand-drawn", "imperfect", "uneven", "organic", "subtle"],
|
|
485
|
-
description: "Hand-drawn with architectural irregularity",
|
|
486
|
-
artistic: !1
|
|
487
|
-
},
|
|
488
|
-
{
|
|
489
|
-
name: "Informal Unsettling",
|
|
490
|
-
googleFontsName: "Coming Soon",
|
|
491
|
-
categories: ["hand-drawn", "informal", "imperfect", "unsettling", "subtle"],
|
|
492
|
-
description: "Informal handwriting that feels slightly off",
|
|
493
|
-
artistic: !1
|
|
494
|
-
},
|
|
495
|
-
{
|
|
496
|
-
name: "Manic Handwriting",
|
|
497
|
-
googleFontsName: "Gloria Hallelujah",
|
|
498
|
-
categories: ["hand-drawn", "playful", "manic", "uneven", "unsettling", "moderate"],
|
|
499
|
-
description: "Playful handwriting that can feel manic or unsettled",
|
|
500
|
-
artistic: !0
|
|
501
|
-
},
|
|
502
|
-
{
|
|
503
|
-
name: "Quick Imperfect",
|
|
504
|
-
googleFontsName: "Just Another Hand",
|
|
505
|
-
categories: ["hand-drawn", "scratchy", "quick", "imperfect", "uneven", "subtle"],
|
|
506
|
-
description: "Quick scratchy handwriting with natural imperfection",
|
|
507
|
-
artistic: !1
|
|
508
|
-
},
|
|
509
|
-
{
|
|
510
|
-
name: "Organic Handwriting",
|
|
511
|
-
googleFontsName: "Kalam",
|
|
512
|
-
categories: ["hand-drawn", "organic", "natural", "flowing", "subtle"],
|
|
513
|
-
description: "Organic natural handwriting with flowing quality",
|
|
514
|
-
artistic: !1
|
|
515
|
-
},
|
|
516
|
-
{
|
|
517
|
-
name: "Flowing Tension",
|
|
518
|
-
googleFontsName: "Satisfy",
|
|
519
|
-
categories: ["script", "flowing", "tension", "elegant", "unsettling", "subtle"],
|
|
520
|
-
description: "Flowing script with underlying tension",
|
|
521
|
-
artistic: !0
|
|
522
|
-
},
|
|
523
|
-
{
|
|
524
|
-
name: "Unsettling Elegance",
|
|
525
|
-
googleFontsName: "Yellowtail",
|
|
526
|
-
categories: ["script", "elegant", "stylized", "unsettling", "uneven", "moderate"],
|
|
527
|
-
description: "Stylized elegance with unsettling undertones",
|
|
528
|
-
artistic: !0
|
|
529
|
-
},
|
|
530
|
-
{
|
|
531
|
-
name: "Typewriter Imperfect",
|
|
532
|
-
googleFontsName: "Cutive Mono",
|
|
533
|
-
categories: ["typewriter", "monospace", "imperfect", "decayed", "vintage", "subtle"],
|
|
534
|
-
description: "Imperfect vintage typewriter with character",
|
|
535
|
-
artistic: !0
|
|
536
|
-
}
|
|
537
|
-
];
|
|
538
|
-
function L(s) {
|
|
539
|
-
const e = s.toLowerCase().split(/\s+/).filter((t) => t.length > 0), o = [], n = [];
|
|
540
|
-
for (const t of e)
|
|
541
|
-
t.startsWith("-") && t.length > 1 ? n.push(t.slice(1)) : o.push(t);
|
|
542
|
-
return { positive: o, negative: n };
|
|
543
|
-
}
|
|
544
|
-
function O(s, e) {
|
|
545
|
-
const o = /* @__PURE__ */ new Set(), n = /* @__PURE__ */ new Map(), t = 2, i = [];
|
|
546
|
-
for (const l of s) {
|
|
547
|
-
if (i.length >= e) break;
|
|
548
|
-
if (o.has(l.font.googleFontsName))
|
|
549
|
-
continue;
|
|
550
|
-
const r = l.font.categories[0], a = n.get(r) || 0;
|
|
551
|
-
a >= t || (o.add(l.font.googleFontsName), n.set(r, a + 1), i.push(l.font));
|
|
552
|
-
}
|
|
553
|
-
return i;
|
|
554
|
-
}
|
|
555
|
-
function y(s, e) {
|
|
556
|
-
const { positive: o, negative: n } = L(s), t = (e == null ? void 0 : e.limit) ?? 10, l = k.map((r) => {
|
|
557
|
-
let a = 0;
|
|
558
|
-
for (const c of o) {
|
|
559
|
-
for (const u of r.categories)
|
|
560
|
-
(u.includes(c) || c.includes(u)) && (a += 10);
|
|
561
|
-
r.name.toLowerCase().includes(c) && (a += 15), r.description.toLowerCase().includes(c) && (a += 8);
|
|
562
|
-
}
|
|
563
|
-
for (const c of n) {
|
|
564
|
-
for (const u of r.categories)
|
|
565
|
-
(u.includes(c) || c.includes(u)) && (a -= 20);
|
|
566
|
-
r.name.toLowerCase().includes(c) && (a -= 15), r.description.toLowerCase().includes(c) && (a -= 10);
|
|
567
|
-
}
|
|
568
|
-
return r.artistic && (a += 1), { font: r, score: a };
|
|
569
|
-
}).filter((r) => r.score > 0).sort((r, a) => a.score - r.score);
|
|
570
|
-
return O(l, t);
|
|
571
|
-
}
|
|
572
|
-
function P(s) {
|
|
573
|
-
return y(s)[0];
|
|
574
|
-
}
|
|
575
|
-
const p = /* @__PURE__ */ new Set();
|
|
576
|
-
function N(s) {
|
|
577
|
-
return new Promise((e, o) => {
|
|
578
|
-
const n = s.replace(/\s+/g, "+");
|
|
579
|
-
if (p.has(n)) {
|
|
580
|
-
e();
|
|
266
|
+
const u = /* @__PURE__ */ new Set();
|
|
267
|
+
function b(o) {
|
|
268
|
+
return new Promise((t, n) => {
|
|
269
|
+
const i = o.replace(/\s+/g, "+");
|
|
270
|
+
if (u.has(i)) {
|
|
271
|
+
t();
|
|
581
272
|
return;
|
|
582
273
|
}
|
|
583
274
|
if (document.querySelector(
|
|
584
|
-
`link[href*="fonts.googleapis.com"][href*="${
|
|
275
|
+
`link[href*="fonts.googleapis.com"][href*="${i}"]`
|
|
585
276
|
)) {
|
|
586
|
-
|
|
277
|
+
u.add(i), t();
|
|
587
278
|
return;
|
|
588
279
|
}
|
|
589
|
-
const
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
},
|
|
593
|
-
console.warn(`Failed to load Google Font: ${
|
|
594
|
-
}, document.head.appendChild(
|
|
280
|
+
const e = document.createElement("link");
|
|
281
|
+
e.rel = "stylesheet", e.href = `https://fonts.googleapis.com/css2?family=${i}:wght@400&display=swap`, e.onload = () => {
|
|
282
|
+
u.add(i), t();
|
|
283
|
+
}, e.onerror = () => {
|
|
284
|
+
console.warn(`Failed to load Google Font: ${o}`), n(new Error(`Failed to load Google Font: ${o}`));
|
|
285
|
+
}, document.head.appendChild(e);
|
|
595
286
|
});
|
|
596
287
|
}
|
|
597
|
-
function
|
|
598
|
-
return Promise.all(
|
|
288
|
+
function E(o) {
|
|
289
|
+
return Promise.all(o.map((t) => b(t)));
|
|
599
290
|
}
|
|
600
|
-
function
|
|
601
|
-
const
|
|
602
|
-
return
|
|
291
|
+
function D(o) {
|
|
292
|
+
const t = o.replace(/\s+/g, "+");
|
|
293
|
+
return u.has(t);
|
|
603
294
|
}
|
|
604
|
-
function
|
|
605
|
-
const
|
|
295
|
+
function Y(o, t = "sans-serif") {
|
|
296
|
+
const n = [
|
|
606
297
|
"Caveat",
|
|
607
298
|
"Dancing Script",
|
|
608
299
|
"Finger Paint",
|
|
@@ -621,7 +312,7 @@ function I(s, e = "sans-serif") {
|
|
|
621
312
|
"Kalam",
|
|
622
313
|
"Satisfy",
|
|
623
314
|
"Yellowtail"
|
|
624
|
-
],
|
|
315
|
+
], i = [
|
|
625
316
|
"VT323",
|
|
626
317
|
"Press Start 2P",
|
|
627
318
|
"Share Tech Mono",
|
|
@@ -629,69 +320,34 @@ function I(s, e = "sans-serif") {
|
|
|
629
320
|
"Special Elite",
|
|
630
321
|
"Cutive Mono"
|
|
631
322
|
];
|
|
632
|
-
let
|
|
633
|
-
return
|
|
634
|
-
}
|
|
635
|
-
function M(s, e) {
|
|
636
|
-
const o = s.toLowerCase(), n = e.rejectedFont.toLowerCase(), t = e.negativeAspects.map((a) => a.toLowerCase()), i = e.positiveAspects.map((a) => a.toLowerCase());
|
|
637
|
-
return y(s).filter(
|
|
638
|
-
(a) => a.googleFontsName.toLowerCase() !== n && a.name.toLowerCase() !== n
|
|
639
|
-
).map((a) => {
|
|
640
|
-
let c = 0;
|
|
641
|
-
for (const d of a.categories)
|
|
642
|
-
o.includes(d) && (c += 5);
|
|
643
|
-
for (const d of i)
|
|
644
|
-
(a.categories.some((h) => h.includes(d) || d.includes(h)) || a.name.toLowerCase().includes(d) || a.description.toLowerCase().includes(d)) && (c += 15);
|
|
645
|
-
for (const d of t)
|
|
646
|
-
(a.categories.some((h) => h.includes(d) || d.includes(h)) || a.name.toLowerCase().includes(d) || a.description.toLowerCase().includes(d)) && (c -= 20);
|
|
647
|
-
const u = i.some(
|
|
648
|
-
(d) => d.includes("striking") || d.includes("artistic") || d.includes("unique")
|
|
649
|
-
);
|
|
650
|
-
return u && a.artistic && (c += 10), u && !a.artistic && (c -= 5), { font: a, score: c };
|
|
651
|
-
}).filter((a) => a.score > 0).sort((a, c) => c.score - a.score).map((a) => a.font);
|
|
652
|
-
}
|
|
653
|
-
function Y(s, e) {
|
|
654
|
-
return M(s, e)[0];
|
|
323
|
+
let a = t;
|
|
324
|
+
return n.includes(o) ? a = "cursive" : i.includes(o) && (a = "monospace"), `'${o}', ${a}`;
|
|
655
325
|
}
|
|
656
326
|
if (typeof window < "u") {
|
|
657
|
-
const
|
|
658
|
-
AnimatedText:
|
|
659
|
-
FallingAnimation:
|
|
660
|
-
SplittingAnimation:
|
|
661
|
-
GlitchingAnimation:
|
|
662
|
-
FloatingAnimation:
|
|
663
|
-
calculateDisintegration:
|
|
664
|
-
// Font utilities
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
loadGoogleFonts: B,
|
|
670
|
-
isFontLoaded: G,
|
|
671
|
-
getFontFamily: I,
|
|
672
|
-
refineSuggestion: M,
|
|
673
|
-
refineFont: Y,
|
|
674
|
-
MOOD_CATEGORIES: H,
|
|
675
|
-
INTENSITY_CATEGORIES: R
|
|
327
|
+
const o = {
|
|
328
|
+
AnimatedText: S,
|
|
329
|
+
FallingAnimation: y,
|
|
330
|
+
SplittingAnimation: w,
|
|
331
|
+
GlitchingAnimation: C,
|
|
332
|
+
FloatingAnimation: M,
|
|
333
|
+
calculateDisintegration: F,
|
|
334
|
+
// Font utilities (core only)
|
|
335
|
+
loadGoogleFont: b,
|
|
336
|
+
loadGoogleFonts: E,
|
|
337
|
+
isFontLoaded: D,
|
|
338
|
+
getFontFamily: Y
|
|
676
339
|
};
|
|
677
|
-
window.TypographyToolkit =
|
|
340
|
+
window.TypographyToolkit = o, window.AnimatedText = S;
|
|
678
341
|
}
|
|
679
342
|
export {
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
G as isFontLoaded,
|
|
691
|
-
N as loadGoogleFont,
|
|
692
|
-
B as loadGoogleFonts,
|
|
693
|
-
Y as refineFont,
|
|
694
|
-
M as refineSuggestion,
|
|
695
|
-
P as suggestFont,
|
|
696
|
-
y as suggestFonts
|
|
343
|
+
S as AnimatedText,
|
|
344
|
+
y as FallingAnimation,
|
|
345
|
+
M as FloatingAnimation,
|
|
346
|
+
C as GlitchingAnimation,
|
|
347
|
+
w as SplittingAnimation,
|
|
348
|
+
F as calculateDisintegration,
|
|
349
|
+
Y as getFontFamily,
|
|
350
|
+
D as isFontLoaded,
|
|
351
|
+
b as loadGoogleFont,
|
|
352
|
+
E as loadGoogleFonts
|
|
697
353
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var TypographyToolkit=function(g){"use strict";class f{update(e,o,n,t={}){const i=t.speed||1,l=t.amplitude||20,r=o*.2,c=(n*10*i+r*5)%l-l/2;return{...e,y:c}}}class F{update(e,o,n,t={}){const i=t.speed||1,l=t.amplitude||4,r=o*.2,a=Math.sin(n*.5*i+r)*l;return{...e,x:a}}}class v{constructor(){this.lastUpdate=0,this.glitchX=0,this.glitchY=0,this.glitchRot=0}update(e,o,n,t={}){const i=t.amplitude||3;return n-this.lastUpdate>.1&&(this.glitchX=(Math.random()-.5)*i,this.glitchY=(Math.random()-.5)*(i*.67),this.glitchRot=(Math.random()-.5)*i,this.lastUpdate=n),{...e,x:this.glitchX,y:this.glitchY,rotation:this.glitchRot}}}class S{update(e,o,n,t={}){const i=t.speed||1,l=t.amplitude||15,r=o*.2,c=-((n*8*i+r*4)%l-l/2);return{...e,y:c}}}function G(s,e){const{x:o,y:n,rotation:t,scale:i,opacity:l}=e;s.style.transform=`translate(${o}px, ${n}px) rotate(${t}deg) scale(${i})`,s.style.opacity=l.toString()}function C(s,e,o,n,t,i){if(!i.enabled)return{state:{x:0,y:0,rotation:0,scale:1,opacity:1},applied:!1};const l=i.radius||80,r=i.strength||1,a=i.behaviors||["fall-away","split-apart","explode"],c=o-s,h=n-e,d=Math.sqrt(c*c+h*h);if(d>=l)return{state:{x:0,y:0,rotation:0,scale:1,opacity:1},applied:!1};const u=(1-d/l)*r,m=Math.atan2(h,c),B=a[t%a.length];let p;switch(B){case"fall-away":const Y=Math.cos(m)*u*20,$=Math.sin(m)*u*40+u*30;p={x:Y,y:$,rotation:u*15,scale:1,opacity:1-u*.6};break;case"split-apart":const L=t%2===0?1:-1;p={x:L*u*50,y:(Math.random()-.5)*u*10,rotation:u*10*L,scale:1,opacity:1-u*.6};break;case"explode":const O=m+(Math.random()-.5)*.5;p={x:Math.cos(O)*u*40,y:Math.sin(O)*u*40,rotation:u*30,scale:1+u*.4,opacity:1-u*.6};break;default:p={x:0,y:0,rotation:0,scale:1,opacity:1}}return{state:p,applied:!0}}class b{constructor(e){var o;if(this.letters=[],this.animationSpeedMultiplier=1,this.animationFrame=null,this.mouseX=0,this.mouseY=0,this.mouseMoveHandler=null,this.startTime=Date.now(),this.isDestroyed=!1,this.container=e.container,this.animationTypes=e.animations||["falling","splitting","glitching","floating"],this.cycle=e.cycle!==!1,this.speed=e.speed||1,this.amplitude=e.amplitude||1,this.animationEasing=e.animationEasing||"linear",this.disintegration=e.disintegration||{enabled:!1},this.style=e.style||{},this.fadeOut=e.fadeOut||0,this.callbacks=e.callbacks,e.animationSpeed!==void 0&&(this.animationSpeedMultiplier=this.parseAnimationSpeed(e.animationSpeed)),this.textContainer=document.createElement("div"),this.textContainer.style.position="absolute",this.textContainer.style.pointerEvents="none",this.textContainer.style.zIndex="1",e.containerClass&&(this.textContainer.className=e.containerClass),e.containerStyle&&Object.entries(e.containerStyle).forEach(([n,t])=>{this.textContainer.style.setProperty(n,t)}),e.position){let n=e.position.x,t=e.position.y;if(e.position.constrainToViewport){this.container.getBoundingClientRect();const i=window.innerWidth,l=window.innerHeight,r=e.text.length*20;n!==void 0&&(n=Math.max(0,Math.min(n,i-r))),t!==void 0&&(t=Math.max(0,Math.min(t,l-50)))}n!==void 0&&(this.textContainer.style.left=`${n}px`),t!==void 0&&(this.textContainer.style.top=`${t}px`)}this.createLetters(e.text),this.setupMouseTracking(),this.startAnimation(),(o=this.callbacks)!=null&&o.onCreate&&this.callbacks.onCreate(this.textContainer),this.fadeOut>0&&setTimeout(()=>this.destroy(),this.fadeOut)}createLetters(e){e.toUpperCase().split("").forEach((n,t)=>{if(n===" "){const r=document.createTextNode(" ");this.textContainer.appendChild(r);return}const i=document.createElement("span");i.className="animated-letter",i.textContent=n,i.dataset.index=t.toString(),i.dataset.char=n,this.applyStyle(i),i.style.display="inline-block",i.style.position="relative",i.style.transition="transform 0.1s ease-out",this.textContainer.appendChild(i);const l=i.getBoundingClientRect();this.letters.push({element:i,index:t,char:n,baseX:l.left,baseY:l.top})}),this.container.appendChild(this.textContainer)}applyStyle(e){this.style.fontFamily&&(e.style.fontFamily=this.style.fontFamily),this.style.fontSize&&(e.style.fontSize=`${this.style.fontSize}px`),this.style.color&&(e.style.color=this.style.color),this.style.fontWeight&&(e.style.fontWeight=this.style.fontWeight),this.style.textShadow&&(e.style.textShadow=this.style.textShadow),this.style.letterSpacing&&(e.style.letterSpacing=this.style.letterSpacing),this.style.textTransform&&(e.style.textTransform=this.style.textTransform)}setupMouseTracking(){this.disintegration.enabled&&(this.mouseMoveHandler=e=>{this.mouseX=e.clientX,this.mouseY=e.clientY},document.addEventListener("mousemove",this.mouseMoveHandler))}startAnimation(){const e=()=>{if(this.isDestroyed)return;const o=(Date.now()-this.startTime)*.001;this.letters.forEach((n,t)=>{var h;const i=n.element.getBoundingClientRect(),l=i.left+i.width/2,r=i.top+i.height/2,a=C(l,r,this.mouseX,this.mouseY,t,this.disintegration);let c;if(a.applied)c=a.state,(h=this.callbacks)!=null&&h.onDisintegrate&&this.callbacks.onDisintegrate(t);else{const d=this.getAnimationType(t);c=this.getAnimation(d).update({x:0,y:0,rotation:0,scale:1,opacity:1},t,o,{speed:this.speed*this.animationSpeedMultiplier,amplitude:this.amplitude*(d==="falling"||d==="floating"?20:4)})}G(n.element,c)}),this.animationFrame=requestAnimationFrame(e)};this.animationFrame=requestAnimationFrame(e)}getAnimationType(e){return this.cycle?this.animationTypes[e%this.animationTypes.length]:this.animationTypes[0]}getAnimation(e){switch(e){case"falling":return new f;case"splitting":return new F;case"glitching":return new v;case"floating":return new S;default:return new f}}parseAnimationSpeed(e){if(typeof e=="number")return e;switch(e){case"slow":return .5;case"normal":return 1;case"fast":return 2;default:return 1}}getAnimationSpeed(){return this.animationSpeedMultiplier}setAnimationSpeed(e){this.animationSpeedMultiplier=this.parseAnimationSpeed(e)}getAnimationEasing(){return this.animationEasing}setAnimationEasing(e){this.animationEasing=e}destroy(){var e;this.isDestroyed||(this.isDestroyed=!0,this.animationFrame!==null&&cancelAnimationFrame(this.animationFrame),this.mouseMoveHandler&&document.removeEventListener("mousemove",this.mouseMoveHandler),(e=this.callbacks)!=null&&e.onDestroy&&this.callbacks.onDestroy(),this.textContainer.style.transition="opacity 3s ease",this.textContainer.style.opacity="0",setTimeout(()=>{this.textContainer.parentNode&&this.textContainer.parentNode.removeChild(this.textContainer)},3e3))}getElement(){return this.textContainer}}const A=["unsettling","eerie","decayed","weathered","organic","imperfect","uneven","scratchy"],x=["subtle","moderate","intense"],k=[{name:"Hand-drawn Casual",googleFontsName:"Caveat",categories:["hand-drawn","handwriting","casual","sketchy","informal"],description:"Casual handwritten style, friendly and approachable",artistic:!1},{name:"Hand-drawn Playful",googleFontsName:"Finger Paint",categories:["hand-drawn","playful","childlike","casual","sketchy"],description:"Bold hand-drawn style, playful and energetic",artistic:!0},{name:"Hand-drawn Script",googleFontsName:"Dancing Script",categories:["hand-drawn","script","elegant","flowing","cursive"],description:"Elegant flowing script, graceful and organic",artistic:!1},{name:"Gothic Blackletter",googleFontsName:"UnifrakturMaguntia",categories:["gothic","medieval","blackletter","ornate","historical"],description:"Medieval blackletter style, ornate and historical",artistic:!0},{name:"Gothic Horror",googleFontsName:"Creepster",categories:["gothic","horror","creepy","dripping","display","striking","intense"],description:"Horror-style font with dripping effects, very striking",artistic:!0},{name:"Gothic Bold",googleFontsName:"Eater",categories:["gothic","bold","aggressive","display","striking"],description:"Bold aggressive display font, powerful impact",artistic:!0},{name:"Futuristic Digital",googleFontsName:"Orbitron",categories:["futuristic","sci-fi","digital","tech","modern","geometric"],description:"Futuristic geometric font, tech-forward and modern",artistic:!0},{name:"Futuristic Display",googleFontsName:"Bungee",categories:["futuristic","display","bold","condensed","striking"],description:"Bold condensed display font, high impact",artistic:!0},{name:"Futuristic Outline",googleFontsName:"Bungee Shade",categories:["futuristic","outline","display","bold","striking"],description:"Outlined version of Bungee, bold and striking",artistic:!0},{name:"Retro Terminal",googleFontsName:"VT323",categories:["retro","terminal","monospace","pixel","80s","tech"],description:"Retro terminal font, pixelated and nostalgic",artistic:!0},{name:"Retro Pixel",googleFontsName:"Press Start 2P",categories:["retro","pixel","8-bit","arcade","nostalgic","display"],description:"8-bit pixel font, classic arcade style",artistic:!0},{name:"Retro Display",googleFontsName:"Frijole",categories:["retro","playful","rounded","display","casual"],description:"Playful rounded retro font, fun and casual",artistic:!0},{name:"Decorative Ornate",googleFontsName:"Fascinate",categories:["decorative","ornate","display","striking","elaborate"],description:"Highly decorative display font, ornate and elaborate",artistic:!0},{name:"Decorative Outline",googleFontsName:"Fascinate Inline",categories:["decorative","outline","display","ornate","striking"],description:"Outlined decorative font, ornate and striking",artistic:!0},{name:"Decorative Script",googleFontsName:"Fredericka the Great",categories:["decorative","script","ornate","elegant","display"],description:"Elegant decorative script, ornate and sophisticated",artistic:!0},{name:"Horror Dripping",googleFontsName:"Nosifer",categories:["horror","creepy","dripping","blood","striking","display","intense"],description:"Creepy font with blood-dripping effects, very striking",artistic:!0},{name:"Tech Monospace",googleFontsName:"Share Tech Mono",categories:["tech","monospace","terminal","code","modern"],description:"Clean tech monospace font, modern and readable",artistic:!1},{name:"Tech Display",googleFontsName:"Rajdhani",categories:["tech","modern","geometric","sans-serif","futuristic"],description:"Modern geometric tech font, clean and futuristic",artistic:!1},{name:"Organic Flowing",googleFontsName:"Dancing Script",categories:["organic","flowing","natural","script","elegant"],description:"Flowing organic script, natural and elegant",artistic:!1},{name:"Modern Sans",googleFontsName:"Roboto",categories:["modern","clean","sans-serif","readable","professional"],description:"Clean modern sans-serif, professional and readable",artistic:!1},{name:"Modern Serif",googleFontsName:"Playfair Display",categories:["modern","serif","elegant","sophisticated","readable"],description:"Elegant modern serif, sophisticated and readable",artistic:!1},{name:"Bold Condensed",googleFontsName:"Bungee",categories:["bold","condensed","display","striking","impact"],description:"Bold condensed display font, high impact",artistic:!0},{name:"Bold Aggressive",googleFontsName:"Eater",categories:["bold","aggressive","display","striking","powerful"],description:"Bold aggressive display font, powerful and striking",artistic:!0},{name:"Handwritten Thin",googleFontsName:"Amatic SC",categories:["hand-drawn","uneven","organic","unsettling","subtle","scratchy"],description:"Thin hand-drawn letters with subtle irregularity, organic feel",artistic:!0},{name:"Rough Handwriting",googleFontsName:"Rock Salt",categories:["hand-drawn","scratchy","weathered","rough","unsettling","moderate"],description:"Rough, weathered handwriting with natural imperfection",artistic:!0},{name:"Typewriter Degraded",googleFontsName:"Special Elite",categories:["typewriter","decayed","weathered","imperfect","unsettling","moderate"],description:"Degraded typewriter font, vintage with imperfection",artistic:!0},{name:"Casual Handwriting",googleFontsName:"Handlee",categories:["hand-drawn","casual","imperfect","organic","subtle"],description:"Casual handwriting with subtle imperfection",artistic:!1},{name:"Childlike Organic",googleFontsName:"Indie Flower",categories:["hand-drawn","childlike","organic","imperfect","eerie","subtle"],description:"Childlike handwriting, can feel innocent or eerie depending on context",artistic:!1},{name:"Scratchy Personal",googleFontsName:"Shadows Into Light",categories:["hand-drawn","scratchy","personal","unsettling","uneven","moderate"],description:"Scratchy personal handwriting with unsettling quality",artistic:!0},{name:"Hurried Scratchy",googleFontsName:"Reenie Beanie",categories:["hand-drawn","scratchy","hurried","uneven","unsettling","moderate"],description:"Hurried scratchy handwriting with nervous energy",artistic:!0},{name:"Architectural Irregular",googleFontsName:"Architects Daughter",categories:["hand-drawn","imperfect","uneven","organic","subtle"],description:"Hand-drawn with architectural irregularity",artistic:!1},{name:"Informal Unsettling",googleFontsName:"Coming Soon",categories:["hand-drawn","informal","imperfect","unsettling","subtle"],description:"Informal handwriting that feels slightly off",artistic:!1},{name:"Manic Handwriting",googleFontsName:"Gloria Hallelujah",categories:["hand-drawn","playful","manic","uneven","unsettling","moderate"],description:"Playful handwriting that can feel manic or unsettled",artistic:!0},{name:"Quick Imperfect",googleFontsName:"Just Another Hand",categories:["hand-drawn","scratchy","quick","imperfect","uneven","subtle"],description:"Quick scratchy handwriting with natural imperfection",artistic:!1},{name:"Organic Handwriting",googleFontsName:"Kalam",categories:["hand-drawn","organic","natural","flowing","subtle"],description:"Organic natural handwriting with flowing quality",artistic:!1},{name:"Flowing Tension",googleFontsName:"Satisfy",categories:["script","flowing","tension","elegant","unsettling","subtle"],description:"Flowing script with underlying tension",artistic:!0},{name:"Unsettling Elegance",googleFontsName:"Yellowtail",categories:["script","elegant","stylized","unsettling","uneven","moderate"],description:"Stylized elegance with unsettling undertones",artistic:!0},{name:"Typewriter Imperfect",googleFontsName:"Cutive Mono",categories:["typewriter","monospace","imperfect","decayed","vintage","subtle"],description:"Imperfect vintage typewriter with character",artistic:!0}];function I(s){const e=s.toLowerCase().split(/\s+/).filter(t=>t.length>0),o=[],n=[];for(const t of e)t.startsWith("-")&&t.length>1?n.push(t.slice(1)):o.push(t);return{positive:o,negative:n}}function P(s,e){const o=new Set,n=new Map,t=2,i=[];for(const l of s){if(i.length>=e)break;if(o.has(l.font.googleFontsName))continue;const r=l.font.categories[0],a=n.get(r)||0;a>=t||(o.add(l.font.googleFontsName),n.set(r,a+1),i.push(l.font))}return i}function y(s,e){const{positive:o,negative:n}=I(s),t=(e==null?void 0:e.limit)??10,l=k.map(r=>{let a=0;for(const c of o){for(const h of r.categories)(h.includes(c)||c.includes(h))&&(a+=10);r.name.toLowerCase().includes(c)&&(a+=15),r.description.toLowerCase().includes(c)&&(a+=8)}for(const c of n){for(const h of r.categories)(h.includes(c)||c.includes(h))&&(a-=20);r.name.toLowerCase().includes(c)&&(a-=15),r.description.toLowerCase().includes(c)&&(a-=10)}return r.artistic&&(a+=1),{font:r,score:a}}).filter(r=>r.score>0).sort((r,a)=>a.score-r.score);return P(l,t)}function M(s){return y(s)[0]}const w=new Set;function N(s){return new Promise((e,o)=>{const n=s.replace(/\s+/g,"+");if(w.has(n)){e();return}if(document.querySelector(`link[href*="fonts.googleapis.com"][href*="${n}"]`)){w.add(n),e();return}const i=document.createElement("link");i.rel="stylesheet",i.href=`https://fonts.googleapis.com/css2?family=${n}:wght@400&display=swap`,i.onload=()=>{w.add(n),e()},i.onerror=()=>{console.warn(`Failed to load Google Font: ${s}`),o(new Error(`Failed to load Google Font: ${s}`))},document.head.appendChild(i)})}function E(s){return Promise.all(s.map(e=>N(e)))}function D(s){const e=s.replace(/\s+/g,"+");return w.has(e)}function H(s,e="sans-serif"){const o=["Caveat","Dancing Script","Finger Paint","Fredericka the Great","Amatic SC","Handlee","Indie Flower","Shadows Into Light","Rock Salt","Reenie Beanie","Architects Daughter","Coming Soon","Gloria Hallelujah","Just Another Hand","Kalam","Satisfy","Yellowtail"],n=["VT323","Press Start 2P","Share Tech Mono","Special Elite","Cutive Mono"];let t=e;return o.includes(s)?t="cursive":n.includes(s)&&(t="monospace"),`'${s}', ${t}`}function T(s,e){const o=s.toLowerCase(),n=e.rejectedFont.toLowerCase(),t=e.negativeAspects.map(a=>a.toLowerCase()),i=e.positiveAspects.map(a=>a.toLowerCase());return y(s).filter(a=>a.googleFontsName.toLowerCase()!==n&&a.name.toLowerCase()!==n).map(a=>{let c=0;for(const d of a.categories)o.includes(d)&&(c+=5);for(const d of i)(a.categories.some(m=>m.includes(d)||d.includes(m))||a.name.toLowerCase().includes(d)||a.description.toLowerCase().includes(d))&&(c+=15);for(const d of t)(a.categories.some(m=>m.includes(d)||d.includes(m))||a.name.toLowerCase().includes(d)||a.description.toLowerCase().includes(d))&&(c-=20);const h=i.some(d=>d.includes("striking")||d.includes("artistic")||d.includes("unique"));return h&&a.artistic&&(c+=10),h&&!a.artistic&&(c-=5),{font:a,score:c}}).filter(a=>a.score>0).sort((a,c)=>c.score-a.score).map(a=>a.font)}function R(s,e){return T(s,e)[0]}if(typeof window<"u"){const s={AnimatedText:b,FallingAnimation:f,SplittingAnimation:F,GlitchingAnimation:v,FloatingAnimation:S,calculateDisintegration:C,fontSuggestions:k,suggestFonts:y,suggestFont:M,loadGoogleFont:N,loadGoogleFonts:E,isFontLoaded:D,getFontFamily:H,refineSuggestion:T,refineFont:R,MOOD_CATEGORIES:A,INTENSITY_CATEGORIES:x};window.TypographyToolkit=s,window.AnimatedText=b}return g.AnimatedText=b,g.FallingAnimation=f,g.FloatingAnimation=S,g.GlitchingAnimation=v,g.INTENSITY_CATEGORIES=x,g.MOOD_CATEGORIES=A,g.SplittingAnimation=F,g.calculateDisintegration=C,g.fontSuggestions=k,g.getFontFamily=H,g.isFontLoaded=D,g.loadGoogleFont=N,g.loadGoogleFonts=E,g.refineFont=R,g.refineSuggestion=T,g.suggestFont=M,g.suggestFonts=y,Object.defineProperty(g,Symbol.toStringTag,{value:"Module"}),g}({});
|
|
1
|
+
var TypographyToolkit=function(c){"use strict";class f{update(t,a,i,n={}){const e=n.speed||1,l=n.amplitude||20,s=a*.2,d=(i*10*e+s*5)%l-l/2;return{...t,y:d}}}class y{update(t,a,i,n={}){const e=n.speed||1,l=n.amplitude||4,s=a*.2,h=Math.sin(i*.5*e+s)*l;return{...t,x:h}}}class S{constructor(){this.letterStates=new Map}update(t,a,i,n={}){const e=n.amplitude||3,l=n.speed||1;let s=this.letterStates.get(a);s||(s={lastUpdate:i,glitchX:0,glitchY:0,glitchRot:0},this.letterStates.set(a,s));const h=.1/l;return i-s.lastUpdate>h&&(s.glitchX=(Math.random()-.5)*e,s.glitchY=(Math.random()-.5)*(e*.67),s.glitchRot=(Math.random()-.5)*e,s.lastUpdate=i),{...t,x:s.glitchX,y:s.glitchY,rotation:s.glitchRot}}}class x{update(t,a,i,n={}){const e=n.speed||1,l=n.amplitude||15,s=a*.2,d=-((i*8*e+s*4)%l-l/2);return{...t,y:d}}}function E(o,t){const{x:a,y:i,rotation:n,scale:e,opacity:l}=t;o.style.transform=`translate(${a}px, ${i}px) rotate(${n}deg) scale(${e})`,o.style.opacity=l.toString()}function w(o,t,a,i,n,e){if(!e.enabled)return{state:{x:0,y:0,rotation:0,scale:1,opacity:1},applied:!1};const l=e.radius||80,s=e.strength||1,h=e.behaviors||["fall-away","split-apart","explode"],d=a-o,m=i-t,u=Math.sqrt(d*d+m*m);if(u>=l)return{state:{x:0,y:0,rotation:0,scale:1,opacity:1},applied:!1};const r=(1-u/l)*s,M=Math.atan2(m,d),D=h[n%h.length];let p;switch(D){case"fall-away":const Y=Math.cos(M)*r*20,$=Math.sin(M)*r*40+r*30;p={x:Y,y:$,rotation:r*15,scale:1,opacity:1-r*.6};break;case"split-apart":const k=n%2===0?1:-1;p={x:k*r*50,y:(Math.random()-.5)*r*10,rotation:r*10*k,scale:1,opacity:1-r*.6};break;case"explode":const v=M+(Math.random()-.5)*.5;p={x:Math.cos(v)*r*40,y:Math.sin(v)*r*40,rotation:r*30,scale:1+r*.4,opacity:1-r*.6};break;default:p={x:0,y:0,rotation:0,scale:1,opacity:1}}return{state:p,applied:!0}}class C{constructor(t){var a;if(this.letters=[],this.animationSpeedMultiplier=1,this.animationFrame=null,this.mouseX=0,this.mouseY=0,this.mouseMoveHandler=null,this.startTime=Date.now(),this.isDestroyed=!1,this.animationInstances=new Map,this.container=t.container,this.animationTypes=t.animations||["falling","splitting","glitching","floating"],this.cycle=t.cycle!==!1,this.speed=t.speed||1,this.amplitude=t.amplitude||1,this.animationEasing=t.animationEasing||"linear",this.disintegration=t.disintegration||{enabled:!1},this.style=t.style||{},this.fadeOut=t.fadeOut||0,this.callbacks=t.callbacks,t.animationSpeed!==void 0&&(this.animationSpeedMultiplier=this.parseAnimationSpeed(t.animationSpeed)),this.textContainer=document.createElement("div"),this.textContainer.style.position="absolute",this.textContainer.style.pointerEvents="none",this.textContainer.style.zIndex="1",t.containerClass&&(this.textContainer.className=t.containerClass),t.containerStyle&&Object.entries(t.containerStyle).forEach(([i,n])=>{this.textContainer.style.setProperty(i,n)}),t.position){let i=t.position.x,n=t.position.y;if(t.position.constrainToViewport){this.container.getBoundingClientRect();const e=window.innerWidth,l=window.innerHeight,s=t.text.length*20;i!==void 0&&(i=Math.max(0,Math.min(i,e-s))),n!==void 0&&(n=Math.max(0,Math.min(n,l-50)))}i!==void 0&&(this.textContainer.style.left=`${i}px`),n!==void 0&&(this.textContainer.style.top=`${n}px`)}this.createLetters(t.text),this.setupMouseTracking(),this.startAnimation(),(a=this.callbacks)!=null&&a.onCreate&&this.callbacks.onCreate(this.textContainer),this.fadeOut>0&&setTimeout(()=>this.destroy(),this.fadeOut)}createLetters(t){t.toUpperCase().split("").forEach((i,n)=>{if(i===" "){const s=document.createTextNode(" ");this.textContainer.appendChild(s);return}const e=document.createElement("span");e.className="animated-letter",e.textContent=i,e.dataset.index=n.toString(),e.dataset.char=i,this.applyStyle(e),e.style.display="inline-block",e.style.position="relative",e.style.transition="transform 0.1s ease-out",this.textContainer.appendChild(e);const l=e.getBoundingClientRect();this.letters.push({element:e,index:n,char:i,baseX:l.left,baseY:l.top})}),this.container.appendChild(this.textContainer)}applyStyle(t){this.style.fontFamily&&(t.style.fontFamily=this.style.fontFamily),this.style.fontSize&&(t.style.fontSize=`${this.style.fontSize}px`),this.style.color&&(t.style.color=this.style.color),this.style.fontWeight&&(t.style.fontWeight=this.style.fontWeight),this.style.textShadow&&(t.style.textShadow=this.style.textShadow),this.style.letterSpacing&&(t.style.letterSpacing=this.style.letterSpacing),this.style.textTransform&&(t.style.textTransform=this.style.textTransform)}setupMouseTracking(){this.disintegration.enabled&&(this.mouseMoveHandler=t=>{this.mouseX=t.clientX,this.mouseY=t.clientY},document.addEventListener("mousemove",this.mouseMoveHandler))}startAnimation(){const t=()=>{if(this.isDestroyed)return;const a=(Date.now()-this.startTime)*.001;this.letters.forEach((i,n)=>{var m;const e=i.element.getBoundingClientRect(),l=e.left+e.width/2,s=e.top+e.height/2,h=w(l,s,this.mouseX,this.mouseY,n,this.disintegration);let d;if(h.applied)d=h.state,(m=this.callbacks)!=null&&m.onDisintegrate&&this.callbacks.onDisintegrate(n);else{const u=this.getAnimationType(n);d=this.getAnimation(u).update({x:0,y:0,rotation:0,scale:1,opacity:1},n,a,{speed:this.speed*this.animationSpeedMultiplier,amplitude:this.amplitude*(u==="falling"||u==="floating"?20:4)})}E(i.element,d)}),this.animationFrame=requestAnimationFrame(t)};this.animationFrame=requestAnimationFrame(t)}getAnimationType(t){return this.cycle?this.animationTypes[t%this.animationTypes.length]:this.animationTypes[0]}getAnimation(t){if(this.animationInstances.has(t))return this.animationInstances.get(t);let a;switch(t){case"falling":a=new f;break;case"splitting":a=new y;break;case"glitching":a=new S;break;case"floating":a=new x;break;default:a=new f}return this.animationInstances.set(t,a),a}parseAnimationSpeed(t){if(typeof t=="number")return t;switch(t){case"slow":return .5;case"normal":return 1;case"fast":return 2;default:return 1}}getAnimationSpeed(){return this.animationSpeedMultiplier}setAnimationSpeed(t){this.animationSpeedMultiplier=this.parseAnimationSpeed(t)}getAnimationEasing(){return this.animationEasing}setAnimationEasing(t){this.animationEasing=t}destroy(){var t;this.isDestroyed||(this.isDestroyed=!0,this.animationFrame!==null&&cancelAnimationFrame(this.animationFrame),this.mouseMoveHandler&&document.removeEventListener("mousemove",this.mouseMoveHandler),this.animationInstances.clear(),(t=this.callbacks)!=null&&t.onDestroy&&this.callbacks.onDestroy(),this.textContainer.style.transition="opacity 3s ease",this.textContainer.style.opacity="0",setTimeout(()=>{this.textContainer.parentNode&&this.textContainer.parentNode.removeChild(this.textContainer)},3e3))}getElement(){return this.textContainer}}const g=new Set;function F(o){return new Promise((t,a)=>{const i=o.replace(/\s+/g,"+");if(g.has(i)){t();return}if(document.querySelector(`link[href*="fonts.googleapis.com"][href*="${i}"]`)){g.add(i),t();return}const e=document.createElement("link");e.rel="stylesheet",e.href=`https://fonts.googleapis.com/css2?family=${i}:wght@400&display=swap`,e.onload=()=>{g.add(i),t()},e.onerror=()=>{console.warn(`Failed to load Google Font: ${o}`),a(new Error(`Failed to load Google Font: ${o}`))},document.head.appendChild(e)})}function A(o){return Promise.all(o.map(t=>F(t)))}function T(o){const t=o.replace(/\s+/g,"+");return g.has(t)}function b(o,t="sans-serif"){const a=["Caveat","Dancing Script","Finger Paint","Fredericka the Great","Amatic SC","Handlee","Indie Flower","Shadows Into Light","Rock Salt","Reenie Beanie","Architects Daughter","Coming Soon","Gloria Hallelujah","Just Another Hand","Kalam","Satisfy","Yellowtail"],i=["VT323","Press Start 2P","Share Tech Mono","Special Elite","Cutive Mono"];let n=t;return a.includes(o)?n="cursive":i.includes(o)&&(n="monospace"),`'${o}', ${n}`}if(typeof window<"u"){const o={AnimatedText:C,FallingAnimation:f,SplittingAnimation:y,GlitchingAnimation:S,FloatingAnimation:x,calculateDisintegration:w,loadGoogleFont:F,loadGoogleFonts:A,isFontLoaded:T,getFontFamily:b};window.TypographyToolkit=o,window.AnimatedText=C}return c.AnimatedText=C,c.FallingAnimation=f,c.FloatingAnimation=x,c.GlitchingAnimation=S,c.SplittingAnimation=y,c.calculateDisintegration=w,c.getFontFamily=b,c.isFontLoaded=T,c.loadGoogleFont=F,c.loadGoogleFonts=A,Object.defineProperty(c,Symbol.toStringTag,{value:"Module"}),c}({});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
(function(d,p){typeof exports=="object"&&typeof module<"u"?p(exports):typeof define=="function"&&define.amd?define(["exports"],p):(d=typeof globalThis<"u"?globalThis:d||self,p(d.TypographyToolkit={}))})(this,function(d){"use strict";class p{update(e,o,n,t={}){const i=t.speed||1,l=t.amplitude||20,r=o*.2,c=(n*10*i+r*5)%l-l/2;return{...e,y:c}}}class F{update(e,o,n,t={}){const i=t.speed||1,l=t.amplitude||4,r=o*.2,a=Math.sin(n*.5*i+r)*l;return{...e,x:a}}}class S{constructor(){this.lastUpdate=0,this.glitchX=0,this.glitchY=0,this.glitchRot=0}update(e,o,n,t={}){const i=t.amplitude||3;return n-this.lastUpdate>.1&&(this.glitchX=(Math.random()-.5)*i,this.glitchY=(Math.random()-.5)*(i*.67),this.glitchRot=(Math.random()-.5)*i,this.lastUpdate=n),{...e,x:this.glitchX,y:this.glitchY,rotation:this.glitchRot}}}class v{update(e,o,n,t={}){const i=t.speed||1,l=t.amplitude||15,r=o*.2,c=-((n*8*i+r*4)%l-l/2);return{...e,y:c}}}function G(s,e){const{x:o,y:n,rotation:t,scale:i,opacity:l}=e;s.style.transform=`translate(${o}px, ${n}px) rotate(${t}deg) scale(${i})`,s.style.opacity=l.toString()}function C(s,e,o,n,t,i){if(!i.enabled)return{state:{x:0,y:0,rotation:0,scale:1,opacity:1},applied:!1};const l=i.radius||80,r=i.strength||1,a=i.behaviors||["fall-away","split-apart","explode"],c=o-s,h=n-e,g=Math.sqrt(c*c+h*h);if(g>=l)return{state:{x:0,y:0,rotation:0,scale:1,opacity:1},applied:!1};const u=(1-g/l)*r,m=Math.atan2(h,c),B=a[t%a.length];let f;switch(B){case"fall-away":const Y=Math.cos(m)*u*20,$=Math.sin(m)*u*40+u*30;f={x:Y,y:$,rotation:u*15,scale:1,opacity:1-u*.6};break;case"split-apart":const L=t%2===0?1:-1;f={x:L*u*50,y:(Math.random()-.5)*u*10,rotation:u*10*L,scale:1,opacity:1-u*.6};break;case"explode":const O=m+(Math.random()-.5)*.5;f={x:Math.cos(O)*u*40,y:Math.sin(O)*u*40,rotation:u*30,scale:1+u*.4,opacity:1-u*.6};break;default:f={x:0,y:0,rotation:0,scale:1,opacity:1}}return{state:f,applied:!0}}class b{constructor(e){var o;if(this.letters=[],this.animationSpeedMultiplier=1,this.animationFrame=null,this.mouseX=0,this.mouseY=0,this.mouseMoveHandler=null,this.startTime=Date.now(),this.isDestroyed=!1,this.container=e.container,this.animationTypes=e.animations||["falling","splitting","glitching","floating"],this.cycle=e.cycle!==!1,this.speed=e.speed||1,this.amplitude=e.amplitude||1,this.animationEasing=e.animationEasing||"linear",this.disintegration=e.disintegration||{enabled:!1},this.style=e.style||{},this.fadeOut=e.fadeOut||0,this.callbacks=e.callbacks,e.animationSpeed!==void 0&&(this.animationSpeedMultiplier=this.parseAnimationSpeed(e.animationSpeed)),this.textContainer=document.createElement("div"),this.textContainer.style.position="absolute",this.textContainer.style.pointerEvents="none",this.textContainer.style.zIndex="1",e.containerClass&&(this.textContainer.className=e.containerClass),e.containerStyle&&Object.entries(e.containerStyle).forEach(([n,t])=>{this.textContainer.style.setProperty(n,t)}),e.position){let n=e.position.x,t=e.position.y;if(e.position.constrainToViewport){this.container.getBoundingClientRect();const i=window.innerWidth,l=window.innerHeight,r=e.text.length*20;n!==void 0&&(n=Math.max(0,Math.min(n,i-r))),t!==void 0&&(t=Math.max(0,Math.min(t,l-50)))}n!==void 0&&(this.textContainer.style.left=`${n}px`),t!==void 0&&(this.textContainer.style.top=`${t}px`)}this.createLetters(e.text),this.setupMouseTracking(),this.startAnimation(),(o=this.callbacks)!=null&&o.onCreate&&this.callbacks.onCreate(this.textContainer),this.fadeOut>0&&setTimeout(()=>this.destroy(),this.fadeOut)}createLetters(e){e.toUpperCase().split("").forEach((n,t)=>{if(n===" "){const r=document.createTextNode(" ");this.textContainer.appendChild(r);return}const i=document.createElement("span");i.className="animated-letter",i.textContent=n,i.dataset.index=t.toString(),i.dataset.char=n,this.applyStyle(i),i.style.display="inline-block",i.style.position="relative",i.style.transition="transform 0.1s ease-out",this.textContainer.appendChild(i);const l=i.getBoundingClientRect();this.letters.push({element:i,index:t,char:n,baseX:l.left,baseY:l.top})}),this.container.appendChild(this.textContainer)}applyStyle(e){this.style.fontFamily&&(e.style.fontFamily=this.style.fontFamily),this.style.fontSize&&(e.style.fontSize=`${this.style.fontSize}px`),this.style.color&&(e.style.color=this.style.color),this.style.fontWeight&&(e.style.fontWeight=this.style.fontWeight),this.style.textShadow&&(e.style.textShadow=this.style.textShadow),this.style.letterSpacing&&(e.style.letterSpacing=this.style.letterSpacing),this.style.textTransform&&(e.style.textTransform=this.style.textTransform)}setupMouseTracking(){this.disintegration.enabled&&(this.mouseMoveHandler=e=>{this.mouseX=e.clientX,this.mouseY=e.clientY},document.addEventListener("mousemove",this.mouseMoveHandler))}startAnimation(){const e=()=>{if(this.isDestroyed)return;const o=(Date.now()-this.startTime)*.001;this.letters.forEach((n,t)=>{var h;const i=n.element.getBoundingClientRect(),l=i.left+i.width/2,r=i.top+i.height/2,a=C(l,r,this.mouseX,this.mouseY,t,this.disintegration);let c;if(a.applied)c=a.state,(h=this.callbacks)!=null&&h.onDisintegrate&&this.callbacks.onDisintegrate(t);else{const g=this.getAnimationType(t);c=this.getAnimation(g).update({x:0,y:0,rotation:0,scale:1,opacity:1},t,o,{speed:this.speed*this.animationSpeedMultiplier,amplitude:this.amplitude*(g==="falling"||g==="floating"?20:4)})}G(n.element,c)}),this.animationFrame=requestAnimationFrame(e)};this.animationFrame=requestAnimationFrame(e)}getAnimationType(e){return this.cycle?this.animationTypes[e%this.animationTypes.length]:this.animationTypes[0]}getAnimation(e){switch(e){case"falling":return new p;case"splitting":return new F;case"glitching":return new S;case"floating":return new v;default:return new p}}parseAnimationSpeed(e){if(typeof e=="number")return e;switch(e){case"slow":return .5;case"normal":return 1;case"fast":return 2;default:return 1}}getAnimationSpeed(){return this.animationSpeedMultiplier}setAnimationSpeed(e){this.animationSpeedMultiplier=this.parseAnimationSpeed(e)}getAnimationEasing(){return this.animationEasing}setAnimationEasing(e){this.animationEasing=e}destroy(){var e;this.isDestroyed||(this.isDestroyed=!0,this.animationFrame!==null&&cancelAnimationFrame(this.animationFrame),this.mouseMoveHandler&&document.removeEventListener("mousemove",this.mouseMoveHandler),(e=this.callbacks)!=null&&e.onDestroy&&this.callbacks.onDestroy(),this.textContainer.style.transition="opacity 3s ease",this.textContainer.style.opacity="0",setTimeout(()=>{this.textContainer.parentNode&&this.textContainer.parentNode.removeChild(this.textContainer)},3e3))}getElement(){return this.textContainer}}const x=["unsettling","eerie","decayed","weathered","organic","imperfect","uneven","scratchy"],A=["subtle","moderate","intense"],k=[{name:"Hand-drawn Casual",googleFontsName:"Caveat",categories:["hand-drawn","handwriting","casual","sketchy","informal"],description:"Casual handwritten style, friendly and approachable",artistic:!1},{name:"Hand-drawn Playful",googleFontsName:"Finger Paint",categories:["hand-drawn","playful","childlike","casual","sketchy"],description:"Bold hand-drawn style, playful and energetic",artistic:!0},{name:"Hand-drawn Script",googleFontsName:"Dancing Script",categories:["hand-drawn","script","elegant","flowing","cursive"],description:"Elegant flowing script, graceful and organic",artistic:!1},{name:"Gothic Blackletter",googleFontsName:"UnifrakturMaguntia",categories:["gothic","medieval","blackletter","ornate","historical"],description:"Medieval blackletter style, ornate and historical",artistic:!0},{name:"Gothic Horror",googleFontsName:"Creepster",categories:["gothic","horror","creepy","dripping","display","striking","intense"],description:"Horror-style font with dripping effects, very striking",artistic:!0},{name:"Gothic Bold",googleFontsName:"Eater",categories:["gothic","bold","aggressive","display","striking"],description:"Bold aggressive display font, powerful impact",artistic:!0},{name:"Futuristic Digital",googleFontsName:"Orbitron",categories:["futuristic","sci-fi","digital","tech","modern","geometric"],description:"Futuristic geometric font, tech-forward and modern",artistic:!0},{name:"Futuristic Display",googleFontsName:"Bungee",categories:["futuristic","display","bold","condensed","striking"],description:"Bold condensed display font, high impact",artistic:!0},{name:"Futuristic Outline",googleFontsName:"Bungee Shade",categories:["futuristic","outline","display","bold","striking"],description:"Outlined version of Bungee, bold and striking",artistic:!0},{name:"Retro Terminal",googleFontsName:"VT323",categories:["retro","terminal","monospace","pixel","80s","tech"],description:"Retro terminal font, pixelated and nostalgic",artistic:!0},{name:"Retro Pixel",googleFontsName:"Press Start 2P",categories:["retro","pixel","8-bit","arcade","nostalgic","display"],description:"8-bit pixel font, classic arcade style",artistic:!0},{name:"Retro Display",googleFontsName:"Frijole",categories:["retro","playful","rounded","display","casual"],description:"Playful rounded retro font, fun and casual",artistic:!0},{name:"Decorative Ornate",googleFontsName:"Fascinate",categories:["decorative","ornate","display","striking","elaborate"],description:"Highly decorative display font, ornate and elaborate",artistic:!0},{name:"Decorative Outline",googleFontsName:"Fascinate Inline",categories:["decorative","outline","display","ornate","striking"],description:"Outlined decorative font, ornate and striking",artistic:!0},{name:"Decorative Script",googleFontsName:"Fredericka the Great",categories:["decorative","script","ornate","elegant","display"],description:"Elegant decorative script, ornate and sophisticated",artistic:!0},{name:"Horror Dripping",googleFontsName:"Nosifer",categories:["horror","creepy","dripping","blood","striking","display","intense"],description:"Creepy font with blood-dripping effects, very striking",artistic:!0},{name:"Tech Monospace",googleFontsName:"Share Tech Mono",categories:["tech","monospace","terminal","code","modern"],description:"Clean tech monospace font, modern and readable",artistic:!1},{name:"Tech Display",googleFontsName:"Rajdhani",categories:["tech","modern","geometric","sans-serif","futuristic"],description:"Modern geometric tech font, clean and futuristic",artistic:!1},{name:"Organic Flowing",googleFontsName:"Dancing Script",categories:["organic","flowing","natural","script","elegant"],description:"Flowing organic script, natural and elegant",artistic:!1},{name:"Modern Sans",googleFontsName:"Roboto",categories:["modern","clean","sans-serif","readable","professional"],description:"Clean modern sans-serif, professional and readable",artistic:!1},{name:"Modern Serif",googleFontsName:"Playfair Display",categories:["modern","serif","elegant","sophisticated","readable"],description:"Elegant modern serif, sophisticated and readable",artistic:!1},{name:"Bold Condensed",googleFontsName:"Bungee",categories:["bold","condensed","display","striking","impact"],description:"Bold condensed display font, high impact",artistic:!0},{name:"Bold Aggressive",googleFontsName:"Eater",categories:["bold","aggressive","display","striking","powerful"],description:"Bold aggressive display font, powerful and striking",artistic:!0},{name:"Handwritten Thin",googleFontsName:"Amatic SC",categories:["hand-drawn","uneven","organic","unsettling","subtle","scratchy"],description:"Thin hand-drawn letters with subtle irregularity, organic feel",artistic:!0},{name:"Rough Handwriting",googleFontsName:"Rock Salt",categories:["hand-drawn","scratchy","weathered","rough","unsettling","moderate"],description:"Rough, weathered handwriting with natural imperfection",artistic:!0},{name:"Typewriter Degraded",googleFontsName:"Special Elite",categories:["typewriter","decayed","weathered","imperfect","unsettling","moderate"],description:"Degraded typewriter font, vintage with imperfection",artistic:!0},{name:"Casual Handwriting",googleFontsName:"Handlee",categories:["hand-drawn","casual","imperfect","organic","subtle"],description:"Casual handwriting with subtle imperfection",artistic:!1},{name:"Childlike Organic",googleFontsName:"Indie Flower",categories:["hand-drawn","childlike","organic","imperfect","eerie","subtle"],description:"Childlike handwriting, can feel innocent or eerie depending on context",artistic:!1},{name:"Scratchy Personal",googleFontsName:"Shadows Into Light",categories:["hand-drawn","scratchy","personal","unsettling","uneven","moderate"],description:"Scratchy personal handwriting with unsettling quality",artistic:!0},{name:"Hurried Scratchy",googleFontsName:"Reenie Beanie",categories:["hand-drawn","scratchy","hurried","uneven","unsettling","moderate"],description:"Hurried scratchy handwriting with nervous energy",artistic:!0},{name:"Architectural Irregular",googleFontsName:"Architects Daughter",categories:["hand-drawn","imperfect","uneven","organic","subtle"],description:"Hand-drawn with architectural irregularity",artistic:!1},{name:"Informal Unsettling",googleFontsName:"Coming Soon",categories:["hand-drawn","informal","imperfect","unsettling","subtle"],description:"Informal handwriting that feels slightly off",artistic:!1},{name:"Manic Handwriting",googleFontsName:"Gloria Hallelujah",categories:["hand-drawn","playful","manic","uneven","unsettling","moderate"],description:"Playful handwriting that can feel manic or unsettled",artistic:!0},{name:"Quick Imperfect",googleFontsName:"Just Another Hand",categories:["hand-drawn","scratchy","quick","imperfect","uneven","subtle"],description:"Quick scratchy handwriting with natural imperfection",artistic:!1},{name:"Organic Handwriting",googleFontsName:"Kalam",categories:["hand-drawn","organic","natural","flowing","subtle"],description:"Organic natural handwriting with flowing quality",artistic:!1},{name:"Flowing Tension",googleFontsName:"Satisfy",categories:["script","flowing","tension","elegant","unsettling","subtle"],description:"Flowing script with underlying tension",artistic:!0},{name:"Unsettling Elegance",googleFontsName:"Yellowtail",categories:["script","elegant","stylized","unsettling","uneven","moderate"],description:"Stylized elegance with unsettling undertones",artistic:!0},{name:"Typewriter Imperfect",googleFontsName:"Cutive Mono",categories:["typewriter","monospace","imperfect","decayed","vintage","subtle"],description:"Imperfect vintage typewriter with character",artistic:!0}];function I(s){const e=s.toLowerCase().split(/\s+/).filter(t=>t.length>0),o=[],n=[];for(const t of e)t.startsWith("-")&&t.length>1?n.push(t.slice(1)):o.push(t);return{positive:o,negative:n}}function P(s,e){const o=new Set,n=new Map,t=2,i=[];for(const l of s){if(i.length>=e)break;if(o.has(l.font.googleFontsName))continue;const r=l.font.categories[0],a=n.get(r)||0;a>=t||(o.add(l.font.googleFontsName),n.set(r,a+1),i.push(l.font))}return i}function y(s,e){const{positive:o,negative:n}=I(s),t=(e==null?void 0:e.limit)??10,l=k.map(r=>{let a=0;for(const c of o){for(const h of r.categories)(h.includes(c)||c.includes(h))&&(a+=10);r.name.toLowerCase().includes(c)&&(a+=15),r.description.toLowerCase().includes(c)&&(a+=8)}for(const c of n){for(const h of r.categories)(h.includes(c)||c.includes(h))&&(a-=20);r.name.toLowerCase().includes(c)&&(a-=15),r.description.toLowerCase().includes(c)&&(a-=10)}return r.artistic&&(a+=1),{font:r,score:a}}).filter(r=>r.score>0).sort((r,a)=>a.score-r.score);return P(l,t)}function M(s){return y(s)[0]}const w=new Set;function N(s){return new Promise((e,o)=>{const n=s.replace(/\s+/g,"+");if(w.has(n)){e();return}if(document.querySelector(`link[href*="fonts.googleapis.com"][href*="${n}"]`)){w.add(n),e();return}const i=document.createElement("link");i.rel="stylesheet",i.href=`https://fonts.googleapis.com/css2?family=${n}:wght@400&display=swap`,i.onload=()=>{w.add(n),e()},i.onerror=()=>{console.warn(`Failed to load Google Font: ${s}`),o(new Error(`Failed to load Google Font: ${s}`))},document.head.appendChild(i)})}function E(s){return Promise.all(s.map(e=>N(e)))}function D(s){const e=s.replace(/\s+/g,"+");return w.has(e)}function H(s,e="sans-serif"){const o=["Caveat","Dancing Script","Finger Paint","Fredericka the Great","Amatic SC","Handlee","Indie Flower","Shadows Into Light","Rock Salt","Reenie Beanie","Architects Daughter","Coming Soon","Gloria Hallelujah","Just Another Hand","Kalam","Satisfy","Yellowtail"],n=["VT323","Press Start 2P","Share Tech Mono","Special Elite","Cutive Mono"];let t=e;return o.includes(s)?t="cursive":n.includes(s)&&(t="monospace"),`'${s}', ${t}`}function T(s,e){const o=s.toLowerCase(),n=e.rejectedFont.toLowerCase(),t=e.negativeAspects.map(a=>a.toLowerCase()),i=e.positiveAspects.map(a=>a.toLowerCase());return y(s).filter(a=>a.googleFontsName.toLowerCase()!==n&&a.name.toLowerCase()!==n).map(a=>{let c=0;for(const g of a.categories)o.includes(g)&&(c+=5);for(const g of i)(a.categories.some(m=>m.includes(g)||g.includes(m))||a.name.toLowerCase().includes(g)||a.description.toLowerCase().includes(g))&&(c+=15);for(const g of t)(a.categories.some(m=>m.includes(g)||g.includes(m))||a.name.toLowerCase().includes(g)||a.description.toLowerCase().includes(g))&&(c-=20);const h=i.some(g=>g.includes("striking")||g.includes("artistic")||g.includes("unique"));return h&&a.artistic&&(c+=10),h&&!a.artistic&&(c-=5),{font:a,score:c}}).filter(a=>a.score>0).sort((a,c)=>c.score-a.score).map(a=>a.font)}function R(s,e){return T(s,e)[0]}if(typeof window<"u"){const s={AnimatedText:b,FallingAnimation:p,SplittingAnimation:F,GlitchingAnimation:S,FloatingAnimation:v,calculateDisintegration:C,fontSuggestions:k,suggestFonts:y,suggestFont:M,loadGoogleFont:N,loadGoogleFonts:E,isFontLoaded:D,getFontFamily:H,refineSuggestion:T,refineFont:R,MOOD_CATEGORIES:x,INTENSITY_CATEGORIES:A};window.TypographyToolkit=s,window.AnimatedText=b}d.AnimatedText=b,d.FallingAnimation=p,d.FloatingAnimation=v,d.GlitchingAnimation=S,d.INTENSITY_CATEGORIES=A,d.MOOD_CATEGORIES=x,d.SplittingAnimation=F,d.calculateDisintegration=C,d.fontSuggestions=k,d.getFontFamily=H,d.isFontLoaded=D,d.loadGoogleFont=N,d.loadGoogleFonts=E,d.refineFont=R,d.refineSuggestion=T,d.suggestFont=M,d.suggestFonts=y,Object.defineProperty(d,Symbol.toStringTag,{value:"Module"})});
|
|
1
|
+
(function(r,m){typeof exports=="object"&&typeof module<"u"?m(exports):typeof define=="function"&&define.amd?define(["exports"],m):(r=typeof globalThis<"u"?globalThis:r||self,m(r.TypographyToolkit={}))})(this,function(r){"use strict";class m{update(t,a,i,n={}){const e=n.speed||1,l=n.amplitude||20,s=a*.2,d=(i*10*e+s*5)%l-l/2;return{...t,y:d}}}class g{update(t,a,i,n={}){const e=n.speed||1,l=n.amplitude||4,s=a*.2,h=Math.sin(i*.5*e+s)*l;return{...t,x:h}}}class S{constructor(){this.letterStates=new Map}update(t,a,i,n={}){const e=n.amplitude||3,l=n.speed||1;let s=this.letterStates.get(a);s||(s={lastUpdate:i,glitchX:0,glitchY:0,glitchRot:0},this.letterStates.set(a,s));const h=.1/l;return i-s.lastUpdate>h&&(s.glitchX=(Math.random()-.5)*e,s.glitchY=(Math.random()-.5)*(e*.67),s.glitchRot=(Math.random()-.5)*e,s.lastUpdate=i),{...t,x:s.glitchX,y:s.glitchY,rotation:s.glitchRot}}}class x{update(t,a,i,n={}){const e=n.speed||1,l=n.amplitude||15,s=a*.2,d=-((i*8*e+s*4)%l-l/2);return{...t,y:d}}}function E(o,t){const{x:a,y:i,rotation:n,scale:e,opacity:l}=t;o.style.transform=`translate(${a}px, ${i}px) rotate(${n}deg) scale(${e})`,o.style.opacity=l.toString()}function w(o,t,a,i,n,e){if(!e.enabled)return{state:{x:0,y:0,rotation:0,scale:1,opacity:1},applied:!1};const l=e.radius||80,s=e.strength||1,h=e.behaviors||["fall-away","split-apart","explode"],d=a-o,u=i-t,p=Math.sqrt(d*d+u*u);if(p>=l)return{state:{x:0,y:0,rotation:0,scale:1,opacity:1},applied:!1};const c=(1-p/l)*s,M=Math.atan2(u,d),D=h[n%h.length];let f;switch(D){case"fall-away":const Y=Math.cos(M)*c*20,$=Math.sin(M)*c*40+c*30;f={x:Y,y:$,rotation:c*15,scale:1,opacity:1-c*.6};break;case"split-apart":const k=n%2===0?1:-1;f={x:k*c*50,y:(Math.random()-.5)*c*10,rotation:c*10*k,scale:1,opacity:1-c*.6};break;case"explode":const v=M+(Math.random()-.5)*.5;f={x:Math.cos(v)*c*40,y:Math.sin(v)*c*40,rotation:c*30,scale:1+c*.4,opacity:1-c*.6};break;default:f={x:0,y:0,rotation:0,scale:1,opacity:1}}return{state:f,applied:!0}}class C{constructor(t){var a;if(this.letters=[],this.animationSpeedMultiplier=1,this.animationFrame=null,this.mouseX=0,this.mouseY=0,this.mouseMoveHandler=null,this.startTime=Date.now(),this.isDestroyed=!1,this.animationInstances=new Map,this.container=t.container,this.animationTypes=t.animations||["falling","splitting","glitching","floating"],this.cycle=t.cycle!==!1,this.speed=t.speed||1,this.amplitude=t.amplitude||1,this.animationEasing=t.animationEasing||"linear",this.disintegration=t.disintegration||{enabled:!1},this.style=t.style||{},this.fadeOut=t.fadeOut||0,this.callbacks=t.callbacks,t.animationSpeed!==void 0&&(this.animationSpeedMultiplier=this.parseAnimationSpeed(t.animationSpeed)),this.textContainer=document.createElement("div"),this.textContainer.style.position="absolute",this.textContainer.style.pointerEvents="none",this.textContainer.style.zIndex="1",t.containerClass&&(this.textContainer.className=t.containerClass),t.containerStyle&&Object.entries(t.containerStyle).forEach(([i,n])=>{this.textContainer.style.setProperty(i,n)}),t.position){let i=t.position.x,n=t.position.y;if(t.position.constrainToViewport){this.container.getBoundingClientRect();const e=window.innerWidth,l=window.innerHeight,s=t.text.length*20;i!==void 0&&(i=Math.max(0,Math.min(i,e-s))),n!==void 0&&(n=Math.max(0,Math.min(n,l-50)))}i!==void 0&&(this.textContainer.style.left=`${i}px`),n!==void 0&&(this.textContainer.style.top=`${n}px`)}this.createLetters(t.text),this.setupMouseTracking(),this.startAnimation(),(a=this.callbacks)!=null&&a.onCreate&&this.callbacks.onCreate(this.textContainer),this.fadeOut>0&&setTimeout(()=>this.destroy(),this.fadeOut)}createLetters(t){t.toUpperCase().split("").forEach((i,n)=>{if(i===" "){const s=document.createTextNode(" ");this.textContainer.appendChild(s);return}const e=document.createElement("span");e.className="animated-letter",e.textContent=i,e.dataset.index=n.toString(),e.dataset.char=i,this.applyStyle(e),e.style.display="inline-block",e.style.position="relative",e.style.transition="transform 0.1s ease-out",this.textContainer.appendChild(e);const l=e.getBoundingClientRect();this.letters.push({element:e,index:n,char:i,baseX:l.left,baseY:l.top})}),this.container.appendChild(this.textContainer)}applyStyle(t){this.style.fontFamily&&(t.style.fontFamily=this.style.fontFamily),this.style.fontSize&&(t.style.fontSize=`${this.style.fontSize}px`),this.style.color&&(t.style.color=this.style.color),this.style.fontWeight&&(t.style.fontWeight=this.style.fontWeight),this.style.textShadow&&(t.style.textShadow=this.style.textShadow),this.style.letterSpacing&&(t.style.letterSpacing=this.style.letterSpacing),this.style.textTransform&&(t.style.textTransform=this.style.textTransform)}setupMouseTracking(){this.disintegration.enabled&&(this.mouseMoveHandler=t=>{this.mouseX=t.clientX,this.mouseY=t.clientY},document.addEventListener("mousemove",this.mouseMoveHandler))}startAnimation(){const t=()=>{if(this.isDestroyed)return;const a=(Date.now()-this.startTime)*.001;this.letters.forEach((i,n)=>{var u;const e=i.element.getBoundingClientRect(),l=e.left+e.width/2,s=e.top+e.height/2,h=w(l,s,this.mouseX,this.mouseY,n,this.disintegration);let d;if(h.applied)d=h.state,(u=this.callbacks)!=null&&u.onDisintegrate&&this.callbacks.onDisintegrate(n);else{const p=this.getAnimationType(n);d=this.getAnimation(p).update({x:0,y:0,rotation:0,scale:1,opacity:1},n,a,{speed:this.speed*this.animationSpeedMultiplier,amplitude:this.amplitude*(p==="falling"||p==="floating"?20:4)})}E(i.element,d)}),this.animationFrame=requestAnimationFrame(t)};this.animationFrame=requestAnimationFrame(t)}getAnimationType(t){return this.cycle?this.animationTypes[t%this.animationTypes.length]:this.animationTypes[0]}getAnimation(t){if(this.animationInstances.has(t))return this.animationInstances.get(t);let a;switch(t){case"falling":a=new m;break;case"splitting":a=new g;break;case"glitching":a=new S;break;case"floating":a=new x;break;default:a=new m}return this.animationInstances.set(t,a),a}parseAnimationSpeed(t){if(typeof t=="number")return t;switch(t){case"slow":return .5;case"normal":return 1;case"fast":return 2;default:return 1}}getAnimationSpeed(){return this.animationSpeedMultiplier}setAnimationSpeed(t){this.animationSpeedMultiplier=this.parseAnimationSpeed(t)}getAnimationEasing(){return this.animationEasing}setAnimationEasing(t){this.animationEasing=t}destroy(){var t;this.isDestroyed||(this.isDestroyed=!0,this.animationFrame!==null&&cancelAnimationFrame(this.animationFrame),this.mouseMoveHandler&&document.removeEventListener("mousemove",this.mouseMoveHandler),this.animationInstances.clear(),(t=this.callbacks)!=null&&t.onDestroy&&this.callbacks.onDestroy(),this.textContainer.style.transition="opacity 3s ease",this.textContainer.style.opacity="0",setTimeout(()=>{this.textContainer.parentNode&&this.textContainer.parentNode.removeChild(this.textContainer)},3e3))}getElement(){return this.textContainer}}const y=new Set;function F(o){return new Promise((t,a)=>{const i=o.replace(/\s+/g,"+");if(y.has(i)){t();return}if(document.querySelector(`link[href*="fonts.googleapis.com"][href*="${i}"]`)){y.add(i),t();return}const e=document.createElement("link");e.rel="stylesheet",e.href=`https://fonts.googleapis.com/css2?family=${i}:wght@400&display=swap`,e.onload=()=>{y.add(i),t()},e.onerror=()=>{console.warn(`Failed to load Google Font: ${o}`),a(new Error(`Failed to load Google Font: ${o}`))},document.head.appendChild(e)})}function T(o){return Promise.all(o.map(t=>F(t)))}function A(o){const t=o.replace(/\s+/g,"+");return y.has(t)}function b(o,t="sans-serif"){const a=["Caveat","Dancing Script","Finger Paint","Fredericka the Great","Amatic SC","Handlee","Indie Flower","Shadows Into Light","Rock Salt","Reenie Beanie","Architects Daughter","Coming Soon","Gloria Hallelujah","Just Another Hand","Kalam","Satisfy","Yellowtail"],i=["VT323","Press Start 2P","Share Tech Mono","Special Elite","Cutive Mono"];let n=t;return a.includes(o)?n="cursive":i.includes(o)&&(n="monospace"),`'${o}', ${n}`}if(typeof window<"u"){const o={AnimatedText:C,FallingAnimation:m,SplittingAnimation:g,GlitchingAnimation:S,FloatingAnimation:x,calculateDisintegration:w,loadGoogleFont:F,loadGoogleFonts:T,isFontLoaded:A,getFontFamily:b};window.TypographyToolkit=o,window.AnimatedText=C}r.AnimatedText=C,r.FallingAnimation=m,r.FloatingAnimation=x,r.GlitchingAnimation=S,r.SplittingAnimation=g,r.calculateDisintegration=w,r.getFontFamily=b,r.isFontLoaded=A,r.loadGoogleFont=F,r.loadGoogleFonts=T,Object.defineProperty(r,Symbol.toStringTag,{value:"Module"})});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "typography-toolkit",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.0",
|
|
4
4
|
"description": "Letter-by-letter text animations with proximity-based disintegration effects and Google Fonts selection",
|
|
5
5
|
"main": "dist/typography-toolkit.umd.js",
|
|
6
6
|
"module": "dist/typography-toolkit.esm.js",
|