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 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
@@ -0,0 +1,13 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ESNext",
4
+ "module": "CommonJS",
5
+ "outDir": "./dist",
6
+ "rootDir": "./src",
7
+ "strict": true,
8
+ "esModuleInterop": true,
9
+ "skipLibCheck": true
10
+ },
11
+ "include": ["src/**/*"],
12
+ "exclude": ["node_modules"]
13
+ }