akili-specs 2.7.0 → 2.8.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 (74) hide show
  1. package/.claude/commands/akili-archive.md +9 -0
  2. package/.claude/commands/akili-audit.md +9 -0
  3. package/.claude/commands/akili-constitution.md +41 -3
  4. package/.claude/commands/akili-execute.md +10 -1
  5. package/.claude/commands/akili-propose.md +9 -0
  6. package/.claude/commands/akili-quick.md +9 -0
  7. package/.claude/commands/akili-resume.md +9 -0
  8. package/.claude/commands/akili-seo.md +9 -0
  9. package/.claude/commands/akili-specify.md +14 -2
  10. package/.claude/commands/akili-test.md +9 -0
  11. package/.claude/commands/akili-validate.md +9 -0
  12. package/.claude/skills/angular-developer/SKILL.md +4 -0
  13. package/.claude/skills/api-design-principles/SKILL.md +8 -0
  14. package/.claude/skills/aws-serverless/SKILL.md +8 -1
  15. package/.claude/skills/brainstorming/SKILL.md +25 -1
  16. package/.claude/skills/cognitive-doc-design/SKILL.md +14 -0
  17. package/.claude/skills/error-handling-patterns/SKILL.md +8 -0
  18. package/.claude/skills/frontend-design/SKILL.md +8 -1
  19. package/.claude/skills/gsap-animation/SKILL.md +182 -0
  20. package/.claude/skills/gsap-animation/references/frameworks.md +137 -0
  21. package/.claude/skills/{gsap-performance/SKILL.md → gsap-animation/references/performance.md} +10 -20
  22. package/.claude/skills/gsap-animation/references/plugins.md +390 -0
  23. package/.claude/skills/gsap-animation/references/react.md +122 -0
  24. package/.claude/skills/gsap-animation/references/scrolltrigger.md +255 -0
  25. package/.claude/skills/{gsap-timeline/SKILL.md → gsap-animation/references/timeline.md} +7 -19
  26. package/.claude/skills/gsap-animation/references/utils.md +254 -0
  27. package/.claude/skills/judgment-day/SKILL.md +19 -1
  28. package/.claude/skills/kaizen/SKILL.md +1 -0
  29. package/.claude/skills/nestjs-expert/SKILL.md +8 -0
  30. package/.claude/skills/product-manager-toolkit/SKILL.md +7 -1
  31. package/.claude/skills/react-doctor/SKILL.md +6 -0
  32. package/.claude/skills/seo-audit/SKILL.md +18 -9
  33. package/.claude/skills/shadcn-ui/SKILL.md +6 -0
  34. package/.claude/skills/stitch-design/SKILL.md +7 -0
  35. package/.claude/skills/systematic-debugging/SKILL.md +21 -0
  36. package/.claude/skills/tailwind-design-system/SKILL.md +8 -0
  37. package/.claude/skills/ui-ux-pro-max/SKILL.md +21 -0
  38. package/.claude/skills/vercel-react-best-practices/SKILL.md +3 -0
  39. package/.claude/templates/implementer.md +6 -0
  40. package/.claude/templates/leader.md +7 -1
  41. package/.claude/templates/reviewer.md +6 -0
  42. package/.claude/templates/tester.md +6 -0
  43. package/CHANGELOG.md +27 -0
  44. package/LICENSE +1 -1
  45. package/README.md +9 -8
  46. package/bin/akili.js +40 -0
  47. package/docs/cli.md +1 -1
  48. package/docs/commands/akili-constitution.md +11 -11
  49. package/docs/flow.md +20 -0
  50. package/docs/skills/README.md +34 -31
  51. package/docs/skills/brainstorming.md +2 -0
  52. package/docs/skills/cognitive-doc-design.md +2 -0
  53. package/docs/skills/governance.md +77 -0
  54. package/docs/skills/gsap-animation.md +29 -0
  55. package/docs/skills/judgment-day.md +2 -0
  56. package/docs/skills/product-manager-toolkit.md +1 -1
  57. package/docs/skills/seo-audit.md +2 -0
  58. package/docs/skills/systematic-debugging.md +2 -0
  59. package/docs/skills/ui-ux-pro-max.md +2 -0
  60. package/package.json +3 -2
  61. package/.claude/skills/gsap-core/SKILL.md +0 -254
  62. package/.claude/skills/gsap-frameworks/SKILL.md +0 -153
  63. package/.claude/skills/gsap-plugins/SKILL.md +0 -426
  64. package/.claude/skills/gsap-react/SKILL.md +0 -136
  65. package/.claude/skills/gsap-scrolltrigger/SKILL.md +0 -296
  66. package/.claude/skills/gsap-utils/SKILL.md +0 -284
  67. package/docs/skills/gsap-core.md +0 -21
  68. package/docs/skills/gsap-frameworks.md +0 -20
  69. package/docs/skills/gsap-performance.md +0 -21
  70. package/docs/skills/gsap-plugins.md +0 -20
  71. package/docs/skills/gsap-react.md +0 -22
  72. package/docs/skills/gsap-scrolltrigger.md +0 -21
  73. package/docs/skills/gsap-timeline.md +0 -20
  74. package/docs/skills/gsap-utils.md +0 -21
@@ -0,0 +1,137 @@
1
+ # GSAP with Vue, Svelte, and Other Frameworks
2
+
3
+ Read when writing or reviewing GSAP in Vue (or Nuxt), Svelte (or SvelteKit), or other component frameworks with a mounted/unmounted lifecycle. For **React** use `references/react.md` (useGSAP, contextSafe).
4
+
5
+ ## Principles (All Frameworks)
6
+
7
+ - **Create** tweens and ScrollTriggers **after** the component's DOM is available (e.g. onMounted, onMount).
8
+ - **Kill or revert** them on **unmount** so nothing runs on detached nodes and there are no leaks.
9
+ - **Scope selectors** to the component root so `.box` matches only elements inside that component.
10
+
11
+ ## Vue 3 (Composition API)
12
+
13
+ Use **onMounted** to run GSAP after the component is in the DOM; **onUnmounted** to clean up.
14
+
15
+ ```javascript
16
+ import { onMounted, onUnmounted, ref } from "vue";
17
+ import { gsap } from "gsap";
18
+ import { ScrollTrigger } from "gsap/ScrollTrigger";
19
+ gsap.registerPlugin(ScrollTrigger); // once per app, e.g. in main.js
20
+
21
+ export default {
22
+ setup() {
23
+ const container = ref(null);
24
+ let ctx;
25
+
26
+ onMounted(() => {
27
+ if (!container.value) return;
28
+ ctx = gsap.context(() => {
29
+ gsap.to(".box", { x: 100, duration: 0.6 });
30
+ gsap.from(".item", { autoAlpha: 0, y: 20, stagger: 0.1 });
31
+ }, container.value);
32
+ });
33
+
34
+ onUnmounted(() => {
35
+ ctx?.revert();
36
+ });
37
+
38
+ return { container };
39
+ }
40
+ };
41
+ ```
42
+
43
+ - ✅ **gsap.context(callback, scope)** — pass the container ref (`container.value`) so selectors like `.item` are scoped to that root. All animations and ScrollTriggers created inside are tracked and reverted on **ctx.revert()**.
44
+ - ✅ **onUnmounted** — always call **ctx.revert()**.
45
+
46
+ ## Vue 3 (script setup)
47
+
48
+ ```javascript
49
+ <script setup>
50
+ import { onMounted, onUnmounted, ref } from "vue";
51
+ import { gsap } from "gsap";
52
+ import { ScrollTrigger } from "gsap/ScrollTrigger";
53
+
54
+ const container = ref(null);
55
+ let ctx;
56
+
57
+ onMounted(() => {
58
+ if (!container.value) return;
59
+ ctx = gsap.context(() => {
60
+ gsap.to(".box", { x: 100 });
61
+ gsap.from(".item", { autoAlpha: 0, stagger: 0.1 });
62
+ }, container.value);
63
+ });
64
+
65
+ onUnmounted(() => {
66
+ ctx?.revert();
67
+ });
68
+ </script>
69
+
70
+ <template>
71
+ <div ref="container">
72
+ <div class="box">Box</div>
73
+ <div class="item">Item</div>
74
+ </div>
75
+ </template>
76
+ ```
77
+
78
+ ## Svelte
79
+
80
+ Use **onMount** to run GSAP after the DOM is ready; return a cleanup that reverts. Svelte 5 uses a different lifecycle, but the principle is the same: create in "mounted", revert in "destroyed".
81
+
82
+ ```javascript
83
+ <script>
84
+ import { onMount } from "svelte";
85
+ import { gsap } from "gsap";
86
+ import { ScrollTrigger } from "gsap/ScrollTrigger";
87
+
88
+ let container;
89
+
90
+ onMount(() => {
91
+ if (!container) return;
92
+ const ctx = gsap.context(() => {
93
+ gsap.to(".box", { x: 100 });
94
+ gsap.from(".item", { autoAlpha: 0, stagger: 0.1 });
95
+ }, container);
96
+ return () => ctx.revert();
97
+ });
98
+ </script>
99
+
100
+ <div bind:this={container}>
101
+ <div class="box">Box</div>
102
+ <div class="item">Item</div>
103
+ </div>
104
+ ```
105
+
106
+ - ✅ **bind:this={container}** — reference the root element to pass to **gsap.context(scope)**.
107
+ - ✅ **return () => ctx.revert()** — onMount's returned cleanup runs when the component is destroyed.
108
+
109
+ ## Scoping Selectors
110
+
111
+ Do not use global selectors that can match elements outside the current component. Always pass the **scope** (container element or ref) as the second argument to **gsap.context(callback, scope)**.
112
+
113
+ - ✅ **gsap.context(() => { gsap.to(".box", ...) }, containerRef)** — `.box` is only searched inside `containerRef`.
114
+ - ❌ Running **gsap.to(".box", ...)** without a context scope can affect other instances or the rest of the page.
115
+
116
+ ## ScrollTrigger Cleanup
117
+
118
+ ScrollTrigger instances (via the `scrollTrigger` config on a tween/timeline or **ScrollTrigger.create()**) are **included** in **gsap.context()** and reverted on **ctx.revert()**. So:
119
+
120
+ - Create ScrollTriggers inside the same **gsap.context()** callback you use for tweens.
121
+ - Call **ScrollTrigger.refresh()** after layout changes that affect trigger positions — often after DOM updates (nextTick in Vue, tick in Svelte, or after async content load).
122
+
123
+ ## When to Create vs Kill
124
+
125
+ | Lifecycle | Action |
126
+ |-----------|--------|
127
+ | **Mounted** | Create tweens and ScrollTriggers inside **gsap.context(scope)**. |
128
+ | **Unmount / Destroy** | Call **ctx.revert()** so all animations and ScrollTriggers in that context are killed and inline styles reverted. |
129
+
130
+ Do not create GSAP animations in setup or a synchronous top-level script that runs before the root element exists. Wait for **onMounted** / **onMount**.
131
+
132
+ ## Do Not
133
+
134
+ - ❌ Create tweens or ScrollTriggers before the component is mounted; the DOM nodes may not exist yet.
135
+ - ❌ Use selector strings without a **scope** (pass the container to gsap.context()).
136
+ - ❌ Skip cleanup; always call **ctx.revert()** in onUnmounted / onMount's return.
137
+ - ❌ Register plugins inside a component body that runs every render (wasteful); register once at app level.
@@ -1,25 +1,15 @@
1
- ---
2
- name: gsap-performance
3
- description: Official GSAP skill for performance — prefer transforms, avoid layout thrashing, will-change, batching. Use when optimizing GSAP animations, reducing jank, or when the user asks about animation performance, FPS, or smooth 60fps.
4
- license: MIT
5
- ---
6
-
7
1
  # GSAP Performance
8
2
 
9
- ## When to Use This Skill
10
-
11
- Apply when optimizing GSAP animations for smooth 60fps, reducing layout/paint cost, or when the user asks about performance, jank, or best practices for fast animations.
12
-
13
- **Related skills:** Build animations with **gsap-core** (transforms, autoAlpha) and **gsap-timeline**; for ScrollTrigger performance see **gsap-scrolltrigger**.
3
+ Read when optimizing GSAP animations for smooth 60fps, reducing jank/dropped frames, avoiding layout thrashing, or when /akili-validate routes a performance issue here.
14
4
 
15
5
  ## Prefer Transform and Opacity
16
6
 
17
- Animating **transform** (`x`, `y`, `scaleX`, `scaleY`, `rotation`, `rotationX`, `rotationY`, `skewX`, `skewY`) and **opacity** keeps work on the compositor and avoids layout and most paint. Avoid animating layout-heavy properties when a transform can achieve the same effect.
7
+ Animating **transform** (`x`, `y`, `scaleX`, `scaleY`, `rotation`, `rotationX`, `rotationY`, `skewX`, `skewY`) and **opacity** keeps work on the compositor and avoids layout and most paint.
18
8
 
19
9
  - ✅ Prefer: **x**, **y**, **scale**, **rotation**, **opacity**.
20
10
  - ❌ Avoid when possible: **width**, **height**, **top**, **left**, **margin**, **padding** (they trigger layout and can cause jank).
21
11
 
22
- GSAPs **x** and **y** use transforms (translate) by default; use them instead of **left**/**top** for movement.
12
+ GSAP's **x** and **y** use transforms (translate) by default; use them instead of **left**/**top** for movement.
23
13
 
24
14
  ## will-change
25
15
 
@@ -35,13 +25,13 @@ GSAP batches updates internally. When mixing GSAP with direct DOM reads/writes o
35
25
 
36
26
  ## Many Elements (Stagger, Lists)
37
27
 
38
- - Use **stagger** instead of many separate tweens with manual delays when the animation is the same; its more efficient.
39
- - For long lists, consider **virtualization** or animating only visible items; avoid creating hundreds of simultaneous tweens if it causes jank.
28
+ - Use **stagger** instead of many separate tweens with manual delays when the animation is the same; it's more efficient.
29
+ - For long lists, consider **virtualization** or animating only visible items; avoid hundreds of simultaneous tweens if it causes jank.
40
30
  - Reuse timelines where possible; avoid creating new timelines every frame.
41
31
 
42
32
  ## Frequently updated properties (e.g. mouse followers)
43
33
 
44
- Prefer **gsap.quickTo()** for properties that are updated often (e.g. mouse-follower x/y). It reuses a single tween instead of creating new tweens on each update.
34
+ Prefer **gsap.quickTo()** for properties updated often (e.g. mouse-follower x/y). It reuses a single tween instead of creating a new one on each update.
45
35
 
46
36
  ```javascript
47
37
  let xTo = gsap.quickTo("#id", "x", { duration: 0.4, ease: "power3" }),
@@ -55,13 +45,13 @@ document.querySelector("#container").addEventListener("mousemove", (e) => {
55
45
 
56
46
  ## ScrollTrigger and Performance
57
47
 
58
- - **pin: true** promotes the pinned element; pin only whats needed.
48
+ - **pin: true** promotes the pinned element; pin only what's needed.
59
49
  - **scrub** with a small value (e.g. `scrub: 1`) can reduce work during scroll; test on low-end devices.
60
50
  - Call **ScrollTrigger.refresh()** only when layout actually changes (e.g. after content load), not on every resize; debounce when possible.
61
51
 
62
52
  ## Reduce Simultaneous Work
63
53
 
64
- - Pause or kill off-screen or inactive animations when they’re not visible (e.g. when the user navigates away).
54
+ - Pause or kill off-screen or inactive animations when not visible (e.g. when the user navigates away).
65
55
  - Avoid animating huge numbers of properties on many elements at once; simplify or sequence if needed.
66
56
 
67
57
  ## Best practices
@@ -73,7 +63,7 @@ document.querySelector("#container").addEventListener("mousemove", (e) => {
73
63
 
74
64
  ## Do Not
75
65
 
76
- - ❌ Animate **width**/ **height**/ **top**/ **left** for movement when **x**/ **y**/ **scale** can achieve the same look.
77
- - ❌ Set **will-change** or **force3D** on every element just in case”; use for elements that are actually animating.
66
+ - ❌ Animate **width**/**height**/**top**/**left** for movement when **x**/**y**/**scale** can achieve the same look.
67
+ - ❌ Set **will-change** or **force3D** on every element "just in case"; use for elements that are actually animating.
78
68
  - ❌ Create hundreds of overlapping tweens or ScrollTriggers without testing on low-end devices.
79
69
  - ❌ Ignore cleanup; stray tweens and ScrollTriggers keep running and can hurt performance and correctness.
@@ -0,0 +1,390 @@
1
+ # GSAP Plugins
2
+
3
+ Read when using any GSAP plugin: scroll-to, ScrollSmoother, Flip/FLIP, Draggable, Inertia, Observer, SplitText, ScrambleText, DrawSVG, MorphSVG, MotionPath, physics, easing plugins (CustomEase, EasePack, CustomWiggle, CustomBounce), GSDevTools, or Pixi. (ScrollTrigger has its own file: `references/scrolltrigger.md`.)
4
+
5
+ ## Registering Plugins
6
+
7
+ Register each plugin once before first use (see SKILL.md for the shared pattern):
8
+
9
+ ```javascript
10
+ import gsap from "gsap";
11
+ import { ScrollToPlugin } from "gsap/ScrollToPlugin";
12
+ import { Flip } from "gsap/Flip";
13
+ import { Draggable } from "gsap/Draggable";
14
+
15
+ gsap.registerPlugin(ScrollToPlugin, Flip, Draggable);
16
+ ```
17
+
18
+ - ✅ Register before using the plugin in any tween or API call.
19
+ - ✅ In React, register at top level or once in the app (before first `useGSAP`); do not register inside a component that re-renders. `useGSAP` is itself a plugin that needs registration.
20
+
21
+ ## Scroll
22
+
23
+ ### ScrollToPlugin
24
+
25
+ Animates scroll position (window or a scrollable element). Use for "scroll to element/position" without ScrollTrigger.
26
+
27
+ ```javascript
28
+ gsap.registerPlugin(ScrollToPlugin);
29
+
30
+ gsap.to(window, { duration: 1, scrollTo: { y: 500 } });
31
+ gsap.to(window, { duration: 1, scrollTo: { y: "#section", offsetY: 50 } });
32
+ gsap.to(scrollContainer, { duration: 1, scrollTo: { x: "max" } });
33
+ ```
34
+
35
+ | Option | Description |
36
+ |--------|-------------|
37
+ | `x`, `y` | Target scroll position (number), or `"max"` for maximum |
38
+ | `element` | Selector or element to scroll to (scroll-into-view) |
39
+ | `offsetX`, `offsetY` | Offset in pixels from the target position |
40
+
41
+ ### ScrollSmoother
42
+
43
+ Smooth scroll wrapper (smooths native scroll). Requires ScrollTrigger and a specific DOM structure. Register after ScrollTrigger.
44
+
45
+ ```html
46
+ <body>
47
+ <div id="smooth-wrapper">
48
+ <div id="smooth-content">
49
+ <!-- ALL YOUR CONTENT HERE -->
50
+ </div>
51
+ </div>
52
+ <!-- position: fixed elements can go outside -->
53
+ </body>
54
+ ```
55
+
56
+ ## DOM / UI
57
+
58
+ ### Flip
59
+
60
+ Capture state with `Flip.getState()`, change the DOM (layout/classes), then `Flip.from()` animates from the previous state to the new state (FLIP: First, Last, Invert, Play). Use when animating between two layout states (lists, grids, expand/collapse).
61
+
62
+ ```javascript
63
+ gsap.registerPlugin(Flip);
64
+
65
+ const state = Flip.getState(".item");
66
+ // change DOM (reorder, add/remove, change classes)
67
+ Flip.from(state, { duration: 0.5, ease: "power2.inOut" });
68
+ ```
69
+
70
+ | Option | Description |
71
+ |--------|-------------|
72
+ | `absolute` | Use `position: absolute` during the flip (default `false`) |
73
+ | `nested` | When true, only the first level of children is measured (better for nested transforms) |
74
+ | `scale` | When true, scale elements to fit (avoids stretch); default `true` |
75
+ | `simple` | When true, only position/scale animated (faster, less accurate) |
76
+ | `duration`, `ease` | Standard tween options |
77
+
78
+ Docs: https://gsap.com/docs/v3/Plugins/Flip
79
+
80
+ ### Draggable
81
+
82
+ Makes elements draggable, spinnable, or throwable. Use for sliders, cards, reorderable lists, or any drag interaction.
83
+
84
+ ```javascript
85
+ gsap.registerPlugin(Draggable, InertiaPlugin);
86
+
87
+ Draggable.create(".box", { type: "x,y", bounds: "#container", inertia: true });
88
+ Draggable.create(".knob", { type: "rotation" });
89
+ ```
90
+
91
+ | Option | Description |
92
+ |--------|-------------|
93
+ | `type` | `"x"`, `"y"`, `"x,y"`, `"rotation"`, `"scroll"` |
94
+ | `bounds` | Element, selector, or `{ minX, maxX, minY, maxY }` to constrain drag |
95
+ | `inertia` | `true` for throw/momentum (requires InertiaPlugin) |
96
+ | `edgeResistance` | 0–1; resistance when dragging past bounds |
97
+ | `cursor` | CSS cursor during drag |
98
+ | `onDragStart`, `onDrag`, `onDragEnd` | Callbacks; receive event and target |
99
+ | `onThrowUpdate`, `onThrowComplete` | Callbacks when inertia is active |
100
+
101
+ ### Inertia (InertiaPlugin)
102
+
103
+ Works with Draggable for momentum after release, or tracks the velocity of any property so it can glide to a stop. Register with Draggable when using `inertia: true`:
104
+
105
+ ```javascript
106
+ gsap.registerPlugin(Draggable, InertiaPlugin);
107
+ Draggable.create(".box", { type: "x,y", inertia: true });
108
+ ```
109
+
110
+ Track velocity of a property, then use `"auto"` to continue current velocity and glide to a stop:
111
+
112
+ ```javascript
113
+ InertiaPlugin.track(".box", "x");
114
+ gsap.to(obj, { inertia: { x: "auto" } });
115
+ ```
116
+
117
+ ### Observer
118
+
119
+ Normalizes pointer and scroll input across devices. Use for swipe, scroll direction, or custom gesture logic without tying to scroll position.
120
+
121
+ ```javascript
122
+ gsap.registerPlugin(Observer);
123
+
124
+ Observer.create({
125
+ target: "#area",
126
+ onUp: () => {},
127
+ onDown: () => {},
128
+ onLeft: () => {},
129
+ onRight: () => {},
130
+ tolerance: 10
131
+ });
132
+ ```
133
+
134
+ | Option | Description |
135
+ |--------|-------------|
136
+ | `target` | Element or selector to observe |
137
+ | `onUp`, `onDown`, `onLeft`, `onRight` | Callbacks when swipe/scroll passes tolerance in that direction |
138
+ | `tolerance` | Pixels before direction is detected; default 10 |
139
+ | `type` | `"touch"`, `"pointer"`, or `"wheel"` (default `"touch,pointer"`) |
140
+
141
+ ## Text
142
+
143
+ ### SplitText
144
+
145
+ Splits an element's text into characters, words, and/or lines (each in its own element) for staggered animation. Returns an instance with **chars**, **words**, **lines** (and **masks** when `mask` is set). Restore original markup with **revert()** or let **gsap.context()** revert. Integrates with **gsap.context()**, **matchMedia()**, and **useGSAP()**. API: **SplitText.create(target, vars)**.
146
+
147
+ ```javascript
148
+ gsap.registerPlugin(SplitText);
149
+
150
+ const split = SplitText.create(".heading", { type: "words, chars" });
151
+ gsap.from(split.chars, { opacity: 0, y: 20, stagger: 0.03, duration: 0.4 });
152
+ // later: split.revert() or let gsap.context() cleanup revert
153
+ ```
154
+
155
+ With **onSplit()** (3.13.0+), animations run on each split and on re-split when **autoSplit** is used; returning a tween/timeline from **onSplit()** lets SplitText clean up and sync progress on re-split:
156
+
157
+ ```javascript
158
+ SplitText.create(".split", {
159
+ type: "lines",
160
+ autoSplit: true,
161
+ onSplit(self) {
162
+ return gsap.from(self.lines, { y: 100, opacity: 0, stagger: 0.05, duration: 0.5 });
163
+ }
164
+ });
165
+ ```
166
+
167
+ | Option | Description |
168
+ |--------|-------------|
169
+ | **type** | Comma-separated: `"chars"`, `"words"`, `"lines"`. Default `"chars,words,lines"`. Split only what's needed for performance. Avoid chars-only without words/lines, or use **smartWrap: true**. |
170
+ | **charsClass**, **wordsClass**, **linesClass** | CSS class on each split element. Append `"++"` for an incremented class (e.g. `linesClass: "line++"` → `line1`, `line2`, …). |
171
+ | **aria** | `"auto"` (default), `"hidden"`, or `"none"`. `"auto"` adds `aria-label` on the element and `aria-hidden` on split units; `"hidden"` hides all from readers; `"none"` leaves aria unchanged. |
172
+ | **autoSplit** | When `true`, reverts and re-splits when fonts load or element width changes (lines split), avoiding wrong line breaks. **Animations must be created inside onSplit()**; **return** the animation for automatic cleanup and time-sync on re-split. |
173
+ | **onSplit(self)** | Callback when split completes (and on each re-split if **autoSplit**). Returning a tween/timeline enables automatic revert/sync on re-split. |
174
+ | **mask** | `"lines"`, `"words"`, or `"chars"`. Wraps each unit with `overflow: clip` for mask/reveal effects. Access wrappers on the instance's **masks** array. |
175
+ | **tag** | Wrapper tag; default `"div"`. Use `"span"` for inline (transforms like rotation/scale may not render on inline elements in some browsers). |
176
+ | **deepSlice** | When `true` (default), nested elements spanning multiple lines are subdivided so lines don't stretch vertically. Line-splitting only. |
177
+ | **ignore** | Selector or element(s) to leave unsplit (e.g. `ignore: "sup"`). |
178
+ | **smartWrap** | When splitting **chars** only, wraps words in `white-space: nowrap` to avoid mid-word breaks. Ignored if words/lines are split. Default `false`. |
179
+ | **wordDelimiter** | Word boundary: string (default `" "`), RegExp, or `{ delimiter: RegExp, replaceWith: string }`. |
180
+ | **prepareText(text, parent)** | Function returning modified text before splitting (e.g. insert break markers for languages without spaces). |
181
+ | **propIndex** | When `true`, adds a CSS variable with index on each split element (`--word: 1`, `--char: 2`). |
182
+ | **reduceWhiteSpace** | Collapse consecutive spaces; default `true`. From 3.13.0 also honors line breaks / `<pre>`. |
183
+ | **onRevert** | Callback when the instance is reverted. |
184
+
185
+ **Tips:** Split only what is animated. For custom fonts, split after they load (`document.fonts.ready.then(...)`) or use **autoSplit: true** with **onSplit()**. To avoid kerning shift when splitting chars, use CSS `font-kerning: none; text-rendering: optimizeSpeed;`. Avoid `text-wrap: balance`. SplitText does not support SVG `<text>`.
186
+
187
+ Docs: [SplitText](https://gsap.com/docs/v3/Plugins/SplitText/)
188
+
189
+ ### ScrambleText
190
+
191
+ Animates text with a scramble/glitch effect.
192
+
193
+ ```javascript
194
+ gsap.registerPlugin(ScrambleTextPlugin);
195
+
196
+ gsap.to(".text", {
197
+ duration: 1,
198
+ scrambleText: { text: "New message", chars: "01", revealDelay: 0.5 }
199
+ });
200
+ ```
201
+
202
+ ## SVG
203
+
204
+ ### DrawSVG (DrawSVGPlugin)
205
+
206
+ Reveals/hides the stroke of SVG elements by animating `stroke-dashoffset` / `stroke-dasharray`. Works on `<path>`, `<line>`, `<polyline>`, `<polygon>`, `<rect>`, `<ellipse>`. Use for "drawing"/"erasing" strokes.
207
+
208
+ **drawSVG value:** Describes the **visible segment** of the stroke (`"start end"` in percent or length), not "A to B over time." `"0% 100%"` = full stroke; `"20% 80%"` = stroke only between 20% and 80%. The tween animates from the element's **current** segment to the **target** segment. Single value (e.g. `0`, `"100%"`) means start is 0.
209
+
210
+ **Required:** The element must have a visible stroke (`stroke` + `stroke-width`), else nothing draws.
211
+
212
+ ```javascript
213
+ gsap.registerPlugin(DrawSVGPlugin);
214
+
215
+ gsap.from("#path", { duration: 1, drawSVG: 0 }); // nothing → full stroke
216
+ gsap.fromTo("#path", { drawSVG: "0% 0%" }, { drawSVG: "0% 100%", duration: 1 });
217
+ gsap.to("#path", { duration: 1, drawSVG: "20% 80%" }); // middle only
218
+ ```
219
+
220
+ **Caveats:** Only affects stroke (not fill). Prefer single-segment `<path>` elements. Contents of `<use>` cannot be visually changed. **DrawSVGPlugin.getLength(element)** and **DrawSVGPlugin.getPosition(element)** return stroke length/position.
221
+
222
+ Docs: [DrawSVG](https://gsap.com/docs/v3/Plugins/DrawSVGPlugin)
223
+
224
+ ### MorphSVG (MorphSVGPlugin)
225
+
226
+ Morphs one SVG shape into another by animating the `d` attribute. Start/end shapes need not share point counts. Works on `<path>`, `<polyline>`, `<polygon>`; primitives are converted internally or via **MorphSVGPlugin.convertToPath()**.
227
+
228
+ **morphSVG value:** a **selector**, **element**, **raw path data**, or (for polygon/polyline) a **points string**. Full config uses the **object form** with **shape** required.
229
+
230
+ ```javascript
231
+ gsap.registerPlugin(MorphSVGPlugin);
232
+
233
+ MorphSVGPlugin.convertToPath("circle, rect, ellipse, line"); // if needed
234
+
235
+ gsap.to("#diamond", { duration: 1, morphSVG: "#lightning", ease: "power2.inOut" });
236
+ gsap.to("#diamond", {
237
+ duration: 1,
238
+ morphSVG: { shape: "#lightning", type: "rotational", shapeIndex: 2 }
239
+ });
240
+ ```
241
+
242
+ | Option | Description |
243
+ |--------|-------------|
244
+ | **shape** | _(Required.)_ Target shape: selector, element, or raw path string. |
245
+ | **type** | `"linear"` (default) or `"rotational"`. Rotational uses angle/length interpolation and can avoid mid-morph kinks. |
246
+ | **map** | Segment matching: `"size"` (default), `"position"`, or `"complexity"`. |
247
+ | **shapeIndex** | Offsets which start point maps to the first end point (avoids crossing/inverting). Number for single-segment; **array** for multi-segment (negative reverses that segment). Use **shapeIndex: "log"** once to log the auto value; **findShapeIndex(start, end)** gives an interactive UI. Closed paths only. |
248
+ | **smooth** | (3.14+). Smoothing points. Number, `"auto"`, or object `{ points, redraw, persist }`. `redraw: false` keeps original anchors; `persist: false` removes added points on end. |
249
+ | **curveMode** | Boolean (3.14+). Interpolates control-handle angle/length instead of raw x/y to avoid kinks. |
250
+ | **origin** | Rotation origin for **type: "rotational"**. `"50% 50%"` (default) or `"20% 60%, 35% 90%"` for different start/end origins. |
251
+ | **precision** | Decimal places for output path data; default `2`. |
252
+ | **precompile** | Array of precomputed path strings (or `"log"` once, copy from console). Skips startup calc for complex morphs; `<path>` only. |
253
+ | **render** | Function(rawPath, target) each update — e.g. draw to canvas. |
254
+ | **updateTarget** | Set `false` (with **render**, e.g. canvas-only) so the original `<path>` isn't updated. |
255
+
256
+ **Utilities:** **convertToPath(selector | element)**, **rawPathToString(rawPath)**, **stringToRawPath(d)**. The plugin stores the original `d` for tweening back.
257
+
258
+ **Tips:** For twisted/inverted morphs set **shapeIndex** (`"log"` or findShapeIndex()). Precompile only when the first frame is slow; it doesn't fix jank during the tween.
259
+
260
+ Docs: [MorphSVG](https://gsap.com/docs/v3/Plugins/MorphSVGPlugin)
261
+
262
+ ### MotionPath (MotionPathPlugin)
263
+
264
+ Animates an element along an SVG path.
265
+
266
+ ```javascript
267
+ gsap.registerPlugin(MotionPathPlugin);
268
+
269
+ gsap.to(".dot", {
270
+ duration: 2,
271
+ motionPath: { path: "#path", align: "#path", alignOrigin: [0.5, 0.5] }
272
+ });
273
+ ```
274
+
275
+ | Option | Description |
276
+ |--------|-------------|
277
+ | `path` | SVG path element, selector, or path data string |
278
+ | `align` | Path element or selector to align the target to |
279
+ | `alignOrigin` | `[x, y]` origin (0–1); default `[0.5, 0.5]` |
280
+ | `autoRotate` | Rotate element to follow path tangent |
281
+ | `curviness` | 0–2; path smoothing |
282
+
283
+ ### MotionPathHelper
284
+
285
+ Visual editor for MotionPath (alignment, offset). Development only.
286
+
287
+ ```javascript
288
+ gsap.registerPlugin(MotionPathPlugin, MotionPathHelperPlugin);
289
+
290
+ const helper = MotionPathHelper.create(".dot", "#path", { end: 0.5 });
291
+ ```
292
+
293
+ ## Easing
294
+
295
+ ### CustomEase
296
+
297
+ Custom easing curves (cubic-bezier or SVG path) — use when a built-in ease is not enough. Register when using:
298
+
299
+ ```javascript
300
+ gsap.registerPlugin(CustomEase);
301
+
302
+ // Simple cubic-bezier (same values as CSS cubic-bezier())
303
+ const myEase = CustomEase.create("my-ease", ".17,.67,.83,.67");
304
+ gsap.to(".item", { x: 100, ease: myEase, duration: 1 });
305
+
306
+ // Complex curve with any number of control points, as normalized SVG path data
307
+ const hop = CustomEase.create("hop", "M0,0 C0,0 0.056,0.442 0.175,0.442 0.294,0.442 0.332,0 0.332,0 0.332,0 0.414,1 0.671,1 0.991,1 1,0 1,0");
308
+ gsap.to(".item", { x: 100, ease: hop, duration: 1 });
309
+ ```
310
+
311
+ ### EasePack
312
+
313
+ Adds more named eases (SlowMo, RoughEase, ExpoScaleEase). Register and use by name in tweens.
314
+
315
+ ### CustomWiggle
316
+
317
+ Wiggle/shake easing — a value oscillates multiple times.
318
+
319
+ ### CustomBounce
320
+
321
+ Bounce-style easing with configurable strength.
322
+
323
+ ## Physics
324
+
325
+ ### Physics2D (Physics2DPlugin)
326
+
327
+ 2D physics (velocity, angle, gravity). Use for projectiles, bouncing.
328
+
329
+ ```javascript
330
+ gsap.registerPlugin(Physics2DPlugin);
331
+
332
+ gsap.to(".ball", {
333
+ duration: 2,
334
+ physics2D: { velocity: 250, angle: 80, gravity: 500 }
335
+ });
336
+ ```
337
+
338
+ ### PhysicsProps (PhysicsPropsPlugin)
339
+
340
+ Applies physics to property values.
341
+
342
+ ```javascript
343
+ gsap.registerPlugin(PhysicsPropsPlugin);
344
+
345
+ gsap.to(".obj", {
346
+ duration: 2,
347
+ physicsProps: {
348
+ x: { velocity: 100, end: 300 },
349
+ y: { velocity: -50, acceleration: 200 }
350
+ }
351
+ });
352
+ ```
353
+
354
+ ## Development
355
+
356
+ ### GSDevTools
357
+
358
+ UI for scrubbing timelines, toggling, and debugging. **Development only — do not ship.**
359
+
360
+ ```javascript
361
+ gsap.registerPlugin(GSDevTools);
362
+ GSDevTools.create({ animation: tl });
363
+ ```
364
+
365
+ ## Other
366
+
367
+ ### Pixi (PixiPlugin)
368
+
369
+ Integrates GSAP with PixiJS for animating Pixi display objects.
370
+
371
+ ```javascript
372
+ gsap.registerPlugin(PixiPlugin);
373
+
374
+ const sprite = new PIXI.Sprite(texture);
375
+ gsap.to(sprite, { pixi: { x: 200, y: 100, scale: 1.5 }, duration: 1 });
376
+ ```
377
+
378
+ ## Best practices
379
+
380
+ - ✅ Register every plugin used with **gsap.registerPlugin()** before first use.
381
+ - ✅ Use **Flip.getState()** → DOM change → **Flip.from()** for layout transitions; use **Draggable** + **InertiaPlugin** for drag with momentum.
382
+ - ✅ Revert plugin instances (e.g. `splitInstance.revert()`) when components unmount or elements are removed.
383
+
384
+ ## Do Not
385
+
386
+ - ❌ Use a plugin in a tween or API without registering it first.
387
+ - ❌ Ship GSDevTools or development-only plugins to production.
388
+
389
+ ### Learn More
390
+ https://gsap.com/docs/v3/Plugins/