create-anima 0.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/dist/index.d.ts +2 -0
- package/dist/index.js +252 -0
- package/package.json +20 -0
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import fs from 'node:fs';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { fileURLToPath } from 'node:url';
|
|
5
|
+
import readline from 'node:readline';
|
|
6
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
7
|
+
const TEMPLATES = {
|
|
8
|
+
'package.json': (name) => `{
|
|
9
|
+
"name": "${name}",
|
|
10
|
+
"private": true,
|
|
11
|
+
"version": "0.0.0",
|
|
12
|
+
"type": "module",
|
|
13
|
+
"scripts": {
|
|
14
|
+
"dev": "vite",
|
|
15
|
+
"build": "tsc -b && vite build",
|
|
16
|
+
"preview": "vite preview"
|
|
17
|
+
},
|
|
18
|
+
"dependencies": {
|
|
19
|
+
"@it-compiles/anima": "^0.1.1",
|
|
20
|
+
"@radix-ui/react-dialog": "^1.1.15",
|
|
21
|
+
"lucide-react": "^0.562.0",
|
|
22
|
+
"react": "^19.2.0",
|
|
23
|
+
"react-dom": "^19.2.0",
|
|
24
|
+
"tailwindcss": "^4.1.18",
|
|
25
|
+
"@tailwindcss/vite": "^4.1.18"
|
|
26
|
+
},
|
|
27
|
+
"devDependencies": {
|
|
28
|
+
"@types/react": "^19.2.5",
|
|
29
|
+
"@types/react-dom": "^19.2.3",
|
|
30
|
+
"@vitejs/plugin-react": "^5.1.1",
|
|
31
|
+
"typescript": "~5.9.3",
|
|
32
|
+
"vite": "^7.2.4"
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
`,
|
|
36
|
+
'vite.config.ts': () => `import { defineConfig } from 'vite';
|
|
37
|
+
import react from '@vitejs/plugin-react';
|
|
38
|
+
import tailwindcss from '@tailwindcss/vite';
|
|
39
|
+
import { animaPlugin } from '@it-compiles/anima/vite';
|
|
40
|
+
|
|
41
|
+
export default defineConfig({
|
|
42
|
+
plugins: [react(), tailwindcss(), animaPlugin()],
|
|
43
|
+
});
|
|
44
|
+
`,
|
|
45
|
+
'tsconfig.json': () => `{
|
|
46
|
+
"compilerOptions": {
|
|
47
|
+
"target": "ES2022",
|
|
48
|
+
"lib": ["ES2022", "DOM", "DOM.Iterable"],
|
|
49
|
+
"module": "ESNext",
|
|
50
|
+
"skipLibCheck": true,
|
|
51
|
+
"moduleResolution": "bundler",
|
|
52
|
+
"allowImportingTsExtensions": true,
|
|
53
|
+
"isolatedModules": true,
|
|
54
|
+
"moduleDetection": "force",
|
|
55
|
+
"noEmit": true,
|
|
56
|
+
"jsx": "react-jsx",
|
|
57
|
+
"strict": true,
|
|
58
|
+
"noUnusedLocals": true,
|
|
59
|
+
"noUnusedParameters": true,
|
|
60
|
+
"noFallthroughCasesInSwitch": true,
|
|
61
|
+
"noUncheckedSideEffectImports": true
|
|
62
|
+
},
|
|
63
|
+
"include": ["src"]
|
|
64
|
+
}
|
|
65
|
+
`,
|
|
66
|
+
'index.html': (name) => `<!doctype html>
|
|
67
|
+
<html lang="en">
|
|
68
|
+
<head>
|
|
69
|
+
<meta charset="UTF-8" />
|
|
70
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
71
|
+
<title>${name}</title>
|
|
72
|
+
</head>
|
|
73
|
+
<body>
|
|
74
|
+
<div id="root"></div>
|
|
75
|
+
<script type="module" src="/src/main.tsx"></script>
|
|
76
|
+
</body>
|
|
77
|
+
</html>
|
|
78
|
+
`,
|
|
79
|
+
'src/main.tsx': () => `import { StrictMode } from 'react';
|
|
80
|
+
import { createRoot } from 'react-dom/client';
|
|
81
|
+
import './index.css';
|
|
82
|
+
import App from './App';
|
|
83
|
+
|
|
84
|
+
createRoot(document.getElementById('root')!).render(
|
|
85
|
+
<StrictMode>
|
|
86
|
+
<App />
|
|
87
|
+
</StrictMode>,
|
|
88
|
+
);
|
|
89
|
+
`,
|
|
90
|
+
'src/index.css': () => `@import "tailwindcss";
|
|
91
|
+
|
|
92
|
+
html, body, #root {
|
|
93
|
+
@apply h-full flex flex-col overflow-hidden bg-zinc-900 text-zinc-50;
|
|
94
|
+
}
|
|
95
|
+
`,
|
|
96
|
+
'src/vite-env.d.ts': () => `/// <reference types="vite/client" />
|
|
97
|
+
`,
|
|
98
|
+
'src/App.tsx': () => `import { useState } from 'react';
|
|
99
|
+
import { AnimaPlayer, RenderDialog } from '@it-compiles/anima/react';
|
|
100
|
+
import animation from './animation';
|
|
101
|
+
|
|
102
|
+
export default function App() {
|
|
103
|
+
const [renderOpen, setRenderOpen] = useState(false);
|
|
104
|
+
|
|
105
|
+
return (
|
|
106
|
+
<div className="h-full flex flex-col">
|
|
107
|
+
<div className="flex items-center justify-between p-4 border-b border-neutral-700">
|
|
108
|
+
<h1 className="text-lg font-medium">My Animation</h1>
|
|
109
|
+
<button
|
|
110
|
+
onClick={() => setRenderOpen(true)}
|
|
111
|
+
className="px-4 py-2 bg-blue-600 hover:bg-blue-500 text-white text-sm font-medium rounded transition-colors"
|
|
112
|
+
>
|
|
113
|
+
Render Video
|
|
114
|
+
</button>
|
|
115
|
+
</div>
|
|
116
|
+
|
|
117
|
+
<div className="flex-1 overflow-hidden">
|
|
118
|
+
<AnimaPlayer animation={animation} controls autoPlay />
|
|
119
|
+
</div>
|
|
120
|
+
|
|
121
|
+
<RenderDialog
|
|
122
|
+
open={renderOpen}
|
|
123
|
+
onOpenChange={setRenderOpen}
|
|
124
|
+
animation={animation}
|
|
125
|
+
/>
|
|
126
|
+
</div>
|
|
127
|
+
);
|
|
128
|
+
}
|
|
129
|
+
`,
|
|
130
|
+
'src/animation.ts': () => `import { defineAnimation, easeOut, easeBack, Screen } from '@it-compiles/anima';
|
|
131
|
+
|
|
132
|
+
export default defineAnimation((scene) => {
|
|
133
|
+
// Set background
|
|
134
|
+
scene.bg('#1a1a2e');
|
|
135
|
+
|
|
136
|
+
// Create objects
|
|
137
|
+
const title = scene.text('Hello, Anima!', {
|
|
138
|
+
size: 72,
|
|
139
|
+
color: '#ffffff',
|
|
140
|
+
font: 'system-ui',
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
const subtitle = scene.text('Edit src/animation.ts to get started', {
|
|
144
|
+
size: 24,
|
|
145
|
+
color: '#888888',
|
|
146
|
+
font: 'system-ui',
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
// Build timeline
|
|
150
|
+
return (t) => {
|
|
151
|
+
// Animate title
|
|
152
|
+
t.tween(800, easeBack, (ctx, u) => {
|
|
153
|
+
ctx.pin(title, 'center').to(Screen.at(0.5, 0.4), u);
|
|
154
|
+
ctx.scale(title).from(0).to(1, u);
|
|
155
|
+
ctx.opacity(title).from(0).to(1, u);
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
// Animate subtitle after title
|
|
159
|
+
t.tween(600, easeOut, (ctx, u) => {
|
|
160
|
+
ctx.pin(subtitle, 'center').to(Screen.at(0.5, 0.55), u);
|
|
161
|
+
ctx.opacity(subtitle).from(0).to(1, u);
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
// Hold for a moment
|
|
165
|
+
t.wait(1000);
|
|
166
|
+
|
|
167
|
+
// Fade out
|
|
168
|
+
t.tween(500, easeOut, (ctx, u) => {
|
|
169
|
+
ctx.opacity(title).to(0, u);
|
|
170
|
+
ctx.opacity(subtitle).to(0, u);
|
|
171
|
+
});
|
|
172
|
+
};
|
|
173
|
+
});
|
|
174
|
+
`,
|
|
175
|
+
};
|
|
176
|
+
async function prompt(question) {
|
|
177
|
+
const rl = readline.createInterface({
|
|
178
|
+
input: process.stdin,
|
|
179
|
+
output: process.stdout,
|
|
180
|
+
});
|
|
181
|
+
return new Promise((resolve) => {
|
|
182
|
+
rl.question(question, (answer) => {
|
|
183
|
+
rl.close();
|
|
184
|
+
resolve(answer.trim());
|
|
185
|
+
});
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
function isValidPackageName(name) {
|
|
189
|
+
return /^(?:@[a-z0-9-*~][a-z0-9-*._~]*\/)?[a-z0-9-~][a-z0-9-._~]*$/.test(name);
|
|
190
|
+
}
|
|
191
|
+
function toValidPackageName(name) {
|
|
192
|
+
return name
|
|
193
|
+
.toLowerCase()
|
|
194
|
+
.replace(/\s+/g, '-')
|
|
195
|
+
.replace(/[^a-z0-9-~._]/g, '-')
|
|
196
|
+
.replace(/^[._-]+/, '')
|
|
197
|
+
.replace(/[._-]+$/, '');
|
|
198
|
+
}
|
|
199
|
+
async function main() {
|
|
200
|
+
console.log();
|
|
201
|
+
console.log(' \x1b[36m@it-compiles/anima\x1b[0m - Create Animation Project');
|
|
202
|
+
console.log();
|
|
203
|
+
let projectName = process.argv[2];
|
|
204
|
+
if (!projectName) {
|
|
205
|
+
projectName = await prompt(' Project name: ');
|
|
206
|
+
}
|
|
207
|
+
if (!projectName) {
|
|
208
|
+
console.log(' \x1b[31mProject name is required\x1b[0m');
|
|
209
|
+
process.exit(1);
|
|
210
|
+
}
|
|
211
|
+
const targetDir = path.resolve(process.cwd(), projectName);
|
|
212
|
+
const packageName = toValidPackageName(path.basename(targetDir));
|
|
213
|
+
if (!isValidPackageName(packageName)) {
|
|
214
|
+
console.log(` \x1b[31mInvalid package name: ${packageName}\x1b[0m`);
|
|
215
|
+
process.exit(1);
|
|
216
|
+
}
|
|
217
|
+
if (fs.existsSync(targetDir)) {
|
|
218
|
+
const files = fs.readdirSync(targetDir);
|
|
219
|
+
if (files.length > 0) {
|
|
220
|
+
console.log(` \x1b[31mDirectory ${projectName} is not empty\x1b[0m`);
|
|
221
|
+
process.exit(1);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
else {
|
|
225
|
+
fs.mkdirSync(targetDir, { recursive: true });
|
|
226
|
+
}
|
|
227
|
+
console.log();
|
|
228
|
+
console.log(` Creating project in \x1b[32m${targetDir}\x1b[0m`);
|
|
229
|
+
console.log();
|
|
230
|
+
// Create src directory
|
|
231
|
+
fs.mkdirSync(path.join(targetDir, 'src'), { recursive: true });
|
|
232
|
+
// Write all template files
|
|
233
|
+
for (const [filePath, template] of Object.entries(TEMPLATES)) {
|
|
234
|
+
const content = typeof template === 'function'
|
|
235
|
+
? template(packageName)
|
|
236
|
+
: template;
|
|
237
|
+
const fullPath = path.join(targetDir, filePath);
|
|
238
|
+
fs.writeFileSync(fullPath, content);
|
|
239
|
+
console.log(` \x1b[32m+\x1b[0m ${filePath}`);
|
|
240
|
+
}
|
|
241
|
+
console.log();
|
|
242
|
+
console.log(' \x1b[32mDone!\x1b[0m Now run:');
|
|
243
|
+
console.log();
|
|
244
|
+
console.log(` cd ${projectName}`);
|
|
245
|
+
console.log(' npm install');
|
|
246
|
+
console.log(' npm run dev');
|
|
247
|
+
console.log();
|
|
248
|
+
}
|
|
249
|
+
main().catch((err) => {
|
|
250
|
+
console.error(err);
|
|
251
|
+
process.exit(1);
|
|
252
|
+
});
|
package/package.json
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "create-anima",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"bin": {
|
|
6
|
+
"create-anima": "./dist/index.js"
|
|
7
|
+
},
|
|
8
|
+
"files": [
|
|
9
|
+
"dist",
|
|
10
|
+
"template"
|
|
11
|
+
],
|
|
12
|
+
"scripts": {
|
|
13
|
+
"build": "tsc",
|
|
14
|
+
"dev": "tsc --watch"
|
|
15
|
+
},
|
|
16
|
+
"devDependencies": {
|
|
17
|
+
"@types/node": "^24.10.1",
|
|
18
|
+
"typescript": "~5.9.3"
|
|
19
|
+
}
|
|
20
|
+
}
|