@gilav21/shadcn-angular 0.0.10 → 0.0.11
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/commands/add.js +97 -25
- package/dist/commands/init.js +29 -0
- package/dist/index.js +1 -1
- package/dist/registry/index.js +22 -2
- package/package.json +2 -2
- package/src/commands/add.ts +106 -25
- package/src/commands/init.ts +38 -0
- package/src/index.ts +1 -1
- package/src/registry/index.ts +22 -2
package/dist/commands/add.js
CHANGED
|
@@ -105,67 +105,139 @@ export async function add(components, options) {
|
|
|
105
105
|
const targetDir = options.path
|
|
106
106
|
? path.join(cwd, options.path)
|
|
107
107
|
: path.join(cwd, 'src/components/ui');
|
|
108
|
-
// Check for existing files
|
|
109
|
-
const
|
|
108
|
+
// Check for existing files and diff
|
|
109
|
+
const componentsToInstall = [];
|
|
110
|
+
const componentsToSkip = [];
|
|
111
|
+
const conflictingComponents = [];
|
|
112
|
+
const contentCache = new Map();
|
|
113
|
+
const checkSpinner = ora('Checking for conflicts...').start();
|
|
110
114
|
for (const name of allComponents) {
|
|
111
115
|
const component = registry[name];
|
|
116
|
+
let hasChanges = false;
|
|
117
|
+
let isFullyPresent = true;
|
|
112
118
|
for (const file of component.files) {
|
|
113
119
|
const targetPath = path.join(targetDir, file);
|
|
114
120
|
if (await fs.pathExists(targetPath)) {
|
|
115
|
-
|
|
121
|
+
const localContent = await fs.readFile(targetPath, 'utf-8');
|
|
122
|
+
try {
|
|
123
|
+
let remoteContent = await fetchComponentContent(file, options);
|
|
124
|
+
// Transform imports for comparison
|
|
125
|
+
const utilsAlias = config.aliases.utils;
|
|
126
|
+
remoteContent = remoteContent.replace(/(\.\.\/)+lib\/utils/g, utilsAlias);
|
|
127
|
+
const normalize = (str) => str.replace(/\s+/g, '').trim();
|
|
128
|
+
if (normalize(localContent) !== normalize(remoteContent)) {
|
|
129
|
+
hasChanges = true;
|
|
130
|
+
}
|
|
131
|
+
contentCache.set(file, remoteContent); // Cache for installation
|
|
132
|
+
}
|
|
133
|
+
catch (error) {
|
|
134
|
+
// unexpected error fetching remote
|
|
135
|
+
console.warn(`Could not fetch remote content for comparison: ${file}`);
|
|
136
|
+
hasChanges = true; // Assume changed/unknown
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
else {
|
|
140
|
+
isFullyPresent = false;
|
|
116
141
|
}
|
|
117
142
|
}
|
|
143
|
+
if (isFullyPresent && !hasChanges) {
|
|
144
|
+
componentsToSkip.push(name);
|
|
145
|
+
}
|
|
146
|
+
else if (hasChanges) {
|
|
147
|
+
conflictingComponents.push(name);
|
|
148
|
+
}
|
|
149
|
+
else {
|
|
150
|
+
componentsToInstall.push(name);
|
|
151
|
+
}
|
|
118
152
|
}
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
153
|
+
checkSpinner.stop();
|
|
154
|
+
let componentsToOverwrite = [];
|
|
155
|
+
if (conflictingComponents.length > 0) {
|
|
156
|
+
if (options.overwrite) {
|
|
157
|
+
componentsToOverwrite = conflictingComponents;
|
|
158
|
+
}
|
|
159
|
+
else if (options.yes) {
|
|
160
|
+
componentsToOverwrite = []; // Skip conflicts in non-interactive mode unless --overwrite
|
|
161
|
+
}
|
|
162
|
+
else {
|
|
163
|
+
console.log(chalk.yellow(`\n${conflictingComponents.length} component(s) have local changes or are different from remote.`));
|
|
164
|
+
const { selected } = await prompts({
|
|
165
|
+
type: 'multiselect',
|
|
166
|
+
name: 'selected',
|
|
167
|
+
message: 'Select components to OVERWRITE (Unselected will be skipped):',
|
|
168
|
+
choices: conflictingComponents.map(name => ({
|
|
169
|
+
title: name,
|
|
170
|
+
value: name,
|
|
171
|
+
})),
|
|
172
|
+
hint: '- Space to select, Enter to confirm',
|
|
173
|
+
});
|
|
174
|
+
componentsToOverwrite = selected || [];
|
|
129
175
|
}
|
|
130
176
|
}
|
|
177
|
+
// Final list of components to process
|
|
178
|
+
// We process:
|
|
179
|
+
// 1. componentsToInstall (Brand new or partial)
|
|
180
|
+
// 2. componentsToOverwrite (User selected)
|
|
181
|
+
// We SKIP:
|
|
182
|
+
// 1. componentsToSkip (Identical)
|
|
183
|
+
// 2. conflictingComponents NOT in componentsToOverwrite
|
|
184
|
+
const finalComponents = [...componentsToInstall, ...componentsToOverwrite];
|
|
185
|
+
if (finalComponents.length === 0 && componentsToSkip.length > 0) {
|
|
186
|
+
console.log(chalk.green(`\nAll components are up to date! (${componentsToSkip.length} skipped)`));
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
if (finalComponents.length === 0) {
|
|
190
|
+
console.log(chalk.dim('\nNo components to install.'));
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
131
193
|
const spinner = ora('Installing components...').start();
|
|
132
194
|
let successCount = 0;
|
|
133
195
|
try {
|
|
134
196
|
await fs.ensureDir(targetDir);
|
|
135
|
-
for (const name of
|
|
197
|
+
for (const name of finalComponents) {
|
|
136
198
|
const component = registry[name];
|
|
137
199
|
let componentSuccess = true;
|
|
138
200
|
for (const file of component.files) {
|
|
139
201
|
const targetPath = path.join(targetDir, file);
|
|
140
202
|
try {
|
|
141
|
-
let content =
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
203
|
+
let content = contentCache.get(file);
|
|
204
|
+
if (!content) {
|
|
205
|
+
content = await fetchComponentContent(file, options);
|
|
206
|
+
// Transform imports if not already transformed (cached is transformed)
|
|
207
|
+
const utilsAlias = config.aliases.utils;
|
|
208
|
+
content = content.replace(/(\.\.\/)+lib\/utils/g, utilsAlias);
|
|
209
|
+
}
|
|
146
210
|
await fs.ensureDir(path.dirname(targetPath));
|
|
147
211
|
await fs.writeFile(targetPath, content);
|
|
148
|
-
spinner.text = `Added ${file}`;
|
|
212
|
+
// spinner.text = `Added ${file}`; // Too verbose?
|
|
149
213
|
}
|
|
150
214
|
catch (err) {
|
|
151
215
|
spinner.warn(`Could not add ${file}: ${err.message}`);
|
|
152
216
|
componentSuccess = false;
|
|
153
217
|
}
|
|
154
218
|
}
|
|
155
|
-
if (componentSuccess)
|
|
219
|
+
if (componentSuccess) {
|
|
156
220
|
successCount++;
|
|
221
|
+
spinner.text = `Added ${name}`;
|
|
222
|
+
}
|
|
157
223
|
}
|
|
158
224
|
if (successCount > 0) {
|
|
159
|
-
spinner.succeed(chalk.green(`Added ${successCount} component(s)`));
|
|
225
|
+
spinner.succeed(chalk.green(`Success! Added ${successCount} component(s)`));
|
|
160
226
|
console.log('\n' + chalk.dim('Components added:'));
|
|
161
|
-
|
|
227
|
+
finalComponents.forEach(name => {
|
|
162
228
|
console.log(chalk.dim(' - ') + chalk.cyan(name));
|
|
163
229
|
});
|
|
164
|
-
console.log('');
|
|
165
230
|
}
|
|
166
231
|
else {
|
|
167
|
-
spinner.
|
|
232
|
+
spinner.info('No new components installed.');
|
|
233
|
+
}
|
|
234
|
+
if (componentsToSkip.length > 0) {
|
|
235
|
+
console.log('\n' + chalk.dim('Components skipped (up to date):'));
|
|
236
|
+
componentsToSkip.forEach(name => {
|
|
237
|
+
console.log(chalk.dim(' - ') + chalk.gray(name));
|
|
238
|
+
});
|
|
168
239
|
}
|
|
240
|
+
console.log('');
|
|
169
241
|
}
|
|
170
242
|
catch (error) {
|
|
171
243
|
spinner.fail('Failed to add components');
|
package/dist/commands/init.js
CHANGED
|
@@ -195,6 +195,35 @@ export async function init(options) {
|
|
|
195
195
|
};
|
|
196
196
|
await fs.writeJson(postcssrcPath, configContent, { spaces: 4 });
|
|
197
197
|
}
|
|
198
|
+
// Configure app.config.ts with Lucide icons
|
|
199
|
+
spinner.text = 'Configuring icons in app.config.ts...';
|
|
200
|
+
const appConfigPath = path.join(cwd, 'src/app/app.config.ts');
|
|
201
|
+
if (await fs.pathExists(appConfigPath)) {
|
|
202
|
+
let appConfigContent = await fs.readFile(appConfigPath, 'utf-8');
|
|
203
|
+
// Add imports
|
|
204
|
+
if (!appConfigContent.includes('LucideAngularModule')) {
|
|
205
|
+
const iconImports = "import { LucideAngularModule, ArrowDown, ArrowUp, ChevronsUpDown, ChevronLeft, ChevronRight, ChevronsLeft, ChevronsRight } from 'lucide-angular';";
|
|
206
|
+
appConfigContent = iconImports + '\n' + appConfigContent;
|
|
207
|
+
}
|
|
208
|
+
if (!appConfigContent.includes('importProvidersFrom')) {
|
|
209
|
+
appConfigContent = "import { importProvidersFrom } from '@angular/core';\n" + appConfigContent;
|
|
210
|
+
}
|
|
211
|
+
// Add provider
|
|
212
|
+
const providerCode = `
|
|
213
|
+
importProvidersFrom(LucideAngularModule.pick({
|
|
214
|
+
ArrowDown,
|
|
215
|
+
ArrowUp,
|
|
216
|
+
ChevronsUpDown,
|
|
217
|
+
ChevronLeft,
|
|
218
|
+
ChevronRight,
|
|
219
|
+
ChevronsLeft,
|
|
220
|
+
ChevronsRight
|
|
221
|
+
}))`;
|
|
222
|
+
if (!appConfigContent.includes('LucideAngularModule.pick')) {
|
|
223
|
+
appConfigContent = appConfigContent.replace(/providers:\s*\[/, `providers: [${providerCode},`);
|
|
224
|
+
await fs.writeFile(appConfigPath, appConfigContent);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
198
227
|
spinner.succeed(chalk.green('Project initialized successfully!'));
|
|
199
228
|
console.log('\n' + chalk.bold('Next steps:'));
|
|
200
229
|
console.log(chalk.dim(' 1. Add components: ') + chalk.cyan('npx @gilav21/shadcn-angular add button'));
|
package/dist/index.js
CHANGED
|
@@ -6,7 +6,7 @@ const program = new Command();
|
|
|
6
6
|
program
|
|
7
7
|
.name('shadcn-angular')
|
|
8
8
|
.description('CLI for adding shadcn-angular components to your Angular project')
|
|
9
|
-
.version('0.0.
|
|
9
|
+
.version('0.0.10');
|
|
10
10
|
program
|
|
11
11
|
.command('init')
|
|
12
12
|
.description('Initialize shadcn-angular in your project')
|
package/dist/registry/index.js
CHANGED
|
@@ -89,6 +89,25 @@ export const registry = {
|
|
|
89
89
|
files: ['date-picker.component.ts'],
|
|
90
90
|
dependencies: ['calendar'],
|
|
91
91
|
},
|
|
92
|
+
'data-table': {
|
|
93
|
+
name: 'data-table',
|
|
94
|
+
files: [
|
|
95
|
+
'data-table/data-table.component.ts',
|
|
96
|
+
'data-table/data-table-column-header.component.ts',
|
|
97
|
+
'data-table/data-table-pagination.component.ts',
|
|
98
|
+
'data-table/data-table.types.ts',
|
|
99
|
+
'data-table/cell-host.directive.ts',
|
|
100
|
+
],
|
|
101
|
+
dependencies: [
|
|
102
|
+
'table',
|
|
103
|
+
'input',
|
|
104
|
+
'button',
|
|
105
|
+
'checkbox',
|
|
106
|
+
'select',
|
|
107
|
+
'pagination',
|
|
108
|
+
'popover',
|
|
109
|
+
],
|
|
110
|
+
},
|
|
92
111
|
dialog: {
|
|
93
112
|
name: 'dialog',
|
|
94
113
|
files: ['dialog.component.ts'],
|
|
@@ -124,7 +143,8 @@ export const registry = {
|
|
|
124
143
|
},
|
|
125
144
|
'input-group': {
|
|
126
145
|
name: 'input-group',
|
|
127
|
-
files: ['input-group.component.ts'],
|
|
146
|
+
files: ['input-group.component.ts', 'input-group.token.ts'],
|
|
147
|
+
dependencies: ['input'],
|
|
128
148
|
},
|
|
129
149
|
'input-otp': {
|
|
130
150
|
name: 'input-otp',
|
|
@@ -262,7 +282,7 @@ export const registry = {
|
|
|
262
282
|
'chip-list': {
|
|
263
283
|
name: 'chip-list',
|
|
264
284
|
files: ['chip-list.component.ts'],
|
|
265
|
-
dependencies: ['badge', 'button'],
|
|
285
|
+
dependencies: ['badge', 'button', 'input', 'input-group'],
|
|
266
286
|
},
|
|
267
287
|
'emoji-picker': {
|
|
268
288
|
name: 'emoji-picker',
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gilav21/shadcn-angular",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.11",
|
|
4
4
|
"description": "CLI for adding shadcn-angular components to your project",
|
|
5
5
|
"bin": {
|
|
6
6
|
"shadcn-angular": "./dist/index.js"
|
|
@@ -32,4 +32,4 @@
|
|
|
32
32
|
"@types/prompts": "^2.4.9",
|
|
33
33
|
"typescript": "^5.5.0"
|
|
34
34
|
}
|
|
35
|
-
}
|
|
35
|
+
}
|
package/src/commands/add.ts
CHANGED
|
@@ -124,38 +124,106 @@ export async function add(components: string[], options: AddOptions) {
|
|
|
124
124
|
? path.join(cwd, options.path)
|
|
125
125
|
: path.join(cwd, 'src/components/ui');
|
|
126
126
|
|
|
127
|
-
// Check for existing files
|
|
128
|
-
const
|
|
127
|
+
// Check for existing files and diff
|
|
128
|
+
const componentsToInstall: ComponentName[] = [];
|
|
129
|
+
const componentsToSkip: string[] = [];
|
|
130
|
+
const conflictingComponents: ComponentName[] = [];
|
|
131
|
+
const contentCache = new Map<string, string>();
|
|
132
|
+
|
|
133
|
+
const checkSpinner = ora('Checking for conflicts...').start();
|
|
134
|
+
|
|
129
135
|
for (const name of allComponents) {
|
|
130
136
|
const component = registry[name];
|
|
137
|
+
let hasChanges = false;
|
|
138
|
+
let isFullyPresent = true;
|
|
139
|
+
|
|
131
140
|
for (const file of component.files) {
|
|
132
141
|
const targetPath = path.join(targetDir, file);
|
|
133
142
|
if (await fs.pathExists(targetPath)) {
|
|
134
|
-
|
|
143
|
+
const localContent = await fs.readFile(targetPath, 'utf-8');
|
|
144
|
+
|
|
145
|
+
try {
|
|
146
|
+
let remoteContent = await fetchComponentContent(file, options);
|
|
147
|
+
// Transform imports for comparison
|
|
148
|
+
const utilsAlias = config.aliases.utils;
|
|
149
|
+
remoteContent = remoteContent.replace(/(\.\.\/)+lib\/utils/g, utilsAlias);
|
|
150
|
+
|
|
151
|
+
const normalize = (str: string) => str.replace(/\s+/g, '').trim();
|
|
152
|
+
if (normalize(localContent) !== normalize(remoteContent)) {
|
|
153
|
+
hasChanges = true;
|
|
154
|
+
}
|
|
155
|
+
contentCache.set(file, remoteContent); // Cache for installation
|
|
156
|
+
} catch (error) {
|
|
157
|
+
// unexpected error fetching remote
|
|
158
|
+
console.warn(`Could not fetch remote content for comparison: ${file}`);
|
|
159
|
+
hasChanges = true; // Assume changed/unknown
|
|
160
|
+
}
|
|
161
|
+
} else {
|
|
162
|
+
isFullyPresent = false;
|
|
135
163
|
}
|
|
136
164
|
}
|
|
165
|
+
|
|
166
|
+
if (isFullyPresent && !hasChanges) {
|
|
167
|
+
componentsToSkip.push(name);
|
|
168
|
+
} else if (hasChanges) {
|
|
169
|
+
conflictingComponents.push(name);
|
|
170
|
+
} else {
|
|
171
|
+
componentsToInstall.push(name);
|
|
172
|
+
}
|
|
137
173
|
}
|
|
138
174
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
if (
|
|
147
|
-
|
|
148
|
-
|
|
175
|
+
checkSpinner.stop();
|
|
176
|
+
|
|
177
|
+
let componentsToOverwrite: ComponentName[] = [];
|
|
178
|
+
|
|
179
|
+
if (conflictingComponents.length > 0) {
|
|
180
|
+
if (options.overwrite) {
|
|
181
|
+
componentsToOverwrite = conflictingComponents;
|
|
182
|
+
} else if (options.yes) {
|
|
183
|
+
componentsToOverwrite = []; // Skip conflicts in non-interactive mode unless --overwrite
|
|
184
|
+
} else {
|
|
185
|
+
console.log(chalk.yellow(`\n${conflictingComponents.length} component(s) have local changes or are different from remote.`));
|
|
186
|
+
const { selected } = await prompts({
|
|
187
|
+
type: 'multiselect',
|
|
188
|
+
name: 'selected',
|
|
189
|
+
message: 'Select components to OVERWRITE (Unselected will be skipped):',
|
|
190
|
+
choices: conflictingComponents.map(name => ({
|
|
191
|
+
title: name,
|
|
192
|
+
value: name,
|
|
193
|
+
})),
|
|
194
|
+
hint: '- Space to select, Enter to confirm',
|
|
195
|
+
});
|
|
196
|
+
componentsToOverwrite = selected || [];
|
|
149
197
|
}
|
|
150
198
|
}
|
|
151
199
|
|
|
200
|
+
// Final list of components to process
|
|
201
|
+
// We process:
|
|
202
|
+
// 1. componentsToInstall (Brand new or partial)
|
|
203
|
+
// 2. componentsToOverwrite (User selected)
|
|
204
|
+
// We SKIP:
|
|
205
|
+
// 1. componentsToSkip (Identical)
|
|
206
|
+
// 2. conflictingComponents NOT in componentsToOverwrite
|
|
207
|
+
|
|
208
|
+
const finalComponents = [...componentsToInstall, ...componentsToOverwrite];
|
|
209
|
+
|
|
210
|
+
if (finalComponents.length === 0 && componentsToSkip.length > 0) {
|
|
211
|
+
console.log(chalk.green(`\nAll components are up to date! (${componentsToSkip.length} skipped)`));
|
|
212
|
+
return;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
if (finalComponents.length === 0) {
|
|
216
|
+
console.log(chalk.dim('\nNo components to install.'));
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
219
|
+
|
|
152
220
|
const spinner = ora('Installing components...').start();
|
|
153
221
|
let successCount = 0;
|
|
154
222
|
|
|
155
223
|
try {
|
|
156
224
|
await fs.ensureDir(targetDir);
|
|
157
225
|
|
|
158
|
-
for (const name of
|
|
226
|
+
for (const name of finalComponents) {
|
|
159
227
|
const component = registry[name];
|
|
160
228
|
let componentSuccess = true;
|
|
161
229
|
|
|
@@ -163,35 +231,48 @@ export async function add(components: string[], options: AddOptions) {
|
|
|
163
231
|
const targetPath = path.join(targetDir, file);
|
|
164
232
|
|
|
165
233
|
try {
|
|
166
|
-
let content =
|
|
234
|
+
let content = contentCache.get(file);
|
|
235
|
+
if (!content) {
|
|
236
|
+
content = await fetchComponentContent(file, options);
|
|
237
|
+
// Transform imports if not already transformed (cached is transformed)
|
|
238
|
+
const utilsAlias = config.aliases.utils;
|
|
239
|
+
content = content.replace(/(\.\.\/)+lib\/utils/g, utilsAlias);
|
|
240
|
+
}
|
|
167
241
|
|
|
168
|
-
// Transform imports
|
|
169
|
-
// Replace ../lib/utils (or similar relative paths) with the configured alias
|
|
170
|
-
const utilsAlias = config.aliases.utils;
|
|
171
|
-
content = content.replace(/(\.\.\/)+lib\/utils/g, utilsAlias);
|
|
172
242
|
await fs.ensureDir(path.dirname(targetPath));
|
|
173
243
|
await fs.writeFile(targetPath, content);
|
|
174
|
-
spinner.text = `Added ${file}`;
|
|
244
|
+
// spinner.text = `Added ${file}`; // Too verbose?
|
|
175
245
|
} catch (err: any) {
|
|
176
246
|
spinner.warn(`Could not add ${file}: ${err.message}`);
|
|
177
247
|
componentSuccess = false;
|
|
178
248
|
}
|
|
179
249
|
}
|
|
180
|
-
if (componentSuccess)
|
|
250
|
+
if (componentSuccess) {
|
|
251
|
+
successCount++;
|
|
252
|
+
spinner.text = `Added ${name}`;
|
|
253
|
+
}
|
|
181
254
|
}
|
|
182
255
|
|
|
183
256
|
if (successCount > 0) {
|
|
184
|
-
spinner.succeed(chalk.green(`Added ${successCount} component(s)`));
|
|
257
|
+
spinner.succeed(chalk.green(`Success! Added ${successCount} component(s)`));
|
|
185
258
|
|
|
186
259
|
console.log('\n' + chalk.dim('Components added:'));
|
|
187
|
-
|
|
260
|
+
finalComponents.forEach(name => {
|
|
188
261
|
console.log(chalk.dim(' - ') + chalk.cyan(name));
|
|
189
262
|
});
|
|
190
|
-
console.log('');
|
|
191
263
|
} else {
|
|
192
|
-
spinner.
|
|
264
|
+
spinner.info('No new components installed.');
|
|
193
265
|
}
|
|
194
266
|
|
|
267
|
+
if (componentsToSkip.length > 0) {
|
|
268
|
+
console.log('\n' + chalk.dim('Components skipped (up to date):'));
|
|
269
|
+
componentsToSkip.forEach(name => {
|
|
270
|
+
console.log(chalk.dim(' - ') + chalk.gray(name));
|
|
271
|
+
});
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
console.log('');
|
|
275
|
+
|
|
195
276
|
} catch (error) {
|
|
196
277
|
spinner.fail('Failed to add components');
|
|
197
278
|
console.error(error);
|
package/src/commands/init.ts
CHANGED
|
@@ -224,6 +224,44 @@ export async function init(options: InitOptions) {
|
|
|
224
224
|
await fs.writeJson(postcssrcPath, configContent, { spaces: 4 });
|
|
225
225
|
}
|
|
226
226
|
|
|
227
|
+
// Configure app.config.ts with Lucide icons
|
|
228
|
+
spinner.text = 'Configuring icons in app.config.ts...';
|
|
229
|
+
const appConfigPath = path.join(cwd, 'src/app/app.config.ts');
|
|
230
|
+
|
|
231
|
+
if (await fs.pathExists(appConfigPath)) {
|
|
232
|
+
let appConfigContent = await fs.readFile(appConfigPath, 'utf-8');
|
|
233
|
+
|
|
234
|
+
// Add imports
|
|
235
|
+
if (!appConfigContent.includes('LucideAngularModule')) {
|
|
236
|
+
const iconImports = "import { LucideAngularModule, ArrowDown, ArrowUp, ChevronsUpDown, ChevronLeft, ChevronRight, ChevronsLeft, ChevronsRight } from 'lucide-angular';";
|
|
237
|
+
appConfigContent = iconImports + '\n' + appConfigContent;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
if (!appConfigContent.includes('importProvidersFrom')) {
|
|
241
|
+
appConfigContent = "import { importProvidersFrom } from '@angular/core';\n" + appConfigContent;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
// Add provider
|
|
245
|
+
const providerCode = `
|
|
246
|
+
importProvidersFrom(LucideAngularModule.pick({
|
|
247
|
+
ArrowDown,
|
|
248
|
+
ArrowUp,
|
|
249
|
+
ChevronsUpDown,
|
|
250
|
+
ChevronLeft,
|
|
251
|
+
ChevronRight,
|
|
252
|
+
ChevronsLeft,
|
|
253
|
+
ChevronsRight
|
|
254
|
+
}))`;
|
|
255
|
+
|
|
256
|
+
if (!appConfigContent.includes('LucideAngularModule.pick')) {
|
|
257
|
+
appConfigContent = appConfigContent.replace(
|
|
258
|
+
/providers:\s*\[/,
|
|
259
|
+
`providers: [${providerCode},`
|
|
260
|
+
);
|
|
261
|
+
await fs.writeFile(appConfigPath, appConfigContent);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
|
|
227
265
|
spinner.succeed(chalk.green('Project initialized successfully!'));
|
|
228
266
|
|
|
229
267
|
console.log('\n' + chalk.bold('Next steps:'));
|
package/src/index.ts
CHANGED
package/src/registry/index.ts
CHANGED
|
@@ -98,6 +98,25 @@ export const registry: Record<string, ComponentDefinition> = {
|
|
|
98
98
|
files: ['date-picker.component.ts'],
|
|
99
99
|
dependencies: ['calendar'],
|
|
100
100
|
},
|
|
101
|
+
'data-table': {
|
|
102
|
+
name: 'data-table',
|
|
103
|
+
files: [
|
|
104
|
+
'data-table/data-table.component.ts',
|
|
105
|
+
'data-table/data-table-column-header.component.ts',
|
|
106
|
+
'data-table/data-table-pagination.component.ts',
|
|
107
|
+
'data-table/data-table.types.ts',
|
|
108
|
+
'data-table/cell-host.directive.ts',
|
|
109
|
+
],
|
|
110
|
+
dependencies: [
|
|
111
|
+
'table',
|
|
112
|
+
'input',
|
|
113
|
+
'button',
|
|
114
|
+
'checkbox',
|
|
115
|
+
'select',
|
|
116
|
+
'pagination',
|
|
117
|
+
'popover',
|
|
118
|
+
],
|
|
119
|
+
},
|
|
101
120
|
dialog: {
|
|
102
121
|
name: 'dialog',
|
|
103
122
|
files: ['dialog.component.ts'],
|
|
@@ -133,7 +152,8 @@ export const registry: Record<string, ComponentDefinition> = {
|
|
|
133
152
|
},
|
|
134
153
|
'input-group': {
|
|
135
154
|
name: 'input-group',
|
|
136
|
-
files: ['input-group.component.ts'],
|
|
155
|
+
files: ['input-group.component.ts', 'input-group.token.ts'],
|
|
156
|
+
dependencies: ['input'],
|
|
137
157
|
},
|
|
138
158
|
'input-otp': {
|
|
139
159
|
name: 'input-otp',
|
|
@@ -271,7 +291,7 @@ export const registry: Record<string, ComponentDefinition> = {
|
|
|
271
291
|
'chip-list': {
|
|
272
292
|
name: 'chip-list',
|
|
273
293
|
files: ['chip-list.component.ts'],
|
|
274
|
-
dependencies: ['badge', 'button'],
|
|
294
|
+
dependencies: ['badge', 'button', 'input', 'input-group'],
|
|
275
295
|
},
|
|
276
296
|
'emoji-picker': {
|
|
277
297
|
name: 'emoji-picker',
|