@gilav21/shadcn-angular 0.0.14 → 0.0.16
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 +67 -4
- package/dist/commands/init.js +75 -46
- package/dist/registry/index.d.ts +5 -0
- package/dist/registry/index.js +106 -6
- package/dist/utils/config.d.ts +0 -1
- package/dist/utils/config.js +0 -1
- package/dist/utils/shortcut-registry.d.ts +7 -0
- package/dist/utils/shortcut-registry.js +58 -0
- package/package.json +1 -1
- package/src/commands/add.ts +95 -22
- package/src/commands/init.ts +147 -118
- package/src/registry/index.ts +111 -6
- package/src/utils/config.ts +0 -2
- package/src/utils/shortcut-registry.ts +79 -0
package/src/commands/add.ts
CHANGED
|
@@ -4,18 +4,20 @@ import { fileURLToPath } from 'url';
|
|
|
4
4
|
import prompts from 'prompts';
|
|
5
5
|
import chalk from 'chalk';
|
|
6
6
|
import ora from 'ora';
|
|
7
|
-
import { getConfig } from '../utils/config.js';
|
|
8
|
-
import { registry, type ComponentName } from '../registry/index.js';
|
|
9
|
-
import { installPackages } from '../utils/package-manager.js';
|
|
7
|
+
import { getConfig } from '../utils/config.js';
|
|
8
|
+
import { registry, type ComponentName } from '../registry/index.js';
|
|
9
|
+
import { installPackages } from '../utils/package-manager.js';
|
|
10
|
+
import { writeShortcutRegistryIndex, type ShortcutRegistryEntry } from '../utils/shortcut-registry.js';
|
|
10
11
|
|
|
11
12
|
const __filename = fileURLToPath(import.meta.url);
|
|
12
13
|
const __dirname = path.dirname(__filename);
|
|
13
14
|
|
|
14
15
|
// Base URL for the component registry (GitHub raw content)
|
|
15
|
-
const REGISTRY_BASE_URL = 'https://raw.githubusercontent.com/gilav21/shadcn-angular/master/packages/components/ui';
|
|
16
|
+
const REGISTRY_BASE_URL = 'https://raw.githubusercontent.com/gilav21/shadcn-angular/master/packages/components/ui';
|
|
17
|
+
const LIB_REGISTRY_BASE_URL = 'https://raw.githubusercontent.com/gilav21/shadcn-angular/master/packages/components/lib';
|
|
16
18
|
|
|
17
19
|
// Components source directory (relative to CLI dist folder) for local dev
|
|
18
|
-
function getLocalComponentsDir(): string | null {
|
|
20
|
+
function getLocalComponentsDir(): string | null {
|
|
19
21
|
// From dist/commands/add.js -> packages/components/ui
|
|
20
22
|
const fromDist = path.resolve(__dirname, '../../../components/ui');
|
|
21
23
|
if (fs.existsSync(fromDist)) {
|
|
@@ -29,15 +31,38 @@ function getLocalComponentsDir(): string | null {
|
|
|
29
31
|
return null;
|
|
30
32
|
}
|
|
31
33
|
|
|
32
|
-
interface AddOptions {
|
|
34
|
+
interface AddOptions {
|
|
33
35
|
yes?: boolean;
|
|
34
36
|
overwrite?: boolean;
|
|
35
37
|
all?: boolean;
|
|
36
38
|
path?: string;
|
|
37
|
-
remote?: boolean; // Force remote fetch
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
|
|
39
|
+
remote?: boolean; // Force remote fetch
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function getLocalLibDir(): string | null {
|
|
43
|
+
const fromDist = path.resolve(__dirname, '../../../components/lib');
|
|
44
|
+
if (fs.existsSync(fromDist)) {
|
|
45
|
+
return fromDist;
|
|
46
|
+
}
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function resolveProjectPath(cwd: string, inputPath: string): string {
|
|
51
|
+
const resolved = path.resolve(cwd, inputPath);
|
|
52
|
+
const relative = path.relative(cwd, resolved);
|
|
53
|
+
if (relative.startsWith('..') || path.isAbsolute(relative)) {
|
|
54
|
+
throw new Error(`Path must stay inside the project directory: ${inputPath}`);
|
|
55
|
+
}
|
|
56
|
+
return resolved;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function aliasToProjectPath(aliasOrPath: string): string {
|
|
60
|
+
return aliasOrPath.startsWith('@/')
|
|
61
|
+
? path.join('src', aliasOrPath.slice(2))
|
|
62
|
+
: aliasOrPath;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
async function fetchComponentContent(file: string, options: AddOptions): Promise<string> {
|
|
41
66
|
const localDir = getLocalComponentsDir();
|
|
42
67
|
|
|
43
68
|
// 1. Prefer local if available and not forced remote
|
|
@@ -62,7 +87,41 @@ async function fetchComponentContent(file: string, options: AddOptions): Promise
|
|
|
62
87
|
}
|
|
63
88
|
throw error;
|
|
64
89
|
}
|
|
65
|
-
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
async function fetchLibContent(file: string, options: AddOptions): Promise<string> {
|
|
93
|
+
const localDir = getLocalLibDir();
|
|
94
|
+
|
|
95
|
+
if (localDir && !options.remote) {
|
|
96
|
+
const localPath = path.join(localDir, file);
|
|
97
|
+
if (await fs.pathExists(localPath)) {
|
|
98
|
+
return fs.readFile(localPath, 'utf-8');
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const url = `${LIB_REGISTRY_BASE_URL}/${file}`;
|
|
103
|
+
const response = await fetch(url);
|
|
104
|
+
if (!response.ok) {
|
|
105
|
+
throw new Error(`Failed to fetch library file from ${url}: ${response.statusText}`);
|
|
106
|
+
}
|
|
107
|
+
return response.text();
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function collectInstalledShortcutEntries(targetDir: string): ShortcutRegistryEntry[] {
|
|
111
|
+
const entries: ShortcutRegistryEntry[] = [];
|
|
112
|
+
for (const definition of Object.values(registry)) {
|
|
113
|
+
if (!definition.shortcutDefinitions?.length) {
|
|
114
|
+
continue;
|
|
115
|
+
}
|
|
116
|
+
for (const shortcutDefinition of definition.shortcutDefinitions) {
|
|
117
|
+
const sourcePath = path.join(targetDir, shortcutDefinition.sourceFile);
|
|
118
|
+
if (fs.existsSync(sourcePath)) {
|
|
119
|
+
entries.push(shortcutDefinition);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
return entries;
|
|
124
|
+
}
|
|
66
125
|
|
|
67
126
|
export async function add(components: string[], options: AddOptions) {
|
|
68
127
|
const cwd = process.cwd();
|
|
@@ -121,9 +180,8 @@ export async function add(components: string[], options: AddOptions) {
|
|
|
121
180
|
};
|
|
122
181
|
componentsToAdd.forEach(c => resolveDeps(c));
|
|
123
182
|
|
|
124
|
-
const
|
|
125
|
-
|
|
126
|
-
: path.join(cwd, 'src/components/ui');
|
|
183
|
+
const uiBasePath = options.path ?? aliasToProjectPath(config.aliases.ui || 'src/components/ui');
|
|
184
|
+
const targetDir = resolveProjectPath(cwd, uiBasePath);
|
|
127
185
|
|
|
128
186
|
// Check for existing files and diff
|
|
129
187
|
const componentsToInstall: ComponentName[] = [];
|
|
@@ -149,7 +207,7 @@ export async function add(components: string[], options: AddOptions) {
|
|
|
149
207
|
const utilsAlias = config.aliases.utils;
|
|
150
208
|
remoteContent = remoteContent.replace(/(\.\.\/)+lib\/utils/g, utilsAlias);
|
|
151
209
|
|
|
152
|
-
const normalize = (str: string) => str.replace(/\
|
|
210
|
+
const normalize = (str: string) => str.replace(/\r\n/g, '\n').trim();
|
|
153
211
|
if (normalize(localContent) !== normalize(remoteContent)) {
|
|
154
212
|
hasChanges = true;
|
|
155
213
|
}
|
|
@@ -265,8 +323,8 @@ export async function add(components: string[], options: AddOptions) {
|
|
|
265
323
|
spinner.info('No new components installed.');
|
|
266
324
|
}
|
|
267
325
|
|
|
268
|
-
if (finalComponents.length > 0) {
|
|
269
|
-
const npmDependencies = new Set<string>();
|
|
326
|
+
if (finalComponents.length > 0) {
|
|
327
|
+
const npmDependencies = new Set<string>();
|
|
270
328
|
for (const name of finalComponents) {
|
|
271
329
|
const component = registry[name];
|
|
272
330
|
if (component.npmDependencies) {
|
|
@@ -283,11 +341,26 @@ export async function add(components: string[], options: AddOptions) {
|
|
|
283
341
|
depSpinner.fail('Failed to install dependencies.');
|
|
284
342
|
console.error(e);
|
|
285
343
|
}
|
|
286
|
-
}
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
const shortcutEntries = collectInstalledShortcutEntries(targetDir);
|
|
348
|
+
if (shortcutEntries.length > 0) {
|
|
349
|
+
const utilsPathResolved = resolveProjectPath(cwd, aliasToProjectPath(config.aliases.utils) + '.ts');
|
|
350
|
+
const utilsDir = path.dirname(utilsPathResolved);
|
|
351
|
+
const shortcutServicePath = path.join(utilsDir, 'shortcut-binding.service.ts');
|
|
352
|
+
|
|
353
|
+
if (!await fs.pathExists(shortcutServicePath)) {
|
|
354
|
+
const shortcutServiceContent = await fetchLibContent('shortcut-binding.service.ts', options);
|
|
355
|
+
await fs.ensureDir(utilsDir);
|
|
356
|
+
await fs.writeFile(shortcutServicePath, shortcutServiceContent);
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
await writeShortcutRegistryIndex(cwd, config, shortcutEntries);
|
|
361
|
+
|
|
362
|
+
if (componentsToSkip.length > 0) {
|
|
363
|
+
console.log('\n' + chalk.dim('Components skipped (up to date):'));
|
|
291
364
|
componentsToSkip.forEach(name => {
|
|
292
365
|
console.log(chalk.dim(' - ') + chalk.gray(name));
|
|
293
366
|
});
|
package/src/commands/init.ts
CHANGED
|
@@ -1,19 +1,66 @@
|
|
|
1
|
-
import fs from 'fs-extra';
|
|
2
|
-
import path from 'path';
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
import
|
|
6
|
-
import
|
|
7
|
-
import { getDefaultConfig, type Config } from '../utils/config.js';
|
|
8
|
-
import { getStylesTemplate } from '../templates/styles.js';
|
|
9
|
-
import { getUtilsTemplate } from '../templates/utils.js';
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
1
|
+
import fs from 'fs-extra';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { fileURLToPath } from 'url';
|
|
4
|
+
import prompts from 'prompts';
|
|
5
|
+
import chalk from 'chalk';
|
|
6
|
+
import ora from 'ora';
|
|
7
|
+
import { getDefaultConfig, type Config } from '../utils/config.js';
|
|
8
|
+
import { getStylesTemplate } from '../templates/styles.js';
|
|
9
|
+
import { getUtilsTemplate } from '../templates/utils.js';
|
|
10
|
+
import { installPackages } from '../utils/package-manager.js';
|
|
11
|
+
import { writeShortcutRegistryIndex } from '../utils/shortcut-registry.js';
|
|
12
|
+
|
|
13
|
+
const LIB_REGISTRY_BASE_URL = 'https://raw.githubusercontent.com/gilav21/shadcn-angular/master/packages/components/lib';
|
|
14
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
15
|
+
const __dirname = path.dirname(__filename);
|
|
16
|
+
|
|
17
|
+
function getLocalLibDir(): string | null {
|
|
18
|
+
const fromDist = path.resolve(__dirname, '../../../components/lib');
|
|
19
|
+
if (fs.existsSync(fromDist)) {
|
|
20
|
+
return fromDist;
|
|
21
|
+
}
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
async function fetchLibFileContent(file: string): Promise<string> {
|
|
26
|
+
const localLibDir = getLocalLibDir();
|
|
27
|
+
if (localLibDir) {
|
|
28
|
+
const localPath = path.join(localLibDir, file);
|
|
29
|
+
if (await fs.pathExists(localPath)) {
|
|
30
|
+
return fs.readFile(localPath, 'utf-8');
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const url = `${LIB_REGISTRY_BASE_URL}/${file}`;
|
|
35
|
+
const response = await fetch(url);
|
|
36
|
+
if (!response.ok) {
|
|
37
|
+
throw new Error(`Failed to fetch library file from ${url}: ${response.statusText}`);
|
|
38
|
+
}
|
|
39
|
+
return response.text();
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
interface InitOptions {
|
|
43
|
+
yes?: boolean;
|
|
44
|
+
defaults?: boolean;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function resolveProjectPath(cwd: string, inputPath: string): string {
|
|
48
|
+
const resolved = path.resolve(cwd, inputPath);
|
|
49
|
+
const relative = path.relative(cwd, resolved);
|
|
50
|
+
if (relative.startsWith('..') || path.isAbsolute(relative)) {
|
|
51
|
+
throw new Error(`Path must stay inside the project directory: ${inputPath}`);
|
|
52
|
+
}
|
|
53
|
+
return resolved;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function resolveAliasOrPath(cwd: string, aliasOrPath: string): string {
|
|
57
|
+
const normalized = aliasOrPath.startsWith('@/')
|
|
58
|
+
? path.join('src', aliasOrPath.slice(2))
|
|
59
|
+
: aliasOrPath;
|
|
60
|
+
return resolveProjectPath(cwd, normalized);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export async function init(options: InitOptions) {
|
|
17
64
|
console.log(chalk.bold('\n🎨 Welcome to shadcn-angular!\n'));
|
|
18
65
|
|
|
19
66
|
const cwd = process.cwd();
|
|
@@ -26,26 +73,30 @@ export async function init(options: InitOptions) {
|
|
|
26
73
|
process.exit(1);
|
|
27
74
|
}
|
|
28
75
|
|
|
29
|
-
// Check if already initialized
|
|
30
|
-
const componentsJsonPath = path.join(cwd, 'components.json');
|
|
31
|
-
if (await fs.pathExists(componentsJsonPath)) {
|
|
32
|
-
const
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
76
|
+
// Check if already initialized
|
|
77
|
+
const componentsJsonPath = path.join(cwd, 'components.json');
|
|
78
|
+
if (await fs.pathExists(componentsJsonPath)) {
|
|
79
|
+
const overwrite = options.yes
|
|
80
|
+
? true
|
|
81
|
+
: (await prompts({
|
|
82
|
+
type: 'confirm',
|
|
83
|
+
name: 'overwrite',
|
|
84
|
+
message: 'components.json already exists. Overwrite?',
|
|
85
|
+
initial: false,
|
|
86
|
+
})).overwrite;
|
|
87
|
+
if (!overwrite) {
|
|
88
|
+
console.log(chalk.dim('Initialization cancelled.'));
|
|
89
|
+
return;
|
|
41
90
|
}
|
|
42
91
|
}
|
|
43
92
|
|
|
44
|
-
let config: Config;
|
|
93
|
+
let config: Config;
|
|
94
|
+
let createShortcutRegistry = true;
|
|
45
95
|
|
|
46
|
-
if (options.defaults || options.yes) {
|
|
47
|
-
config = getDefaultConfig();
|
|
48
|
-
|
|
96
|
+
if (options.defaults || options.yes) {
|
|
97
|
+
config = getDefaultConfig();
|
|
98
|
+
createShortcutRegistry = true;
|
|
99
|
+
} else {
|
|
49
100
|
const THEME_COLORS: Record<string, string> = {
|
|
50
101
|
zinc: '#71717a',
|
|
51
102
|
slate: '#64748b',
|
|
@@ -123,16 +174,22 @@ export async function init(options: InitOptions) {
|
|
|
123
174
|
message: 'Where would you like to install utils?',
|
|
124
175
|
initial: 'src/components/lib',
|
|
125
176
|
},
|
|
126
|
-
{
|
|
127
|
-
type: 'text',
|
|
128
|
-
name: 'globalCss',
|
|
129
|
-
message: 'Where is your global styles file?',
|
|
130
|
-
initial: 'src/styles.scss',
|
|
131
|
-
},
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
177
|
+
{
|
|
178
|
+
type: 'text',
|
|
179
|
+
name: 'globalCss',
|
|
180
|
+
message: 'Where is your global styles file?',
|
|
181
|
+
initial: 'src/styles.scss',
|
|
182
|
+
},
|
|
183
|
+
{
|
|
184
|
+
type: 'confirm',
|
|
185
|
+
name: 'createShortcutRegistry',
|
|
186
|
+
message: 'Would you like to create a shortcut registry scaffold?',
|
|
187
|
+
initial: true,
|
|
188
|
+
},
|
|
189
|
+
]);
|
|
190
|
+
|
|
191
|
+
config = {
|
|
192
|
+
$schema: 'https://shadcn-angular.dev/schema.json',
|
|
136
193
|
style: 'default',
|
|
137
194
|
tailwind: {
|
|
138
195
|
css: responses.globalCss,
|
|
@@ -144,10 +201,10 @@ export async function init(options: InitOptions) {
|
|
|
144
201
|
components: responses.componentsPath.replace('src/', '@/'), // Basic heuristic
|
|
145
202
|
utils: responses.utilsPath.replace('src/', '@/').replace('.ts', ''),
|
|
146
203
|
ui: responses.componentsPath.replace('src/', '@/'),
|
|
147
|
-
},
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
}
|
|
204
|
+
},
|
|
205
|
+
};
|
|
206
|
+
createShortcutRegistry = responses.createShortcutRegistry ?? true;
|
|
207
|
+
}
|
|
151
208
|
|
|
152
209
|
const spinner = ora('Initializing project...').start();
|
|
153
210
|
|
|
@@ -163,26 +220,37 @@ export async function init(options: InitOptions) {
|
|
|
163
220
|
// If config came from defaults, aliases are set.
|
|
164
221
|
// We can reverse-map alias to path: @/ -> src/
|
|
165
222
|
|
|
166
|
-
const utilsPathResolved = config.aliases.utils
|
|
167
|
-
const utilsDir = path.dirname(
|
|
168
|
-
|
|
169
|
-
await fs.ensureDir(utilsDir);
|
|
170
|
-
await fs.writeFile(
|
|
171
|
-
spinner.text = 'Created utils.ts';
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
const
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
223
|
+
const utilsPathResolved = resolveAliasOrPath(cwd, config.aliases.utils + '.ts');
|
|
224
|
+
const utilsDir = path.dirname(utilsPathResolved); // utils usually ends in path/to/utils
|
|
225
|
+
|
|
226
|
+
await fs.ensureDir(utilsDir);
|
|
227
|
+
await fs.writeFile(utilsPathResolved, getUtilsTemplate());
|
|
228
|
+
spinner.text = 'Created utils.ts';
|
|
229
|
+
|
|
230
|
+
const shortcutServicePath = path.join(utilsDir, 'shortcut-binding.service.ts');
|
|
231
|
+
const shortcutServiceContent = await fetchLibFileContent('shortcut-binding.service.ts');
|
|
232
|
+
await fs.writeFile(shortcutServicePath, shortcutServiceContent);
|
|
233
|
+
spinner.text = 'Created shortcut-binding.service.ts';
|
|
234
|
+
|
|
235
|
+
if (createShortcutRegistry) {
|
|
236
|
+
await writeShortcutRegistryIndex(cwd, config, []);
|
|
237
|
+
spinner.text = 'Created shortcut-registry.index.ts';
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
// Create tailwind.css file in the same directory as the global styles
|
|
241
|
+
const userStylesPath = resolveProjectPath(cwd, config.tailwind.css);
|
|
242
|
+
const stylesDir = path.dirname(userStylesPath);
|
|
243
|
+
const tailwindCssPath = path.join(stylesDir, 'tailwind.css');
|
|
244
|
+
|
|
245
|
+
// Write the tailwind.css file with all Tailwind directives
|
|
246
|
+
await fs.ensureDir(stylesDir);
|
|
247
|
+
await fs.writeFile(tailwindCssPath, getStylesTemplate(config.tailwind.baseColor, config.tailwind.theme));
|
|
248
|
+
spinner.text = 'Created tailwind.css';
|
|
249
|
+
|
|
250
|
+
// Add import to the user's global styles file if not already present
|
|
251
|
+
let userStyles = await fs.pathExists(userStylesPath)
|
|
252
|
+
? await fs.readFile(userStylesPath, 'utf-8')
|
|
253
|
+
: '';
|
|
186
254
|
|
|
187
255
|
const tailwindImport = '@import "./tailwind.css";';
|
|
188
256
|
if (!userStyles.includes('tailwind.css')) {
|
|
@@ -190,26 +258,24 @@ export async function init(options: InitOptions) {
|
|
|
190
258
|
userStyles = tailwindImport + '\n\n' + userStyles;
|
|
191
259
|
await fs.writeFile(userStylesPath, userStyles);
|
|
192
260
|
spinner.text = 'Added tailwind.css import to styles';
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
// Create components/ui directory
|
|
196
|
-
const
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
spinner.text = 'Created components directory';
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
// Create components/ui directory
|
|
264
|
+
const uiDir = resolveAliasOrPath(cwd, config.aliases.ui);
|
|
265
|
+
await fs.ensureDir(uiDir);
|
|
266
|
+
spinner.text = 'Created components directory';
|
|
200
267
|
|
|
201
268
|
// Install dependencies
|
|
202
269
|
spinner.text = 'Installing dependencies...';
|
|
203
|
-
const dependencies = [
|
|
204
|
-
'clsx',
|
|
205
|
-
'tailwind-merge',
|
|
270
|
+
const dependencies = [
|
|
271
|
+
'clsx',
|
|
272
|
+
'tailwind-merge',
|
|
206
273
|
'class-variance-authority',
|
|
207
|
-
'lucide-angular',
|
|
208
274
|
'tailwindcss',
|
|
209
|
-
'postcss',
|
|
210
|
-
'@tailwindcss/postcss'
|
|
211
|
-
];
|
|
212
|
-
await
|
|
275
|
+
'postcss',
|
|
276
|
+
'@tailwindcss/postcss'
|
|
277
|
+
];
|
|
278
|
+
await installPackages(dependencies, { cwd });
|
|
213
279
|
|
|
214
280
|
// Setup PostCSS - create .postcssrc.json which is the preferred format for Angular
|
|
215
281
|
spinner.text = 'Configuring PostCSS...';
|
|
@@ -224,43 +290,6 @@ export async function init(options: InitOptions) {
|
|
|
224
290
|
await fs.writeJson(postcssrcPath, configContent, { spaces: 4 });
|
|
225
291
|
}
|
|
226
292
|
|
|
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
293
|
|
|
265
294
|
spinner.succeed(chalk.green('Project initialized successfully!'));
|
|
266
295
|
|