typography-toolkit 1.3.0 → 1.3.1

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,6 +1,6 @@
1
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;
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;
4
4
  return {
5
5
  ...e,
6
6
  y: c
@@ -8,54 +8,62 @@ class f {
8
8
  }
9
9
  }
10
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;
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;
13
13
  return {
14
14
  ...e,
15
- x: a
15
+ x: n
16
16
  };
17
17
  }
18
18
  }
19
19
  class S {
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), {
23
+ update(e, o, a, t = {}) {
24
+ const i = t.amplitude || 3, l = t.speed || 1;
25
+ let s = this.letterStates.get(o);
26
+ s || (s = {
27
+ lastUpdate: a,
28
+ glitchX: 0,
29
+ glitchY: 0,
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), {
26
34
  ...e,
27
- x: this.glitchX,
28
- y: this.glitchY,
29
- rotation: this.glitchRot
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 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);
36
44
  return {
37
45
  ...e,
38
46
  y: c
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 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();
45
53
  }
46
- function b(s, e, o, n, t, i) {
54
+ function k(r, e, o, a, t, i) {
47
55
  if (!i.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);
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);
53
61
  if (d >= 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];
66
+ const g = (1 - d / l) * s, h = Math.atan2(u, c), T = n[t % n.length];
59
67
  let m;
60
68
  switch (T) {
61
69
  case "fall-away":
@@ -99,33 +107,33 @@ function b(s, e, o, n, t, i) {
99
107
  class v {
100
108
  constructor(e) {
101
109
  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);
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);
104
112
  }), e.position) {
105
- let n = e.position.x, t = e.position.y;
113
+ let a = e.position.x, t = e.position.y;
106
114
  if (e.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 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)));
110
118
  }
111
- n !== void 0 && (this.textContainer.style.left = `${n}px`), t !== void 0 && (this.textContainer.style.top = `${t}px`);
119
+ a !== void 0 && (this.textContainer.style.left = `${a}px`), t !== void 0 && (this.textContainer.style.top = `${t}px`);
112
120
  }
113
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);
114
122
  }
115
123
  createLetters(e) {
116
- e.toUpperCase().split("").forEach((n, t) => {
117
- if (n === " ") {
118
- const r = document.createTextNode(" ");
119
- this.textContainer.appendChild(r);
124
+ e.toUpperCase().split("").forEach((a, t) => {
125
+ if (a === " ") {
126
+ const s = document.createTextNode(" ");
127
+ this.textContainer.appendChild(s);
120
128
  return;
121
129
  }
122
130
  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);
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);
124
132
  const l = i.getBoundingClientRect();
125
133
  this.letters.push({
126
134
  element: i,
127
135
  index: t,
128
- char: n,
136
+ char: a,
129
137
  baseX: l.left,
130
138
  baseY: l.top
131
139
  });
@@ -143,19 +151,19 @@ class v {
143
151
  const e = () => {
144
152
  if (this.isDestroyed) return;
145
153
  const o = (Date.now() - this.startTime) * 1e-3;
146
- this.letters.forEach((n, t) => {
154
+ this.letters.forEach((a, t) => {
147
155
  var u;
148
- const i = n.element.getBoundingClientRect(), l = i.left + i.width / 2, r = i.top + i.height / 2, a = b(
156
+ const i = a.element.getBoundingClientRect(), l = i.left + i.width / 2, s = i.top + i.height / 2, n = k(
149
157
  l,
150
- r,
158
+ s,
151
159
  this.mouseX,
152
160
  this.mouseY,
153
161
  t,
154
162
  this.disintegration
155
163
  );
156
164
  let c;
157
- if (a.applied)
158
- c = a.state, (u = this.callbacks) != null && u.onDisintegrate && this.callbacks.onDisintegrate(t);
165
+ if (n.applied)
166
+ c = n.state, (u = this.callbacks) != null && u.onDisintegrate && this.callbacks.onDisintegrate(t);
159
167
  else {
160
168
  const d = this.getAnimationType(t);
161
169
  c = this.getAnimation(d).update(
@@ -168,7 +176,7 @@ class v {
168
176
  }
169
177
  );
170
178
  }
171
- D(n.element, c);
179
+ D(a.element, c);
172
180
  }), this.animationFrame = requestAnimationFrame(e);
173
181
  };
174
182
  this.animationFrame = requestAnimationFrame(e);
@@ -177,18 +185,26 @@ class v {
177
185
  return this.cycle ? this.animationTypes[e % this.animationTypes.length] : this.animationTypes[0];
178
186
  }
179
187
  getAnimation(e) {
188
+ if (this.animationInstances.has(e))
189
+ return this.animationInstances.get(e);
190
+ let o;
180
191
  switch (e) {
181
192
  case "falling":
182
- return new f();
193
+ o = new f();
194
+ break;
183
195
  case "splitting":
184
- return new C();
196
+ o = new C();
197
+ break;
185
198
  case "glitching":
186
- return new S();
199
+ o = new S();
200
+ break;
187
201
  case "floating":
188
- return new x();
202
+ o = new b();
203
+ break;
189
204
  default:
190
- return new f();
205
+ o = new f();
191
206
  }
207
+ return this.animationInstances.set(e, o), o;
192
208
  }
193
209
  /**
194
210
  * Parse animation speed preset or numeric value to a multiplier
@@ -236,7 +252,7 @@ class v {
236
252
  */
237
253
  destroy() {
238
254
  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(() => {
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(() => {
240
256
  this.textContainer.parentNode && this.textContainer.parentNode.removeChild(this.textContainer);
241
257
  }, 3e3));
242
258
  }
@@ -256,7 +272,7 @@ const H = [
256
272
  "imperfect",
257
273
  "uneven",
258
274
  "scratchy"
259
- ], R = ["subtle", "moderate", "intense"], k = [
275
+ ], R = ["subtle", "moderate", "intense"], x = [
260
276
  // Hand-drawn / Handwriting
261
277
  {
262
278
  name: "Hand-drawn Casual",
@@ -535,73 +551,73 @@ const H = [
535
551
  artistic: !0
536
552
  }
537
553
  ];
538
- function L(s) {
539
- const e = s.toLowerCase().split(/\s+/).filter((t) => t.length > 0), o = [], n = [];
554
+ function L(r) {
555
+ const e = r.toLowerCase().split(/\s+/).filter((t) => t.length > 0), o = [], a = [];
540
556
  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 };
557
+ t.startsWith("-") && t.length > 1 ? a.push(t.slice(1)) : o.push(t);
558
+ return { positive: o, negative: a };
543
559
  }
544
- function O(s, e) {
545
- const o = /* @__PURE__ */ new Set(), n = /* @__PURE__ */ new Map(), t = 2, i = [];
546
- for (const l of s) {
560
+ function I(r, e) {
561
+ const o = /* @__PURE__ */ new Set(), a = /* @__PURE__ */ new Map(), t = 2, i = [];
562
+ for (const l of r) {
547
563
  if (i.length >= e) break;
548
564
  if (o.has(l.font.googleFontsName))
549
565
  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));
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));
552
568
  }
553
569
  return i;
554
570
  }
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;
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;
558
574
  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);
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);
562
578
  }
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);
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);
567
583
  }
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);
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);
571
587
  }
572
- function P(s) {
573
- return y(s)[0];
588
+ function O(r) {
589
+ return y(r)[0];
574
590
  }
575
591
  const p = /* @__PURE__ */ new Set();
576
- function N(s) {
592
+ function N(r) {
577
593
  return new Promise((e, o) => {
578
- const n = s.replace(/\s+/g, "+");
579
- if (p.has(n)) {
594
+ const a = r.replace(/\s+/g, "+");
595
+ if (p.has(a)) {
580
596
  e();
581
597
  return;
582
598
  }
583
599
  if (document.querySelector(
584
- `link[href*="fonts.googleapis.com"][href*="${n}"]`
600
+ `link[href*="fonts.googleapis.com"][href*="${a}"]`
585
601
  )) {
586
- p.add(n), e();
602
+ p.add(a), e();
587
603
  return;
588
604
  }
589
605
  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();
606
+ i.rel = "stylesheet", i.href = `https://fonts.googleapis.com/css2?family=${a}:wght@400&display=swap`, i.onload = () => {
607
+ p.add(a), e();
592
608
  }, i.onerror = () => {
593
- console.warn(`Failed to load Google Font: ${s}`), o(new Error(`Failed to load Google Font: ${s}`));
609
+ console.warn(`Failed to load Google Font: ${r}`), o(new Error(`Failed to load Google Font: ${r}`));
594
610
  }, document.head.appendChild(i);
595
611
  });
596
612
  }
597
- function B(s) {
598
- return Promise.all(s.map((e) => N(e)));
613
+ function P(r) {
614
+ return Promise.all(r.map((e) => N(e)));
599
615
  }
600
- function G(s) {
601
- const e = s.replace(/\s+/g, "+");
616
+ function B(r) {
617
+ const e = r.replace(/\s+/g, "+");
602
618
  return p.has(e);
603
619
  }
604
- function I(s, e = "sans-serif") {
620
+ function G(r, e = "sans-serif") {
605
621
  const o = [
606
622
  "Caveat",
607
623
  "Dancing Script",
@@ -621,7 +637,7 @@ function I(s, e = "sans-serif") {
621
637
  "Kalam",
622
638
  "Satisfy",
623
639
  "Yellowtail"
624
- ], n = [
640
+ ], a = [
625
641
  "VT323",
626
642
  "Press Start 2P",
627
643
  "Share Tech Mono",
@@ -630,68 +646,68 @@ function I(s, e = "sans-serif") {
630
646
  "Cutive Mono"
631
647
  ];
632
648
  let t = e;
633
- return o.includes(s) ? t = "cursive" : n.includes(s) && (t = "monospace"), `'${s}', ${t}`;
649
+ return o.includes(r) ? t = "cursive" : a.includes(r) && (t = "monospace"), `'${r}', ${t}`;
634
650
  }
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) => {
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) => {
640
656
  let c = 0;
641
- for (const d of a.categories)
657
+ for (const d of n.categories)
642
658
  o.includes(d) && (c += 5);
643
659
  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);
660
+ (n.categories.some((h) => h.includes(d) || d.includes(h)) || n.name.toLowerCase().includes(d) || n.description.toLowerCase().includes(d)) && (c += 15);
645
661
  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);
662
+ (n.categories.some((h) => h.includes(d) || d.includes(h)) || n.name.toLowerCase().includes(d) || n.description.toLowerCase().includes(d)) && (c -= 20);
647
663
  const u = i.some(
648
664
  (d) => d.includes("striking") || d.includes("artistic") || d.includes("unique")
649
665
  );
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);
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);
652
668
  }
653
- function Y(s, e) {
654
- return M(s, e)[0];
669
+ function Y(r, e) {
670
+ return M(r, e)[0];
655
671
  }
656
672
  if (typeof window < "u") {
657
- const s = {
673
+ const r = {
658
674
  AnimatedText: v,
659
675
  FallingAnimation: f,
660
676
  SplittingAnimation: C,
661
677
  GlitchingAnimation: S,
662
- FloatingAnimation: x,
663
- calculateDisintegration: b,
678
+ FloatingAnimation: b,
679
+ calculateDisintegration: k,
664
680
  // Font utilities
665
- fontSuggestions: k,
681
+ fontSuggestions: x,
666
682
  suggestFonts: y,
667
- suggestFont: P,
683
+ suggestFont: O,
668
684
  loadGoogleFont: N,
669
- loadGoogleFonts: B,
670
- isFontLoaded: G,
671
- getFontFamily: I,
685
+ loadGoogleFonts: P,
686
+ isFontLoaded: B,
687
+ getFontFamily: G,
672
688
  refineSuggestion: M,
673
689
  refineFont: Y,
674
690
  MOOD_CATEGORIES: H,
675
691
  INTENSITY_CATEGORIES: R
676
692
  };
677
- window.TypographyToolkit = s, window.AnimatedText = v;
693
+ window.TypographyToolkit = r, window.AnimatedText = v;
678
694
  }
679
695
  export {
680
696
  v as AnimatedText,
681
697
  f as FallingAnimation,
682
- x as FloatingAnimation,
698
+ b as FloatingAnimation,
683
699
  S as GlitchingAnimation,
684
700
  R as INTENSITY_CATEGORIES,
685
701
  H as MOOD_CATEGORIES,
686
702
  C as SplittingAnimation,
687
- b as calculateDisintegration,
688
- k as fontSuggestions,
689
- I as getFontFamily,
690
- G as isFontLoaded,
703
+ k as calculateDisintegration,
704
+ x as fontSuggestions,
705
+ G as getFontFamily,
706
+ B as isFontLoaded,
691
707
  N as loadGoogleFont,
692
- B as loadGoogleFonts,
708
+ P as loadGoogleFonts,
693
709
  Y as refineFont,
694
710
  M as refineSuggestion,
695
- P as suggestFont,
711
+ O as suggestFont,
696
712
  y as suggestFonts
697
713
  };
@@ -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(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 +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(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"})});
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "typography-toolkit",
3
- "version": "1.3.0",
3
+ "version": "1.3.1",
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",