@mehshekari/gsap-motion 2.1.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/LICENSE +21 -0
- package/NOTICE.md +24 -0
- package/README.md +59 -0
- package/bin/gsap-motion.mjs +304 -0
- package/package.json +48 -0
- package/skill/LICENSE +21 -0
- package/skill/NOTICE.md +24 -0
- package/skill/SKILL.md +181 -0
- package/skill/example/cinematic-intro.md +202 -0
- package/skill/example/magnetic-button.md +101 -0
- package/skill/example/svg-loader.md +180 -0
- package/skill/preset/card-stack.md +175 -0
- package/skill/preset/cinematic.md +140 -0
- package/skill/preset/cursor.md +184 -0
- package/skill/preset/loader.md +172 -0
- package/skill/preset/magnetic.md +155 -0
- package/skill/preset/marquee.md +177 -0
- package/skill/preset/page-transition.md +151 -0
- package/skill/preset/reveal.md +146 -0
- package/skill/preset/scroll-storytelling.md +176 -0
- package/skill/reference/accessibility.md +143 -0
- package/skill/reference/core-gsap.md +233 -0
- package/skill/reference/flip.md +220 -0
- package/skill/reference/frameworks.md +153 -0
- package/skill/reference/interaction.md +183 -0
- package/skill/reference/motion-design.md +144 -0
- package/skill/reference/performance.md +216 -0
- package/skill/reference/project-rules.md +178 -0
- package/skill/reference/react-nextjs.md +234 -0
- package/skill/reference/routing.md +119 -0
- package/skill/reference/scrolltrigger.md +191 -0
- package/skill/reference/svg.md +201 -0
- package/skill/reference/text.md +150 -0
- package/skill/reference/three-r3f.md +161 -0
- package/skill/reference/timeline.md +147 -0
- package/skill/scripts/audit-gsap.mjs +157 -0
- package/skill/scripts/audit-svg.mjs +358 -0
- package/skill/scripts/lib/rules.mjs +555 -0
- package/skill/scripts/lib/source.mjs +238 -0
- package/skill/template/useScrollScene.ts +126 -0
- package/skill/template/useTimeline.ts +110 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 mehran.shekari
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/NOTICE.md
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Notice
|
|
2
|
+
|
|
3
|
+
This skill — its instructions, references, presets, examples, templates and
|
|
4
|
+
scripts — is released under the MIT License. See [LICENSE](LICENSE).
|
|
5
|
+
|
|
6
|
+
## GSAP is licensed separately
|
|
7
|
+
|
|
8
|
+
**GSAP is not part of this skill, and it is not MIT-licensed.** The code this
|
|
9
|
+
skill writes uses GSAP (`gsap`, its plugins, and `@gsap/react`), which is
|
|
10
|
+
published by GreenSock, now part of Webflow, under the GSAP Standard License:
|
|
11
|
+
<https://gsap.com/standard-license>
|
|
12
|
+
|
|
13
|
+
In short, at the time of writing: GSAP and every one of its plugins are free to
|
|
14
|
+
use, including in commercial projects. The notable restriction is that GSAP may
|
|
15
|
+
not be used, without Webflow's written consent, in a tool that lets people build
|
|
16
|
+
visual animations without code in competition with Webflow.
|
|
17
|
+
|
|
18
|
+
That summary is not legal advice. Read the licence itself before relying on it,
|
|
19
|
+
and check it again when you upgrade.
|
|
20
|
+
|
|
21
|
+
This skill does not bundle or redistribute GSAP. Install it from npm.
|
|
22
|
+
|
|
23
|
+
"GSAP" and "GreenSock" are trademarks of their respective owners. This project
|
|
24
|
+
is not affiliated with or endorsed by GreenSock or Webflow.
|
package/README.md
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# @mehshekari/gsap-motion
|
|
2
|
+
|
|
3
|
+
Install the **gsap-creative-animation** Agent Skill — a senior motion engineer
|
|
4
|
+
for GSAP — and run its audits for silent animation failures, with `npx`.
|
|
5
|
+
|
|
6
|
+
```bash
|
|
7
|
+
npx @mehshekari/gsap-motion add # this project: .claude/skills/
|
|
8
|
+
npx @mehshekari/gsap-motion add --global # every project: ~/.claude/skills/
|
|
9
|
+
npx @mehshekari/gsap-motion audit src # find silent GSAP failures; exits 1 on an error
|
|
10
|
+
npx @mehshekari/gsap-motion doctor # what is installed, and is your GSAP recent enough
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
No dependencies, no install scripts, Node.js 18 or later.
|
|
14
|
+
|
|
15
|
+
## Commands
|
|
16
|
+
|
|
17
|
+
| Command | What it does |
|
|
18
|
+
| --- | --- |
|
|
19
|
+
| `add` | Installs or updates the skill in `.claude/skills/` for this project. `--global` installs it in `~/.claude/skills/` for your user; `--dir <path>` installs it into any agent's skills directory. `--force` reinstalls the same version. |
|
|
20
|
+
| `remove` | Uninstalls it. Takes the same `--global` and `--dir`. It only ever removes a directory that holds this skill. |
|
|
21
|
+
| `audit [path...]` | Scans for leaks, per-frame cost, eased loops, shared plugin ids, unregistered plugins and shipped dev tooling. Default path `src`. `--quiet` for errors only, `--json` for scripts. |
|
|
22
|
+
| `audit-svg <file...>` | Reports what DrawSVG can draw, what MorphSVG can morph, and what will fail silently. `--morph a.svg b.svg` compares a pair; `--hues` also reports hard-coded hues. |
|
|
23
|
+
| `doctor` | Checks Node.js, the installed skill's version for this project and your user, your project's `gsap` and `@gsap/react`, and whether an `ANIMATION.md` exists. |
|
|
24
|
+
|
|
25
|
+
## In CI
|
|
26
|
+
|
|
27
|
+
The audit needs no install. Pin the version, so a new rule cannot fail your
|
|
28
|
+
build without warning:
|
|
29
|
+
|
|
30
|
+
```json
|
|
31
|
+
"lint": "eslint && npx @mehshekari/gsap-motion@2.1.0 audit src --quiet"
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Or install it with `npm install --save-dev --save-exact @mehshekari/gsap-motion`.
|
|
35
|
+
The command it adds is `gsap-motion`:
|
|
36
|
+
|
|
37
|
+
```json
|
|
38
|
+
"lint": "eslint && gsap-motion audit src --quiet"
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Claude Code plugin
|
|
42
|
+
|
|
43
|
+
The same skill is also a Claude Code plugin:
|
|
44
|
+
|
|
45
|
+
```text
|
|
46
|
+
/plugin marketplace add mehShekari/gsap-motion
|
|
47
|
+
/plugin install gsap-motion@mehshekari
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Documentation
|
|
51
|
+
|
|
52
|
+
Everything else — the commands the skill gives your agent, the audit's rules,
|
|
53
|
+
waivers, configuration with `ANIMATION.md`, compatibility and limitations — is in
|
|
54
|
+
the [repository](https://github.com/mehShekari/gsap-motion#readme).
|
|
55
|
+
|
|
56
|
+
## License
|
|
57
|
+
|
|
58
|
+
MIT. GSAP is licensed separately; see `NOTICE.md`. This project is not affiliated
|
|
59
|
+
with GreenSock or Webflow.
|
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* gsap-motion — the gsap-creative-animation skill, from npm.
|
|
5
|
+
*
|
|
6
|
+
* npx @mehshekari/gsap-motion add [--global | --dir <skills-dir>] [--force]
|
|
7
|
+
* npx @mehshekari/gsap-motion remove [--global | --dir <skills-dir>]
|
|
8
|
+
* npx @mehshekari/gsap-motion audit [path...] [--quiet] [--json]
|
|
9
|
+
* npx @mehshekari/gsap-motion audit-svg <file.svg...> [--morph] [--hues]
|
|
10
|
+
* npx @mehshekari/gsap-motion doctor
|
|
11
|
+
*
|
|
12
|
+
* Installed as a dependency, the same commands run as `gsap-motion <command>`.
|
|
13
|
+
*
|
|
14
|
+
* No dependencies and no install scripts. `npx` runs whatever it downloads, so
|
|
15
|
+
* this file and the skill it carries are the whole of what runs.
|
|
16
|
+
*/
|
|
17
|
+
import { spawnSync } from "node:child_process";
|
|
18
|
+
import {
|
|
19
|
+
copyFileSync,
|
|
20
|
+
existsSync,
|
|
21
|
+
mkdirSync,
|
|
22
|
+
readdirSync,
|
|
23
|
+
readFileSync,
|
|
24
|
+
rmSync,
|
|
25
|
+
} from "node:fs";
|
|
26
|
+
import { homedir } from "node:os";
|
|
27
|
+
import { dirname, join, relative, resolve, sep } from "node:path";
|
|
28
|
+
import { fileURLToPath } from "node:url";
|
|
29
|
+
|
|
30
|
+
const SKILL_NAME = "gsap-creative-animation";
|
|
31
|
+
const PACKAGE_ROOT = resolve(dirname(fileURLToPath(import.meta.url)), "..");
|
|
32
|
+
const pkg = JSON.parse(
|
|
33
|
+
readFileSync(join(PACKAGE_ROOT, "package.json"), "utf8"),
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* The skill this package carries. Published, it is bundled beside `bin/`. Run
|
|
38
|
+
* from a clone of the repository it is read straight from the plugin, so the
|
|
39
|
+
* CLI can be developed and tested without bundling first.
|
|
40
|
+
*/
|
|
41
|
+
const SKILL_DIR = [
|
|
42
|
+
join(PACKAGE_ROOT, "skill"),
|
|
43
|
+
resolve(PACKAGE_ROOT, "..", "..", "plugins", "gsap-motion", "skills", SKILL_NAME),
|
|
44
|
+
].find((dir) => existsSync(join(dir, "SKILL.md")));
|
|
45
|
+
|
|
46
|
+
const useColor = process.stdout.isTTY && !process.env.NO_COLOR;
|
|
47
|
+
const paint = (code) => (text) =>
|
|
48
|
+
useColor ? `\x1b[${code}m${text}\x1b[0m` : text;
|
|
49
|
+
const bold = paint(1);
|
|
50
|
+
const dim = paint(2);
|
|
51
|
+
const green = paint(32);
|
|
52
|
+
const yellow = paint(33);
|
|
53
|
+
const red = paint(31);
|
|
54
|
+
|
|
55
|
+
const HELP = `${bold("gsap-motion")} ${pkg.version} — the ${SKILL_NAME} skill, from npm
|
|
56
|
+
|
|
57
|
+
Usage
|
|
58
|
+
npx ${pkg.name} <command> [options]
|
|
59
|
+
|
|
60
|
+
Commands
|
|
61
|
+
add Install or update the skill for this project (.claude/skills)
|
|
62
|
+
--global ...for your user instead (~/.claude/skills)
|
|
63
|
+
--dir <path> ...into another agent's skills directory
|
|
64
|
+
--force Reinstall even when this version is already installed
|
|
65
|
+
remove Uninstall it (accepts --global and --dir)
|
|
66
|
+
audit [path...] Find silent GSAP failures. Default path: src
|
|
67
|
+
--quiet Errors only
|
|
68
|
+
--json Machine-readable output
|
|
69
|
+
audit-svg <file...> What an SVG can do before you animate it
|
|
70
|
+
--morph <a> <b> Compare a morph pair
|
|
71
|
+
--hues Also report hard-coded hues
|
|
72
|
+
doctor Check Node, the installed skill and your project's GSAP
|
|
73
|
+
--version Print the version
|
|
74
|
+
|
|
75
|
+
Docs: https://github.com/mehShekari/gsap-motion`;
|
|
76
|
+
|
|
77
|
+
function fail(message, code = 1) {
|
|
78
|
+
console.error(`${red("error")} ${message}`);
|
|
79
|
+
process.exit(code);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function option(args, name) {
|
|
83
|
+
const index = args.indexOf(name);
|
|
84
|
+
if (index === -1) return undefined;
|
|
85
|
+
const value = args[index + 1];
|
|
86
|
+
if (!value || value.startsWith("--")) fail(`${name} needs a value.`, 2);
|
|
87
|
+
return value;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const flag = (args, name) => args.includes(name);
|
|
91
|
+
|
|
92
|
+
/** The skill's name and version, read from a SKILL.md — or null if there is none. */
|
|
93
|
+
function skillInfo(dir) {
|
|
94
|
+
const file = join(dir, "SKILL.md");
|
|
95
|
+
if (!existsSync(file)) return null;
|
|
96
|
+
const text = readFileSync(file, "utf8").replace(/\r\n/g, "\n");
|
|
97
|
+
return {
|
|
98
|
+
name: text.match(/^name:\s*(.+)$/m)?.[1]?.trim() ?? null,
|
|
99
|
+
version:
|
|
100
|
+
text.match(
|
|
101
|
+
/\nmetadata:\n(?:[ \t]+[\w-]+:.*\n)*?[ \t]+version:\s*"?([\d.]+)"?/,
|
|
102
|
+
)?.[1] ?? "unknown",
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/** Where `add` and `remove` act: this project, the user, or an explicit directory. */
|
|
107
|
+
function skillsDir(args) {
|
|
108
|
+
const dir = option(args, "--dir");
|
|
109
|
+
if (dir && flag(args, "--global")) fail("Use --global or --dir, not both.", 2);
|
|
110
|
+
if (dir) return resolve(dir);
|
|
111
|
+
return join(flag(args, "--global") ? homedir() : process.cwd(), ".claude", "skills");
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/** Tests belong to the repository, never to a user's install. */
|
|
115
|
+
const isTestPath = (path) =>
|
|
116
|
+
path === "scripts/test" || path.startsWith("scripts/test/");
|
|
117
|
+
|
|
118
|
+
function copyTree(from, to, base = from) {
|
|
119
|
+
let copied = 0;
|
|
120
|
+
mkdirSync(to, { recursive: true });
|
|
121
|
+
for (const entry of readdirSync(from, { withFileTypes: true })) {
|
|
122
|
+
const source = join(from, entry.name);
|
|
123
|
+
if (isTestPath(relative(base, source).split(sep).join("/"))) continue;
|
|
124
|
+
const target = join(to, entry.name);
|
|
125
|
+
if (entry.isDirectory()) copied += copyTree(source, target, base);
|
|
126
|
+
else if (entry.isFile()) {
|
|
127
|
+
copyFileSync(source, target);
|
|
128
|
+
copied += 1;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
return copied;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
function add(args) {
|
|
135
|
+
const bundled = skillInfo(SKILL_DIR);
|
|
136
|
+
const target = join(skillsDir(args), SKILL_NAME);
|
|
137
|
+
const existing = skillInfo(target);
|
|
138
|
+
|
|
139
|
+
if (existsSync(target)) {
|
|
140
|
+
if (existing?.name !== SKILL_NAME) {
|
|
141
|
+
fail(`${target} exists and is not the ${SKILL_NAME} skill. Nothing was changed.`);
|
|
142
|
+
}
|
|
143
|
+
if (existing.version === bundled.version && !flag(args, "--force")) {
|
|
144
|
+
console.log(`${green("✓")} ${SKILL_NAME} ${bundled.version} is already installed at ${target}`);
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
rmSync(target, { recursive: true, force: true });
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
const files = copyTree(SKILL_DIR, target);
|
|
151
|
+
const what = existing
|
|
152
|
+
? `Updated ${SKILL_NAME} ${existing.version} → ${bundled.version}`
|
|
153
|
+
: `Installed ${SKILL_NAME} ${bundled.version}`;
|
|
154
|
+
console.log(`${green("✓")} ${what} (${files} files)`);
|
|
155
|
+
console.log(` ${target}`);
|
|
156
|
+
console.log(
|
|
157
|
+
dim(
|
|
158
|
+
option(args, "--dir")
|
|
159
|
+
? " Point your agent at this directory if it does not read it already."
|
|
160
|
+
: flag(args, "--global")
|
|
161
|
+
? " Available in every project. Start a new Claude Code session to load it."
|
|
162
|
+
: " Commit .claude/skills to share it with your team. Start a new Claude Code session to load it.",
|
|
163
|
+
),
|
|
164
|
+
);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
function remove(args) {
|
|
168
|
+
const target = join(skillsDir(args), SKILL_NAME);
|
|
169
|
+
if (!existsSync(target)) {
|
|
170
|
+
console.log(`Nothing to remove at ${target}`);
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
if (skillInfo(target)?.name !== SKILL_NAME) {
|
|
174
|
+
fail(`${target} is not the ${SKILL_NAME} skill. Nothing was removed.`);
|
|
175
|
+
}
|
|
176
|
+
rmSync(target, { recursive: true, force: true });
|
|
177
|
+
console.log(`${green("✓")} Removed ${target}`);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
function runScript(script, args) {
|
|
181
|
+
const result = spawnSync(
|
|
182
|
+
process.execPath,
|
|
183
|
+
[join(SKILL_DIR, "scripts", script), ...args],
|
|
184
|
+
{ stdio: "inherit" },
|
|
185
|
+
);
|
|
186
|
+
if (result.error) fail(result.error.message);
|
|
187
|
+
process.exit(result.status ?? 1);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
function doctor() {
|
|
191
|
+
const bundled = skillInfo(SKILL_DIR);
|
|
192
|
+
const mark = { ok: green("✓"), warn: yellow("!"), info: dim("·") };
|
|
193
|
+
const report = (state, message, hint) => {
|
|
194
|
+
console.log(`${mark[state]} ${message}`);
|
|
195
|
+
if (hint && state !== "ok") console.log(` ${dim(hint)}`);
|
|
196
|
+
};
|
|
197
|
+
|
|
198
|
+
console.log(`${bold("gsap-motion")} ${pkg.version}, carrying ${SKILL_NAME} ${bundled.version}\n`);
|
|
199
|
+
|
|
200
|
+
const nodeMajor = Number(process.versions.node.split(".")[0]);
|
|
201
|
+
report(
|
|
202
|
+
nodeMajor >= 18 ? "ok" : "warn",
|
|
203
|
+
`Node.js ${process.versions.node}`,
|
|
204
|
+
"The audit scripts need Node.js 18 or later.",
|
|
205
|
+
);
|
|
206
|
+
|
|
207
|
+
for (const [scope, root, command] of [
|
|
208
|
+
["this project", process.cwd(), `npx ${pkg.name} add`],
|
|
209
|
+
["your user", homedir(), `npx ${pkg.name} add --global`],
|
|
210
|
+
]) {
|
|
211
|
+
const location = join(root, ".claude", "skills", SKILL_NAME);
|
|
212
|
+
const installed = skillInfo(location);
|
|
213
|
+
if (!installed) report("info", `Not installed for ${scope}`, `${command} installs it at ${location}`);
|
|
214
|
+
else if (installed.version === bundled.version) report("ok", `Installed for ${scope}: ${installed.version}`);
|
|
215
|
+
else report("warn", `Installed for ${scope}: ${installed.version}`, `${command} updates it to ${bundled.version}.`);
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
const manifest = join(process.cwd(), "package.json");
|
|
219
|
+
if (!existsSync(manifest)) {
|
|
220
|
+
report("info", "No package.json here", "Run doctor from your project root to check its GSAP version.");
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
let project;
|
|
225
|
+
try {
|
|
226
|
+
project = JSON.parse(readFileSync(manifest, "utf8"));
|
|
227
|
+
} catch {
|
|
228
|
+
report("warn", "package.json could not be read as JSON");
|
|
229
|
+
return;
|
|
230
|
+
}
|
|
231
|
+
const deps = { ...project.dependencies, ...project.devDependencies };
|
|
232
|
+
const minor = (range) => {
|
|
233
|
+
const match = String(range).match(/(\d+)\.(\d+)/);
|
|
234
|
+
return match ? [Number(match[1]), Number(match[2])] : null;
|
|
235
|
+
};
|
|
236
|
+
|
|
237
|
+
if (!deps.gsap) {
|
|
238
|
+
report("warn", "gsap is not a dependency", "Install it with `npm install gsap`.");
|
|
239
|
+
} else {
|
|
240
|
+
const version = minor(deps.gsap);
|
|
241
|
+
if (!version) report("info", `gsap ${deps.gsap}`, "Could not read a minor version; the skill assumes 3.13 or later.");
|
|
242
|
+
else {
|
|
243
|
+
const [major, min] = version;
|
|
244
|
+
report(
|
|
245
|
+
major > 3 || (major === 3 && min >= 13) ? "ok" : "warn",
|
|
246
|
+
`gsap ${deps.gsap}`,
|
|
247
|
+
"The skill assumes GSAP 3.13 or later, where every plugin is free. Upgrade with `npm install gsap@latest`.",
|
|
248
|
+
);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
if (deps.react) {
|
|
253
|
+
report(
|
|
254
|
+
deps["@gsap/react"] ? "ok" : "warn",
|
|
255
|
+
deps["@gsap/react"] ? `@gsap/react ${deps["@gsap/react"]}` : "@gsap/react is not a dependency",
|
|
256
|
+
"React projects need it for useGSAP: `npm install @gsap/react`.",
|
|
257
|
+
);
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
const rules = existsSync(join(process.cwd(), "ANIMATION.md"));
|
|
261
|
+
report(
|
|
262
|
+
rules ? "ok" : "info",
|
|
263
|
+
rules ? "ANIMATION.md found — the skill follows it" : "No ANIMATION.md",
|
|
264
|
+
"Optional. Add one so the skill follows your project's rules; see reference/project-rules.md in the skill.",
|
|
265
|
+
);
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
const [command, ...args] = process.argv.slice(2);
|
|
269
|
+
|
|
270
|
+
if (!SKILL_DIR && !["--version", "-v", "version", "--help", "-h", "help", undefined].includes(command)) {
|
|
271
|
+
fail(`The bundled skill is missing from this installation. Reinstall ${pkg.name}.`);
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
switch (command) {
|
|
275
|
+
case "add":
|
|
276
|
+
add(args);
|
|
277
|
+
break;
|
|
278
|
+
case "remove":
|
|
279
|
+
remove(args);
|
|
280
|
+
break;
|
|
281
|
+
case "audit":
|
|
282
|
+
runScript("audit-gsap.mjs", args);
|
|
283
|
+
break;
|
|
284
|
+
case "audit-svg":
|
|
285
|
+
runScript("audit-svg.mjs", args);
|
|
286
|
+
break;
|
|
287
|
+
case "doctor":
|
|
288
|
+
doctor();
|
|
289
|
+
break;
|
|
290
|
+
case "--version":
|
|
291
|
+
case "-v":
|
|
292
|
+
case "version":
|
|
293
|
+
console.log(pkg.version);
|
|
294
|
+
break;
|
|
295
|
+
case undefined:
|
|
296
|
+
case "--help":
|
|
297
|
+
case "-h":
|
|
298
|
+
case "help":
|
|
299
|
+
console.log(HELP);
|
|
300
|
+
break;
|
|
301
|
+
default:
|
|
302
|
+
console.error(HELP);
|
|
303
|
+
fail(`Unknown command "${command}".`, 2);
|
|
304
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@mehshekari/gsap-motion",
|
|
3
|
+
"version": "2.1.0",
|
|
4
|
+
"description": "Install the gsap-creative-animation Agent Skill, and audit GSAP animation for leaks, jank and accessibility failures — with npx.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"gsap",
|
|
7
|
+
"animation",
|
|
8
|
+
"scrolltrigger",
|
|
9
|
+
"agent-skills",
|
|
10
|
+
"claude-code",
|
|
11
|
+
"skill",
|
|
12
|
+
"audit",
|
|
13
|
+
"cli",
|
|
14
|
+
"react",
|
|
15
|
+
"nextjs"
|
|
16
|
+
],
|
|
17
|
+
"homepage": "https://github.com/mehShekari/gsap-motion#readme",
|
|
18
|
+
"bugs": {
|
|
19
|
+
"url": "https://github.com/mehShekari/gsap-motion/issues"
|
|
20
|
+
},
|
|
21
|
+
"repository": {
|
|
22
|
+
"type": "git",
|
|
23
|
+
"url": "git+https://github.com/mehShekari/gsap-motion.git",
|
|
24
|
+
"directory": "packages/cli"
|
|
25
|
+
},
|
|
26
|
+
"license": "MIT",
|
|
27
|
+
"author": "mehran.shekari (https://github.com/mehShekari)",
|
|
28
|
+
"type": "module",
|
|
29
|
+
"bin": {
|
|
30
|
+
"gsap-motion": "bin/gsap-motion.mjs"
|
|
31
|
+
},
|
|
32
|
+
"files": [
|
|
33
|
+
"bin/",
|
|
34
|
+
"skill/",
|
|
35
|
+
"NOTICE.md"
|
|
36
|
+
],
|
|
37
|
+
"engines": {
|
|
38
|
+
"node": ">=18"
|
|
39
|
+
},
|
|
40
|
+
"scripts": {
|
|
41
|
+
"bundle": "node scripts/bundle-skill.mjs",
|
|
42
|
+
"prepack": "node scripts/bundle-skill.mjs",
|
|
43
|
+
"check-pack": "node scripts/check-pack.mjs"
|
|
44
|
+
},
|
|
45
|
+
"publishConfig": {
|
|
46
|
+
"access": "public"
|
|
47
|
+
}
|
|
48
|
+
}
|
package/skill/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 mehran.shekari
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/skill/NOTICE.md
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Notice
|
|
2
|
+
|
|
3
|
+
This skill — its instructions, references, presets, examples, templates and
|
|
4
|
+
scripts — is released under the MIT License. See [LICENSE](LICENSE).
|
|
5
|
+
|
|
6
|
+
## GSAP is licensed separately
|
|
7
|
+
|
|
8
|
+
**GSAP is not part of this skill, and it is not MIT-licensed.** The code this
|
|
9
|
+
skill writes uses GSAP (`gsap`, its plugins, and `@gsap/react`), which is
|
|
10
|
+
published by GreenSock, now part of Webflow, under the GSAP Standard License:
|
|
11
|
+
<https://gsap.com/standard-license>
|
|
12
|
+
|
|
13
|
+
In short, at the time of writing: GSAP and every one of its plugins are free to
|
|
14
|
+
use, including in commercial projects. The notable restriction is that GSAP may
|
|
15
|
+
not be used, without Webflow's written consent, in a tool that lets people build
|
|
16
|
+
visual animations without code in competition with Webflow.
|
|
17
|
+
|
|
18
|
+
That summary is not legal advice. Read the licence itself before relying on it,
|
|
19
|
+
and check it again when you upgrade.
|
|
20
|
+
|
|
21
|
+
This skill does not bundle or redistribute GSAP. Install it from npm.
|
|
22
|
+
|
|
23
|
+
"GSAP" and "GreenSock" are trademarks of their respective owners. This project
|
|
24
|
+
is not affiliated with or endorsed by GreenSock or Webflow.
|