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 f {
2
- update(e, o, a, t = {}) {
3
- const i = t.speed || 1, l = t.amplitude || 20, s = o * 0.2, c = (a * 10 * i + s * 5) % l - l / 2;
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
- ...e,
6
- y: c
5
+ ...t,
6
+ y: h
7
7
  };
8
8
  }
9
9
  }
10
- class C {
11
- update(e, o, a, t = {}) {
12
- const i = t.speed || 1, l = t.amplitude || 4, s = o * 0.2, n = Math.sin(a * 0.5 * i + s) * l;
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
- ...e,
15
- x: n
14
+ ...t,
15
+ x: c
16
16
  };
17
17
  }
18
18
  }
19
- class S {
19
+ class C {
20
20
  constructor() {
21
21
  this.letterStates = /* @__PURE__ */ new Map();
22
22
  }
23
- update(e, o, a, t = {}) {
24
- const i = t.amplitude || 3, l = t.speed || 1;
25
- let s = this.letterStates.get(o);
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: a,
27
+ lastUpdate: i,
28
28
  glitchX: 0,
29
29
  glitchY: 0,
30
30
  glitchRot: 0
31
- }, this.letterStates.set(o, s));
32
- const n = 0.1 / l;
33
- return a - s.lastUpdate > n && (s.glitchX = (Math.random() - 0.5) * i, s.glitchY = (Math.random() - 0.5) * (i * 0.67), s.glitchRot = (Math.random() - 0.5) * i, s.lastUpdate = a), {
34
- ...e,
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 b {
42
- update(e, o, a, t = {}) {
43
- const i = t.speed || 1, l = t.amplitude || 15, s = o * 0.2, c = -((a * 8 * i + s * 4) % l - l / 2);
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
- ...e,
46
- y: c
45
+ ...t,
46
+ y: h
47
47
  };
48
48
  }
49
49
  }
50
- function D(r, e) {
51
- const { x: o, y: a, rotation: t, scale: i, opacity: l } = e;
52
- r.style.transform = `translate(${o}px, ${a}px) rotate(${t}deg) scale(${i})`, r.style.opacity = l.toString();
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 k(r, e, o, a, t, i) {
55
- if (!i.enabled)
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 = i.radius || 80, s = i.strength || 1, n = i.behaviors || ["fall-away", "split-apart", "explode"], c = o - r, u = a - e, d = Math.sqrt(c * c + u * u);
61
- if (d >= l)
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 g = (1 - d / l) * s, h = Math.atan2(u, c), T = n[t % n.length];
67
- let m;
68
- switch (T) {
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(h) * g * 20, E = Math.sin(h) * g * 40 + g * 30;
71
- m = {
70
+ const A = Math.cos(f) * r * 20, T = Math.sin(f) * r * 40 + r * 30;
71
+ p = {
72
72
  x: A,
73
- y: E,
74
- rotation: g * 15,
73
+ y: T,
74
+ rotation: r * 15,
75
75
  scale: 1,
76
- opacity: 1 - g * 0.6
76
+ opacity: 1 - r * 0.6
77
77
  };
78
78
  break;
79
79
  case "split-apart":
80
- const w = t % 2 === 0 ? 1 : -1;
81
- m = {
82
- x: w * g * 50,
83
- y: (Math.random() - 0.5) * g * 10,
84
- rotation: g * 10 * w,
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 - g * 0.6
86
+ opacity: 1 - r * 0.6
87
87
  };
88
88
  break;
89
89
  case "explode":
90
- const F = h + (Math.random() - 0.5) * 0.5;
91
- m = {
92
- x: Math.cos(F) * g * 40,
93
- y: Math.sin(F) * g * 40,
94
- rotation: g * 30,
95
- scale: 1 + g * 0.4,
96
- opacity: 1 - g * 0.6
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
- m = { x: 0, y: 0, rotation: 0, scale: 1, opacity: 1 };
100
+ p = { x: 0, y: 0, rotation: 0, scale: 1, opacity: 1 };
101
101
  }
102
102
  return {
103
- state: m,
103
+ state: p,
104
104
  applied: !0
105
105
  };
106
106
  }
107
- class v {
108
- constructor(e) {
109
- var o;
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 = 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]) => {
111
- this.textContainer.style.setProperty(a, t);
112
- }), e.position) {
113
- let a = e.position.x, t = e.position.y;
114
- if (e.position.constrainToViewport) {
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 i = window.innerWidth, l = window.innerHeight, s = e.text.length * 20;
117
- a !== void 0 && (a = Math.max(0, Math.min(a, i - s))), t !== void 0 && (t = Math.max(0, Math.min(t, l - 50)));
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
- a !== void 0 && (this.textContainer.style.left = `${a}px`), t !== void 0 && (this.textContainer.style.top = `${t}px`);
119
+ i !== void 0 && (this.textContainer.style.left = `${i}px`), a !== void 0 && (this.textContainer.style.top = `${a}px`);
120
120
  }
121
- 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);
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(e) {
124
- e.toUpperCase().split("").forEach((a, t) => {
125
- if (a === " ") {
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 i = document.createElement("span");
131
- 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);
132
- const l = i.getBoundingClientRect();
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: i,
135
- index: t,
136
- char: a,
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(e) {
143
- 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);
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 = (e) => {
147
- this.mouseX = e.clientX, this.mouseY = e.clientY;
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 e = () => {
151
+ const t = () => {
152
152
  if (this.isDestroyed) return;
153
- const o = (Date.now() - this.startTime) * 1e-3;
154
- this.letters.forEach((a, t) => {
155
- var u;
156
- const i = a.element.getBoundingClientRect(), l = i.left + i.width / 2, s = i.top + i.height / 2, n = k(
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
- t,
161
+ a,
162
162
  this.disintegration
163
163
  );
164
- let c;
165
- if (n.applied)
166
- c = n.state, (u = this.callbacks) != null && u.onDisintegrate && this.callbacks.onDisintegrate(t);
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 d = this.getAnimationType(t);
169
- c = this.getAnimation(d).update(
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
- t,
172
- o,
171
+ a,
172
+ n,
173
173
  {
174
174
  speed: this.speed * this.animationSpeedMultiplier,
175
- amplitude: this.amplitude * (d === "falling" || d === "floating" ? 20 : 4)
175
+ amplitude: this.amplitude * (m === "falling" || m === "floating" ? 20 : 4)
176
176
  }
177
177
  );
178
178
  }
179
- D(a.element, c);
180
- }), this.animationFrame = requestAnimationFrame(e);
179
+ v(i.element, h);
180
+ }), this.animationFrame = requestAnimationFrame(t);
181
181
  };
182
- this.animationFrame = requestAnimationFrame(e);
182
+ this.animationFrame = requestAnimationFrame(t);
183
183
  }
184
- getAnimationType(e) {
185
- return this.cycle ? this.animationTypes[e % this.animationTypes.length] : this.animationTypes[0];
184
+ getAnimationType(t) {
185
+ return this.cycle ? this.animationTypes[t % this.animationTypes.length] : this.animationTypes[0];
186
186
  }
187
- getAnimation(e) {
188
- if (this.animationInstances.has(e))
189
- return this.animationInstances.get(e);
190
- let o;
191
- switch (e) {
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
- o = new f();
193
+ n = new y();
194
194
  break;
195
195
  case "splitting":
196
- o = new C();
196
+ n = new w();
197
197
  break;
198
198
  case "glitching":
199
- o = new S();
199
+ n = new C();
200
200
  break;
201
201
  case "floating":
202
- o = new b();
202
+ n = new M();
203
203
  break;
204
204
  default:
205
- o = new f();
205
+ n = new y();
206
206
  }
207
- return this.animationInstances.set(e, o), o;
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(e) {
213
- if (typeof e == "number")
214
- return e;
215
- switch (e) {
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(e) {
236
- this.animationSpeedMultiplier = this.parseAnimationSpeed(e);
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(e) {
248
- this.animationEasing = e;
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 e;
255
- 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(() => {
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 H = [
267
- "unsettling",
268
- "eerie",
269
- "decayed",
270
- "weathered",
271
- "organic",
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*="${a}"]`
275
+ `link[href*="fonts.googleapis.com"][href*="${i}"]`
601
276
  )) {
602
- p.add(a), e();
277
+ u.add(i), t();
603
278
  return;
604
279
  }
605
- const i = document.createElement("link");
606
- i.rel = "stylesheet", i.href = `https://fonts.googleapis.com/css2?family=${a}:wght@400&display=swap`, i.onload = () => {
607
- p.add(a), e();
608
- }, i.onerror = () => {
609
- console.warn(`Failed to load Google Font: ${r}`), o(new Error(`Failed to load Google Font: ${r}`));
610
- }, document.head.appendChild(i);
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 P(r) {
614
- return Promise.all(r.map((e) => N(e)));
288
+ function E(o) {
289
+ return Promise.all(o.map((t) => b(t)));
615
290
  }
616
- function B(r) {
617
- const e = r.replace(/\s+/g, "+");
618
- return p.has(e);
291
+ function D(o) {
292
+ const t = o.replace(/\s+/g, "+");
293
+ return u.has(t);
619
294
  }
620
- function G(r, e = "sans-serif") {
621
- const o = [
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
- ], a = [
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 t = e;
649
- return o.includes(r) ? t = "cursive" : a.includes(r) && (t = "monospace"), `'${r}', ${t}`;
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 r = {
674
- AnimatedText: v,
675
- FallingAnimation: f,
676
- SplittingAnimation: C,
677
- GlitchingAnimation: S,
678
- FloatingAnimation: b,
679
- calculateDisintegration: k,
680
- // Font utilities
681
- fontSuggestions: x,
682
- suggestFonts: y,
683
- suggestFont: O,
684
- loadGoogleFont: N,
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 = r, window.AnimatedText = v;
340
+ window.TypographyToolkit = o, window.AnimatedText = S;
694
341
  }
695
342
  export {
696
- v as AnimatedText,
697
- f as FallingAnimation,
698
- b as FloatingAnimation,
699
- S as GlitchingAnimation,
700
- R as INTENSITY_CATEGORIES,
701
- H as MOOD_CATEGORIES,
702
- C as SplittingAnimation,
703
- k as calculateDisintegration,
704
- x as fontSuggestions,
705
- G as getFontFamily,
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.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",