@gilav21/shadcn-angular 0.0.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/dist/commands/add.d.ts +9 -0
- package/dist/commands/add.js +161 -0
- package/dist/commands/init.d.ts +6 -0
- package/dist/commands/init.js +135 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +26 -0
- package/dist/registry/index.d.ts +7 -0
- package/dist/registry/index.js +224 -0
- package/dist/templates/styles.d.ts +3 -0
- package/dist/templates/styles.js +317 -0
- package/dist/templates/utils.d.ts +1 -0
- package/dist/templates/utils.js +12 -0
- package/dist/utils/config.d.ts +18 -0
- package/dist/utils/config.js +35 -0
- package/package.json +35 -0
- package/src/commands/add.ts +187 -0
- package/src/commands/init.ts +155 -0
- package/src/index.ts +31 -0
- package/src/registry/index.ts +233 -0
- package/src/templates/styles.ts +322 -0
- package/src/templates/utils.ts +12 -0
- package/src/utils/config.ts +55 -0
- package/tsconfig.json +25 -0
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import fs from 'fs-extra';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import prompts from 'prompts';
|
|
4
|
+
import chalk from 'chalk';
|
|
5
|
+
import ora from 'ora';
|
|
6
|
+
import { execa } from 'execa';
|
|
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
|
+
interface InitOptions {
|
|
12
|
+
yes?: boolean;
|
|
13
|
+
defaults?: boolean;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export async function init(options: InitOptions) {
|
|
17
|
+
console.log(chalk.bold('\n🎨 Welcome to shadcn-angular!\n'));
|
|
18
|
+
|
|
19
|
+
const cwd = process.cwd();
|
|
20
|
+
|
|
21
|
+
// Check if this is an Angular project
|
|
22
|
+
const angularJsonPath = path.join(cwd, 'angular.json');
|
|
23
|
+
if (!await fs.pathExists(angularJsonPath)) {
|
|
24
|
+
console.log(chalk.red('Error: This does not appear to be an Angular project.'));
|
|
25
|
+
console.log(chalk.dim('Please run this command in the root of your Angular project.'));
|
|
26
|
+
process.exit(1);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Check if already initialized
|
|
30
|
+
const componentsJsonPath = path.join(cwd, 'components.json');
|
|
31
|
+
if (await fs.pathExists(componentsJsonPath)) {
|
|
32
|
+
const { overwrite } = await prompts({
|
|
33
|
+
type: 'confirm',
|
|
34
|
+
name: 'overwrite',
|
|
35
|
+
message: 'components.json already exists. Overwrite?',
|
|
36
|
+
initial: false,
|
|
37
|
+
});
|
|
38
|
+
if (!overwrite) {
|
|
39
|
+
console.log(chalk.dim('Initialization cancelled.'));
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
let config: Config;
|
|
45
|
+
|
|
46
|
+
if (options.defaults || options.yes) {
|
|
47
|
+
config = getDefaultConfig();
|
|
48
|
+
} else {
|
|
49
|
+
const responses = await prompts([
|
|
50
|
+
{
|
|
51
|
+
type: 'select',
|
|
52
|
+
name: 'style',
|
|
53
|
+
message: 'Which style would you like to use?',
|
|
54
|
+
choices: [
|
|
55
|
+
{ title: 'Default', value: 'default' },
|
|
56
|
+
{ title: 'New York', value: 'new-york' },
|
|
57
|
+
],
|
|
58
|
+
initial: 0,
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
type: 'select',
|
|
62
|
+
name: 'baseColor',
|
|
63
|
+
message: 'Which color would you like to use as base color?',
|
|
64
|
+
choices: [
|
|
65
|
+
{ title: 'Neutral', value: 'neutral' },
|
|
66
|
+
{ title: 'Slate', value: 'slate' },
|
|
67
|
+
{ title: 'Stone', value: 'stone' },
|
|
68
|
+
{ title: 'Gray', value: 'gray' },
|
|
69
|
+
{ title: 'Zinc', value: 'zinc' },
|
|
70
|
+
],
|
|
71
|
+
initial: 0,
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
type: 'text',
|
|
75
|
+
name: 'componentsPath',
|
|
76
|
+
message: 'Where would you like to install components?',
|
|
77
|
+
initial: 'src/components/ui',
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
type: 'text',
|
|
81
|
+
name: 'utilsPath',
|
|
82
|
+
message: 'Where would you like to install utils?',
|
|
83
|
+
initial: 'src/components/lib',
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
type: 'text',
|
|
87
|
+
name: 'globalCss',
|
|
88
|
+
message: 'Where is your global CSS file?',
|
|
89
|
+
initial: 'src/styles.scss',
|
|
90
|
+
},
|
|
91
|
+
]);
|
|
92
|
+
|
|
93
|
+
config = {
|
|
94
|
+
$schema: 'https://shadcn-angular.dev/schema.json',
|
|
95
|
+
style: responses.style,
|
|
96
|
+
tailwind: {
|
|
97
|
+
css: responses.globalCss,
|
|
98
|
+
baseColor: responses.baseColor,
|
|
99
|
+
cssVariables: true,
|
|
100
|
+
},
|
|
101
|
+
aliases: {
|
|
102
|
+
components: '@/components',
|
|
103
|
+
utils: '@/lib/utils',
|
|
104
|
+
ui: '@/components/ui',
|
|
105
|
+
},
|
|
106
|
+
iconLibrary: 'lucide-angular',
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
const spinner = ora('Initializing project...').start();
|
|
111
|
+
|
|
112
|
+
try {
|
|
113
|
+
// Write components.json
|
|
114
|
+
await fs.writeJson(componentsJsonPath, config, { spaces: 2 });
|
|
115
|
+
spinner.text = 'Created components.json';
|
|
116
|
+
|
|
117
|
+
// Create utils directory and file
|
|
118
|
+
const utilsDir = path.join(cwd, config.aliases.utils.replace('@/', 'src/').replace('/utils', ''));
|
|
119
|
+
await fs.ensureDir(utilsDir);
|
|
120
|
+
await fs.writeFile(path.join(utilsDir, 'utils.ts'), getUtilsTemplate());
|
|
121
|
+
spinner.text = 'Created utils.ts';
|
|
122
|
+
|
|
123
|
+
// Create/update styles file
|
|
124
|
+
const stylesPath = path.join(cwd, config.tailwind.css);
|
|
125
|
+
const existingStyles = await fs.pathExists(stylesPath)
|
|
126
|
+
? await fs.readFile(stylesPath, 'utf-8')
|
|
127
|
+
: '';
|
|
128
|
+
|
|
129
|
+
if (!existingStyles.includes('--background:')) {
|
|
130
|
+
await fs.writeFile(stylesPath, getStylesTemplate(config.tailwind.baseColor) + '\n' + existingStyles);
|
|
131
|
+
spinner.text = 'Updated styles with theme variables';
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// Create components/ui directory
|
|
135
|
+
const uiDir = path.join(cwd, 'src/components/ui');
|
|
136
|
+
await fs.ensureDir(uiDir);
|
|
137
|
+
spinner.text = 'Created components directory';
|
|
138
|
+
|
|
139
|
+
// Install dependencies
|
|
140
|
+
spinner.text = 'Installing dependencies...';
|
|
141
|
+
await execa('npm', ['install', 'clsx', 'tailwind-merge', 'class-variance-authority', '@angular/cdk', 'lucide-angular'], { cwd });
|
|
142
|
+
|
|
143
|
+
spinner.succeed(chalk.green('Project initialized successfully!'));
|
|
144
|
+
|
|
145
|
+
console.log('\n' + chalk.bold('Next steps:'));
|
|
146
|
+
console.log(chalk.dim(' 1. Add components: ') + chalk.cyan('npx shadcn-angular add button'));
|
|
147
|
+
console.log(chalk.dim(' 2. Import and use in your templates'));
|
|
148
|
+
console.log('');
|
|
149
|
+
|
|
150
|
+
} catch (error) {
|
|
151
|
+
spinner.fail('Failed to initialize project');
|
|
152
|
+
console.error(error);
|
|
153
|
+
process.exit(1);
|
|
154
|
+
}
|
|
155
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { Command } from 'commander';
|
|
3
|
+
import { init } from './commands/init.js';
|
|
4
|
+
import { add } from './commands/add.js';
|
|
5
|
+
|
|
6
|
+
const program = new Command();
|
|
7
|
+
|
|
8
|
+
program
|
|
9
|
+
.name('shadcn-angular')
|
|
10
|
+
.description('CLI for adding shadcn-angular components to your Angular project')
|
|
11
|
+
.version('0.0.1');
|
|
12
|
+
|
|
13
|
+
program
|
|
14
|
+
.command('init')
|
|
15
|
+
.description('Initialize shadcn-angular in your project')
|
|
16
|
+
.option('-y, --yes', 'Skip confirmation prompt')
|
|
17
|
+
.option('-d, --defaults', 'Use default configuration')
|
|
18
|
+
.action(init);
|
|
19
|
+
|
|
20
|
+
program
|
|
21
|
+
.command('add')
|
|
22
|
+
.description('Add a component to your project')
|
|
23
|
+
.argument('[components...]', 'The components to add')
|
|
24
|
+
.option('-y, --yes', 'Skip confirmation prompt')
|
|
25
|
+
.option('-o, --overwrite', 'Overwrite existing files')
|
|
26
|
+
.option('-a, --all', 'Add all available components')
|
|
27
|
+
.option('-p, --path <path>', 'The path to add the component to')
|
|
28
|
+
.option('--remote', 'Force remote fetch from GitHub registry')
|
|
29
|
+
.action(add);
|
|
30
|
+
|
|
31
|
+
program.parse();
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
// Component Registry - Defines available components and their file mappings
|
|
2
|
+
// Actual component files are stored in packages/components/ui/
|
|
3
|
+
|
|
4
|
+
export interface ComponentDefinition {
|
|
5
|
+
name: string;
|
|
6
|
+
files: string[]; // Relative paths to component files
|
|
7
|
+
dependencies?: string[]; // Other components this depends on
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export type ComponentName = keyof typeof registry;
|
|
11
|
+
|
|
12
|
+
// Registry maps component names to their file definitions
|
|
13
|
+
// Files are relative to the components/ui directory
|
|
14
|
+
export const registry: Record<string, ComponentDefinition> = {
|
|
15
|
+
accordion: {
|
|
16
|
+
name: 'accordion',
|
|
17
|
+
files: ['accordion.component.ts'],
|
|
18
|
+
},
|
|
19
|
+
alert: {
|
|
20
|
+
name: 'alert',
|
|
21
|
+
files: ['alert.component.ts'],
|
|
22
|
+
},
|
|
23
|
+
'alert-dialog': {
|
|
24
|
+
name: 'alert-dialog',
|
|
25
|
+
files: ['alert-dialog.component.ts'],
|
|
26
|
+
dependencies: ['button'],
|
|
27
|
+
},
|
|
28
|
+
'aspect-ratio': {
|
|
29
|
+
name: 'aspect-ratio',
|
|
30
|
+
files: ['aspect-ratio.component.ts'],
|
|
31
|
+
},
|
|
32
|
+
avatar: {
|
|
33
|
+
name: 'avatar',
|
|
34
|
+
files: ['avatar.component.ts'],
|
|
35
|
+
},
|
|
36
|
+
badge: {
|
|
37
|
+
name: 'badge',
|
|
38
|
+
files: ['badge.component.ts'],
|
|
39
|
+
},
|
|
40
|
+
breadcrumb: {
|
|
41
|
+
name: 'breadcrumb',
|
|
42
|
+
files: ['breadcrumb.component.ts'],
|
|
43
|
+
},
|
|
44
|
+
button: {
|
|
45
|
+
name: 'button',
|
|
46
|
+
files: ['button.component.ts'],
|
|
47
|
+
},
|
|
48
|
+
'button-group': {
|
|
49
|
+
name: 'button-group',
|
|
50
|
+
files: ['button-group.component.ts'],
|
|
51
|
+
dependencies: ['button', 'separator'],
|
|
52
|
+
},
|
|
53
|
+
calendar: {
|
|
54
|
+
name: 'calendar',
|
|
55
|
+
files: ['calendar.component.ts'],
|
|
56
|
+
dependencies: ['button'],
|
|
57
|
+
},
|
|
58
|
+
card: {
|
|
59
|
+
name: 'card',
|
|
60
|
+
files: ['card.component.ts'],
|
|
61
|
+
},
|
|
62
|
+
carousel: {
|
|
63
|
+
name: 'carousel',
|
|
64
|
+
files: ['carousel.component.ts'],
|
|
65
|
+
dependencies: ['button'],
|
|
66
|
+
},
|
|
67
|
+
checkbox: {
|
|
68
|
+
name: 'checkbox',
|
|
69
|
+
files: ['checkbox.component.ts'],
|
|
70
|
+
},
|
|
71
|
+
collapsible: {
|
|
72
|
+
name: 'collapsible',
|
|
73
|
+
files: ['collapsible.component.ts'],
|
|
74
|
+
},
|
|
75
|
+
command: {
|
|
76
|
+
name: 'command',
|
|
77
|
+
files: ['command.component.ts'],
|
|
78
|
+
dependencies: ['dialog', 'separator'],
|
|
79
|
+
},
|
|
80
|
+
'context-menu': {
|
|
81
|
+
name: 'context-menu',
|
|
82
|
+
files: ['context-menu.component.ts'],
|
|
83
|
+
},
|
|
84
|
+
'date-picker': {
|
|
85
|
+
name: 'date-picker',
|
|
86
|
+
files: ['date-picker.component.ts'],
|
|
87
|
+
dependencies: ['calendar', 'popover', 'button'],
|
|
88
|
+
},
|
|
89
|
+
dialog: {
|
|
90
|
+
name: 'dialog',
|
|
91
|
+
files: ['dialog.component.ts'],
|
|
92
|
+
},
|
|
93
|
+
drawer: {
|
|
94
|
+
name: 'drawer',
|
|
95
|
+
files: ['drawer.component.ts'],
|
|
96
|
+
},
|
|
97
|
+
'dropdown-menu': {
|
|
98
|
+
name: 'dropdown-menu',
|
|
99
|
+
files: ['dropdown-menu.component.ts'],
|
|
100
|
+
},
|
|
101
|
+
empty: {
|
|
102
|
+
name: 'empty',
|
|
103
|
+
files: ['empty.component.ts'],
|
|
104
|
+
},
|
|
105
|
+
field: {
|
|
106
|
+
name: 'field',
|
|
107
|
+
files: ['field.component.ts'],
|
|
108
|
+
},
|
|
109
|
+
'hover-card': {
|
|
110
|
+
name: 'hover-card',
|
|
111
|
+
files: ['hover-card.component.ts'],
|
|
112
|
+
},
|
|
113
|
+
input: {
|
|
114
|
+
name: 'input',
|
|
115
|
+
files: ['input.component.ts'],
|
|
116
|
+
},
|
|
117
|
+
'input-group': {
|
|
118
|
+
name: 'input-group',
|
|
119
|
+
files: ['input-group.component.ts'],
|
|
120
|
+
dependencies: ['input', 'button'],
|
|
121
|
+
},
|
|
122
|
+
'input-otp': {
|
|
123
|
+
name: 'input-otp',
|
|
124
|
+
files: ['input-otp.component.ts'],
|
|
125
|
+
},
|
|
126
|
+
kbd: {
|
|
127
|
+
name: 'kbd',
|
|
128
|
+
files: ['kbd.component.ts'],
|
|
129
|
+
},
|
|
130
|
+
label: {
|
|
131
|
+
name: 'label',
|
|
132
|
+
files: ['label.component.ts'],
|
|
133
|
+
},
|
|
134
|
+
menubar: {
|
|
135
|
+
name: 'menubar',
|
|
136
|
+
files: ['menubar.component.ts'],
|
|
137
|
+
},
|
|
138
|
+
'native-select': {
|
|
139
|
+
name: 'native-select',
|
|
140
|
+
files: ['native-select.component.ts'],
|
|
141
|
+
},
|
|
142
|
+
'navigation-menu': {
|
|
143
|
+
name: 'navigation-menu',
|
|
144
|
+
files: ['navigation-menu.component.ts'],
|
|
145
|
+
},
|
|
146
|
+
pagination: {
|
|
147
|
+
name: 'pagination',
|
|
148
|
+
files: ['pagination.component.ts'],
|
|
149
|
+
dependencies: ['button'],
|
|
150
|
+
},
|
|
151
|
+
popover: {
|
|
152
|
+
name: 'popover',
|
|
153
|
+
files: ['popover.component.ts'],
|
|
154
|
+
},
|
|
155
|
+
progress: {
|
|
156
|
+
name: 'progress',
|
|
157
|
+
files: ['progress.component.ts'],
|
|
158
|
+
},
|
|
159
|
+
'radio-group': {
|
|
160
|
+
name: 'radio-group',
|
|
161
|
+
files: ['radio-group.component.ts'],
|
|
162
|
+
},
|
|
163
|
+
resizable: {
|
|
164
|
+
name: 'resizable',
|
|
165
|
+
files: ['resizable.component.ts'],
|
|
166
|
+
},
|
|
167
|
+
'scroll-area': {
|
|
168
|
+
name: 'scroll-area',
|
|
169
|
+
files: ['scroll-area.component.ts'],
|
|
170
|
+
},
|
|
171
|
+
select: {
|
|
172
|
+
name: 'select',
|
|
173
|
+
files: ['select.component.ts'],
|
|
174
|
+
},
|
|
175
|
+
separator: {
|
|
176
|
+
name: 'separator',
|
|
177
|
+
files: ['separator.component.ts'],
|
|
178
|
+
},
|
|
179
|
+
sheet: {
|
|
180
|
+
name: 'sheet',
|
|
181
|
+
files: ['sheet.component.ts'],
|
|
182
|
+
},
|
|
183
|
+
sidebar: {
|
|
184
|
+
name: 'sidebar',
|
|
185
|
+
files: ['sidebar.component.ts'],
|
|
186
|
+
dependencies: ['button', 'sheet', 'separator', 'tooltip', 'input', 'skeleton'],
|
|
187
|
+
},
|
|
188
|
+
skeleton: {
|
|
189
|
+
name: 'skeleton',
|
|
190
|
+
files: ['skeleton.component.ts'],
|
|
191
|
+
},
|
|
192
|
+
slider: {
|
|
193
|
+
name: 'slider',
|
|
194
|
+
files: ['slider.component.ts'],
|
|
195
|
+
},
|
|
196
|
+
spinner: {
|
|
197
|
+
name: 'spinner',
|
|
198
|
+
files: ['spinner.component.ts'],
|
|
199
|
+
},
|
|
200
|
+
switch: {
|
|
201
|
+
name: 'switch',
|
|
202
|
+
files: ['switch.component.ts'],
|
|
203
|
+
},
|
|
204
|
+
table: {
|
|
205
|
+
name: 'table',
|
|
206
|
+
files: ['table.component.ts'],
|
|
207
|
+
},
|
|
208
|
+
tabs: {
|
|
209
|
+
name: 'tabs',
|
|
210
|
+
files: ['tabs.component.ts'],
|
|
211
|
+
},
|
|
212
|
+
textarea: {
|
|
213
|
+
name: 'textarea',
|
|
214
|
+
files: ['textarea.component.ts'],
|
|
215
|
+
},
|
|
216
|
+
toast: {
|
|
217
|
+
name: 'toast',
|
|
218
|
+
files: ['toast.component.ts'],
|
|
219
|
+
},
|
|
220
|
+
toggle: {
|
|
221
|
+
name: 'toggle',
|
|
222
|
+
files: ['toggle.component.ts'],
|
|
223
|
+
},
|
|
224
|
+
'toggle-group': {
|
|
225
|
+
name: 'toggle-group',
|
|
226
|
+
files: ['toggle-group.component.ts'],
|
|
227
|
+
dependencies: ['toggle'],
|
|
228
|
+
},
|
|
229
|
+
tooltip: {
|
|
230
|
+
name: 'tooltip',
|
|
231
|
+
files: ['tooltip.component.ts'],
|
|
232
|
+
},
|
|
233
|
+
};
|