@cosmictraveler002/anim-kit 1.0.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. package/README.md +275 -50
  2. package/dist/anim-kit.standalone.js +18 -8
  3. package/dist/anim-kit.standalone.js.map +1 -1
  4. package/dist/core/gsap.d.ts +2 -1
  5. package/dist/core/gsap.d.ts.map +1 -1
  6. package/dist/core/gsap.js +3 -2
  7. package/dist/core/gsap.js.map +1 -1
  8. package/dist/core/split.d.ts.map +1 -1
  9. package/dist/core/split.js +15 -2
  10. package/dist/core/split.js.map +1 -1
  11. package/dist/effects/clip-wipe.d.ts +31 -0
  12. package/dist/effects/clip-wipe.d.ts.map +1 -0
  13. package/dist/effects/clip-wipe.js +82 -0
  14. package/dist/effects/clip-wipe.js.map +1 -0
  15. package/dist/effects/counter.d.ts +9 -0
  16. package/dist/effects/counter.d.ts.map +1 -1
  17. package/dist/effects/counter.js +17 -7
  18. package/dist/effects/counter.js.map +1 -1
  19. package/dist/effects/cursor-follower.d.ts.map +1 -1
  20. package/dist/effects/cursor-follower.js +22 -4
  21. package/dist/effects/cursor-follower.js.map +1 -1
  22. package/dist/effects/flip-words.d.ts +31 -0
  23. package/dist/effects/flip-words.d.ts.map +1 -0
  24. package/dist/effects/flip-words.js +104 -0
  25. package/dist/effects/flip-words.js.map +1 -0
  26. package/dist/effects/line-reveal.d.ts +6 -2
  27. package/dist/effects/line-reveal.d.ts.map +1 -1
  28. package/dist/effects/line-reveal.js +8 -4
  29. package/dist/effects/line-reveal.js.map +1 -1
  30. package/dist/effects/magnetic.d.ts +15 -0
  31. package/dist/effects/magnetic.d.ts.map +1 -0
  32. package/dist/effects/magnetic.js +59 -0
  33. package/dist/effects/magnetic.js.map +1 -0
  34. package/dist/effects/media-settle.d.ts +30 -0
  35. package/dist/effects/media-settle.d.ts.map +1 -0
  36. package/dist/effects/media-settle.js +55 -0
  37. package/dist/effects/media-settle.js.map +1 -0
  38. package/dist/effects/roll-text.d.ts +13 -0
  39. package/dist/effects/roll-text.d.ts.map +1 -0
  40. package/dist/effects/roll-text.js +91 -0
  41. package/dist/effects/roll-text.js.map +1 -0
  42. package/dist/effects/scramble-text.d.ts +17 -0
  43. package/dist/effects/scramble-text.d.ts.map +1 -0
  44. package/dist/effects/scramble-text.js +93 -0
  45. package/dist/effects/scramble-text.js.map +1 -0
  46. package/dist/effects/unfold-reveal.d.ts +23 -0
  47. package/dist/effects/unfold-reveal.d.ts.map +1 -0
  48. package/dist/effects/unfold-reveal.js +53 -0
  49. package/dist/effects/unfold-reveal.js.map +1 -0
  50. package/dist/index.d.ts +25 -2
  51. package/dist/index.d.ts.map +1 -1
  52. package/dist/index.js +19 -2
  53. package/dist/index.js.map +1 -1
  54. package/dist/styles/anim-kit.css +22 -0
  55. package/package.json +6 -3
  56. package/src/core/gsap.ts +3 -2
  57. package/src/core/split.ts +16 -2
  58. package/src/effects/clip-wipe.ts +141 -0
  59. package/src/effects/counter.ts +26 -6
  60. package/src/effects/cursor-follower.ts +21 -4
  61. package/src/effects/flip-words.ts +148 -0
  62. package/src/effects/line-reveal.ts +12 -5
  63. package/src/effects/magnetic.ts +87 -0
  64. package/src/effects/media-settle.ts +106 -0
  65. package/src/effects/roll-text.ts +118 -0
  66. package/src/effects/scramble-text.ts +122 -0
  67. package/src/effects/unfold-reveal.ts +92 -0
  68. package/src/index.ts +33 -2
  69. package/src/styles/anim-kit.css +22 -0
package/dist/index.d.ts CHANGED
@@ -7,26 +7,35 @@
7
7
  * split() text splitting with mask support
8
8
  *
9
9
  * Scroll effects:
10
- * lineReveal() masked staggered text reveal
10
+ * lineReveal() masked staggered text reveal (lines or chars)
11
11
  * maskReveal() inline overflow-hidden heading reveal
12
12
  * revealRule() line that draws to full width
13
+ * unfoldReveal() blocks that scale open from an edge
14
+ * clipWipe() clip-path inset wipe reveal
13
15
  * parallax() data-speed parallax
14
16
  * horizontalScroll() pinned horizontal gallery
15
17
  * stackedCards() / stackedCardsPinned() pinned card deck
16
18
  * scatterText() pinned horizontal band with per-char settle
17
19
  * heroShrink() media that scales down as it scrolls away
20
+ * mediaSettle() media that settles from a larger entrance scale
18
21
  * navHide() header that hides on scroll-down
19
22
  * logoReveal() SVG wordmark assembling letter by letter
20
23
  *
21
24
  * Infinite / loops:
22
25
  * marquee() dual-row constant-speed marquee
23
26
  * dragStrip() infinite draggable carousel with rotation
27
+ * rollText() rolling word rotator (seamless row loop)
28
+ *
29
+ * Text extras:
30
+ * scrambleText() decode / cipher reveal per character
31
+ * flipWords() words that glide between two layouts (FLIP)
24
32
  *
25
33
  * Micro-interactions:
26
34
  * liquidButton() SVG wave flood on hover
27
35
  * underlineLink() underline wipe on hover
28
36
  * cursorFollower() spring-follow cursor tag
29
- * counter() tabular number ticker
37
+ * magnetic() elements that pull toward the pointer and spring back
38
+ * counter() tabular number ticker (timed or scroll-progress)
30
39
  * audioBars() equaliser visualiser
31
40
  * themeReveal() View Transitions circular wipe
32
41
  * menuOverlay() clip-path curtain menu
@@ -44,6 +53,10 @@ export { lineReveal } from "./effects/line-reveal.js";
44
53
  export type { LineRevealOptions } from "./effects/line-reveal.js";
45
54
  export { maskReveal, revealRule } from "./effects/mask-reveal.js";
46
55
  export type { MaskRevealOptions } from "./effects/mask-reveal.js";
56
+ export { unfoldReveal } from "./effects/unfold-reveal.js";
57
+ export type { UnfoldRevealOptions } from "./effects/unfold-reveal.js";
58
+ export { clipWipe } from "./effects/clip-wipe.js";
59
+ export type { ClipWipeOptions, ClipWipeFrom } from "./effects/clip-wipe.js";
47
60
  export { parallax } from "./effects/parallax.js";
48
61
  export type { ParallaxOptions } from "./effects/parallax.js";
49
62
  export { horizontalScroll } from "./effects/horizontal-scroll.js";
@@ -54,18 +67,28 @@ export { scatterText } from "./effects/scatter-text.js";
54
67
  export type { ScatterTextOptions } from "./effects/scatter-text.js";
55
68
  export { heroShrink } from "./effects/hero-shrink.js";
56
69
  export type { HeroShrinkOptions } from "./effects/hero-shrink.js";
70
+ export { mediaSettle } from "./effects/media-settle.js";
71
+ export type { MediaSettleOptions } from "./effects/media-settle.js";
57
72
  export { navHide } from "./effects/nav-hide.js";
58
73
  export type { NavHideOptions } from "./effects/nav-hide.js";
59
74
  export { logoReveal } from "./effects/logo-reveal.js";
60
75
  export type { LogoRevealOptions } from "./effects/logo-reveal.js";
61
76
  export { marquee } from "./effects/marquee.js";
62
77
  export type { MarqueeOptions } from "./effects/marquee.js";
78
+ export { rollText } from "./effects/roll-text.js";
79
+ export type { RollTextOptions } from "./effects/roll-text.js";
63
80
  export { dragStrip } from "./effects/drag-strip.js";
64
81
  export type { DragStripOptions } from "./effects/drag-strip.js";
82
+ export { scrambleText } from "./effects/scramble-text.js";
83
+ export type { ScrambleTextOptions } from "./effects/scramble-text.js";
84
+ export { flipWords } from "./effects/flip-words.js";
85
+ export type { FlipWordsOptions } from "./effects/flip-words.js";
65
86
  export { liquidButton, underlineLink } from "./effects/liquid-button.js";
66
87
  export type { LiquidButtonOptions } from "./effects/liquid-button.js";
67
88
  export { cursorFollower } from "./effects/cursor-follower.js";
68
89
  export type { CursorFollowerOptions } from "./effects/cursor-follower.js";
90
+ export { magnetic } from "./effects/magnetic.js";
91
+ export type { MagneticOptions } from "./effects/magnetic.js";
69
92
  export { counter, audioBars } from "./effects/counter.js";
70
93
  export type { CounterOptions, AudioBarsOptions, AudioBarsHandle } from "./effects/counter.js";
71
94
  export { themeReveal } from "./effects/theme-reveal.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -7,26 +7,35 @@
7
7
  * split() text splitting with mask support
8
8
  *
9
9
  * Scroll effects:
10
- * lineReveal() masked staggered text reveal
10
+ * lineReveal() masked staggered text reveal (lines or chars)
11
11
  * maskReveal() inline overflow-hidden heading reveal
12
12
  * revealRule() line that draws to full width
13
+ * unfoldReveal() blocks that scale open from an edge
14
+ * clipWipe() clip-path inset wipe reveal
13
15
  * parallax() data-speed parallax
14
16
  * horizontalScroll() pinned horizontal gallery
15
17
  * stackedCards() / stackedCardsPinned() pinned card deck
16
18
  * scatterText() pinned horizontal band with per-char settle
17
19
  * heroShrink() media that scales down as it scrolls away
20
+ * mediaSettle() media that settles from a larger entrance scale
18
21
  * navHide() header that hides on scroll-down
19
22
  * logoReveal() SVG wordmark assembling letter by letter
20
23
  *
21
24
  * Infinite / loops:
22
25
  * marquee() dual-row constant-speed marquee
23
26
  * dragStrip() infinite draggable carousel with rotation
27
+ * rollText() rolling word rotator (seamless row loop)
28
+ *
29
+ * Text extras:
30
+ * scrambleText() decode / cipher reveal per character
31
+ * flipWords() words that glide between two layouts (FLIP)
24
32
  *
25
33
  * Micro-interactions:
26
34
  * liquidButton() SVG wave flood on hover
27
35
  * underlineLink() underline wipe on hover
28
36
  * cursorFollower() spring-follow cursor tag
29
- * counter() tabular number ticker
37
+ * magnetic() elements that pull toward the pointer and spring back
38
+ * counter() tabular number ticker (timed or scroll-progress)
30
39
  * audioBars() equaliser visualiser
31
40
  * themeReveal() View Transitions circular wipe
32
41
  * menuOverlay() clip-path curtain menu
@@ -41,19 +50,27 @@ export { toArray, one, onReady, compose, raf, prefersReducedMotion } from "./cor
41
50
  /* ---- scroll effects ---- */
42
51
  export { lineReveal } from "./effects/line-reveal.js";
43
52
  export { maskReveal, revealRule } from "./effects/mask-reveal.js";
53
+ export { unfoldReveal } from "./effects/unfold-reveal.js";
54
+ export { clipWipe } from "./effects/clip-wipe.js";
44
55
  export { parallax } from "./effects/parallax.js";
45
56
  export { horizontalScroll } from "./effects/horizontal-scroll.js";
46
57
  export { stackedCards, stackedCardsPinned } from "./effects/stacked-cards.js";
47
58
  export { scatterText } from "./effects/scatter-text.js";
48
59
  export { heroShrink } from "./effects/hero-shrink.js";
60
+ export { mediaSettle } from "./effects/media-settle.js";
49
61
  export { navHide } from "./effects/nav-hide.js";
50
62
  export { logoReveal } from "./effects/logo-reveal.js";
51
63
  /* ---- loops ---- */
52
64
  export { marquee } from "./effects/marquee.js";
65
+ export { rollText } from "./effects/roll-text.js";
53
66
  export { dragStrip } from "./effects/drag-strip.js";
67
+ /* ---- text extras ---- */
68
+ export { scrambleText } from "./effects/scramble-text.js";
69
+ export { flipWords } from "./effects/flip-words.js";
54
70
  /* ---- micro-interactions ---- */
55
71
  export { liquidButton, underlineLink } from "./effects/liquid-button.js";
56
72
  export { cursorFollower } from "./effects/cursor-follower.js";
73
+ export { magnetic } from "./effects/magnetic.js";
57
74
  export { counter, audioBars } from "./effects/counter.js";
58
75
  export { themeReveal } from "./effects/theme-reveal.js";
59
76
  export { menuOverlay } from "./effects/menu-overlay.js";
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAEH,oBAAoB;AACpB,OAAO,EAAE,IAAI,EAAE,aAAa,EAAE,SAAS,EAAE,SAAS,EAAE,UAAU,EAAE,cAAc,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAExH,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AAExC,OAAO,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AACxC,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAG3F,8BAA8B;AAC9B,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAGtD,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAGlE,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAGjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AAGlE,OAAO,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAG9E,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAGxD,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAGtD,OAAO,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAGhD,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAGtD,qBAAqB;AACrB,OAAO,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAG/C,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAGpD,kCAAkC;AAClC,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAGzE,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAG9D,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAG1D,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAGxD,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAGxD,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AAEH,oBAAoB;AACpB,OAAO,EAAE,IAAI,EAAE,aAAa,EAAE,SAAS,EAAE,SAAS,EAAE,UAAU,EAAE,cAAc,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAExH,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AAExC,OAAO,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AACxC,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAG3F,8BAA8B;AAC9B,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAGtD,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAGlE,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAG1D,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAGlD,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAGjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AAGlE,OAAO,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAG9E,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAGxD,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAGtD,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAGxD,OAAO,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAGhD,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAGtD,qBAAqB;AACrB,OAAO,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAG/C,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAGlD,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAGpD,2BAA2B;AAC3B,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAG1D,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAGpD,kCAAkC;AAClC,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAGzE,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAG9D,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAGjD,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAG1D,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAGxD,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAGxD,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC"}
@@ -43,6 +43,13 @@
43
43
  will-change: transform;
44
44
  }
45
45
 
46
+ /* Per-char masks produced by lineReveal({ split: "chars" }) / split(). */
47
+ .ak-char-mask {
48
+ display: inline-block;
49
+ overflow: clip;
50
+ vertical-align: bottom;
51
+ }
52
+
46
53
  .ak-space {
47
54
  display: inline-block;
48
55
  white-space: pre;
@@ -197,6 +204,21 @@
197
204
  background: linear-gradient(to left, var(--ak-background, #fff) 0%, transparent 100%);
198
205
  }
199
206
 
207
+ /* ------------------------------------------------------------------ */
208
+ /* Rolling text (rollText) */
209
+ /* ------------------------------------------------------------------ */
210
+
211
+ /* The effect measures a row, then sets the box height + overflow inline so
212
+ teardown can restore authored styles exactly. This is the authored base. */
213
+ .ak-roll {
214
+ display: inline-block;
215
+ vertical-align: bottom;
216
+ }
217
+
218
+ .ak-roll__inner {
219
+ will-change: transform;
220
+ }
221
+
200
222
  /* ------------------------------------------------------------------ */
201
223
  /* Drag strip */
202
224
  /* ------------------------------------------------------------------ */
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@cosmictraveler002/anim-kit",
3
- "version": "1.0.0",
4
- "description": "Modular, framework-agnostic animation library inspired by dzinrstudio.com — GSAP + ScrollTrigger + Lenis effects packaged as composable ES modules.",
3
+ "version": "1.2.0",
4
+ "description": "Modular, framework-agnostic animation library — GSAP + ScrollTrigger + Lenis effects packaged as composable ES modules.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
7
7
  "module": "./dist/index.js",
@@ -68,12 +68,15 @@
68
68
  "publishConfig": {
69
69
  "access": "public"
70
70
  },
71
+ "engines": {
72
+ "node": ">=20.0.0"
73
+ },
71
74
  "dependencies": {
72
75
  "gsap": "^3.13.0",
73
76
  "lenis": "^1.3.11"
74
77
  },
75
78
  "devDependencies": {
76
- "jsdom": "^30.1.1",
79
+ "jsdom": "^25.0.1",
77
80
  "tsup": "^8.5.1",
78
81
  "typescript": "^5.7.3"
79
82
  }
package/src/core/gsap.ts CHANGED
@@ -10,10 +10,11 @@ import { SplitText } from "gsap/SplitText";
10
10
  import { Draggable } from "gsap/Draggable";
11
11
  import { CustomEase } from "gsap/CustomEase";
12
12
  import { ScrollSmoother } from "gsap/ScrollSmoother";
13
+ import { Flip } from "gsap/Flip";
13
14
  import { toArray } from "./util.js";
14
15
  import type { TargetLike } from "./types.js";
15
16
 
16
- export { gsap, ScrollTrigger, SplitText, Draggable, CustomEase, ScrollSmoother };
17
+ export { gsap, ScrollTrigger, SplitText, Draggable, CustomEase, ScrollSmoother, Flip };
17
18
 
18
19
  /** Named eases recovered from dzinrstudio.com's bundles. */
19
20
  export const EASES = {
@@ -34,7 +35,7 @@ export function initGSAP(): void {
34
35
  if (initted || typeof window === "undefined") return;
35
36
  initted = true;
36
37
 
37
- gsap.registerPlugin(ScrollTrigger, SplitText, Draggable, CustomEase);
38
+ gsap.registerPlugin(ScrollTrigger, SplitText, Draggable, CustomEase, Flip);
38
39
 
39
40
  // ScrollSmoother is a bonus for people who prefer it over Lenis; it is only
40
41
  // registered so `ScrollSmoother.create()` works if you call it yourself.
package/src/core/split.ts CHANGED
@@ -42,12 +42,16 @@ export function split(target: Element | string, options: SplitOptions): SplitRes
42
42
 
43
43
  if (!el) return { elements: [], revert: () => {} };
44
44
 
45
+ const primary = Array.isArray(options.type) ? options.type[0] : options.type;
46
+
45
47
  // Prefer SplitText: it handles nested markup, <br> and font metrics properly.
46
48
  if (typeof SplitText !== "undefined" && SplitText?.create) {
47
49
  try {
48
50
  const st = SplitText.create(el, {
49
51
  type: options.type,
50
- mask: options.mask ? "lines" : undefined,
52
+ // Mask the primary split type — "lines" for text reveals, "chars" for
53
+ // per-character masked reveals (each fragment gets a -mask wrapper).
54
+ mask: options.mask ? primary : undefined,
51
55
  linesClass: options.linesClass ?? "ak-line++",
52
56
  wordsClass: options.wordsClass ?? "ak-word++",
53
57
  charsClass: options.charsClass ?? "ak-char++",
@@ -98,6 +102,16 @@ function manualSplit(el: HTMLElement, options: SplitOptions): SplitResult {
98
102
  span.className = cls.replace("++", String(i));
99
103
  span.textContent = text;
100
104
  generated.push(span);
105
+ if (options.mask && type === "chars") {
106
+ // Mirror SplitText: each char inside an overflow-hidden mask wrapper.
107
+ // Return the wrapper so the caller inserts mask > span intact.
108
+ const mask = document.createElement("span");
109
+ mask.className = `${span.className}-mask`;
110
+ mask.style.overflow = "hidden";
111
+ mask.style.display = "inline-block";
112
+ mask.appendChild(span);
113
+ return mask;
114
+ }
101
115
  return span;
102
116
  };
103
117
 
@@ -131,7 +145,7 @@ function manualSplit(el: HTMLElement, options: SplitOptions): SplitResult {
131
145
  el.innerHTML = "";
132
146
  el.appendChild(frag);
133
147
 
134
- if (options.mask) {
148
+ if (options.mask && type !== "chars") {
135
149
  gsap.set(generated, { display: "inline-block" });
136
150
  }
137
151
 
@@ -0,0 +1,141 @@
1
+ /**
2
+ * Clip wipe — a `clip-path: inset()` reveal.
3
+ *
4
+ * The element is collapsed behind one edge, corner (or inside a frame margin)
5
+ * and the inset animates to zero, wiping it into view:
6
+ *
7
+ * from: "left" inset(0 100% 0 0) → grows rightward from the left edge
8
+ * from: "right" inset(0 0 0 100%) → grows leftward from the right edge
9
+ * from: "top" inset(0 0 100% 0) → grows downward from the top edge
10
+ * from: "bottom" inset(100% 0 0 0) → grows upward from the bottom edge
11
+ * from: "top-left" inset(0 100% 100% 0) → opens toward the bottom-right corner
12
+ * from: "top-right" inset(0 0 100% 100%) → opens toward the bottom-left corner
13
+ * from: "bottom-left" inset(100% 100% 0 0) → opens toward the top-right corner
14
+ * from: "bottom-right" inset(100% 0 0 100%) → opens toward the top-left corner
15
+ * from: "frame" inset(15% 15% 15% 15%) → opens out of a centered frame
16
+ *
17
+ * The wipe can also be bound to scroll progress (`scrub`), so the inset
18
+ * opens as the element travels through the viewport — the reveal then
19
+ * reverses with the scroll instead of playing once.
20
+ *
21
+ * Works on images, videos, blocks and text. destroy() kills the tween and
22
+ * removes the inline clip-path.
23
+ */
24
+ import { gsap, ScrollTrigger, initGSAP } from "../core/gsap.js";
25
+ import { guard } from "../core/guard.js";
26
+ import { toArray } from "../core/util.js";
27
+ import type { CommonOptions, Destroy, TargetLike } from "../core/types.js";
28
+
29
+ export type ClipWipeFrom =
30
+ | "left"
31
+ | "right"
32
+ | "top"
33
+ | "bottom"
34
+ | "top-left"
35
+ | "top-right"
36
+ | "bottom-left"
37
+ | "bottom-right"
38
+ | "frame";
39
+
40
+ export interface ClipWipeOptions extends CommonOptions {
41
+ /** Which edge or corner the wipe starts from. @default "left" */
42
+ from?: ClipWipeFrom;
43
+ /** Frame margin in % (only used when `from: "frame"`). @default 15 */
44
+ inset?: number;
45
+ /** Animation duration, seconds. @default 1 */
46
+ duration?: number;
47
+ /** GSAP ease. @default "power3.out" */
48
+ ease?: string;
49
+ /** Stagger between targets, seconds. @default 0.08 */
50
+ stagger?: number;
51
+ /** Delay before playing, seconds. @default 0 */
52
+ delay?: number;
53
+ /** "scroll" plays on enter, "immediate" plays at once. @default "scroll" */
54
+ mode?: "scroll" | "immediate";
55
+ /** ScrollTrigger start position. @default "top 85%" */
56
+ start?: string;
57
+ /** ScrollTrigger end position (scrub mode). @default "top 20%" */
58
+ end?: string;
59
+ /** Re-wipe when leaving / re-entering the viewport. @default false */
60
+ replay?: boolean;
61
+ /**
62
+ * Bind the wipe to scroll progress instead of playing it on enter —
63
+ * number = scrub smoothing seconds, `true` = immediate. unset = one-shot.
64
+ */
65
+ scrub?: number | boolean;
66
+ }
67
+
68
+ const FROM: Record<string, string> = {
69
+ left: "inset(0% 100% 0% 0%)",
70
+ right: "inset(0% 0% 0% 100%)",
71
+ top: "inset(0% 0% 100% 0%)",
72
+ bottom: "inset(100% 0% 0% 0%)",
73
+ "top-left": "inset(0% 100% 100% 0%)",
74
+ "top-right": "inset(0% 0% 100% 100%)",
75
+ "bottom-left": "inset(100% 100% 0% 0%)",
76
+ "bottom-right": "inset(100% 0% 0% 100%)",
77
+ };
78
+ const TO = "inset(0% 0% 0% 0%)";
79
+
80
+ export function clipWipe(target: TargetLike, options: ClipWipeOptions = {}): Destroy {
81
+ initGSAP();
82
+
83
+ const {
84
+ from = "left",
85
+ inset = 15,
86
+ duration = 1,
87
+ ease = "power3.out",
88
+ stagger = 0.08,
89
+ delay = 0,
90
+ mode = "scroll",
91
+ start = "top 85%",
92
+ end = "top 20%",
93
+ replay = false,
94
+ scrub,
95
+ } = options;
96
+
97
+ const els = toArray<HTMLElement>(target);
98
+ if (!els.length) return () => {};
99
+
100
+ return guard(options, run);
101
+
102
+ function run(): Destroy {
103
+ const startClip = from === "frame" ? `inset(${inset}% ${inset}% ${inset}% ${inset}%)` : FROM[from];
104
+
105
+ gsap.set(els, { clipPath: startClip });
106
+
107
+ const vars: gsap.TweenVars = {
108
+ clipPath: TO,
109
+ duration,
110
+ ease,
111
+ stagger,
112
+ delay,
113
+ overwrite: "auto",
114
+ };
115
+ if (scrub !== undefined) {
116
+ vars.ease = "none";
117
+ vars.scrollTrigger = {
118
+ trigger: els[0],
119
+ start,
120
+ end,
121
+ scrub: scrub === true ? true : scrub,
122
+ };
123
+ } else if (mode === "scroll") {
124
+ vars.scrollTrigger = {
125
+ trigger: els[0],
126
+ start,
127
+ toggleActions: replay ? "play reverse play reverse" : "play none none none",
128
+ };
129
+ }
130
+
131
+ const tween = gsap.to(els, vars);
132
+ ScrollTrigger.refresh();
133
+
134
+ return () => {
135
+ tween.scrollTrigger?.kill();
136
+ tween.kill();
137
+ gsap.set(els, { clearProps: "clipPath" });
138
+ ScrollTrigger.refresh();
139
+ };
140
+ }
141
+ }
@@ -4,8 +4,11 @@
4
4
  * Drives an element's `textContent` from `from` to `to` with an easing curve,
5
5
  * optionally triggered by ScrollTrigger. Uses integer stepping so there is no
6
6
  * fractional flicker, and pairs with `tabular-nums` for stable layout.
7
+ * `progress: true` swaps the timed tween for a scrubbed one — the number
8
+ * follows scroll progress (a hero percentage readout).
7
9
  *
8
10
  * counter("[data-count]", { to: 100, duration: 4, ease: "power1.inOut" })
11
+ * counter("[data-progress]", { progress: true, pad: 2, suffix: "%" })
9
12
  */
10
13
  import { gsap, ScrollTrigger, initGSAP, killTweens } from "../core/gsap.js";
11
14
  import { guard } from "../core/guard.js";
@@ -27,7 +30,16 @@ export interface CounterOptions extends CommonOptions {
27
30
  suffix?: string;
28
31
  /** Animate when scrolled into view instead of immediately. @default false */
29
32
  onScroll?: boolean;
33
+ /**
34
+ * Drive the number from scroll progress instead of a timed tween: the value
35
+ * scrubs from `from` to `to` across `start` → `end`. Ignores `onScroll`.
36
+ * @default false
37
+ */
38
+ progress?: boolean;
39
+ /** ScrollTrigger start position (`onScroll` or `progress`). @default "top 90%" */
30
40
  start?: string;
41
+ /** ScrollTrigger end position (only with `progress`). @default "bottom top" */
42
+ end?: string;
31
43
  onComplete?: (value: number) => void;
32
44
  }
33
45
 
@@ -45,7 +57,9 @@ export function counter(target: TargetLike, options: CounterOptions = {}): Destr
45
57
  pad = 0,
46
58
  suffix = "",
47
59
  onScroll = false,
60
+ progress = false,
48
61
  start = "top 90%",
62
+ end = "bottom top",
49
63
  onComplete,
50
64
  } = options;
51
65
 
@@ -67,20 +81,26 @@ export function counter(target: TargetLike, options: CounterOptions = {}): Destr
67
81
  duration,
68
82
  ease,
69
83
  onUpdate: render,
70
- onComplete: () => {
71
- render();
72
- onComplete?.(Math.round(state.v));
73
- },
84
+ onComplete: progress
85
+ ? undefined
86
+ : () => {
87
+ render();
88
+ onComplete?.(Math.round(state.v));
89
+ },
74
90
  };
75
91
 
76
- if (onScroll) {
92
+ if (progress) {
93
+ // Scroll-bound: value follows viewport progress, no timed completion.
94
+ vars.ease = "none";
95
+ vars.scrollTrigger = { trigger: el, start, end, scrub: true };
96
+ } else if (onScroll) {
77
97
  vars.scrollTrigger = { trigger: el, start, once: true };
78
98
  }
79
99
 
80
100
  tweens.push(gsap.to(state, vars));
81
101
  });
82
102
 
83
- if (onScroll) ScrollTrigger.refresh();
103
+ if (onScroll || progress) ScrollTrigger.refresh();
84
104
 
85
105
  return () => {
86
106
  tweens.forEach((t) => {
@@ -5,6 +5,10 @@
5
5
  * whole thing fades/blurs in when the pointer enters the hot zone. The label
6
6
  * uses `mix-blend-mode: exclusion` so it inverts over any background.
7
7
  *
8
+ * The tag is pinned `position: fixed` and driven in VIEWPORT space
9
+ * (clientX/clientY + offset), so it can live anywhere in the DOM — it only
10
+ * reacts while the pointer is over the zone.
11
+ *
8
12
  * cursorFollower(zone, { follower: ".ak-cursor" })
9
13
  */
10
14
  import { gsap, initGSAP, killTweens } from "../core/gsap.js";
@@ -51,7 +55,11 @@ export function cursorFollower(
51
55
  };
52
56
 
53
57
  el.style.mixBlendMode = blendMode as never;
54
- el.style.position = "absolute";
58
+ // Viewport space: position:fixed + clientX/clientY keeps the tag at the
59
+ // pointer wherever it sits in the DOM. (The old position:absolute +
60
+ // zone-relative math only lined up when the tag was a child of the zone —
61
+ // a body-level tag landed near the document origin instead, off-screen.)
62
+ el.style.position = "fixed";
55
63
  el.style.left = "0";
56
64
  el.style.top = "0";
57
65
  el.style.pointerEvents = "none";
@@ -61,10 +69,19 @@ export function cursorFollower(
61
69
  const xTo = gsap.quickTo(el, "x", { ...spring, duration: 0.4, ease: "power3" });
62
70
  const yTo = gsap.quickTo(el, "y", { ...spring, duration: 0.4, ease: "power3" });
63
71
 
72
+ // First move lands on the pointer; later moves spring after it — starting
73
+ // from (0,0), the spring would otherwise carry the tag in from the corner.
74
+ let snapped = false;
64
75
  const onMove = (e: PointerEvent) => {
65
- const r = area.getBoundingClientRect();
66
- xTo(e.clientX - r.left + offset);
67
- yTo(e.clientY - r.top + offset);
76
+ const x = e.clientX + offset;
77
+ const y = e.clientY + offset;
78
+ if (snapped) {
79
+ xTo(x);
80
+ yTo(y);
81
+ } else {
82
+ gsap.set(el, { x, y });
83
+ snapped = true;
84
+ }
68
85
  if (fade) gsap.to(el, { opacity: 1, duration: 0.25, overwrite: "auto" });
69
86
  };
70
87