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