typography-toolkit 1.3.0 → 1.4.0

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