@ng-shangjc/cli 1.0.0-beta

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,216 @@
1
+ # @ng-shangjc/cli
2
+
3
+ A powerful CLI tool for managing and installing ng-shangjc UI components in your Angular projects.
4
+
5
+ ## Installation
6
+
7
+ Install the CLI globally:
8
+
9
+ ```bash
10
+ npm install -g @ng-shangjc/cli
11
+ ```
12
+
13
+ Or use npx to run without installation:
14
+
15
+ ```bash
16
+ npx @ng-shangjc/cli <command>
17
+ ```
18
+
19
+ ## Prerequisites
20
+
21
+ - Angular project (angular.json must be present)
22
+ - Node.js 16 or higher
23
+ - npm or yarn package manager
24
+
25
+ ## Commands
26
+
27
+ ### `init`
28
+
29
+ Initialize shangjc configuration in your Angular project.
30
+
31
+ ```bash
32
+ ng-shangjc init
33
+ ```
34
+
35
+ This command will:
36
+ - Verify you're in an Angular project
37
+ - Create a `shangjc.config.json` configuration file
38
+ - Prompt for component installation preferences
39
+ - Set up your project for component installations
40
+
41
+ **Configuration options:**
42
+ - **Components Path**: Where to install components (default: `src/ui/shangjc`)
43
+ - **Component Type**: Standalone (recommended) or Module-based
44
+ - **Project Type**: Angular application setup
45
+ - **Theme Configuration**: Default theme and variants
46
+ - **Tailwind Config**: Whether to configure Tailwind CSS
47
+
48
+ ### `install`
49
+
50
+ Install a specific component into your project.
51
+
52
+ ```bash
53
+ ng-shangjc install <component>
54
+ ```
55
+
56
+ **Options:**
57
+ - `-p, --path <path>`: Override the installation path from config
58
+
59
+ **Examples:**
60
+ ```bash
61
+ # Install button component
62
+ ng-shangjc install button
63
+
64
+ # Install to custom path
65
+ ng-shangjc install button --path src/components/ui
66
+
67
+ # Install dialog component
68
+ ng-shangjc install dialog
69
+ ```
70
+
71
+ **Available Components:**
72
+ - `button` - Button component with variants
73
+ - `input` - Input field component
74
+ - `card` - Card container component
75
+ - `switch` - Toggle switch component
76
+ - `dialog` - Modal dialog component
77
+ - `tooltip` - Tooltip component
78
+ - `select` - Select dropdown component
79
+ - `checkbox` - Checkbox component
80
+ - `radio-group` - Radio button group component
81
+ - `textarea` - Textarea component
82
+ - `badge` - Badge component
83
+ - `alert` - Alert/notification component
84
+
85
+ **Installation Process:**
86
+ 1. Validates component availability
87
+ 2. Checks for existing installation
88
+ 3. Installs dependencies (like @ng-shangjc/utils)
89
+ 4. Copies component files to your project
90
+ 5. Generates index.ts file
91
+ 6. Updates shangjc.config.json
92
+ 7. Provides usage instructions
93
+
94
+ ### `variants`
95
+
96
+ Show variant configurations for components.
97
+
98
+ ```bash
99
+ # Show all component variants
100
+ ng-shangjc variants
101
+
102
+ # Show variants for specific component
103
+ ng-shangjc variants button
104
+ ```
105
+
106
+ This command displays:
107
+ - Available variants for each component
108
+ - Default variant settings
109
+ - CSS classes for each variant
110
+ - Variant descriptions
111
+
112
+ ## Configuration File
113
+
114
+ The CLI creates and manages a `shangjc.config.json` file in your project root:
115
+
116
+ ```json
117
+ {
118
+ "version": "1.0.0",
119
+ "componentsPath": "src/ui/shangjc",
120
+ "componentType": "standalone",
121
+ "projectType": "angular",
122
+ "theme": {
123
+ "current": "default",
124
+ "variants": {
125
+ "button": ["primary", "secondary", "outline"],
126
+ "card": ["default", "elevated"]
127
+ }
128
+ },
129
+ "tailwindConfig": true,
130
+ "installedComponents": ["button", "input"],
131
+ "utilsVersion": "1.0.0"
132
+ }
133
+ ```
134
+
135
+ ## Component Usage
136
+
137
+ After installing components, you can import and use them in your Angular application:
138
+
139
+ ```typescript
140
+ // Import the component
141
+ import { ButtonComponent } from './ui/shangjc/button';
142
+
143
+ // Use in your component
144
+ @Component({
145
+ selector: 'app-example',
146
+ template: `
147
+ <shangjc-button variant="primary" size="md">
148
+ Click me
149
+ </shangjc-button>
150
+ `,
151
+ standalone: true,
152
+ imports: [ButtonComponent]
153
+ })
154
+ export class ExampleComponent {}
155
+ ```
156
+
157
+ ## Features
158
+
159
+ - **Interactive Setup**: Guided initialization with prompts
160
+ - **Dependency Management**: Automatic installation of required dependencies
161
+ - **Configuration Management**: Centralized config file for project settings
162
+ - **Component Variants**: Support for multiple component themes and styles
163
+ - **Path Validation**: Ensures components are installed in valid locations
164
+ - **Reinstallation Support**: Option to reinstall existing components
165
+ - **Error Handling**: Clear error messages and validation
166
+
167
+ ## Troubleshooting
168
+
169
+ ### "Not an Angular project" error
170
+ Ensure you're running the CLI from the root directory of your Angular project where `angular.json` is located.
171
+
172
+ ### Component installation fails
173
+ - Check that you have sufficient permissions
174
+ - Verify your network connection for dependency installation
175
+ - Ensure the target directory is writable
176
+
177
+ ### Configuration issues
178
+ - Delete `shangjc.config.json` and run `ng-shangjc init` again
179
+ - Check that your components path starts with `src/`
180
+
181
+ ## Development
182
+
183
+ For CLI development:
184
+
185
+ ```bash
186
+ # Clone the repository
187
+ git clone <repository-url>
188
+
189
+ # Install dependencies
190
+ npm install
191
+
192
+ # Build the CLI
193
+ npm run build
194
+
195
+ # Run in development mode
196
+ npm run dev
197
+ ```
198
+
199
+ ## Contributing
200
+
201
+ 1. Fork the repository
202
+ 2. Create a feature branch
203
+ 3. Make your changes
204
+ 4. Add tests if applicable
205
+ 5. Submit a pull request
206
+
207
+ ## License
208
+
209
+ This project is licensed under the MIT License.
210
+
211
+ ## Support
212
+
213
+ For issues and questions:
214
+ - Create an issue on GitHub
215
+ - Check the documentation
216
+ - Review existing issues for solutions
@@ -0,0 +1,280 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.initProject = initProject;
40
+ const fs = __importStar(require("fs-extra"));
41
+ const inquirer_1 = __importDefault(require("inquirer"));
42
+ async function initProject() {
43
+ console.log('šŸš€ Initializing shangjc in your project...');
44
+ // Check if Angular project
45
+ if (!fs.existsSync('angular.json')) {
46
+ console.error('āŒ This is not an Angular project.');
47
+ process.exit(1);
48
+ }
49
+ // Check if shangjc.config.json already exists
50
+ if (fs.existsSync('shangjc.config.json')) {
51
+ console.log('āš ļø shangjc.config.json already exists.');
52
+ const { overwrite } = await inquirer_1.default.prompt([
53
+ {
54
+ type: 'confirm',
55
+ name: 'overwrite',
56
+ message: 'Do you want to overwrite the existing configuration?',
57
+ default: false
58
+ }
59
+ ]);
60
+ if (!overwrite) {
61
+ console.log('Initialization cancelled.');
62
+ return;
63
+ }
64
+ }
65
+ // Ask for configuration
66
+ const config = await inquirer_1.default.prompt([
67
+ {
68
+ type: 'input',
69
+ name: 'componentsPath',
70
+ message: 'Where would you like to install components?',
71
+ default: 'src/ui/shangjc',
72
+ validate: (input) => {
73
+ if (!input.trim())
74
+ return 'Components path is required';
75
+ if (!input.startsWith('src/'))
76
+ return 'Path should be within src directory';
77
+ return true;
78
+ }
79
+ },
80
+ {
81
+ type: 'list',
82
+ name: 'componentType',
83
+ message: 'Which component type do you prefer?',
84
+ choices: [
85
+ { name: 'Standalone (Recommended)', value: 'standalone' },
86
+ { name: 'Module-based', value: 'module' }
87
+ ],
88
+ default: 'standalone'
89
+ },
90
+ {
91
+ type: 'confirm',
92
+ name: 'installTailwind',
93
+ message: 'Do you want to configure Tailwind CSS 4?',
94
+ default: true
95
+ },
96
+ {
97
+ type: 'list',
98
+ name: 'theme',
99
+ message: 'Choose your default theme:',
100
+ choices: [
101
+ { name: 'Default (Light)', value: 'default' },
102
+ { name: 'Dark', value: 'dark' },
103
+ { name: 'Both (Light + Dark)', value: 'both' }
104
+ ],
105
+ default: 'both',
106
+ when: (answers) => answers.installTailwind
107
+ }
108
+ ]);
109
+ try {
110
+ // Create components directory
111
+ await fs.ensureDir(config.componentsPath);
112
+ console.log(`āœ… Created ${config.componentsPath} directory`);
113
+ // Create shangjc config
114
+ const configFile = {
115
+ version: '1.0.0',
116
+ componentsPath: config.componentsPath,
117
+ componentType: config.componentType,
118
+ projectType: 'angular',
119
+ theme: {
120
+ current: config.theme || 'default',
121
+ variants: {
122
+ default: {
123
+ primary: 'hsl(var(--primary))',
124
+ secondary: 'hsl(var(--secondary))',
125
+ accent: 'hsl(var(--accent))',
126
+ muted: 'hsl(var(--muted))',
127
+ destructive: 'hsl(var(--destructive))',
128
+ background: 'hsl(var(--background))',
129
+ foreground: 'hsl(var(--foreground))',
130
+ border: 'hsl(var(--border))',
131
+ input: 'hsl(var(--input))',
132
+ ring: 'hsl(var(--ring))'
133
+ }
134
+ }
135
+ },
136
+ tailwindConfig: config.installTailwind,
137
+ installedComponents: [],
138
+ utilsVersion: '^1.0.0'
139
+ };
140
+ await fs.writeJson('shangjc.config.json', configFile, { spaces: 2 });
141
+ console.log('āœ… Created shangjc.config.json config file');
142
+ if (config.installTailwind) {
143
+ await setupTailwind();
144
+ }
145
+ console.log('šŸŽ‰ shangjc initialized successfully!');
146
+ console.log('\nšŸ“– Next steps:');
147
+ console.log('1. Install a component: npx @ng-shangjc/cli install button');
148
+ console.log('2. Import and use in your components');
149
+ }
150
+ catch (error) {
151
+ console.error('āŒ Initialization failed:', error);
152
+ process.exit(1);
153
+ }
154
+ }
155
+ async function setupTailwind() {
156
+ // Check if tailwind.config.js exists
157
+ const tailwindConfigPath = 'tailwind.config.js';
158
+ if (!fs.existsSync(tailwindConfigPath)) {
159
+ const tailwindConfig = `/** @type {import('tailwindcss').Config} */
160
+ module.exports = {
161
+ content: [
162
+ "./src/**/*.{html,ts}",
163
+ ],
164
+ darkMode: 'class',
165
+ theme: {
166
+ extend: {
167
+ colors: {
168
+ primary: {
169
+ DEFAULT: 'hsl(var(--primary))',
170
+ foreground: 'hsl(var(--primary-foreground))',
171
+ },
172
+ secondary: {
173
+ DEFAULT: 'hsl(var(--secondary))',
174
+ foreground: 'hsl(var(--secondary-foreground))',
175
+ },
176
+ muted: {
177
+ DEFAULT: 'hsl(var(--muted))',
178
+ foreground: 'hsl(var(--muted-foreground))',
179
+ },
180
+ accent: {
181
+ DEFAULT: 'hsl(var(--accent))',
182
+ foreground: 'hsl(var(--accent-foreground))',
183
+ },
184
+ destructive: {
185
+ DEFAULT: 'hsl(var(--destructive))',
186
+ foreground: 'hsl(var(--destructive-foreground))',
187
+ },
188
+ border: 'hsl(var(--border))',
189
+ input: 'hsl(var(--input))',
190
+ ring: 'hsl(var(--ring))',
191
+ background: 'hsl(var(--background))',
192
+ foreground: 'hsl(var(--foreground))',
193
+ },
194
+ borderRadius: {
195
+ lg: 'var(--radius)',
196
+ md: 'calc(var(--radius) - 2px)',
197
+ sm: 'calc(var(--radius) - 4px)',
198
+ },
199
+ },
200
+ },
201
+ plugins: [],
202
+ };`;
203
+ await fs.writeFile(tailwindConfigPath, tailwindConfig);
204
+ console.log('āœ… Created tailwind.config.js');
205
+ }
206
+ // Update global styles with Tailwind 4 @theme directive
207
+ const globalStylesPath = 'src/styles.css';
208
+ // Check if styles.css exists, if not try other common locations
209
+ let stylesPath = globalStylesPath;
210
+ if (!fs.existsSync(globalStylesPath)) {
211
+ if (fs.existsSync('src/global.css')) {
212
+ stylesPath = 'src/global.css';
213
+ }
214
+ else if (fs.existsSync('src/app.css')) {
215
+ stylesPath = 'src/app.css';
216
+ }
217
+ }
218
+ const globalStyles = `@import 'tailwindcss';
219
+
220
+ @theme {
221
+ --color-primary: 222.2 47.4% 11.2%;
222
+ --color-primary-foreground: 210 40% 98%;
223
+ --color-secondary: 210 40% 96.1%;
224
+ --color-secondary-foreground: 222.2 47.4% 11.2%;
225
+ --color-muted: 210 40% 96.1%;
226
+ --color-muted-foreground: 215.4 16.3% 46.9%;
227
+ --color-accent: 210 40% 96.1%;
228
+ --color-accent-foreground: 222.2 47.4% 11.2%;
229
+ --color-destructive: 0 84.2% 60.2%;
230
+ --color-destructive-foreground: 210 40% 98%;
231
+ --color-border: 214.3 31.8% 91.4%;
232
+ --color-input: 214.3 31.8% 91.4%;
233
+ --color-ring: 222.2 84% 4.9%;
234
+ --color-background: 0 0% 100%;
235
+ --color-foreground: 222.2 84% 4.9%;
236
+ --radius: 0.5rem;
237
+ }
238
+
239
+ .dark {
240
+ --color-primary: 210 40% 98%;
241
+ --color-primary-foreground: 222.2 47.4% 11.2%;
242
+ --color-secondary: 217.2 32.6% 17.5%;
243
+ --color-secondary-foreground: 210 40% 98%;
244
+ --color-muted: 217.2 32.6% 17.5%;
245
+ --color-muted-foreground: 215 20.2% 65.1%;
246
+ --color-accent: 217.2 32.6% 17.5%;
247
+ --color-accent-foreground: 210 40% 98%;
248
+ --color-destructive: 0 62.8% 30.6%;
249
+ --color-destructive-foreground: 210 40% 98%;
250
+ --color-border: 217.2 32.6% 17.5%;
251
+ --color-input: 217.2 32.6% 17.5%;
252
+ --color-ring: 212.7 26.8% 83.9%;
253
+ --color-background: 222.2 84% 4.9%;
254
+ --color-foreground: 210 40% 98%;
255
+ }
256
+
257
+ @layer base {
258
+ * {
259
+ @apply border-border;
260
+ }
261
+ body {
262
+ @apply bg-background text-foreground;
263
+ }
264
+ }`;
265
+ // Append to existing styles or create new file
266
+ if (fs.existsSync(stylesPath)) {
267
+ const existingContent = await fs.readFile(stylesPath, 'utf8');
268
+ if (!existingContent.includes('@import \'tailwindcss\'')) {
269
+ await fs.appendFile(stylesPath, '\n\n' + globalStyles);
270
+ console.log(`āœ… Updated ${stylesPath} with Tailwind 4 theme`);
271
+ }
272
+ else {
273
+ console.log(`āš ļø ${stylesPath} already contains Tailwind imports`);
274
+ }
275
+ }
276
+ else {
277
+ await fs.writeFile(stylesPath, globalStyles);
278
+ console.log(`āœ… Created ${stylesPath} with Tailwind 4 theme`);
279
+ }
280
+ }