shadcn-extras 0.1.1
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 +75 -0
- package/dist/index.js +194 -0
- package/package.json +41 -0
- package/src/index.ts +258 -0
- package/tsconfig.json +13 -0
package/README.md
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# Motion Primitives CLI
|
|
2
|
+
|
|
3
|
+
A command-line interface for easily adding beautiful, animated components to your React project.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
You can use the CLI directly with npx:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npx motion-primitives <command>
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Or install it globally:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npm install -g motion-primitives
|
|
17
|
+
motion-primitives <command>
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Usage
|
|
21
|
+
|
|
22
|
+
### List available components
|
|
23
|
+
|
|
24
|
+
To see all available animated components:
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
npx motion-primitives list
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
This will display a list of all available components along with descriptions and required dependencies.
|
|
31
|
+
|
|
32
|
+
### Add a component
|
|
33
|
+
|
|
34
|
+
To add a specific component to your project:
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
npx motion-primitives add <component-name>
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
For example:
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
npx motion-primitives add text-morph
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
This will:
|
|
47
|
+
|
|
48
|
+
1. Create a `components/motion-primitives` directory in your project (if it doesn't exist)
|
|
49
|
+
2. Download and add the component files
|
|
50
|
+
3. Automatically install any required dependencies using your preferred package manager (npm, yarn, or pnpm)
|
|
51
|
+
|
|
52
|
+
The CLI automatically detects which package manager you're using based on lock files in your project.
|
|
53
|
+
|
|
54
|
+
## Available Components
|
|
55
|
+
|
|
56
|
+
Motion Primitives offers a variety of beautiful and performant animated components, including:
|
|
57
|
+
|
|
58
|
+
- **Animated UI Elements**: Accordion, Dialog, Text Effects, Carousels
|
|
59
|
+
- **Interactive Animations**: Magnetic elements, Spotlights, Tilt effects
|
|
60
|
+
- **Text Animations**: Text morphing, Text loops, Text scramble effects, Spinning text
|
|
61
|
+
- **And many more!**
|
|
62
|
+
|
|
63
|
+
For the complete list, run `npx motion-primitives list`.
|
|
64
|
+
|
|
65
|
+
## Dependencies
|
|
66
|
+
|
|
67
|
+
Most components require the `motion` library. When you add a component, the CLI will automatically install the required dependencies using your preferred package manager.
|
|
68
|
+
|
|
69
|
+
## Contributing
|
|
70
|
+
|
|
71
|
+
Contributions are welcome! Please feel free to submit a Pull Request.
|
|
72
|
+
|
|
73
|
+
## License
|
|
74
|
+
|
|
75
|
+
[MIT](LICENSE)
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
4
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
5
|
+
};
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
const commander_1 = require("commander");
|
|
8
|
+
const fs_1 = require("fs");
|
|
9
|
+
const path_1 = require("path");
|
|
10
|
+
const ora_1 = __importDefault(require("ora"));
|
|
11
|
+
const node_fetch_1 = __importDefault(require("node-fetch"));
|
|
12
|
+
const child_process_1 = require("child_process");
|
|
13
|
+
// Read package.json for version info
|
|
14
|
+
const packageJson = JSON.parse((0, fs_1.readFileSync)((0, path_1.join)(__dirname, '..', 'package.json'), 'utf8'));
|
|
15
|
+
const MOTION_PRIMITIVES_REGISTRY_URL = 'https://raw.githubusercontent.com/nayanrdeveloper/shadcn-extras/dev/public/c/registry.json';
|
|
16
|
+
const MOTION_PRIMITIVES_BASE_URL = 'https://raw.githubusercontent.com/nayanrdeveloper/shadcn-extras/dev/';
|
|
17
|
+
const TARGET_DIR = 'components/shadcn-extras';
|
|
18
|
+
async function fetchRegistry(url) {
|
|
19
|
+
const response = await (0, node_fetch_1.default)(url);
|
|
20
|
+
if (!response.ok) {
|
|
21
|
+
throw new Error(`Failed to fetch registry from ${url}: ${response.status}`);
|
|
22
|
+
}
|
|
23
|
+
return response.json();
|
|
24
|
+
}
|
|
25
|
+
async function fetchFile(url) {
|
|
26
|
+
const response = await (0, node_fetch_1.default)(url);
|
|
27
|
+
if (!response.ok) {
|
|
28
|
+
throw new Error(`Failed to fetch file from ${url}: ${response.status}`);
|
|
29
|
+
}
|
|
30
|
+
return response.text();
|
|
31
|
+
}
|
|
32
|
+
// Detect package manager (npm, yarn, pnpm)
|
|
33
|
+
function detectPackageManager() {
|
|
34
|
+
try {
|
|
35
|
+
// Check for yarn.lock or package-lock.json
|
|
36
|
+
if ((0, fs_1.existsSync)('yarn.lock')) {
|
|
37
|
+
return 'yarn';
|
|
38
|
+
}
|
|
39
|
+
else if ((0, fs_1.existsSync)('pnpm-lock.yaml')) {
|
|
40
|
+
return 'pnpm';
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
return 'npm'; // Default to npm
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
catch (error) {
|
|
47
|
+
return 'npm'; // Default to npm on error
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
// Install dependencies using detected package manager
|
|
51
|
+
function installDependencies(dependencies) {
|
|
52
|
+
const packageManager = detectPackageManager();
|
|
53
|
+
const spinner = (0, ora_1.default)('Installing dependencies...').start();
|
|
54
|
+
try {
|
|
55
|
+
const installCommand = packageManager === 'yarn'
|
|
56
|
+
? `yarn add ${dependencies.join(' ')}`
|
|
57
|
+
: packageManager === 'pnpm'
|
|
58
|
+
? `pnpm add ${dependencies.join(' ')}`
|
|
59
|
+
: `npm install ${dependencies.join(' ')}`;
|
|
60
|
+
(0, child_process_1.execSync)(installCommand, { stdio: 'ignore' });
|
|
61
|
+
spinner.succeed(`Dependencies installed successfully with ${packageManager}`);
|
|
62
|
+
return true;
|
|
63
|
+
}
|
|
64
|
+
catch (error) {
|
|
65
|
+
spinner.fail(`Failed to install dependencies: ${error}`);
|
|
66
|
+
console.log('\nPlease install them manually:');
|
|
67
|
+
console.log(`${packageManager === 'yarn' ? 'yarn add' : packageManager === 'pnpm' ? 'pnpm add' : 'npm install'} ${dependencies.join(' ')}`);
|
|
68
|
+
return false;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
// Display the welcome banner
|
|
72
|
+
function displayBanner() {
|
|
73
|
+
console.log(`
|
|
74
|
+
┌────────────────────────────────────────────┐
|
|
75
|
+
│ │
|
|
76
|
+
│ Motion Primitives CLI │
|
|
77
|
+
│ │
|
|
78
|
+
│ Beautiful, animated components │
|
|
79
|
+
│ for your React projects │
|
|
80
|
+
│ │
|
|
81
|
+
│ Version: ${packageJson.version} │
|
|
82
|
+
│ │
|
|
83
|
+
└────────────────────────────────────────────┘
|
|
84
|
+
`);
|
|
85
|
+
}
|
|
86
|
+
commander_1.program
|
|
87
|
+
.name('motion-primitives')
|
|
88
|
+
.description('CLI to add beautiful, animated components to your app')
|
|
89
|
+
.version(packageJson.version);
|
|
90
|
+
commander_1.program
|
|
91
|
+
.command('add')
|
|
92
|
+
.argument('<component>', 'The component to add (e.g., accordion, text-morph)')
|
|
93
|
+
.description('Add a motion-primitives component to your project')
|
|
94
|
+
.action(async (component) => {
|
|
95
|
+
const spinner = (0, ora_1.default)(`Adding ${component}...`).start();
|
|
96
|
+
try {
|
|
97
|
+
// Fetch the motion-primitives registry
|
|
98
|
+
const motionPrimitivesRegistry = await fetchRegistry(MOTION_PRIMITIVES_REGISTRY_URL);
|
|
99
|
+
const componentEntry = motionPrimitivesRegistry.items.find((item) => item.name === component);
|
|
100
|
+
if (!componentEntry) {
|
|
101
|
+
spinner.fail(`Component "${component}" not found in motion-primitives registry`);
|
|
102
|
+
console.log('\nRun "npx motion-primitives list" to see all available components');
|
|
103
|
+
process.exit(1);
|
|
104
|
+
}
|
|
105
|
+
// Collect all files and dependencies
|
|
106
|
+
const allFiles = [];
|
|
107
|
+
const allDependencies = new Set(componentEntry.dependencies || []);
|
|
108
|
+
// Process all files from registry.json
|
|
109
|
+
for (const file of componentEntry.files) {
|
|
110
|
+
const content = file.content ||
|
|
111
|
+
(await fetchFile(`${MOTION_PRIMITIVES_BASE_URL}${file.path}`));
|
|
112
|
+
const fileName = file.path.split('/').pop();
|
|
113
|
+
allFiles.push({ path: fileName, content });
|
|
114
|
+
}
|
|
115
|
+
// Create target directory if it doesn't exist
|
|
116
|
+
if (!(0, fs_1.existsSync)(TARGET_DIR)) {
|
|
117
|
+
(0, fs_1.mkdirSync)(TARGET_DIR, { recursive: true });
|
|
118
|
+
}
|
|
119
|
+
// Write all files to components/motion-primitives/
|
|
120
|
+
for (const { path, content } of allFiles) {
|
|
121
|
+
const filePath = (0, path_1.join)(TARGET_DIR, path);
|
|
122
|
+
(0, fs_1.writeFileSync)(filePath, content);
|
|
123
|
+
console.log(`✓ Added ${path} to ${filePath}`);
|
|
124
|
+
}
|
|
125
|
+
spinner.succeed(`Component "${component}" added successfully!`);
|
|
126
|
+
// Install dependencies automatically
|
|
127
|
+
const depsArray = Array.from(allDependencies);
|
|
128
|
+
if (depsArray.length > 0) {
|
|
129
|
+
const installSuccess = installDependencies(depsArray);
|
|
130
|
+
// Add usage example
|
|
131
|
+
if (componentEntry.title) {
|
|
132
|
+
const pascalCaseName = component
|
|
133
|
+
.split('-')
|
|
134
|
+
.map((part) => part.charAt(0).toUpperCase() + part.slice(1))
|
|
135
|
+
.join('');
|
|
136
|
+
console.log('\nExample usage:');
|
|
137
|
+
console.log('```jsx');
|
|
138
|
+
console.log(`import { ${pascalCaseName} } from '@/components/motion-primitives/${component}';`);
|
|
139
|
+
console.log('\n// Then in your JSX:');
|
|
140
|
+
console.log(`<${pascalCaseName} />`);
|
|
141
|
+
console.log('```');
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
else {
|
|
145
|
+
console.log('No additional dependencies needed.');
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
catch (error) {
|
|
149
|
+
spinner.fail(`Error: ${error.message || error}`);
|
|
150
|
+
process.exit(1);
|
|
151
|
+
}
|
|
152
|
+
});
|
|
153
|
+
commander_1.program
|
|
154
|
+
.command('list')
|
|
155
|
+
.description('List all available motion-primitives components')
|
|
156
|
+
.action(async () => {
|
|
157
|
+
const spinner = (0, ora_1.default)('Fetching components...').start();
|
|
158
|
+
try {
|
|
159
|
+
// Fetch the motion-primitives registry
|
|
160
|
+
const motionPrimitivesRegistry = await fetchRegistry(MOTION_PRIMITIVES_REGISTRY_URL);
|
|
161
|
+
spinner.succeed(`Found ${motionPrimitivesRegistry.items.length} components`);
|
|
162
|
+
console.log('\nAvailable components:');
|
|
163
|
+
console.log('====================\n');
|
|
164
|
+
motionPrimitivesRegistry.items.forEach((item) => {
|
|
165
|
+
console.log(`${item.name} - ${item.title}`);
|
|
166
|
+
if (item.description) {
|
|
167
|
+
console.log(` ${item.description}`);
|
|
168
|
+
}
|
|
169
|
+
if (item.dependencies && item.dependencies.length > 0) {
|
|
170
|
+
console.log(` Dependencies: ${item.dependencies.join(', ')}`);
|
|
171
|
+
}
|
|
172
|
+
console.log('');
|
|
173
|
+
});
|
|
174
|
+
console.log('\nTo add a component run:');
|
|
175
|
+
console.log(' npx motion-primitives add <component-name>');
|
|
176
|
+
}
|
|
177
|
+
catch (error) {
|
|
178
|
+
spinner.fail(`Error: ${error.message || error}`);
|
|
179
|
+
process.exit(1);
|
|
180
|
+
}
|
|
181
|
+
});
|
|
182
|
+
// Add a default command if no command is provided
|
|
183
|
+
commander_1.program.action(() => {
|
|
184
|
+
displayBanner();
|
|
185
|
+
console.log('A tool for adding beautiful, animated components to your React app\n');
|
|
186
|
+
console.log('Available commands:');
|
|
187
|
+
console.log(' add <component> - Add a component to your project');
|
|
188
|
+
console.log(' Example: npx motion-primitives add text-morph');
|
|
189
|
+
console.log('\n list - List all available components');
|
|
190
|
+
console.log(' Example: npx motion-primitives list');
|
|
191
|
+
console.log('\n --help - Show help information');
|
|
192
|
+
console.log('\nDocumentation: https://github.com/ibelick/motion-primitives');
|
|
193
|
+
});
|
|
194
|
+
commander_1.program.parse(process.argv);
|
package/package.json
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "shadcn-extras",
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"description": "CLI to add shadcn-extras components to your app",
|
|
5
|
+
"bin": {
|
|
6
|
+
"shadcn-extras": "./dist/index.js"
|
|
7
|
+
},
|
|
8
|
+
"type": "commonjs",
|
|
9
|
+
"scripts": {
|
|
10
|
+
"build": "tsc",
|
|
11
|
+
"start": "node dist/index.js",
|
|
12
|
+
"dev": "tsc -w",
|
|
13
|
+
"prepublishOnly": "npm run build"
|
|
14
|
+
},
|
|
15
|
+
"dependencies": {
|
|
16
|
+
"commander": "^9.5.0",
|
|
17
|
+
"node-fetch": "^2.7.0",
|
|
18
|
+
"ora": "^5.4.1"
|
|
19
|
+
},
|
|
20
|
+
"devDependencies": {
|
|
21
|
+
"@types/node": "^18.19.123",
|
|
22
|
+
"@types/node-fetch": "^2.6.13",
|
|
23
|
+
"@types/ora": "^3.1.0",
|
|
24
|
+
"typescript": "^4.9.5"
|
|
25
|
+
},
|
|
26
|
+
"repository": {
|
|
27
|
+
"type": "git",
|
|
28
|
+
"url": "https://github.com/nayanrdeveloper/shadcn-extras.git",
|
|
29
|
+
"directory": "cli"
|
|
30
|
+
},
|
|
31
|
+
"keywords": [
|
|
32
|
+
"animation",
|
|
33
|
+
"components",
|
|
34
|
+
"motion",
|
|
35
|
+
"ui",
|
|
36
|
+
"react",
|
|
37
|
+
"cli"
|
|
38
|
+
],
|
|
39
|
+
"author": "ibelick",
|
|
40
|
+
"license": "MIT"
|
|
41
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { program } from 'commander';
|
|
4
|
+
import { existsSync, mkdirSync, writeFileSync, readFileSync } from 'fs';
|
|
5
|
+
import { join } from 'path';
|
|
6
|
+
import ora from 'ora';
|
|
7
|
+
import fetch from 'node-fetch';
|
|
8
|
+
import { execSync } from 'child_process';
|
|
9
|
+
|
|
10
|
+
// Read package.json for version info
|
|
11
|
+
const packageJson = JSON.parse(
|
|
12
|
+
readFileSync(join(__dirname, '..', 'package.json'), 'utf8')
|
|
13
|
+
);
|
|
14
|
+
|
|
15
|
+
const MOTION_PRIMITIVES_REGISTRY_URL =
|
|
16
|
+
'https://raw.githubusercontent.com/nayanrdeveloper/shadcn-extras/dev/public/c/registry.json';
|
|
17
|
+
const MOTION_PRIMITIVES_BASE_URL =
|
|
18
|
+
'https://raw.githubusercontent.com/nayanrdeveloper/shadcn-extras/dev/';
|
|
19
|
+
const TARGET_DIR = 'components/shadcn-extras';
|
|
20
|
+
|
|
21
|
+
interface FileEntry {
|
|
22
|
+
path: string;
|
|
23
|
+
type: string;
|
|
24
|
+
content?: string;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
interface RegistryItem {
|
|
28
|
+
name: string;
|
|
29
|
+
title?: string;
|
|
30
|
+
description?: string;
|
|
31
|
+
dependencies?: string[];
|
|
32
|
+
registryDependencies?: string[]; // Kept for reference, not used here
|
|
33
|
+
files: FileEntry[];
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
interface Registry {
|
|
37
|
+
items: RegistryItem[];
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
async function fetchRegistry(url: string): Promise<Registry> {
|
|
41
|
+
const response = await fetch(url);
|
|
42
|
+
if (!response.ok) {
|
|
43
|
+
throw new Error(`Failed to fetch registry from ${url}: ${response.status}`);
|
|
44
|
+
}
|
|
45
|
+
return response.json();
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
async function fetchFile(url: string): Promise<string> {
|
|
49
|
+
const response = await fetch(url);
|
|
50
|
+
if (!response.ok) {
|
|
51
|
+
throw new Error(`Failed to fetch file from ${url}: ${response.status}`);
|
|
52
|
+
}
|
|
53
|
+
return response.text();
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Detect package manager (npm, yarn, pnpm)
|
|
57
|
+
function detectPackageManager(): string {
|
|
58
|
+
try {
|
|
59
|
+
// Check for yarn.lock or package-lock.json
|
|
60
|
+
if (existsSync('yarn.lock')) {
|
|
61
|
+
return 'yarn';
|
|
62
|
+
} else if (existsSync('pnpm-lock.yaml')) {
|
|
63
|
+
return 'pnpm';
|
|
64
|
+
} else {
|
|
65
|
+
return 'npm'; // Default to npm
|
|
66
|
+
}
|
|
67
|
+
} catch (error) {
|
|
68
|
+
return 'npm'; // Default to npm on error
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Install dependencies using detected package manager
|
|
73
|
+
function installDependencies(dependencies: string[]): boolean {
|
|
74
|
+
const packageManager = detectPackageManager();
|
|
75
|
+
const spinner = ora('Installing dependencies...').start();
|
|
76
|
+
|
|
77
|
+
try {
|
|
78
|
+
const installCommand =
|
|
79
|
+
packageManager === 'yarn'
|
|
80
|
+
? `yarn add ${dependencies.join(' ')}`
|
|
81
|
+
: packageManager === 'pnpm'
|
|
82
|
+
? `pnpm add ${dependencies.join(' ')}`
|
|
83
|
+
: `npm install ${dependencies.join(' ')}`;
|
|
84
|
+
|
|
85
|
+
execSync(installCommand, { stdio: 'ignore' });
|
|
86
|
+
spinner.succeed(
|
|
87
|
+
`Dependencies installed successfully with ${packageManager}`
|
|
88
|
+
);
|
|
89
|
+
return true;
|
|
90
|
+
} catch (error) {
|
|
91
|
+
spinner.fail(`Failed to install dependencies: ${error}`);
|
|
92
|
+
console.log('\nPlease install them manually:');
|
|
93
|
+
console.log(
|
|
94
|
+
`${packageManager === 'yarn' ? 'yarn add' : packageManager === 'pnpm' ? 'pnpm add' : 'npm install'} ${dependencies.join(' ')}`
|
|
95
|
+
);
|
|
96
|
+
return false;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// Display the welcome banner
|
|
101
|
+
function displayBanner() {
|
|
102
|
+
console.log(`
|
|
103
|
+
┌────────────────────────────────────────────┐
|
|
104
|
+
│ │
|
|
105
|
+
│ Motion Primitives CLI │
|
|
106
|
+
│ │
|
|
107
|
+
│ Beautiful, animated components │
|
|
108
|
+
│ for your React projects │
|
|
109
|
+
│ │
|
|
110
|
+
│ Version: ${packageJson.version} │
|
|
111
|
+
│ │
|
|
112
|
+
└────────────────────────────────────────────┘
|
|
113
|
+
`);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
program
|
|
117
|
+
.name('motion-primitives')
|
|
118
|
+
.description('CLI to add beautiful, animated components to your app')
|
|
119
|
+
.version(packageJson.version);
|
|
120
|
+
|
|
121
|
+
program
|
|
122
|
+
.command('add')
|
|
123
|
+
.argument('<component>', 'The component to add (e.g., accordion, text-morph)')
|
|
124
|
+
.description('Add a motion-primitives component to your project')
|
|
125
|
+
.action(async (component: string) => {
|
|
126
|
+
const spinner = ora(`Adding ${component}...`).start();
|
|
127
|
+
|
|
128
|
+
try {
|
|
129
|
+
// Fetch the motion-primitives registry
|
|
130
|
+
const motionPrimitivesRegistry = await fetchRegistry(
|
|
131
|
+
MOTION_PRIMITIVES_REGISTRY_URL
|
|
132
|
+
);
|
|
133
|
+
const componentEntry = motionPrimitivesRegistry.items.find(
|
|
134
|
+
(item) => item.name === component
|
|
135
|
+
);
|
|
136
|
+
if (!componentEntry) {
|
|
137
|
+
spinner.fail(
|
|
138
|
+
`Component "${component}" not found in motion-primitives registry`
|
|
139
|
+
);
|
|
140
|
+
console.log(
|
|
141
|
+
'\nRun "npx motion-primitives list" to see all available components'
|
|
142
|
+
);
|
|
143
|
+
process.exit(1);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// Collect all files and dependencies
|
|
147
|
+
const allFiles: { path: string; content: string }[] = [];
|
|
148
|
+
const allDependencies: Set<string> = new Set(
|
|
149
|
+
componentEntry.dependencies || []
|
|
150
|
+
);
|
|
151
|
+
|
|
152
|
+
// Process all files from registry.json
|
|
153
|
+
for (const file of componentEntry.files) {
|
|
154
|
+
const content =
|
|
155
|
+
file.content ||
|
|
156
|
+
(await fetchFile(`${MOTION_PRIMITIVES_BASE_URL}${file.path}`));
|
|
157
|
+
const fileName = file.path.split('/').pop()!;
|
|
158
|
+
allFiles.push({ path: fileName, content });
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// Create target directory if it doesn't exist
|
|
162
|
+
if (!existsSync(TARGET_DIR)) {
|
|
163
|
+
mkdirSync(TARGET_DIR, { recursive: true });
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// Write all files to components/motion-primitives/
|
|
167
|
+
for (const { path, content } of allFiles) {
|
|
168
|
+
const filePath = join(TARGET_DIR, path);
|
|
169
|
+
writeFileSync(filePath, content);
|
|
170
|
+
console.log(`✓ Added ${path} to ${filePath}`);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
spinner.succeed(`Component "${component}" added successfully!`);
|
|
174
|
+
|
|
175
|
+
// Install dependencies automatically
|
|
176
|
+
const depsArray = Array.from(allDependencies);
|
|
177
|
+
if (depsArray.length > 0) {
|
|
178
|
+
const installSuccess = installDependencies(depsArray);
|
|
179
|
+
|
|
180
|
+
// Add usage example
|
|
181
|
+
if (componentEntry.title) {
|
|
182
|
+
const pascalCaseName = component
|
|
183
|
+
.split('-')
|
|
184
|
+
.map((part) => part.charAt(0).toUpperCase() + part.slice(1))
|
|
185
|
+
.join('');
|
|
186
|
+
|
|
187
|
+
console.log('\nExample usage:');
|
|
188
|
+
console.log('```jsx');
|
|
189
|
+
console.log(
|
|
190
|
+
`import { ${pascalCaseName} } from '@/components/motion-primitives/${component}';`
|
|
191
|
+
);
|
|
192
|
+
console.log('\n// Then in your JSX:');
|
|
193
|
+
console.log(`<${pascalCaseName} />`);
|
|
194
|
+
console.log('```');
|
|
195
|
+
}
|
|
196
|
+
} else {
|
|
197
|
+
console.log('No additional dependencies needed.');
|
|
198
|
+
}
|
|
199
|
+
} catch (error: any) {
|
|
200
|
+
spinner.fail(`Error: ${error.message || error}`);
|
|
201
|
+
process.exit(1);
|
|
202
|
+
}
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
program
|
|
206
|
+
.command('list')
|
|
207
|
+
.description('List all available motion-primitives components')
|
|
208
|
+
.action(async () => {
|
|
209
|
+
const spinner = ora('Fetching components...').start();
|
|
210
|
+
|
|
211
|
+
try {
|
|
212
|
+
// Fetch the motion-primitives registry
|
|
213
|
+
const motionPrimitivesRegistry = await fetchRegistry(
|
|
214
|
+
MOTION_PRIMITIVES_REGISTRY_URL
|
|
215
|
+
);
|
|
216
|
+
|
|
217
|
+
spinner.succeed(
|
|
218
|
+
`Found ${motionPrimitivesRegistry.items.length} components`
|
|
219
|
+
);
|
|
220
|
+
|
|
221
|
+
console.log('\nAvailable components:');
|
|
222
|
+
console.log('====================\n');
|
|
223
|
+
|
|
224
|
+
motionPrimitivesRegistry.items.forEach((item) => {
|
|
225
|
+
console.log(`${item.name} - ${item.title}`);
|
|
226
|
+
if (item.description) {
|
|
227
|
+
console.log(` ${item.description}`);
|
|
228
|
+
}
|
|
229
|
+
if (item.dependencies && item.dependencies.length > 0) {
|
|
230
|
+
console.log(` Dependencies: ${item.dependencies.join(', ')}`);
|
|
231
|
+
}
|
|
232
|
+
console.log('');
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
console.log('\nTo add a component run:');
|
|
236
|
+
console.log(' npx motion-primitives add <component-name>');
|
|
237
|
+
} catch (error: any) {
|
|
238
|
+
spinner.fail(`Error: ${error.message || error}`);
|
|
239
|
+
process.exit(1);
|
|
240
|
+
}
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
// Add a default command if no command is provided
|
|
244
|
+
program.action(() => {
|
|
245
|
+
displayBanner();
|
|
246
|
+
console.log(
|
|
247
|
+
'A tool for adding beautiful, animated components to your React app\n'
|
|
248
|
+
);
|
|
249
|
+
console.log('Available commands:');
|
|
250
|
+
console.log(' add <component> - Add a component to your project');
|
|
251
|
+
console.log(' Example: npx motion-primitives add text-morph');
|
|
252
|
+
console.log('\n list - List all available components');
|
|
253
|
+
console.log(' Example: npx motion-primitives list');
|
|
254
|
+
console.log('\n --help - Show help information');
|
|
255
|
+
console.log('\nDocumentation: https://github.com/ibelick/motion-primitives');
|
|
256
|
+
});
|
|
257
|
+
|
|
258
|
+
program.parse(process.argv);
|
package/tsconfig.json
ADDED