typography-toolkit 1.2.0 → 1.3.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,201 +1,242 @@
|
|
|
1
1
|
class f {
|
|
2
|
-
update(
|
|
3
|
-
const
|
|
2
|
+
update(e, o, n, t = {}) {
|
|
3
|
+
const i = t.speed || 1, l = t.amplitude || 20, r = o * 0.2, c = (n * 10 * i + r * 5) % l - l / 2;
|
|
4
4
|
return {
|
|
5
|
-
...
|
|
6
|
-
y:
|
|
5
|
+
...e,
|
|
6
|
+
y: c
|
|
7
7
|
};
|
|
8
8
|
}
|
|
9
9
|
}
|
|
10
10
|
class C {
|
|
11
|
-
update(
|
|
12
|
-
const
|
|
11
|
+
update(e, o, n, t = {}) {
|
|
12
|
+
const i = t.speed || 1, l = t.amplitude || 4, r = o * 0.2, a = Math.sin(n * 0.5 * i + r) * l;
|
|
13
13
|
return {
|
|
14
|
-
...
|
|
14
|
+
...e,
|
|
15
15
|
x: a
|
|
16
16
|
};
|
|
17
17
|
}
|
|
18
18
|
}
|
|
19
|
-
class
|
|
19
|
+
class S {
|
|
20
20
|
constructor() {
|
|
21
21
|
this.lastUpdate = 0, this.glitchX = 0, this.glitchY = 0, this.glitchRot = 0;
|
|
22
22
|
}
|
|
23
|
-
update(
|
|
24
|
-
const
|
|
25
|
-
return
|
|
26
|
-
...
|
|
23
|
+
update(e, o, n, t = {}) {
|
|
24
|
+
const i = t.amplitude || 3;
|
|
25
|
+
return n - this.lastUpdate > 0.1 && (this.glitchX = (Math.random() - 0.5) * i, this.glitchY = (Math.random() - 0.5) * (i * 0.67), this.glitchRot = (Math.random() - 0.5) * i, this.lastUpdate = n), {
|
|
26
|
+
...e,
|
|
27
27
|
x: this.glitchX,
|
|
28
28
|
y: this.glitchY,
|
|
29
29
|
rotation: this.glitchRot
|
|
30
30
|
};
|
|
31
31
|
}
|
|
32
32
|
}
|
|
33
|
-
class
|
|
34
|
-
update(
|
|
35
|
-
const
|
|
33
|
+
class x {
|
|
34
|
+
update(e, o, n, t = {}) {
|
|
35
|
+
const i = t.speed || 1, l = t.amplitude || 15, r = o * 0.2, c = -((n * 8 * i + r * 4) % l - l / 2);
|
|
36
36
|
return {
|
|
37
|
-
...
|
|
38
|
-
y:
|
|
37
|
+
...e,
|
|
38
|
+
y: c
|
|
39
39
|
};
|
|
40
40
|
}
|
|
41
41
|
}
|
|
42
|
-
function
|
|
43
|
-
const { x: o, y:
|
|
44
|
-
|
|
42
|
+
function D(s, e) {
|
|
43
|
+
const { x: o, y: n, rotation: t, scale: i, opacity: l } = e;
|
|
44
|
+
s.style.transform = `translate(${o}px, ${n}px) rotate(${t}deg) scale(${i})`, s.style.opacity = l.toString();
|
|
45
45
|
}
|
|
46
|
-
function b(
|
|
47
|
-
if (!
|
|
46
|
+
function b(s, e, o, n, t, i) {
|
|
47
|
+
if (!i.enabled)
|
|
48
48
|
return {
|
|
49
49
|
state: { x: 0, y: 0, rotation: 0, scale: 1, opacity: 1 },
|
|
50
50
|
applied: !1
|
|
51
51
|
};
|
|
52
|
-
const
|
|
53
|
-
if (
|
|
52
|
+
const l = i.radius || 80, r = i.strength || 1, a = i.behaviors || ["fall-away", "split-apart", "explode"], c = o - s, u = n - e, d = Math.sqrt(c * c + u * u);
|
|
53
|
+
if (d >= l)
|
|
54
54
|
return {
|
|
55
55
|
state: { x: 0, y: 0, rotation: 0, scale: 1, opacity: 1 },
|
|
56
56
|
applied: !1
|
|
57
57
|
};
|
|
58
|
-
const
|
|
59
|
-
let
|
|
60
|
-
switch (
|
|
58
|
+
const g = (1 - d / l) * r, h = Math.atan2(u, c), T = a[t % a.length];
|
|
59
|
+
let m;
|
|
60
|
+
switch (T) {
|
|
61
61
|
case "fall-away":
|
|
62
|
-
const
|
|
63
|
-
|
|
64
|
-
x:
|
|
65
|
-
y:
|
|
66
|
-
rotation:
|
|
62
|
+
const A = Math.cos(h) * g * 20, E = Math.sin(h) * g * 40 + g * 30;
|
|
63
|
+
m = {
|
|
64
|
+
x: A,
|
|
65
|
+
y: E,
|
|
66
|
+
rotation: g * 15,
|
|
67
67
|
scale: 1,
|
|
68
|
-
opacity: 1 -
|
|
68
|
+
opacity: 1 - g * 0.6
|
|
69
69
|
};
|
|
70
70
|
break;
|
|
71
71
|
case "split-apart":
|
|
72
|
-
const w =
|
|
73
|
-
|
|
74
|
-
x: w *
|
|
75
|
-
y: (Math.random() - 0.5) *
|
|
76
|
-
rotation:
|
|
72
|
+
const w = t % 2 === 0 ? 1 : -1;
|
|
73
|
+
m = {
|
|
74
|
+
x: w * g * 50,
|
|
75
|
+
y: (Math.random() - 0.5) * g * 10,
|
|
76
|
+
rotation: g * 10 * w,
|
|
77
77
|
scale: 1,
|
|
78
|
-
opacity: 1 -
|
|
78
|
+
opacity: 1 - g * 0.6
|
|
79
79
|
};
|
|
80
80
|
break;
|
|
81
81
|
case "explode":
|
|
82
|
-
const F =
|
|
83
|
-
|
|
84
|
-
x: Math.cos(F) *
|
|
85
|
-
y: Math.sin(F) *
|
|
86
|
-
rotation:
|
|
87
|
-
scale: 1 +
|
|
88
|
-
opacity: 1 -
|
|
82
|
+
const F = h + (Math.random() - 0.5) * 0.5;
|
|
83
|
+
m = {
|
|
84
|
+
x: Math.cos(F) * g * 40,
|
|
85
|
+
y: Math.sin(F) * g * 40,
|
|
86
|
+
rotation: g * 30,
|
|
87
|
+
scale: 1 + g * 0.4,
|
|
88
|
+
opacity: 1 - g * 0.6
|
|
89
89
|
};
|
|
90
90
|
break;
|
|
91
91
|
default:
|
|
92
|
-
|
|
92
|
+
m = { x: 0, y: 0, rotation: 0, scale: 1, opacity: 1 };
|
|
93
93
|
}
|
|
94
94
|
return {
|
|
95
|
-
state:
|
|
95
|
+
state: m,
|
|
96
96
|
applied: !0
|
|
97
97
|
};
|
|
98
98
|
}
|
|
99
|
-
class
|
|
100
|
-
constructor(
|
|
99
|
+
class v {
|
|
100
|
+
constructor(e) {
|
|
101
101
|
var o;
|
|
102
|
-
if (this.letters = [], 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 (
|
|
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 = 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]) => {
|
|
103
|
+
this.textContainer.style.setProperty(n, t);
|
|
104
|
+
}), e.position) {
|
|
105
|
+
let n = e.position.x, t = e.position.y;
|
|
106
|
+
if (e.position.constrainToViewport) {
|
|
107
107
|
this.container.getBoundingClientRect();
|
|
108
|
-
const
|
|
109
|
-
|
|
108
|
+
const i = window.innerWidth, l = window.innerHeight, r = e.text.length * 20;
|
|
109
|
+
n !== void 0 && (n = Math.max(0, Math.min(n, i - r))), t !== void 0 && (t = Math.max(0, Math.min(t, l - 50)));
|
|
110
110
|
}
|
|
111
|
-
|
|
111
|
+
n !== void 0 && (this.textContainer.style.left = `${n}px`), t !== void 0 && (this.textContainer.style.top = `${t}px`);
|
|
112
112
|
}
|
|
113
|
-
this.createLetters(
|
|
113
|
+
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);
|
|
114
114
|
}
|
|
115
|
-
createLetters(
|
|
116
|
-
|
|
117
|
-
if (
|
|
118
|
-
const
|
|
119
|
-
this.textContainer.appendChild(
|
|
115
|
+
createLetters(e) {
|
|
116
|
+
e.toUpperCase().split("").forEach((n, t) => {
|
|
117
|
+
if (n === " ") {
|
|
118
|
+
const r = document.createTextNode(" ");
|
|
119
|
+
this.textContainer.appendChild(r);
|
|
120
120
|
return;
|
|
121
121
|
}
|
|
122
|
-
const
|
|
123
|
-
|
|
124
|
-
const
|
|
122
|
+
const i = document.createElement("span");
|
|
123
|
+
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);
|
|
124
|
+
const l = i.getBoundingClientRect();
|
|
125
125
|
this.letters.push({
|
|
126
|
-
element:
|
|
127
|
-
index:
|
|
128
|
-
char:
|
|
129
|
-
baseX:
|
|
130
|
-
baseY:
|
|
126
|
+
element: i,
|
|
127
|
+
index: t,
|
|
128
|
+
char: n,
|
|
129
|
+
baseX: l.left,
|
|
130
|
+
baseY: l.top
|
|
131
131
|
});
|
|
132
132
|
}), this.container.appendChild(this.textContainer);
|
|
133
133
|
}
|
|
134
|
-
applyStyle(
|
|
135
|
-
this.style.fontFamily && (
|
|
134
|
+
applyStyle(e) {
|
|
135
|
+
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);
|
|
136
136
|
}
|
|
137
137
|
setupMouseTracking() {
|
|
138
|
-
this.disintegration.enabled && (this.mouseMoveHandler = (
|
|
139
|
-
this.mouseX =
|
|
138
|
+
this.disintegration.enabled && (this.mouseMoveHandler = (e) => {
|
|
139
|
+
this.mouseX = e.clientX, this.mouseY = e.clientY;
|
|
140
140
|
}, document.addEventListener("mousemove", this.mouseMoveHandler));
|
|
141
141
|
}
|
|
142
142
|
startAnimation() {
|
|
143
|
-
const
|
|
143
|
+
const e = () => {
|
|
144
144
|
if (this.isDestroyed) return;
|
|
145
145
|
const o = (Date.now() - this.startTime) * 1e-3;
|
|
146
|
-
this.letters.forEach((
|
|
147
|
-
var
|
|
148
|
-
const
|
|
149
|
-
|
|
150
|
-
|
|
146
|
+
this.letters.forEach((n, t) => {
|
|
147
|
+
var u;
|
|
148
|
+
const i = n.element.getBoundingClientRect(), l = i.left + i.width / 2, r = i.top + i.height / 2, a = b(
|
|
149
|
+
l,
|
|
150
|
+
r,
|
|
151
151
|
this.mouseX,
|
|
152
152
|
this.mouseY,
|
|
153
|
-
|
|
153
|
+
t,
|
|
154
154
|
this.disintegration
|
|
155
155
|
);
|
|
156
|
-
let
|
|
156
|
+
let c;
|
|
157
157
|
if (a.applied)
|
|
158
|
-
|
|
158
|
+
c = a.state, (u = this.callbacks) != null && u.onDisintegrate && this.callbacks.onDisintegrate(t);
|
|
159
159
|
else {
|
|
160
|
-
const
|
|
161
|
-
|
|
160
|
+
const d = this.getAnimationType(t);
|
|
161
|
+
c = this.getAnimation(d).update(
|
|
162
162
|
{ x: 0, y: 0, rotation: 0, scale: 1, opacity: 1 },
|
|
163
|
-
|
|
163
|
+
t,
|
|
164
164
|
o,
|
|
165
165
|
{
|
|
166
|
-
speed: this.speed,
|
|
167
|
-
amplitude: this.amplitude * (
|
|
166
|
+
speed: this.speed * this.animationSpeedMultiplier,
|
|
167
|
+
amplitude: this.amplitude * (d === "falling" || d === "floating" ? 20 : 4)
|
|
168
168
|
}
|
|
169
169
|
);
|
|
170
170
|
}
|
|
171
|
-
|
|
172
|
-
}), this.animationFrame = requestAnimationFrame(
|
|
171
|
+
D(n.element, c);
|
|
172
|
+
}), this.animationFrame = requestAnimationFrame(e);
|
|
173
173
|
};
|
|
174
|
-
this.animationFrame = requestAnimationFrame(
|
|
174
|
+
this.animationFrame = requestAnimationFrame(e);
|
|
175
175
|
}
|
|
176
|
-
getAnimationType(
|
|
177
|
-
return this.cycle ? this.animationTypes[
|
|
176
|
+
getAnimationType(e) {
|
|
177
|
+
return this.cycle ? this.animationTypes[e % this.animationTypes.length] : this.animationTypes[0];
|
|
178
178
|
}
|
|
179
|
-
getAnimation(
|
|
180
|
-
switch (
|
|
179
|
+
getAnimation(e) {
|
|
180
|
+
switch (e) {
|
|
181
181
|
case "falling":
|
|
182
182
|
return new f();
|
|
183
183
|
case "splitting":
|
|
184
184
|
return new C();
|
|
185
185
|
case "glitching":
|
|
186
|
-
return new
|
|
186
|
+
return new S();
|
|
187
187
|
case "floating":
|
|
188
|
-
return new
|
|
188
|
+
return new x();
|
|
189
189
|
default:
|
|
190
190
|
return new f();
|
|
191
191
|
}
|
|
192
192
|
}
|
|
193
|
+
/**
|
|
194
|
+
* Parse animation speed preset or numeric value to a multiplier
|
|
195
|
+
*/
|
|
196
|
+
parseAnimationSpeed(e) {
|
|
197
|
+
if (typeof e == "number")
|
|
198
|
+
return e;
|
|
199
|
+
switch (e) {
|
|
200
|
+
case "slow":
|
|
201
|
+
return 0.5;
|
|
202
|
+
case "normal":
|
|
203
|
+
return 1;
|
|
204
|
+
case "fast":
|
|
205
|
+
return 2;
|
|
206
|
+
default:
|
|
207
|
+
return 1;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Get the current animation speed multiplier
|
|
212
|
+
*/
|
|
213
|
+
getAnimationSpeed() {
|
|
214
|
+
return this.animationSpeedMultiplier;
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* Set the animation speed multiplier (supports numeric values and presets)
|
|
218
|
+
*/
|
|
219
|
+
setAnimationSpeed(e) {
|
|
220
|
+
this.animationSpeedMultiplier = this.parseAnimationSpeed(e);
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Get the current animation easing function
|
|
224
|
+
*/
|
|
225
|
+
getAnimationEasing() {
|
|
226
|
+
return this.animationEasing;
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Set the animation easing function
|
|
230
|
+
*/
|
|
231
|
+
setAnimationEasing(e) {
|
|
232
|
+
this.animationEasing = e;
|
|
233
|
+
}
|
|
193
234
|
/**
|
|
194
235
|
* Destroy the animated text instance
|
|
195
236
|
*/
|
|
196
237
|
destroy() {
|
|
197
|
-
var
|
|
198
|
-
this.isDestroyed || (this.isDestroyed = !0, this.animationFrame !== null && cancelAnimationFrame(this.animationFrame), this.mouseMoveHandler && document.removeEventListener("mousemove", this.mouseMoveHandler), (
|
|
238
|
+
var e;
|
|
239
|
+
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(() => {
|
|
199
240
|
this.textContainer.parentNode && this.textContainer.parentNode.removeChild(this.textContainer);
|
|
200
241
|
}, 3e3));
|
|
201
242
|
}
|
|
@@ -206,7 +247,16 @@ class x {
|
|
|
206
247
|
return this.textContainer;
|
|
207
248
|
}
|
|
208
249
|
}
|
|
209
|
-
const
|
|
250
|
+
const H = [
|
|
251
|
+
"unsettling",
|
|
252
|
+
"eerie",
|
|
253
|
+
"decayed",
|
|
254
|
+
"weathered",
|
|
255
|
+
"organic",
|
|
256
|
+
"imperfect",
|
|
257
|
+
"uneven",
|
|
258
|
+
"scratchy"
|
|
259
|
+
], R = ["subtle", "moderate", "intense"], k = [
|
|
210
260
|
// Hand-drawn / Handwriting
|
|
211
261
|
{
|
|
212
262
|
name: "Hand-drawn Casual",
|
|
@@ -240,7 +290,7 @@ const S = [
|
|
|
240
290
|
{
|
|
241
291
|
name: "Gothic Horror",
|
|
242
292
|
googleFontsName: "Creepster",
|
|
243
|
-
categories: ["gothic", "horror", "creepy", "dripping", "display", "striking"],
|
|
293
|
+
categories: ["gothic", "horror", "creepy", "dripping", "display", "striking", "intense"],
|
|
244
294
|
description: "Horror-style font with dripping effects, very striking",
|
|
245
295
|
artistic: !0
|
|
246
296
|
},
|
|
@@ -321,7 +371,7 @@ const S = [
|
|
|
321
371
|
{
|
|
322
372
|
name: "Horror Dripping",
|
|
323
373
|
googleFontsName: "Nosifer",
|
|
324
|
-
categories: ["horror", "creepy", "dripping", "blood", "striking", "display"],
|
|
374
|
+
categories: ["horror", "creepy", "dripping", "blood", "striking", "display", "intense"],
|
|
325
375
|
description: "Creepy font with blood-dripping effects, very striking",
|
|
326
376
|
artistic: !0
|
|
327
377
|
},
|
|
@@ -377,110 +427,271 @@ const S = [
|
|
|
377
427
|
categories: ["bold", "aggressive", "display", "striking", "powerful"],
|
|
378
428
|
description: "Bold aggressive display font, powerful and striking",
|
|
379
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
|
|
380
536
|
}
|
|
381
537
|
];
|
|
382
|
-
function
|
|
383
|
-
const
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
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);
|
|
390
571
|
}
|
|
391
|
-
function
|
|
392
|
-
return y(
|
|
572
|
+
function P(s) {
|
|
573
|
+
return y(s)[0];
|
|
393
574
|
}
|
|
394
|
-
const
|
|
395
|
-
function
|
|
396
|
-
return new Promise((
|
|
397
|
-
const
|
|
398
|
-
if (
|
|
399
|
-
|
|
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();
|
|
400
581
|
return;
|
|
401
582
|
}
|
|
402
583
|
if (document.querySelector(
|
|
403
|
-
`link[href*="fonts.googleapis.com"][href*="${
|
|
584
|
+
`link[href*="fonts.googleapis.com"][href*="${n}"]`
|
|
404
585
|
)) {
|
|
405
|
-
|
|
586
|
+
p.add(n), e();
|
|
406
587
|
return;
|
|
407
588
|
}
|
|
408
|
-
const
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
},
|
|
412
|
-
console.warn(`Failed to load Google Font: ${
|
|
413
|
-
}, document.head.appendChild(
|
|
589
|
+
const i = document.createElement("link");
|
|
590
|
+
i.rel = "stylesheet", i.href = `https://fonts.googleapis.com/css2?family=${n}:wght@400&display=swap`, i.onload = () => {
|
|
591
|
+
p.add(n), e();
|
|
592
|
+
}, i.onerror = () => {
|
|
593
|
+
console.warn(`Failed to load Google Font: ${s}`), o(new Error(`Failed to load Google Font: ${s}`));
|
|
594
|
+
}, document.head.appendChild(i);
|
|
414
595
|
});
|
|
415
596
|
}
|
|
416
|
-
function B(
|
|
417
|
-
return Promise.all(
|
|
597
|
+
function B(s) {
|
|
598
|
+
return Promise.all(s.map((e) => N(e)));
|
|
418
599
|
}
|
|
419
|
-
function
|
|
420
|
-
const
|
|
421
|
-
return
|
|
600
|
+
function G(s) {
|
|
601
|
+
const e = s.replace(/\s+/g, "+");
|
|
602
|
+
return p.has(e);
|
|
422
603
|
}
|
|
423
|
-
function
|
|
424
|
-
const o = [
|
|
425
|
-
|
|
426
|
-
|
|
604
|
+
function I(s, e = "sans-serif") {
|
|
605
|
+
const o = [
|
|
606
|
+
"Caveat",
|
|
607
|
+
"Dancing Script",
|
|
608
|
+
"Finger Paint",
|
|
609
|
+
"Fredericka the Great",
|
|
610
|
+
// Subtle unsettling / organic fonts
|
|
611
|
+
"Amatic SC",
|
|
612
|
+
"Handlee",
|
|
613
|
+
"Indie Flower",
|
|
614
|
+
"Shadows Into Light",
|
|
615
|
+
"Rock Salt",
|
|
616
|
+
"Reenie Beanie",
|
|
617
|
+
"Architects Daughter",
|
|
618
|
+
"Coming Soon",
|
|
619
|
+
"Gloria Hallelujah",
|
|
620
|
+
"Just Another Hand",
|
|
621
|
+
"Kalam",
|
|
622
|
+
"Satisfy",
|
|
623
|
+
"Yellowtail"
|
|
624
|
+
], n = [
|
|
625
|
+
"VT323",
|
|
626
|
+
"Press Start 2P",
|
|
627
|
+
"Share Tech Mono",
|
|
628
|
+
// Typewriter fonts
|
|
629
|
+
"Special Elite",
|
|
630
|
+
"Cutive Mono"
|
|
631
|
+
];
|
|
632
|
+
let t = e;
|
|
633
|
+
return o.includes(s) ? t = "cursive" : n.includes(s) && (t = "monospace"), `'${s}', ${t}`;
|
|
427
634
|
}
|
|
428
|
-
function M(
|
|
429
|
-
const o =
|
|
430
|
-
return y(
|
|
431
|
-
(a) => a.googleFontsName.toLowerCase() !==
|
|
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
|
|
432
639
|
).map((a) => {
|
|
433
|
-
let
|
|
434
|
-
for (const
|
|
435
|
-
o.includes(
|
|
436
|
-
for (const
|
|
437
|
-
(a.categories.some((
|
|
438
|
-
for (const
|
|
439
|
-
(a.categories.some((
|
|
440
|
-
const
|
|
441
|
-
(
|
|
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")
|
|
442
649
|
);
|
|
443
|
-
return
|
|
444
|
-
}).filter((a) => a.score > 0).sort((a,
|
|
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);
|
|
445
652
|
}
|
|
446
|
-
function
|
|
447
|
-
return M(
|
|
653
|
+
function Y(s, e) {
|
|
654
|
+
return M(s, e)[0];
|
|
448
655
|
}
|
|
449
656
|
if (typeof window < "u") {
|
|
450
|
-
const
|
|
451
|
-
AnimatedText:
|
|
657
|
+
const s = {
|
|
658
|
+
AnimatedText: v,
|
|
452
659
|
FallingAnimation: f,
|
|
453
660
|
SplittingAnimation: C,
|
|
454
|
-
GlitchingAnimation:
|
|
455
|
-
FloatingAnimation:
|
|
661
|
+
GlitchingAnimation: S,
|
|
662
|
+
FloatingAnimation: x,
|
|
456
663
|
calculateDisintegration: b,
|
|
457
664
|
// Font utilities
|
|
458
|
-
fontSuggestions:
|
|
665
|
+
fontSuggestions: k,
|
|
459
666
|
suggestFonts: y,
|
|
460
|
-
suggestFont:
|
|
461
|
-
loadGoogleFont:
|
|
667
|
+
suggestFont: P,
|
|
668
|
+
loadGoogleFont: N,
|
|
462
669
|
loadGoogleFonts: B,
|
|
463
|
-
isFontLoaded:
|
|
464
|
-
getFontFamily:
|
|
670
|
+
isFontLoaded: G,
|
|
671
|
+
getFontFamily: I,
|
|
465
672
|
refineSuggestion: M,
|
|
466
|
-
refineFont:
|
|
673
|
+
refineFont: Y,
|
|
674
|
+
MOOD_CATEGORIES: H,
|
|
675
|
+
INTENSITY_CATEGORIES: R
|
|
467
676
|
};
|
|
468
|
-
window.TypographyToolkit =
|
|
677
|
+
window.TypographyToolkit = s, window.AnimatedText = v;
|
|
469
678
|
}
|
|
470
679
|
export {
|
|
471
|
-
|
|
680
|
+
v as AnimatedText,
|
|
472
681
|
f as FallingAnimation,
|
|
473
|
-
|
|
474
|
-
|
|
682
|
+
x as FloatingAnimation,
|
|
683
|
+
S as GlitchingAnimation,
|
|
684
|
+
R as INTENSITY_CATEGORIES,
|
|
685
|
+
H as MOOD_CATEGORIES,
|
|
475
686
|
C as SplittingAnimation,
|
|
476
687
|
b as calculateDisintegration,
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
688
|
+
k as fontSuggestions,
|
|
689
|
+
I as getFontFamily,
|
|
690
|
+
G as isFontLoaded,
|
|
691
|
+
N as loadGoogleFont,
|
|
481
692
|
B as loadGoogleFonts,
|
|
482
|
-
|
|
693
|
+
Y as refineFont,
|
|
483
694
|
M as refineSuggestion,
|
|
484
|
-
|
|
695
|
+
P as suggestFont,
|
|
485
696
|
y as suggestFonts
|
|
486
697
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var TypographyToolkit=function(d){"use strict";class f{update(t,o,e,i={}){const s=i.speed||1,l=i.amplitude||20,h=o*.2,c=(e*10*s+h*5)%l-l/2;return{...t,y:c}}}class w{update(t,o,e,i={}){const s=i.speed||1,l=i.amplitude||4,h=o*.2,a=Math.sin(e*.5*s+h)*l;return{...t,x:a}}}class C{constructor(){this.lastUpdate=0,this.glitchX=0,this.glitchY=0,this.glitchRot=0}update(t,o,e,i={}){const s=i.amplitude||3;return e-this.lastUpdate>.1&&(this.glitchX=(Math.random()-.5)*s,this.glitchY=(Math.random()-.5)*(s*.67),this.glitchRot=(Math.random()-.5)*s,this.lastUpdate=e),{...t,x:this.glitchX,y:this.glitchY,rotation:this.glitchRot}}}class v{update(t,o,e,i={}){const s=i.speed||1,l=i.amplitude||15,h=o*.2,c=-((e*8*s+h*4)%l-l/2);return{...t,y:c}}}function B(n,t){const{x:o,y:e,rotation:i,scale:s,opacity:l}=t;n.style.transform=`translate(${o}px, ${e}px) rotate(${i}deg) scale(${s})`,n.style.opacity=l.toString()}function k(n,t,o,e,i,s){if(!s.enabled)return{state:{x:0,y:0,rotation:0,scale:1,opacity:1},applied:!1};const l=s.radius||80,h=s.strength||1,a=s.behaviors||["fall-away","split-apart","explode"],c=o-n,u=e-t,r=Math.sqrt(c*c+u*u);if(r>=l)return{state:{x:0,y:0,rotation:0,scale:1,opacity:1},applied:!1};const g=(1-r/l)*h,m=Math.atan2(u,c),R=a[i%a.length];let p;switch(R){case"fall-away":const H=Math.cos(m)*g*20,G=Math.sin(m)*g*40+g*30;p={x:H,y:G,rotation:g*15,scale:1,opacity:1-g*.6};break;case"split-apart":const E=i%2===0?1:-1;p={x:E*g*50,y:(Math.random()-.5)*g*10,rotation:g*10*E,scale:1,opacity:1-g*.6};break;case"explode":const P=m+(Math.random()-.5)*.5;p={x:Math.cos(P)*g*40,y:Math.sin(P)*g*40,rotation:g*30,scale:1+g*.4,opacity:1-g*.6};break;default:p={x:0,y:0,rotation:0,scale:1,opacity:1}}return{state:p,applied:!0}}class b{constructor(t){var o;if(this.letters=[],this.animationFrame=null,this.mouseX=0,this.mouseY=0,this.mouseMoveHandler=null,this.startTime=Date.now(),this.isDestroyed=!1,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.disintegration=t.disintegration||{enabled:!1},this.style=t.style||{},this.fadeOut=t.fadeOut||0,this.callbacks=t.callbacks,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(([e,i])=>{this.textContainer.style.setProperty(e,i)}),t.position){let e=t.position.x,i=t.position.y;if(t.position.constrainToViewport){this.container.getBoundingClientRect();const s=window.innerWidth,l=window.innerHeight,h=t.text.length*20;e!==void 0&&(e=Math.max(0,Math.min(e,s-h))),i!==void 0&&(i=Math.max(0,Math.min(i,l-50)))}e!==void 0&&(this.textContainer.style.left=`${e}px`),i!==void 0&&(this.textContainer.style.top=`${i}px`)}this.createLetters(t.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(t){t.toUpperCase().split("").forEach((e,i)=>{if(e===" "){const h=document.createTextNode(" ");this.textContainer.appendChild(h);return}const s=document.createElement("span");s.className="animated-letter",s.textContent=e,s.dataset.index=i.toString(),s.dataset.char=e,this.applyStyle(s),s.style.display="inline-block",s.style.position="relative",s.style.transition="transform 0.1s ease-out",this.textContainer.appendChild(s);const l=s.getBoundingClientRect();this.letters.push({element:s,index:i,char:e,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 o=(Date.now()-this.startTime)*.001;this.letters.forEach((e,i)=>{var u;const s=e.element.getBoundingClientRect(),l=s.left+s.width/2,h=s.top+s.height/2,a=k(l,h,this.mouseX,this.mouseY,i,this.disintegration);let c;if(a.applied)c=a.state,(u=this.callbacks)!=null&&u.onDisintegrate&&this.callbacks.onDisintegrate(i);else{const r=this.getAnimationType(i);c=this.getAnimation(r).update({x:0,y:0,rotation:0,scale:1,opacity:1},i,o,{speed:this.speed,amplitude:this.amplitude*(r==="falling"||r==="floating"?20:4)})}B(e.element,c)}),this.animationFrame=requestAnimationFrame(t)};this.animationFrame=requestAnimationFrame(t)}getAnimationType(t){return this.cycle?this.animationTypes[t%this.animationTypes.length]:this.animationTypes[0]}getAnimation(t){switch(t){case"falling":return new f;case"splitting":return new w;case"glitching":return new C;case"floating":return new v;default:return new f}}destroy(){var t;this.isDestroyed||(this.isDestroyed=!0,this.animationFrame!==null&&cancelAnimationFrame(this.animationFrame),this.mouseMoveHandler&&document.removeEventListener("mousemove",this.mouseMoveHandler),(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 x=[{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"],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"],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}];function y(n){const t=n.toLowerCase();return x.map(e=>{let i=0;for(const s of e.categories)t.includes(s)&&(i+=10);return(e.name.toLowerCase().includes(t)||t.includes(e.name.toLowerCase()))&&(i+=15),(e.description.toLowerCase().includes(t)||t.includes(e.description.toLowerCase()))&&(i+=8),e.artistic&&(i+=1),{font:e,score:i}}).filter(e=>e.score>0).sort((e,i)=>i.score-e.score).map(e=>e.font)}function M(n){return y(n)[0]}const F=new Set;function S(n){return new Promise((t,o)=>{const e=n.replace(/\s+/g,"+");if(F.has(e)){t();return}if(document.querySelector(`link[href*="fonts.googleapis.com"][href*="${e}"]`)){F.add(e),t();return}const s=document.createElement("link");s.rel="stylesheet",s.href=`https://fonts.googleapis.com/css2?family=${e}:wght@400&display=swap`,s.onload=()=>{F.add(e),t()},s.onerror=()=>{console.warn(`Failed to load Google Font: ${n}`),o(new Error(`Failed to load Google Font: ${n}`))},document.head.appendChild(s)})}function N(n){return Promise.all(n.map(t=>S(t)))}function D(n){const t=n.replace(/\s+/g,"+");return F.has(t)}function A(n,t="sans-serif"){const o=["Caveat","Dancing Script","Finger Paint","Fredericka the Great"],e=["VT323","Press Start 2P","Share Tech Mono"];let i=t;return o.includes(n)?i="cursive":e.includes(n)&&(i="monospace"),`'${n}', ${i}`}function T(n,t){const o=n.toLowerCase(),e=t.rejectedFont.toLowerCase(),i=t.negativeAspects.map(a=>a.toLowerCase()),s=t.positiveAspects.map(a=>a.toLowerCase());return y(n).filter(a=>a.googleFontsName.toLowerCase()!==e&&a.name.toLowerCase()!==e).map(a=>{let c=0;for(const r of a.categories)o.includes(r)&&(c+=5);for(const r of s)(a.categories.some(m=>m.includes(r)||r.includes(m))||a.name.toLowerCase().includes(r)||a.description.toLowerCase().includes(r))&&(c+=15);for(const r of i)(a.categories.some(m=>m.includes(r)||r.includes(m))||a.name.toLowerCase().includes(r)||a.description.toLowerCase().includes(r))&&(c-=20);const u=s.some(r=>r.includes("striking")||r.includes("artistic")||r.includes("unique"));return u&&a.artistic&&(c+=10),u&&!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 L(n,t){return T(n,t)[0]}if(typeof window<"u"){const n={AnimatedText:b,FallingAnimation:f,SplittingAnimation:w,GlitchingAnimation:C,FloatingAnimation:v,calculateDisintegration:k,fontSuggestions:x,suggestFonts:y,suggestFont:M,loadGoogleFont:S,loadGoogleFonts:N,isFontLoaded:D,getFontFamily:A,refineSuggestion:T,refineFont:L};window.TypographyToolkit=n,window.AnimatedText=b}return d.AnimatedText=b,d.FallingAnimation=f,d.FloatingAnimation=v,d.GlitchingAnimation=C,d.SplittingAnimation=w,d.calculateDisintegration=k,d.fontSuggestions=x,d.getFontFamily=A,d.isFontLoaded=D,d.loadGoogleFont=S,d.loadGoogleFonts=N,d.refineFont=L,d.refineSuggestion=T,d.suggestFont=M,d.suggestFonts=y,Object.defineProperty(d,Symbol.toStringTag,{value:"Module"}),d}({});
|
|
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 +1 @@
|
|
|
1
|
-
(function(l,m){typeof exports=="object"&&typeof module<"u"?m(exports):typeof define=="function"&&define.amd?define(["exports"],m):(l=typeof globalThis<"u"?globalThis:l||self,m(l.TypographyToolkit={}))})(this,function(l){"use strict";class m{update(t,o,e,i={}){const s=i.speed||1,c=i.amplitude||20,h=o*.2,d=(e*10*s+h*5)%c-c/2;return{...t,y:d}}}class w{update(t,o,e,i={}){const s=i.speed||1,c=i.amplitude||4,h=o*.2,n=Math.sin(e*.5*s+h)*c;return{...t,x:n}}}class C{constructor(){this.lastUpdate=0,this.glitchX=0,this.glitchY=0,this.glitchRot=0}update(t,o,e,i={}){const s=i.amplitude||3;return e-this.lastUpdate>.1&&(this.glitchX=(Math.random()-.5)*s,this.glitchY=(Math.random()-.5)*(s*.67),this.glitchRot=(Math.random()-.5)*s,this.lastUpdate=e),{...t,x:this.glitchX,y:this.glitchY,rotation:this.glitchRot}}}class v{update(t,o,e,i={}){const s=i.speed||1,c=i.amplitude||15,h=o*.2,d=-((e*8*s+h*4)%c-c/2);return{...t,y:d}}}function B(a,t){const{x:o,y:e,rotation:i,scale:s,opacity:c}=t;a.style.transform=`translate(${o}px, ${e}px) rotate(${i}deg) scale(${s})`,a.style.opacity=c.toString()}function x(a,t,o,e,i,s){if(!s.enabled)return{state:{x:0,y:0,rotation:0,scale:1,opacity:1},applied:!1};const c=s.radius||80,h=s.strength||1,n=s.behaviors||["fall-away","split-apart","explode"],d=o-a,u=e-t,r=Math.sqrt(d*d+u*u);if(r>=c)return{state:{x:0,y:0,rotation:0,scale:1,opacity:1},applied:!1};const g=(1-r/c)*h,p=Math.atan2(u,d),R=n[i%n.length];let f;switch(R){case"fall-away":const H=Math.cos(p)*g*20,G=Math.sin(p)*g*40+g*30;f={x:H,y:G,rotation:g*15,scale:1,opacity:1-g*.6};break;case"split-apart":const E=i%2===0?1:-1;f={x:E*g*50,y:(Math.random()-.5)*g*10,rotation:g*10*E,scale:1,opacity:1-g*.6};break;case"explode":const P=p+(Math.random()-.5)*.5;f={x:Math.cos(P)*g*40,y:Math.sin(P)*g*40,rotation:g*30,scale:1+g*.4,opacity:1-g*.6};break;default:f={x:0,y:0,rotation:0,scale:1,opacity:1}}return{state:f,applied:!0}}class b{constructor(t){var o;if(this.letters=[],this.animationFrame=null,this.mouseX=0,this.mouseY=0,this.mouseMoveHandler=null,this.startTime=Date.now(),this.isDestroyed=!1,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.disintegration=t.disintegration||{enabled:!1},this.style=t.style||{},this.fadeOut=t.fadeOut||0,this.callbacks=t.callbacks,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(([e,i])=>{this.textContainer.style.setProperty(e,i)}),t.position){let e=t.position.x,i=t.position.y;if(t.position.constrainToViewport){this.container.getBoundingClientRect();const s=window.innerWidth,c=window.innerHeight,h=t.text.length*20;e!==void 0&&(e=Math.max(0,Math.min(e,s-h))),i!==void 0&&(i=Math.max(0,Math.min(i,c-50)))}e!==void 0&&(this.textContainer.style.left=`${e}px`),i!==void 0&&(this.textContainer.style.top=`${i}px`)}this.createLetters(t.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(t){t.toUpperCase().split("").forEach((e,i)=>{if(e===" "){const h=document.createTextNode(" ");this.textContainer.appendChild(h);return}const s=document.createElement("span");s.className="animated-letter",s.textContent=e,s.dataset.index=i.toString(),s.dataset.char=e,this.applyStyle(s),s.style.display="inline-block",s.style.position="relative",s.style.transition="transform 0.1s ease-out",this.textContainer.appendChild(s);const c=s.getBoundingClientRect();this.letters.push({element:s,index:i,char:e,baseX:c.left,baseY:c.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 o=(Date.now()-this.startTime)*.001;this.letters.forEach((e,i)=>{var u;const s=e.element.getBoundingClientRect(),c=s.left+s.width/2,h=s.top+s.height/2,n=x(c,h,this.mouseX,this.mouseY,i,this.disintegration);let d;if(n.applied)d=n.state,(u=this.callbacks)!=null&&u.onDisintegrate&&this.callbacks.onDisintegrate(i);else{const r=this.getAnimationType(i);d=this.getAnimation(r).update({x:0,y:0,rotation:0,scale:1,opacity:1},i,o,{speed:this.speed,amplitude:this.amplitude*(r==="falling"||r==="floating"?20:4)})}B(e.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){switch(t){case"falling":return new m;case"splitting":return new w;case"glitching":return new C;case"floating":return new v;default:return new m}}destroy(){var t;this.isDestroyed||(this.isDestroyed=!0,this.animationFrame!==null&&cancelAnimationFrame(this.animationFrame),this.mouseMoveHandler&&document.removeEventListener("mousemove",this.mouseMoveHandler),(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 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"],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"],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}];function y(a){const t=a.toLowerCase();return k.map(e=>{let i=0;for(const s of e.categories)t.includes(s)&&(i+=10);return(e.name.toLowerCase().includes(t)||t.includes(e.name.toLowerCase()))&&(i+=15),(e.description.toLowerCase().includes(t)||t.includes(e.description.toLowerCase()))&&(i+=8),e.artistic&&(i+=1),{font:e,score:i}}).filter(e=>e.score>0).sort((e,i)=>i.score-e.score).map(e=>e.font)}function M(a){return y(a)[0]}const F=new Set;function S(a){return new Promise((t,o)=>{const e=a.replace(/\s+/g,"+");if(F.has(e)){t();return}if(document.querySelector(`link[href*="fonts.googleapis.com"][href*="${e}"]`)){F.add(e),t();return}const s=document.createElement("link");s.rel="stylesheet",s.href=`https://fonts.googleapis.com/css2?family=${e}:wght@400&display=swap`,s.onload=()=>{F.add(e),t()},s.onerror=()=>{console.warn(`Failed to load Google Font: ${a}`),o(new Error(`Failed to load Google Font: ${a}`))},document.head.appendChild(s)})}function N(a){return Promise.all(a.map(t=>S(t)))}function D(a){const t=a.replace(/\s+/g,"+");return F.has(t)}function A(a,t="sans-serif"){const o=["Caveat","Dancing Script","Finger Paint","Fredericka the Great"],e=["VT323","Press Start 2P","Share Tech Mono"];let i=t;return o.includes(a)?i="cursive":e.includes(a)&&(i="monospace"),`'${a}', ${i}`}function T(a,t){const o=a.toLowerCase(),e=t.rejectedFont.toLowerCase(),i=t.negativeAspects.map(n=>n.toLowerCase()),s=t.positiveAspects.map(n=>n.toLowerCase());return y(a).filter(n=>n.googleFontsName.toLowerCase()!==e&&n.name.toLowerCase()!==e).map(n=>{let d=0;for(const r of n.categories)o.includes(r)&&(d+=5);for(const r of s)(n.categories.some(p=>p.includes(r)||r.includes(p))||n.name.toLowerCase().includes(r)||n.description.toLowerCase().includes(r))&&(d+=15);for(const r of i)(n.categories.some(p=>p.includes(r)||r.includes(p))||n.name.toLowerCase().includes(r)||n.description.toLowerCase().includes(r))&&(d-=20);const u=s.some(r=>r.includes("striking")||r.includes("artistic")||r.includes("unique"));return u&&n.artistic&&(d+=10),u&&!n.artistic&&(d-=5),{font:n,score:d}}).filter(n=>n.score>0).sort((n,d)=>d.score-n.score).map(n=>n.font)}function L(a,t){return T(a,t)[0]}if(typeof window<"u"){const a={AnimatedText:b,FallingAnimation:m,SplittingAnimation:w,GlitchingAnimation:C,FloatingAnimation:v,calculateDisintegration:x,fontSuggestions:k,suggestFonts:y,suggestFont:M,loadGoogleFont:S,loadGoogleFonts:N,isFontLoaded:D,getFontFamily:A,refineSuggestion:T,refineFont:L};window.TypographyToolkit=a,window.AnimatedText=b}l.AnimatedText=b,l.FallingAnimation=m,l.FloatingAnimation=v,l.GlitchingAnimation=C,l.SplittingAnimation=w,l.calculateDisintegration=x,l.fontSuggestions=k,l.getFontFamily=A,l.isFontLoaded=D,l.loadGoogleFont=S,l.loadGoogleFonts=N,l.refineFont=L,l.refineSuggestion=T,l.suggestFont=M,l.suggestFonts=y,Object.defineProperty(l,Symbol.toStringTag,{value:"Module"})});
|
|
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"})});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "typography-toolkit",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.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",
|