@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.
- package/README.md +275 -50
- package/dist/anim-kit.standalone.js +18 -8
- package/dist/anim-kit.standalone.js.map +1 -1
- package/dist/core/gsap.d.ts +2 -1
- package/dist/core/gsap.d.ts.map +1 -1
- package/dist/core/gsap.js +3 -2
- package/dist/core/gsap.js.map +1 -1
- package/dist/core/split.d.ts.map +1 -1
- package/dist/core/split.js +15 -2
- package/dist/core/split.js.map +1 -1
- package/dist/effects/clip-wipe.d.ts +31 -0
- package/dist/effects/clip-wipe.d.ts.map +1 -0
- package/dist/effects/clip-wipe.js +82 -0
- package/dist/effects/clip-wipe.js.map +1 -0
- package/dist/effects/counter.d.ts +9 -0
- package/dist/effects/counter.d.ts.map +1 -1
- package/dist/effects/counter.js +17 -7
- package/dist/effects/counter.js.map +1 -1
- package/dist/effects/cursor-follower.d.ts.map +1 -1
- package/dist/effects/cursor-follower.js +22 -4
- package/dist/effects/cursor-follower.js.map +1 -1
- package/dist/effects/flip-words.d.ts +31 -0
- package/dist/effects/flip-words.d.ts.map +1 -0
- package/dist/effects/flip-words.js +104 -0
- package/dist/effects/flip-words.js.map +1 -0
- package/dist/effects/line-reveal.d.ts +6 -2
- package/dist/effects/line-reveal.d.ts.map +1 -1
- package/dist/effects/line-reveal.js +8 -4
- package/dist/effects/line-reveal.js.map +1 -1
- package/dist/effects/magnetic.d.ts +15 -0
- package/dist/effects/magnetic.d.ts.map +1 -0
- package/dist/effects/magnetic.js +59 -0
- package/dist/effects/magnetic.js.map +1 -0
- package/dist/effects/media-settle.d.ts +30 -0
- package/dist/effects/media-settle.d.ts.map +1 -0
- package/dist/effects/media-settle.js +55 -0
- package/dist/effects/media-settle.js.map +1 -0
- package/dist/effects/roll-text.d.ts +13 -0
- package/dist/effects/roll-text.d.ts.map +1 -0
- package/dist/effects/roll-text.js +91 -0
- package/dist/effects/roll-text.js.map +1 -0
- package/dist/effects/scramble-text.d.ts +17 -0
- package/dist/effects/scramble-text.d.ts.map +1 -0
- package/dist/effects/scramble-text.js +93 -0
- package/dist/effects/scramble-text.js.map +1 -0
- package/dist/effects/unfold-reveal.d.ts +23 -0
- package/dist/effects/unfold-reveal.d.ts.map +1 -0
- package/dist/effects/unfold-reveal.js +53 -0
- package/dist/effects/unfold-reveal.js.map +1 -0
- package/dist/index.d.ts +25 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +19 -2
- package/dist/index.js.map +1 -1
- package/dist/styles/anim-kit.css +22 -0
- package/package.json +6 -3
- package/src/core/gsap.ts +3 -2
- package/src/core/split.ts +16 -2
- package/src/effects/clip-wipe.ts +141 -0
- package/src/effects/counter.ts +26 -6
- package/src/effects/cursor-follower.ts +21 -4
- package/src/effects/flip-words.ts +148 -0
- package/src/effects/line-reveal.ts +12 -5
- package/src/effects/magnetic.ts +87 -0
- package/src/effects/media-settle.ts +106 -0
- package/src/effects/roll-text.ts +118 -0
- package/src/effects/scramble-text.ts +122 -0
- package/src/effects/unfold-reveal.ts +92 -0
- package/src/index.ts +33 -2
- 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
|
-
*
|
|
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";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA
|
|
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
|
-
*
|
|
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
|
|
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"}
|
package/dist/styles/anim-kit.css
CHANGED
|
@@ -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.
|
|
4
|
-
"description": "Modular, framework-agnostic animation library
|
|
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": "^
|
|
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
|
-
|
|
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
|
+
}
|
package/src/effects/counter.ts
CHANGED
|
@@ -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
|
-
|
|
72
|
-
|
|
73
|
-
|
|
84
|
+
onComplete: progress
|
|
85
|
+
? undefined
|
|
86
|
+
: () => {
|
|
87
|
+
render();
|
|
88
|
+
onComplete?.(Math.round(state.v));
|
|
89
|
+
},
|
|
74
90
|
};
|
|
75
91
|
|
|
76
|
-
if (
|
|
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
|
-
|
|
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
|
|
66
|
-
|
|
67
|
-
|
|
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
|
|