@ng-cn/core 1.0.5 → 1.0.6
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/package.json +1 -1
- package/schematics/component/index.js +123 -32
- package/schematics/component/index.ts +123 -32
- package/schematics/ng-add/index.d.ts +3 -1
- package/schematics/ng-add/index.js +552 -87
- package/schematics/ng-add/index.ts +598 -88
- package/schematics/ng-add/schema.json +22 -41
- package/schematics/package.json +8 -0
- package/README.md +0 -200
- package/schematics/README.md +0 -165
|
@@ -1,89 +1,494 @@
|
|
|
1
|
+
import { join, normalize, Path } from '@angular-devkit/core';
|
|
1
2
|
import { Rule, SchematicContext, Tree } from '@angular-devkit/schematics';
|
|
2
3
|
import { NodePackageInstallTask } from '@angular-devkit/schematics/tasks';
|
|
3
4
|
import { parse as parseJsonc } from 'jsonc-parser';
|
|
4
5
|
|
|
6
|
+
type ThemeVariant = 'shadcn' | 'github' | 'vercel' | 'apple' | 'openai' | 'clickup' | 'linear';
|
|
7
|
+
|
|
5
8
|
interface NgAddOptions {
|
|
6
9
|
project?: string;
|
|
10
|
+
theme?: ThemeVariant;
|
|
7
11
|
skipInstall?: boolean;
|
|
8
12
|
skipStyles?: boolean;
|
|
9
|
-
components?: string
|
|
13
|
+
components?: string; // Can be 'all' or comma-separated list like 'button,card,dialog'
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// All available components in the registry
|
|
17
|
+
const ALL_COMPONENTS = [
|
|
18
|
+
'accordion', 'alert', 'alert-dialog', 'aspect-ratio', 'avatar', 'badge',
|
|
19
|
+
'breadcrumb', 'button', 'button-group', 'calendar', 'card', 'carousel',
|
|
20
|
+
'chart', 'checkbox', 'collapsible', 'combobox', 'command', 'context-menu',
|
|
21
|
+
'data-table', 'date-picker', 'dialog', 'drawer', 'dropdown-menu', 'empty',
|
|
22
|
+
'form', 'hover-card', 'input', 'input-group', 'input-otp', 'kbd', 'label',
|
|
23
|
+
'menubar', 'native-select', 'navigation-menu', 'pagination', 'popover',
|
|
24
|
+
'progress', 'radio-group', 'resizable', 'scroll-area', 'segmented', 'select',
|
|
25
|
+
'separator', 'sheet', 'sidebar', 'skeleton', 'slider', 'spinner', 'switch',
|
|
26
|
+
'table', 'tabs', 'textarea', 'toast', 'toggle', 'toggle-group', 'tooltip',
|
|
27
|
+
'typography'
|
|
28
|
+
];
|
|
29
|
+
|
|
30
|
+
// Registry of all utility files that need to be copied
|
|
31
|
+
const UTILS_FILES_REGISTRY = [
|
|
32
|
+
// Core utils
|
|
33
|
+
'cn.ts',
|
|
34
|
+
'index.ts',
|
|
35
|
+
// Animation utilities
|
|
36
|
+
'animation/index.ts',
|
|
37
|
+
'animation/animation.types.ts',
|
|
38
|
+
'animation/animation.utils.ts',
|
|
39
|
+
'animation/animation-tokens.service.ts',
|
|
40
|
+
'animation/animated.directive.ts',
|
|
41
|
+
'animation/presence.component.ts',
|
|
42
|
+
'animation/presence.directive.ts',
|
|
43
|
+
// Accessibility utilities
|
|
44
|
+
'accessibility/index.ts',
|
|
45
|
+
'accessibility/aria-id.service.ts',
|
|
46
|
+
'accessibility/click-outside.directive.ts',
|
|
47
|
+
'accessibility/focus-management.service.ts',
|
|
48
|
+
'accessibility/focus-trap.directive.ts',
|
|
49
|
+
'accessibility/keyboard-navigation.directive.ts',
|
|
50
|
+
'accessibility/live-region.directive.ts',
|
|
51
|
+
'accessibility/touch-target.directive.ts',
|
|
52
|
+
'accessibility/visually-hidden.component.ts',
|
|
53
|
+
// Positioning utilities
|
|
54
|
+
'positioning/index.ts',
|
|
55
|
+
];
|
|
56
|
+
|
|
57
|
+
// Theme color definitions for all variants
|
|
58
|
+
interface ThemeColors {
|
|
59
|
+
background: string;
|
|
60
|
+
foreground: string;
|
|
61
|
+
card: string;
|
|
62
|
+
cardForeground: string;
|
|
63
|
+
popover: string;
|
|
64
|
+
popoverForeground: string;
|
|
65
|
+
primary: string;
|
|
66
|
+
primaryForeground: string;
|
|
67
|
+
secondary: string;
|
|
68
|
+
secondaryForeground: string;
|
|
69
|
+
muted: string;
|
|
70
|
+
mutedForeground: string;
|
|
71
|
+
accent: string;
|
|
72
|
+
accentForeground: string;
|
|
73
|
+
destructive: string;
|
|
74
|
+
destructiveForeground: string;
|
|
75
|
+
border: string;
|
|
76
|
+
input: string;
|
|
77
|
+
ring: string;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
interface ThemePalette {
|
|
81
|
+
name: string;
|
|
82
|
+
description: string;
|
|
83
|
+
light: ThemeColors;
|
|
84
|
+
dark: ThemeColors;
|
|
10
85
|
}
|
|
11
86
|
|
|
12
|
-
|
|
13
|
-
|
|
87
|
+
const THEME_PALETTES: Record<ThemeVariant, ThemePalette> = {
|
|
88
|
+
shadcn: {
|
|
89
|
+
name: 'shadcn',
|
|
90
|
+
description: 'The default shadcn/ui theme - clean, minimal, and professional',
|
|
91
|
+
light: {
|
|
92
|
+
background: 'oklch(1 0 0)',
|
|
93
|
+
foreground: 'oklch(0.145 0 0)',
|
|
94
|
+
card: 'oklch(1 0 0)',
|
|
95
|
+
cardForeground: 'oklch(0.145 0 0)',
|
|
96
|
+
popover: 'oklch(1 0 0)',
|
|
97
|
+
popoverForeground: 'oklch(0.145 0 0)',
|
|
98
|
+
primary: 'oklch(0.205 0 0)',
|
|
99
|
+
primaryForeground: 'oklch(0.985 0 0)',
|
|
100
|
+
secondary: 'oklch(0.97 0 0)',
|
|
101
|
+
secondaryForeground: 'oklch(0.205 0 0)',
|
|
102
|
+
muted: 'oklch(0.97 0 0)',
|
|
103
|
+
mutedForeground: 'oklch(0.556 0 0)',
|
|
104
|
+
accent: 'oklch(0.97 0 0)',
|
|
105
|
+
accentForeground: 'oklch(0.205 0 0)',
|
|
106
|
+
destructive: 'oklch(0.577 0.245 27.325)',
|
|
107
|
+
destructiveForeground: 'oklch(0.985 0 0)',
|
|
108
|
+
border: 'oklch(0.922 0 0)',
|
|
109
|
+
input: 'oklch(0.922 0 0)',
|
|
110
|
+
ring: 'oklch(0.708 0 0)',
|
|
111
|
+
},
|
|
112
|
+
dark: {
|
|
113
|
+
background: 'oklch(0.145 0 0)',
|
|
114
|
+
foreground: 'oklch(0.985 0 0)',
|
|
115
|
+
card: 'oklch(0.205 0 0)',
|
|
116
|
+
cardForeground: 'oklch(0.985 0 0)',
|
|
117
|
+
popover: 'oklch(0.205 0 0)',
|
|
118
|
+
popoverForeground: 'oklch(0.985 0 0)',
|
|
119
|
+
primary: 'oklch(0.985 0 0)',
|
|
120
|
+
primaryForeground: 'oklch(0.205 0 0)',
|
|
121
|
+
secondary: 'oklch(0.269 0 0)',
|
|
122
|
+
secondaryForeground: 'oklch(0.985 0 0)',
|
|
123
|
+
muted: 'oklch(0.269 0 0)',
|
|
124
|
+
mutedForeground: 'oklch(0.708 0 0)',
|
|
125
|
+
accent: 'oklch(0.269 0 0)',
|
|
126
|
+
accentForeground: 'oklch(0.985 0 0)',
|
|
127
|
+
destructive: 'oklch(0.396 0.141 25.723)',
|
|
128
|
+
destructiveForeground: 'oklch(0.985 0 0)',
|
|
129
|
+
border: 'oklch(0.269 0 0)',
|
|
130
|
+
input: 'oklch(0.269 0 0)',
|
|
131
|
+
ring: 'oklch(0.439 0 0)',
|
|
132
|
+
},
|
|
133
|
+
},
|
|
134
|
+
github: {
|
|
135
|
+
name: 'GitHub',
|
|
136
|
+
description: "Inspired by GitHub's clean developer-focused design",
|
|
137
|
+
light: {
|
|
138
|
+
background: 'oklch(1 0 0)',
|
|
139
|
+
foreground: 'oklch(0.208 0.042 265.755)',
|
|
140
|
+
card: 'oklch(1 0 0)',
|
|
141
|
+
cardForeground: 'oklch(0.208 0.042 265.755)',
|
|
142
|
+
popover: 'oklch(1 0 0)',
|
|
143
|
+
popoverForeground: 'oklch(0.208 0.042 265.755)',
|
|
144
|
+
primary: 'oklch(0.546 0.192 262.881)',
|
|
145
|
+
primaryForeground: 'oklch(1 0 0)',
|
|
146
|
+
secondary: 'oklch(0.968 0.007 247.896)',
|
|
147
|
+
secondaryForeground: 'oklch(0.208 0.042 265.755)',
|
|
148
|
+
muted: 'oklch(0.968 0.007 247.896)',
|
|
149
|
+
mutedForeground: 'oklch(0.443 0.024 264.052)',
|
|
150
|
+
accent: 'oklch(0.968 0.007 247.896)',
|
|
151
|
+
accentForeground: 'oklch(0.208 0.042 265.755)',
|
|
152
|
+
destructive: 'oklch(0.577 0.215 27.325)',
|
|
153
|
+
destructiveForeground: 'oklch(1 0 0)',
|
|
154
|
+
border: 'oklch(0.883 0.012 247.896)',
|
|
155
|
+
input: 'oklch(0.883 0.012 247.896)',
|
|
156
|
+
ring: 'oklch(0.546 0.192 262.881)',
|
|
157
|
+
},
|
|
158
|
+
dark: {
|
|
159
|
+
background: 'oklch(0.177 0.015 265.755)',
|
|
160
|
+
foreground: 'oklch(0.922 0.007 247.896)',
|
|
161
|
+
card: 'oklch(0.208 0.018 265.755)',
|
|
162
|
+
cardForeground: 'oklch(0.922 0.007 247.896)',
|
|
163
|
+
popover: 'oklch(0.208 0.018 265.755)',
|
|
164
|
+
popoverForeground: 'oklch(0.922 0.007 247.896)',
|
|
165
|
+
primary: 'oklch(0.637 0.183 259.533)',
|
|
166
|
+
primaryForeground: 'oklch(1 0 0)',
|
|
167
|
+
secondary: 'oklch(0.272 0.022 265.755)',
|
|
168
|
+
secondaryForeground: 'oklch(0.922 0.007 247.896)',
|
|
169
|
+
muted: 'oklch(0.272 0.022 265.755)',
|
|
170
|
+
mutedForeground: 'oklch(0.627 0.018 264.052)',
|
|
171
|
+
accent: 'oklch(0.272 0.022 265.755)',
|
|
172
|
+
accentForeground: 'oklch(0.922 0.007 247.896)',
|
|
173
|
+
destructive: 'oklch(0.527 0.215 27.325)',
|
|
174
|
+
destructiveForeground: 'oklch(1 0 0)',
|
|
175
|
+
border: 'oklch(0.336 0.024 265.755)',
|
|
176
|
+
input: 'oklch(0.336 0.024 265.755)',
|
|
177
|
+
ring: 'oklch(0.637 0.183 259.533)',
|
|
178
|
+
},
|
|
179
|
+
},
|
|
180
|
+
vercel: {
|
|
181
|
+
name: 'Vercel',
|
|
182
|
+
description: "Vercel's bold black and white design aesthetic",
|
|
183
|
+
light: {
|
|
184
|
+
background: 'oklch(1 0 0)',
|
|
185
|
+
foreground: 'oklch(0 0 0)',
|
|
186
|
+
card: 'oklch(1 0 0)',
|
|
187
|
+
cardForeground: 'oklch(0 0 0)',
|
|
188
|
+
popover: 'oklch(1 0 0)',
|
|
189
|
+
popoverForeground: 'oklch(0 0 0)',
|
|
190
|
+
primary: 'oklch(0 0 0)',
|
|
191
|
+
primaryForeground: 'oklch(1 0 0)',
|
|
192
|
+
secondary: 'oklch(0.968 0 0)',
|
|
193
|
+
secondaryForeground: 'oklch(0 0 0)',
|
|
194
|
+
muted: 'oklch(0.968 0 0)',
|
|
195
|
+
mutedForeground: 'oklch(0.443 0 0)',
|
|
196
|
+
accent: 'oklch(0.968 0 0)',
|
|
197
|
+
accentForeground: 'oklch(0 0 0)',
|
|
198
|
+
destructive: 'oklch(0.577 0.245 27.325)',
|
|
199
|
+
destructiveForeground: 'oklch(1 0 0)',
|
|
200
|
+
border: 'oklch(0.883 0 0)',
|
|
201
|
+
input: 'oklch(0.883 0 0)',
|
|
202
|
+
ring: 'oklch(0 0 0)',
|
|
203
|
+
},
|
|
204
|
+
dark: {
|
|
205
|
+
background: 'oklch(0 0 0)',
|
|
206
|
+
foreground: 'oklch(1 0 0)',
|
|
207
|
+
card: 'oklch(0.117 0 0)',
|
|
208
|
+
cardForeground: 'oklch(1 0 0)',
|
|
209
|
+
popover: 'oklch(0.117 0 0)',
|
|
210
|
+
popoverForeground: 'oklch(1 0 0)',
|
|
211
|
+
primary: 'oklch(1 0 0)',
|
|
212
|
+
primaryForeground: 'oklch(0 0 0)',
|
|
213
|
+
secondary: 'oklch(0.177 0 0)',
|
|
214
|
+
secondaryForeground: 'oklch(1 0 0)',
|
|
215
|
+
muted: 'oklch(0.177 0 0)',
|
|
216
|
+
mutedForeground: 'oklch(0.627 0 0)',
|
|
217
|
+
accent: 'oklch(0.177 0 0)',
|
|
218
|
+
accentForeground: 'oklch(1 0 0)',
|
|
219
|
+
destructive: 'oklch(0.577 0.245 27.325)',
|
|
220
|
+
destructiveForeground: 'oklch(1 0 0)',
|
|
221
|
+
border: 'oklch(0.269 0 0)',
|
|
222
|
+
input: 'oklch(0.269 0 0)',
|
|
223
|
+
ring: 'oklch(1 0 0)',
|
|
224
|
+
},
|
|
225
|
+
},
|
|
226
|
+
apple: {
|
|
227
|
+
name: 'Apple',
|
|
228
|
+
description: "Apple's elegant, sophisticated design language",
|
|
229
|
+
light: {
|
|
230
|
+
background: 'oklch(1 0 0)',
|
|
231
|
+
foreground: 'oklch(0.208 0 0)',
|
|
232
|
+
card: 'oklch(0.985 0.003 247.858)',
|
|
233
|
+
cardForeground: 'oklch(0.208 0 0)',
|
|
234
|
+
popover: 'oklch(0.985 0.003 247.858)',
|
|
235
|
+
popoverForeground: 'oklch(0.208 0 0)',
|
|
236
|
+
primary: 'oklch(0.586 0.228 259.815)',
|
|
237
|
+
primaryForeground: 'oklch(1 0 0)',
|
|
238
|
+
secondary: 'oklch(0.968 0.003 247.858)',
|
|
239
|
+
secondaryForeground: 'oklch(0.208 0 0)',
|
|
240
|
+
muted: 'oklch(0.968 0.003 247.858)',
|
|
241
|
+
mutedForeground: 'oklch(0.506 0 0)',
|
|
242
|
+
accent: 'oklch(0.968 0.003 247.858)',
|
|
243
|
+
accentForeground: 'oklch(0.208 0 0)',
|
|
244
|
+
destructive: 'oklch(0.577 0.245 27.325)',
|
|
245
|
+
destructiveForeground: 'oklch(1 0 0)',
|
|
246
|
+
border: 'oklch(0.922 0.003 247.858)',
|
|
247
|
+
input: 'oklch(0.922 0.003 247.858)',
|
|
248
|
+
ring: 'oklch(0.586 0.228 259.815)',
|
|
249
|
+
},
|
|
250
|
+
dark: {
|
|
251
|
+
background: 'oklch(0 0 0)',
|
|
252
|
+
foreground: 'oklch(0.985 0 0)',
|
|
253
|
+
card: 'oklch(0.145 0.003 247.858)',
|
|
254
|
+
cardForeground: 'oklch(0.985 0 0)',
|
|
255
|
+
popover: 'oklch(0.145 0.003 247.858)',
|
|
256
|
+
popoverForeground: 'oklch(0.985 0 0)',
|
|
257
|
+
primary: 'oklch(0.637 0.237 259.815)',
|
|
258
|
+
primaryForeground: 'oklch(1 0 0)',
|
|
259
|
+
secondary: 'oklch(0.227 0.003 247.858)',
|
|
260
|
+
secondaryForeground: 'oklch(0.985 0 0)',
|
|
261
|
+
muted: 'oklch(0.227 0.003 247.858)',
|
|
262
|
+
mutedForeground: 'oklch(0.627 0 0)',
|
|
263
|
+
accent: 'oklch(0.227 0.003 247.858)',
|
|
264
|
+
accentForeground: 'oklch(0.985 0 0)',
|
|
265
|
+
destructive: 'oklch(0.527 0.215 27.325)',
|
|
266
|
+
destructiveForeground: 'oklch(1 0 0)',
|
|
267
|
+
border: 'oklch(0.295 0.003 247.858)',
|
|
268
|
+
input: 'oklch(0.295 0.003 247.858)',
|
|
269
|
+
ring: 'oklch(0.637 0.237 259.815)',
|
|
270
|
+
},
|
|
271
|
+
},
|
|
272
|
+
openai: {
|
|
273
|
+
name: 'OpenAI',
|
|
274
|
+
description: "OpenAI's modern, tech-forward aesthetic",
|
|
275
|
+
light: {
|
|
276
|
+
background: 'oklch(1 0 0)',
|
|
277
|
+
foreground: 'oklch(0.208 0.01 255.841)',
|
|
278
|
+
card: 'oklch(1 0 0)',
|
|
279
|
+
cardForeground: 'oklch(0.208 0.01 255.841)',
|
|
280
|
+
popover: 'oklch(1 0 0)',
|
|
281
|
+
popoverForeground: 'oklch(0.208 0.01 255.841)',
|
|
282
|
+
primary: 'oklch(0.538 0.163 163.319)',
|
|
283
|
+
primaryForeground: 'oklch(1 0 0)',
|
|
284
|
+
secondary: 'oklch(0.968 0.005 255.841)',
|
|
285
|
+
secondaryForeground: 'oklch(0.208 0.01 255.841)',
|
|
286
|
+
muted: 'oklch(0.968 0.005 255.841)',
|
|
287
|
+
mutedForeground: 'oklch(0.475 0.01 255.841)',
|
|
288
|
+
accent: 'oklch(0.968 0.005 255.841)',
|
|
289
|
+
accentForeground: 'oklch(0.208 0.01 255.841)',
|
|
290
|
+
destructive: 'oklch(0.577 0.245 27.325)',
|
|
291
|
+
destructiveForeground: 'oklch(1 0 0)',
|
|
292
|
+
border: 'oklch(0.906 0.006 255.841)',
|
|
293
|
+
input: 'oklch(0.906 0.006 255.841)',
|
|
294
|
+
ring: 'oklch(0.538 0.163 163.319)',
|
|
295
|
+
},
|
|
296
|
+
dark: {
|
|
297
|
+
background: 'oklch(0.168 0.015 255.841)',
|
|
298
|
+
foreground: 'oklch(0.968 0.005 255.841)',
|
|
299
|
+
card: 'oklch(0.208 0.015 255.841)',
|
|
300
|
+
cardForeground: 'oklch(0.968 0.005 255.841)',
|
|
301
|
+
popover: 'oklch(0.208 0.015 255.841)',
|
|
302
|
+
popoverForeground: 'oklch(0.968 0.005 255.841)',
|
|
303
|
+
primary: 'oklch(0.608 0.183 163.319)',
|
|
304
|
+
primaryForeground: 'oklch(0.168 0.015 255.841)',
|
|
305
|
+
secondary: 'oklch(0.268 0.015 255.841)',
|
|
306
|
+
secondaryForeground: 'oklch(0.968 0.005 255.841)',
|
|
307
|
+
muted: 'oklch(0.268 0.015 255.841)',
|
|
308
|
+
mutedForeground: 'oklch(0.627 0.01 255.841)',
|
|
309
|
+
accent: 'oklch(0.268 0.015 255.841)',
|
|
310
|
+
accentForeground: 'oklch(0.968 0.005 255.841)',
|
|
311
|
+
destructive: 'oklch(0.527 0.215 27.325)',
|
|
312
|
+
destructiveForeground: 'oklch(1 0 0)',
|
|
313
|
+
border: 'oklch(0.336 0.015 255.841)',
|
|
314
|
+
input: 'oklch(0.336 0.015 255.841)',
|
|
315
|
+
ring: 'oklch(0.608 0.183 163.319)',
|
|
316
|
+
},
|
|
317
|
+
},
|
|
318
|
+
clickup: {
|
|
319
|
+
name: 'ClickUp',
|
|
320
|
+
description: "ClickUp's vibrant, colorful productivity aesthetic",
|
|
321
|
+
light: {
|
|
322
|
+
background: 'oklch(1 0 0)',
|
|
323
|
+
foreground: 'oklch(0.229 0.034 277.508)',
|
|
324
|
+
card: 'oklch(1 0 0)',
|
|
325
|
+
cardForeground: 'oklch(0.229 0.034 277.508)',
|
|
326
|
+
popover: 'oklch(1 0 0)',
|
|
327
|
+
popoverForeground: 'oklch(0.229 0.034 277.508)',
|
|
328
|
+
primary: 'oklch(0.638 0.238 288.545)',
|
|
329
|
+
primaryForeground: 'oklch(1 0 0)',
|
|
330
|
+
secondary: 'oklch(0.962 0.021 288.545)',
|
|
331
|
+
secondaryForeground: 'oklch(0.229 0.034 277.508)',
|
|
332
|
+
muted: 'oklch(0.962 0.021 288.545)',
|
|
333
|
+
mutedForeground: 'oklch(0.475 0.028 277.508)',
|
|
334
|
+
accent: 'oklch(0.807 0.181 85.391)',
|
|
335
|
+
accentForeground: 'oklch(0.229 0.034 277.508)',
|
|
336
|
+
destructive: 'oklch(0.577 0.245 27.325)',
|
|
337
|
+
destructiveForeground: 'oklch(1 0 0)',
|
|
338
|
+
border: 'oklch(0.906 0.018 277.508)',
|
|
339
|
+
input: 'oklch(0.906 0.018 277.508)',
|
|
340
|
+
ring: 'oklch(0.638 0.238 288.545)',
|
|
341
|
+
},
|
|
342
|
+
dark: {
|
|
343
|
+
background: 'oklch(0.177 0.028 277.508)',
|
|
344
|
+
foreground: 'oklch(0.968 0.008 277.508)',
|
|
345
|
+
card: 'oklch(0.208 0.032 277.508)',
|
|
346
|
+
cardForeground: 'oklch(0.968 0.008 277.508)',
|
|
347
|
+
popover: 'oklch(0.208 0.032 277.508)',
|
|
348
|
+
popoverForeground: 'oklch(0.968 0.008 277.508)',
|
|
349
|
+
primary: 'oklch(0.688 0.238 288.545)',
|
|
350
|
+
primaryForeground: 'oklch(1 0 0)',
|
|
351
|
+
secondary: 'oklch(0.268 0.038 277.508)',
|
|
352
|
+
secondaryForeground: 'oklch(0.968 0.008 277.508)',
|
|
353
|
+
muted: 'oklch(0.268 0.038 277.508)',
|
|
354
|
+
mutedForeground: 'oklch(0.627 0.018 277.508)',
|
|
355
|
+
accent: 'oklch(0.757 0.181 85.391)',
|
|
356
|
+
accentForeground: 'oklch(0.177 0.028 277.508)',
|
|
357
|
+
destructive: 'oklch(0.527 0.215 27.325)',
|
|
358
|
+
destructiveForeground: 'oklch(1 0 0)',
|
|
359
|
+
border: 'oklch(0.336 0.038 277.508)',
|
|
360
|
+
input: 'oklch(0.336 0.038 277.508)',
|
|
361
|
+
ring: 'oklch(0.688 0.238 288.545)',
|
|
362
|
+
},
|
|
363
|
+
},
|
|
364
|
+
linear: {
|
|
365
|
+
name: 'Linear',
|
|
366
|
+
description: "Linear's sleek, issue tracking inspired design",
|
|
367
|
+
light: {
|
|
368
|
+
background: 'oklch(0.985 0.003 250)',
|
|
369
|
+
foreground: 'oklch(0.229 0.024 265)',
|
|
370
|
+
card: 'oklch(1 0 0)',
|
|
371
|
+
cardForeground: 'oklch(0.229 0.024 265)',
|
|
372
|
+
popover: 'oklch(1 0 0)',
|
|
373
|
+
popoverForeground: 'oklch(0.229 0.024 265)',
|
|
374
|
+
primary: 'oklch(0.538 0.207 262.881)',
|
|
375
|
+
primaryForeground: 'oklch(1 0 0)',
|
|
376
|
+
secondary: 'oklch(0.962 0.008 250)',
|
|
377
|
+
secondaryForeground: 'oklch(0.229 0.024 265)',
|
|
378
|
+
muted: 'oklch(0.962 0.008 250)',
|
|
379
|
+
mutedForeground: 'oklch(0.506 0.018 265)',
|
|
380
|
+
accent: 'oklch(0.962 0.008 250)',
|
|
381
|
+
accentForeground: 'oklch(0.229 0.024 265)',
|
|
382
|
+
destructive: 'oklch(0.577 0.245 27.325)',
|
|
383
|
+
destructiveForeground: 'oklch(1 0 0)',
|
|
384
|
+
border: 'oklch(0.906 0.012 250)',
|
|
385
|
+
input: 'oklch(0.906 0.012 250)',
|
|
386
|
+
ring: 'oklch(0.538 0.207 262.881)',
|
|
387
|
+
},
|
|
388
|
+
dark: {
|
|
389
|
+
background: 'oklch(0.145 0.018 265)',
|
|
390
|
+
foreground: 'oklch(0.962 0.008 250)',
|
|
391
|
+
card: 'oklch(0.177 0.022 265)',
|
|
392
|
+
cardForeground: 'oklch(0.962 0.008 250)',
|
|
393
|
+
popover: 'oklch(0.177 0.022 265)',
|
|
394
|
+
popoverForeground: 'oklch(0.962 0.008 250)',
|
|
395
|
+
primary: 'oklch(0.608 0.217 262.881)',
|
|
396
|
+
primaryForeground: 'oklch(1 0 0)',
|
|
397
|
+
secondary: 'oklch(0.227 0.028 265)',
|
|
398
|
+
secondaryForeground: 'oklch(0.962 0.008 250)',
|
|
399
|
+
muted: 'oklch(0.227 0.028 265)',
|
|
400
|
+
mutedForeground: 'oklch(0.577 0.015 265)',
|
|
401
|
+
accent: 'oklch(0.227 0.028 265)',
|
|
402
|
+
accentForeground: 'oklch(0.962 0.008 250)',
|
|
403
|
+
destructive: 'oklch(0.527 0.215 27.325)',
|
|
404
|
+
destructiveForeground: 'oklch(1 0 0)',
|
|
405
|
+
border: 'oklch(0.295 0.028 265)',
|
|
406
|
+
input: 'oklch(0.295 0.028 265)',
|
|
407
|
+
ring: 'oklch(0.608 0.217 262.881)',
|
|
408
|
+
},
|
|
409
|
+
},
|
|
410
|
+
};
|
|
411
|
+
|
|
412
|
+
// Generate CSS Variables template based on selected theme
|
|
413
|
+
function generateCssVariablesTemplate(theme: ThemeVariant): string {
|
|
414
|
+
const palette = THEME_PALETTES[theme];
|
|
415
|
+
const { light, dark } = palette;
|
|
416
|
+
|
|
417
|
+
return `/* ng-cn/core - shadcn-angular styles */
|
|
418
|
+
/* Theme: ${palette.name} - ${palette.description} */
|
|
14
419
|
@use "tailwindcss";
|
|
15
420
|
|
|
16
421
|
@custom-variant dark (&:is(.dark *));
|
|
17
422
|
|
|
18
423
|
:root {
|
|
19
424
|
--radius: 0.625rem;
|
|
20
|
-
--background:
|
|
21
|
-
--foreground:
|
|
22
|
-
--card:
|
|
23
|
-
--card-foreground:
|
|
24
|
-
--popover:
|
|
25
|
-
--popover-foreground:
|
|
26
|
-
--primary:
|
|
27
|
-
--primary-foreground:
|
|
28
|
-
--secondary:
|
|
29
|
-
--secondary-foreground:
|
|
30
|
-
--muted:
|
|
31
|
-
--muted-foreground:
|
|
32
|
-
--accent:
|
|
33
|
-
--accent-foreground:
|
|
34
|
-
--destructive:
|
|
35
|
-
--destructive-foreground:
|
|
36
|
-
--border:
|
|
37
|
-
--input:
|
|
38
|
-
--ring:
|
|
425
|
+
--background: ${light.background};
|
|
426
|
+
--foreground: ${light.foreground};
|
|
427
|
+
--card: ${light.card};
|
|
428
|
+
--card-foreground: ${light.cardForeground};
|
|
429
|
+
--popover: ${light.popover};
|
|
430
|
+
--popover-foreground: ${light.popoverForeground};
|
|
431
|
+
--primary: ${light.primary};
|
|
432
|
+
--primary-foreground: ${light.primaryForeground};
|
|
433
|
+
--secondary: ${light.secondary};
|
|
434
|
+
--secondary-foreground: ${light.secondaryForeground};
|
|
435
|
+
--muted: ${light.muted};
|
|
436
|
+
--muted-foreground: ${light.mutedForeground};
|
|
437
|
+
--accent: ${light.accent};
|
|
438
|
+
--accent-foreground: ${light.accentForeground};
|
|
439
|
+
--destructive: ${light.destructive};
|
|
440
|
+
--destructive-foreground: ${light.destructiveForeground};
|
|
441
|
+
--border: ${light.border};
|
|
442
|
+
--input: ${light.input};
|
|
443
|
+
--ring: ${light.ring};
|
|
39
444
|
--chart-1: oklch(0.646 0.222 41.116);
|
|
40
445
|
--chart-2: oklch(0.6 0.118 184.704);
|
|
41
446
|
--chart-3: oklch(0.398 0.07 227.392);
|
|
42
447
|
--chart-4: oklch(0.828 0.189 84.429);
|
|
43
448
|
--chart-5: oklch(0.769 0.188 70.08);
|
|
44
|
-
--sidebar:
|
|
45
|
-
--sidebar-foreground:
|
|
46
|
-
--sidebar-primary:
|
|
47
|
-
--sidebar-primary-foreground:
|
|
48
|
-
--sidebar-accent:
|
|
49
|
-
--sidebar-accent-foreground:
|
|
50
|
-
--sidebar-border:
|
|
51
|
-
--sidebar-ring:
|
|
449
|
+
--sidebar: ${light.background};
|
|
450
|
+
--sidebar-foreground: ${light.foreground};
|
|
451
|
+
--sidebar-primary: ${light.primary};
|
|
452
|
+
--sidebar-primary-foreground: ${light.primaryForeground};
|
|
453
|
+
--sidebar-accent: ${light.accent};
|
|
454
|
+
--sidebar-accent-foreground: ${light.accentForeground};
|
|
455
|
+
--sidebar-border: ${light.border};
|
|
456
|
+
--sidebar-ring: ${light.ring};
|
|
52
457
|
}
|
|
53
458
|
|
|
54
459
|
.dark {
|
|
55
|
-
--background:
|
|
56
|
-
--foreground:
|
|
57
|
-
--card:
|
|
58
|
-
--card-foreground:
|
|
59
|
-
--popover:
|
|
60
|
-
--popover-foreground:
|
|
61
|
-
--primary:
|
|
62
|
-
--primary-foreground:
|
|
63
|
-
--secondary:
|
|
64
|
-
--secondary-foreground:
|
|
65
|
-
--muted:
|
|
66
|
-
--muted-foreground:
|
|
67
|
-
--accent:
|
|
68
|
-
--accent-foreground:
|
|
69
|
-
--destructive:
|
|
70
|
-
--destructive-foreground:
|
|
71
|
-
--border:
|
|
72
|
-
--input:
|
|
73
|
-
--ring:
|
|
460
|
+
--background: ${dark.background};
|
|
461
|
+
--foreground: ${dark.foreground};
|
|
462
|
+
--card: ${dark.card};
|
|
463
|
+
--card-foreground: ${dark.cardForeground};
|
|
464
|
+
--popover: ${dark.popover};
|
|
465
|
+
--popover-foreground: ${dark.popoverForeground};
|
|
466
|
+
--primary: ${dark.primary};
|
|
467
|
+
--primary-foreground: ${dark.primaryForeground};
|
|
468
|
+
--secondary: ${dark.secondary};
|
|
469
|
+
--secondary-foreground: ${dark.secondaryForeground};
|
|
470
|
+
--muted: ${dark.muted};
|
|
471
|
+
--muted-foreground: ${dark.mutedForeground};
|
|
472
|
+
--accent: ${dark.accent};
|
|
473
|
+
--accent-foreground: ${dark.accentForeground};
|
|
474
|
+
--destructive: ${dark.destructive};
|
|
475
|
+
--destructive-foreground: ${dark.destructiveForeground};
|
|
476
|
+
--border: ${dark.border};
|
|
477
|
+
--input: ${dark.input};
|
|
478
|
+
--ring: ${dark.ring};
|
|
74
479
|
--chart-1: oklch(0.488 0.243 264.376);
|
|
75
480
|
--chart-2: oklch(0.696 0.17 162.48);
|
|
76
481
|
--chart-3: oklch(0.769 0.188 70.08);
|
|
77
482
|
--chart-4: oklch(0.627 0.265 303.9);
|
|
78
483
|
--chart-5: oklch(0.645 0.246 16.439);
|
|
79
|
-
--sidebar:
|
|
80
|
-
--sidebar-foreground:
|
|
81
|
-
--sidebar-primary:
|
|
82
|
-
--sidebar-primary-foreground:
|
|
83
|
-
--sidebar-accent:
|
|
84
|
-
--sidebar-accent-foreground:
|
|
85
|
-
--sidebar-border:
|
|
86
|
-
--sidebar-ring:
|
|
484
|
+
--sidebar: ${dark.card};
|
|
485
|
+
--sidebar-foreground: ${dark.foreground};
|
|
486
|
+
--sidebar-primary: ${dark.primary};
|
|
487
|
+
--sidebar-primary-foreground: ${dark.primaryForeground};
|
|
488
|
+
--sidebar-accent: ${dark.accent};
|
|
489
|
+
--sidebar-accent-foreground: ${dark.accentForeground};
|
|
490
|
+
--sidebar-border: ${dark.border};
|
|
491
|
+
--sidebar-ring: ${dark.ring};
|
|
87
492
|
}
|
|
88
493
|
|
|
89
494
|
@theme inline {
|
|
@@ -143,6 +548,16 @@ const CSS_VARIABLES_TEMPLATE = `/* ng-cn/core - shadcn-angular styles */
|
|
|
143
548
|
@keyframes collapsible-up { from { height: var(--collapsible-content-height); } to { height: 0; } }
|
|
144
549
|
}
|
|
145
550
|
`;
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
// PostCSS config template for Tailwind CSS v4
|
|
554
|
+
const POSTCSS_CONFIG_TEMPLATE = `/** @type {import('postcss').Config} */
|
|
555
|
+
export default {
|
|
556
|
+
plugins: {
|
|
557
|
+
'@tailwindcss/postcss': {},
|
|
558
|
+
},
|
|
559
|
+
};
|
|
560
|
+
`;
|
|
146
561
|
|
|
147
562
|
// cn utility template
|
|
148
563
|
const CN_UTILITY_TEMPLATE = `import { clsx, type ClassValue } from 'clsx';
|
|
@@ -218,18 +633,37 @@ export function ngAdd(options: NgAddOptions): Rule {
|
|
|
218
633
|
const utilsPath = '/src/app/lib/utils';
|
|
219
634
|
const uiPath = '/src/app/lib/components/ui';
|
|
220
635
|
|
|
221
|
-
//
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
636
|
+
// Copy all utility files from the package
|
|
637
|
+
const sourceUtilsBase = 'node_modules/@ng-cn/core/src/app/lib/utils';
|
|
638
|
+
let utilsFilesCopied = 0;
|
|
639
|
+
|
|
640
|
+
for (const utilFile of UTILS_FILES_REGISTRY) {
|
|
641
|
+
const sourcePath = join(normalize(sourceUtilsBase), normalize(utilFile)) as Path;
|
|
642
|
+
const targetPath = join(normalize(utilsPath), normalize(utilFile)) as Path;
|
|
643
|
+
|
|
644
|
+
const content = tree.read(sourcePath);
|
|
645
|
+
if (content) {
|
|
646
|
+
if (tree.exists(targetPath)) {
|
|
647
|
+
tree.overwrite(targetPath, content);
|
|
648
|
+
} else {
|
|
649
|
+
tree.create(targetPath, content);
|
|
650
|
+
}
|
|
651
|
+
utilsFilesCopied++;
|
|
652
|
+
}
|
|
227
653
|
}
|
|
228
654
|
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
655
|
+
if (utilsFilesCopied > 0) {
|
|
656
|
+
context.logger.info(` + src/app/lib/utils/ (${utilsFilesCopied} files)`);
|
|
657
|
+
} else {
|
|
658
|
+
// Fallback to creating basic files if package files not found
|
|
659
|
+
if (!tree.exists(`${utilsPath}/cn.ts`)) {
|
|
660
|
+
tree.create(`${utilsPath}/cn.ts`, CN_UTILITY_TEMPLATE);
|
|
661
|
+
context.logger.info(` + src/app/lib/utils/cn.ts`);
|
|
662
|
+
}
|
|
663
|
+
if (!tree.exists(`${utilsPath}/index.ts`)) {
|
|
664
|
+
tree.create(`${utilsPath}/index.ts`, UTILS_INDEX_TEMPLATE);
|
|
665
|
+
context.logger.info(` + src/app/lib/utils/index.ts`);
|
|
666
|
+
}
|
|
233
667
|
}
|
|
234
668
|
|
|
235
669
|
// Create ui components directory
|
|
@@ -243,32 +677,58 @@ export function ngAdd(options: NgAddOptions): Rule {
|
|
|
243
677
|
context.logger.info('');
|
|
244
678
|
context.logger.info('🎨 Styles');
|
|
245
679
|
|
|
680
|
+
// Get the selected theme (default to shadcn)
|
|
681
|
+
const selectedTheme: ThemeVariant = options.theme || 'shadcn';
|
|
682
|
+
const themePalette = THEME_PALETTES[selectedTheme];
|
|
683
|
+
|
|
684
|
+
context.logger.info(` Theme: ${themePalette.name} - ${themePalette.description}`);
|
|
685
|
+
|
|
246
686
|
const ngCnStylesPath = '/src/ng-cn.scss';
|
|
247
687
|
const stylesPath = '/src/styles.scss';
|
|
248
688
|
const stylesCssPath = '/src/styles.css';
|
|
249
689
|
|
|
250
|
-
// Create ng-cn.scss with
|
|
251
|
-
|
|
252
|
-
|
|
690
|
+
// Create ng-cn.scss with CSS variables based on selected theme
|
|
691
|
+
const cssTemplate = generateCssVariablesTemplate(selectedTheme);
|
|
692
|
+
tree.create(ngCnStylesPath, cssTemplate);
|
|
693
|
+
context.logger.info(` + src/ng-cn.scss (${themePalette.name} theme variables)`);
|
|
253
694
|
|
|
254
695
|
// Import in styles.scss or styles.css
|
|
255
696
|
if (tree.exists(stylesPath)) {
|
|
256
697
|
const stylesContent = tree.read(stylesPath)!.toString('utf-8');
|
|
257
698
|
if (!stylesContent.includes('ng-cn.scss')) {
|
|
258
|
-
const newContent = `@
|
|
699
|
+
const newContent = `@use './ng-cn.scss';\n\n${stylesContent}`;
|
|
259
700
|
tree.overwrite(stylesPath, newContent);
|
|
260
701
|
context.logger.info(` ✓ Imported in styles.scss`);
|
|
261
702
|
}
|
|
262
703
|
} else if (tree.exists(stylesCssPath)) {
|
|
263
704
|
const stylesContent = tree.read(stylesCssPath)!.toString('utf-8');
|
|
264
705
|
if (!stylesContent.includes('ng-cn.scss')) {
|
|
265
|
-
const newContent = `@
|
|
706
|
+
const newContent = `@use './ng-cn.scss';\n\n${stylesContent}`;
|
|
266
707
|
tree.overwrite(stylesCssPath, newContent);
|
|
267
708
|
context.logger.info(` ✓ Imported in styles.css`);
|
|
268
709
|
}
|
|
269
710
|
}
|
|
270
711
|
}
|
|
271
712
|
|
|
713
|
+
// Create postcss.config.mjs for Tailwind CSS v4
|
|
714
|
+
context.logger.info('');
|
|
715
|
+
context.logger.info('🔧 PostCSS Configuration');
|
|
716
|
+
|
|
717
|
+
const postcssConfigPath = '/postcss.config.mjs';
|
|
718
|
+
if (!tree.exists(postcssConfigPath)) {
|
|
719
|
+
tree.create(postcssConfigPath, POSTCSS_CONFIG_TEMPLATE);
|
|
720
|
+
context.logger.info(` + postcss.config.mjs (Tailwind CSS v4)`);
|
|
721
|
+
} else {
|
|
722
|
+
const existingConfig = tree.read(postcssConfigPath)!.toString('utf-8');
|
|
723
|
+
if (!existingConfig.includes('@tailwindcss/postcss')) {
|
|
724
|
+
// Update existing config to use Tailwind CSS v4
|
|
725
|
+
tree.overwrite(postcssConfigPath, POSTCSS_CONFIG_TEMPLATE);
|
|
726
|
+
context.logger.info(` ✓ postcss.config.mjs updated for Tailwind CSS v4`);
|
|
727
|
+
} else {
|
|
728
|
+
context.logger.info(` ✓ postcss.config.mjs already configured`);
|
|
729
|
+
}
|
|
730
|
+
}
|
|
731
|
+
|
|
272
732
|
// Update tsconfig paths
|
|
273
733
|
context.logger.info('');
|
|
274
734
|
context.logger.info('⚙️ TypeScript Config');
|
|
@@ -278,13 +738,19 @@ export function ngAdd(options: NgAddOptions): Rule {
|
|
|
278
738
|
const tsconfigContent = tree.read(tsconfigPath)!.toString('utf-8');
|
|
279
739
|
const tsconfig = parseJsonc(tsconfigContent) as Record<string, any>;
|
|
280
740
|
tsconfig.compilerOptions = tsconfig.compilerOptions || {};
|
|
741
|
+
|
|
742
|
+
// Set baseUrl for path aliases to work
|
|
743
|
+
if (!tsconfig.compilerOptions.baseUrl) {
|
|
744
|
+
tsconfig.compilerOptions.baseUrl = '.';
|
|
745
|
+
}
|
|
746
|
+
|
|
281
747
|
tsconfig.compilerOptions.paths = tsconfig.compilerOptions.paths || {};
|
|
282
748
|
|
|
283
749
|
const pathAliases: Record<string, string[]> = {
|
|
284
|
-
'@/*': ['src/*'],
|
|
285
|
-
'@/lib/*': ['src/app/lib/*'],
|
|
286
|
-
'@/ui/*': ['src/app/lib/components/ui/*'],
|
|
287
|
-
'@/utils/*': ['src/app/lib/utils/*']
|
|
750
|
+
'@/*': ['./src/*'],
|
|
751
|
+
'@/lib/*': ['./src/app/lib/*'],
|
|
752
|
+
'@/ui/*': ['./src/app/lib/components/ui/*'],
|
|
753
|
+
'@/utils/*': ['./src/app/lib/utils/*']
|
|
288
754
|
};
|
|
289
755
|
|
|
290
756
|
let pathsUpdated = false;
|
|
@@ -304,13 +770,18 @@ export function ngAdd(options: NgAddOptions): Rule {
|
|
|
304
770
|
}
|
|
305
771
|
|
|
306
772
|
// Install selected components
|
|
307
|
-
|
|
773
|
+
const componentsToInstall = parseComponentsOption(options.components);
|
|
774
|
+
if (componentsToInstall.length > 0) {
|
|
308
775
|
context.logger.info('');
|
|
309
|
-
|
|
776
|
+
if (options.components === 'all') {
|
|
777
|
+
context.logger.info(`🚀 Installing ALL ${componentsToInstall.length} components... (Magic Mode)`);
|
|
778
|
+
} else {
|
|
779
|
+
context.logger.info('📦 Selected Components');
|
|
780
|
+
}
|
|
310
781
|
|
|
311
782
|
const packageJson = JSON.parse(tree.read(packageJsonPath)!.toString('utf-8'));
|
|
312
783
|
|
|
313
|
-
for (const component of
|
|
784
|
+
for (const component of componentsToInstall) {
|
|
314
785
|
const packageName = `@ng-cn/${component}`;
|
|
315
786
|
if (!packageJson.dependencies?.[packageName]) {
|
|
316
787
|
packageJson.dependencies = packageJson.dependencies || {};
|
|
@@ -339,23 +810,40 @@ export function ngAdd(options: NgAddOptions): Rule {
|
|
|
339
810
|
context.logger.info(' ╚═╝ ╚═══╝ ╚═════╝ ╚═════╝╚═╝ ╚═══╝');
|
|
340
811
|
context.logger.info('');
|
|
341
812
|
context.logger.info(' ✅ Setup complete! shadcn for Angular');
|
|
813
|
+
|
|
814
|
+
// Show theme info
|
|
815
|
+
const selectedTheme: ThemeVariant = options.theme || 'shadcn';
|
|
816
|
+
const themePalette = THEME_PALETTES[selectedTheme];
|
|
817
|
+
context.logger.info(` 🎨 Theme: ${themePalette.name}`);
|
|
342
818
|
context.logger.info('');
|
|
343
819
|
|
|
344
820
|
// Show selected components summary if any were installed
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
context.logger.info(`│ ${
|
|
821
|
+
const componentsInstalled = parseComponentsOption(options.components);
|
|
822
|
+
if (componentsInstalled.length > 0) {
|
|
823
|
+
if (options.components === 'all') {
|
|
824
|
+
context.logger.info('╭──────────────────────────────────────────────────╮');
|
|
825
|
+
context.logger.info('│ ✨ MAGIC MODE - All components installed! │');
|
|
826
|
+
context.logger.info('│ │');
|
|
827
|
+
context.logger.info(`│ ${componentsInstalled.length} components ready to use │`);
|
|
828
|
+
context.logger.info('│ │');
|
|
829
|
+
context.logger.info('╰──────────────────────────────────────────────────╯');
|
|
830
|
+
} else {
|
|
831
|
+
context.logger.info('╭──────────────────────────────────────────────────╮');
|
|
832
|
+
context.logger.info('│ ✨ Components installed: │');
|
|
833
|
+
context.logger.info('│ │');
|
|
834
|
+
for (const component of componentsInstalled) {
|
|
835
|
+
const paddedComponent = `@ng-cn/${component}`.padEnd(40);
|
|
836
|
+
context.logger.info(`│ ${paddedComponent}│`);
|
|
837
|
+
}
|
|
838
|
+
context.logger.info('│ │');
|
|
839
|
+
context.logger.info('╰──────────────────────────────────────────────────╯');
|
|
352
840
|
}
|
|
353
|
-
context.logger.info('│ │');
|
|
354
|
-
context.logger.info('╰──────────────────────────────────────────────────╯');
|
|
355
841
|
context.logger.info('');
|
|
356
842
|
}
|
|
357
843
|
|
|
358
844
|
context.logger.info('╭──────────────────────────────────────────────────╮');
|
|
845
|
+
context.logger.info('│ ✅ Tailwind CSS v4 configured automatically! │');
|
|
846
|
+
context.logger.info('│ │');
|
|
359
847
|
context.logger.info('│ 🚀 Next steps: │');
|
|
360
848
|
context.logger.info('│ │');
|
|
361
849
|
context.logger.info('│ 1. Add more components: │');
|
|
@@ -375,3 +863,25 @@ export function ngAdd(options: NgAddOptions): Rule {
|
|
|
375
863
|
return tree;
|
|
376
864
|
};
|
|
377
865
|
}
|
|
866
|
+
|
|
867
|
+
/**
|
|
868
|
+
* Parse the components option which can be:
|
|
869
|
+
* - 'all' - install all components
|
|
870
|
+
* - comma-separated list like 'button,card,dialog'
|
|
871
|
+
* - empty string - no components
|
|
872
|
+
*/
|
|
873
|
+
function parseComponentsOption(components?: string): string[] {
|
|
874
|
+
if (!components || components.trim() === '') {
|
|
875
|
+
return [];
|
|
876
|
+
}
|
|
877
|
+
|
|
878
|
+
if (components.toLowerCase() === 'all') {
|
|
879
|
+
return ALL_COMPONENTS;
|
|
880
|
+
}
|
|
881
|
+
|
|
882
|
+
// Parse comma-separated list
|
|
883
|
+
return components
|
|
884
|
+
.split(',')
|
|
885
|
+
.map(c => c.trim().toLowerCase())
|
|
886
|
+
.filter(c => c.length > 0 && ALL_COMPONENTS.includes(c));
|
|
887
|
+
}
|