@gilav21/shadcn-angular 0.0.9 → 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 +85 -18
- package/dist/index.js +1 -1
- package/dist/registry/index.js +126 -2
- package/dist/templates/styles.d.ts +2 -1
- package/dist/templates/styles.js +62 -34
- package/dist/templates/utils.js +9 -0
- package/dist/utils/config.d.ts +2 -1
- package/dist/utils/config.js +1 -0
- package/package.json +2 -2
- package/src/commands/add.ts +106 -25
- package/src/commands/init.ts +98 -18
- package/src/index.ts +1 -1
- package/src/registry/index.ts +126 -2
- package/src/templates/styles.ts +65 -34
- package/src/templates/utils.ts +10 -1
- package/src/utils/config.ts +3 -1
package/dist/templates/styles.js
CHANGED
|
@@ -7,8 +7,6 @@ const baseColors = {
|
|
|
7
7
|
'--card-foreground': 'oklch(0.145 0 0)',
|
|
8
8
|
'--popover': 'oklch(1 0 0)',
|
|
9
9
|
'--popover-foreground': 'oklch(0.145 0 0)',
|
|
10
|
-
'--primary': 'oklch(0.205 0 0)',
|
|
11
|
-
'--primary-foreground': 'oklch(0.985 0 0)',
|
|
12
10
|
'--secondary': 'oklch(0.97 0 0)',
|
|
13
11
|
'--secondary-foreground': 'oklch(0.205 0 0)',
|
|
14
12
|
'--muted': 'oklch(0.97 0 0)',
|
|
@@ -18,7 +16,6 @@ const baseColors = {
|
|
|
18
16
|
'--destructive': 'oklch(0.577 0.245 27.325)',
|
|
19
17
|
'--border': 'oklch(0.922 0 0)',
|
|
20
18
|
'--input': 'oklch(0.922 0 0)',
|
|
21
|
-
'--ring': 'oklch(0.708 0 0)',
|
|
22
19
|
},
|
|
23
20
|
dark: {
|
|
24
21
|
'--background': 'oklch(0.145 0 0)',
|
|
@@ -27,8 +24,6 @@ const baseColors = {
|
|
|
27
24
|
'--card-foreground': 'oklch(0.985 0 0)',
|
|
28
25
|
'--popover': 'oklch(0.269 0 0)',
|
|
29
26
|
'--popover-foreground': 'oklch(0.985 0 0)',
|
|
30
|
-
'--primary': 'oklch(0.922 0 0)',
|
|
31
|
-
'--primary-foreground': 'oklch(0.205 0 0)',
|
|
32
27
|
'--secondary': 'oklch(0.269 0 0)',
|
|
33
28
|
'--secondary-foreground': 'oklch(0.985 0 0)',
|
|
34
29
|
'--muted': 'oklch(0.269 0 0)',
|
|
@@ -38,7 +33,6 @@ const baseColors = {
|
|
|
38
33
|
'--destructive': 'oklch(0.704 0.191 22.216)',
|
|
39
34
|
'--border': 'oklch(1 0 0 / 10%)',
|
|
40
35
|
'--input': 'oklch(1 0 0 / 15%)',
|
|
41
|
-
'--ring': 'oklch(0.556 0 0)',
|
|
42
36
|
},
|
|
43
37
|
},
|
|
44
38
|
slate: {
|
|
@@ -49,8 +43,6 @@ const baseColors = {
|
|
|
49
43
|
'--card-foreground': 'oklch(0.129 0.042 264.695)',
|
|
50
44
|
'--popover': 'oklch(1 0 0)',
|
|
51
45
|
'--popover-foreground': 'oklch(0.129 0.042 264.695)',
|
|
52
|
-
'--primary': 'oklch(0.208 0.042 265.755)',
|
|
53
|
-
'--primary-foreground': 'oklch(0.984 0.003 247.858)',
|
|
54
46
|
'--secondary': 'oklch(0.968 0.007 247.896)',
|
|
55
47
|
'--secondary-foreground': 'oklch(0.208 0.042 265.755)',
|
|
56
48
|
'--muted': 'oklch(0.968 0.007 247.896)',
|
|
@@ -60,7 +52,6 @@ const baseColors = {
|
|
|
60
52
|
'--destructive': 'oklch(0.577 0.245 27.325)',
|
|
61
53
|
'--border': 'oklch(0.929 0.013 255.508)',
|
|
62
54
|
'--input': 'oklch(0.929 0.013 255.508)',
|
|
63
|
-
'--ring': 'oklch(0.704 0.04 256.788)',
|
|
64
55
|
},
|
|
65
56
|
dark: {
|
|
66
57
|
'--background': 'oklch(0.129 0.042 264.695)',
|
|
@@ -69,8 +60,6 @@ const baseColors = {
|
|
|
69
60
|
'--card-foreground': 'oklch(0.984 0.003 247.858)',
|
|
70
61
|
'--popover': 'oklch(0.269 0.04 260.031)',
|
|
71
62
|
'--popover-foreground': 'oklch(0.984 0.003 247.858)',
|
|
72
|
-
'--primary': 'oklch(0.929 0.013 255.508)',
|
|
73
|
-
'--primary-foreground': 'oklch(0.208 0.042 265.755)',
|
|
74
63
|
'--secondary': 'oklch(0.269 0.04 260.031)',
|
|
75
64
|
'--secondary-foreground': 'oklch(0.984 0.003 247.858)',
|
|
76
65
|
'--muted': 'oklch(0.269 0.04 260.031)',
|
|
@@ -80,7 +69,6 @@ const baseColors = {
|
|
|
80
69
|
'--destructive': 'oklch(0.704 0.191 22.216)',
|
|
81
70
|
'--border': 'oklch(1 0 0 / 10%)',
|
|
82
71
|
'--input': 'oklch(1 0 0 / 15%)',
|
|
83
|
-
'--ring': 'oklch(0.554 0.046 257.417)',
|
|
84
72
|
},
|
|
85
73
|
},
|
|
86
74
|
stone: {
|
|
@@ -91,8 +79,6 @@ const baseColors = {
|
|
|
91
79
|
'--card-foreground': 'oklch(0.147 0.004 49.25)',
|
|
92
80
|
'--popover': 'oklch(1 0 0)',
|
|
93
81
|
'--popover-foreground': 'oklch(0.147 0.004 49.25)',
|
|
94
|
-
'--primary': 'oklch(0.216 0.006 56.043)',
|
|
95
|
-
'--primary-foreground': 'oklch(0.985 0.001 106.423)',
|
|
96
82
|
'--secondary': 'oklch(0.97 0.001 106.424)',
|
|
97
83
|
'--secondary-foreground': 'oklch(0.216 0.006 56.043)',
|
|
98
84
|
'--muted': 'oklch(0.97 0.001 106.424)',
|
|
@@ -102,7 +88,6 @@ const baseColors = {
|
|
|
102
88
|
'--destructive': 'oklch(0.577 0.245 27.325)',
|
|
103
89
|
'--border': 'oklch(0.923 0.003 48.717)',
|
|
104
90
|
'--input': 'oklch(0.923 0.003 48.717)',
|
|
105
|
-
'--ring': 'oklch(0.709 0.01 56.259)',
|
|
106
91
|
},
|
|
107
92
|
dark: {
|
|
108
93
|
'--background': 'oklch(0.147 0.004 49.25)',
|
|
@@ -111,8 +96,6 @@ const baseColors = {
|
|
|
111
96
|
'--card-foreground': 'oklch(0.985 0.001 106.423)',
|
|
112
97
|
'--popover': 'oklch(0.268 0.007 34.298)',
|
|
113
98
|
'--popover-foreground': 'oklch(0.985 0.001 106.423)',
|
|
114
|
-
'--primary': 'oklch(0.923 0.003 48.717)',
|
|
115
|
-
'--primary-foreground': 'oklch(0.216 0.006 56.043)',
|
|
116
99
|
'--secondary': 'oklch(0.268 0.007 34.298)',
|
|
117
100
|
'--secondary-foreground': 'oklch(0.985 0.001 106.423)',
|
|
118
101
|
'--muted': 'oklch(0.268 0.007 34.298)',
|
|
@@ -122,7 +105,6 @@ const baseColors = {
|
|
|
122
105
|
'--destructive': 'oklch(0.704 0.191 22.216)',
|
|
123
106
|
'--border': 'oklch(1 0 0 / 10%)',
|
|
124
107
|
'--input': 'oklch(1 0 0 / 15%)',
|
|
125
|
-
'--ring': 'oklch(0.553 0.013 58.071)',
|
|
126
108
|
},
|
|
127
109
|
},
|
|
128
110
|
gray: {
|
|
@@ -133,8 +115,6 @@ const baseColors = {
|
|
|
133
115
|
'--card-foreground': 'oklch(0.13 0.028 261.692)',
|
|
134
116
|
'--popover': 'oklch(1 0 0)',
|
|
135
117
|
'--popover-foreground': 'oklch(0.13 0.028 261.692)',
|
|
136
|
-
'--primary': 'oklch(0.21 0.028 264.532)',
|
|
137
|
-
'--primary-foreground': 'oklch(0.985 0.002 247.839)',
|
|
138
118
|
'--secondary': 'oklch(0.967 0.003 264.542)',
|
|
139
119
|
'--secondary-foreground': 'oklch(0.21 0.028 264.532)',
|
|
140
120
|
'--muted': 'oklch(0.967 0.003 264.542)',
|
|
@@ -144,7 +124,6 @@ const baseColors = {
|
|
|
144
124
|
'--destructive': 'oklch(0.577 0.245 27.325)',
|
|
145
125
|
'--border': 'oklch(0.928 0.006 264.531)',
|
|
146
126
|
'--input': 'oklch(0.928 0.006 264.531)',
|
|
147
|
-
'--ring': 'oklch(0.707 0.022 264.436)',
|
|
148
127
|
},
|
|
149
128
|
dark: {
|
|
150
129
|
'--background': 'oklch(0.13 0.028 261.692)',
|
|
@@ -153,8 +132,6 @@ const baseColors = {
|
|
|
153
132
|
'--card-foreground': 'oklch(0.985 0.002 247.839)',
|
|
154
133
|
'--popover': 'oklch(0.274 0.029 256.848)',
|
|
155
134
|
'--popover-foreground': 'oklch(0.985 0.002 247.839)',
|
|
156
|
-
'--primary': 'oklch(0.928 0.006 264.531)',
|
|
157
|
-
'--primary-foreground': 'oklch(0.21 0.028 264.532)',
|
|
158
135
|
'--secondary': 'oklch(0.274 0.029 256.848)',
|
|
159
136
|
'--secondary-foreground': 'oklch(0.985 0.002 247.839)',
|
|
160
137
|
'--muted': 'oklch(0.274 0.029 256.848)',
|
|
@@ -164,7 +141,6 @@ const baseColors = {
|
|
|
164
141
|
'--destructive': 'oklch(0.704 0.191 22.216)',
|
|
165
142
|
'--border': 'oklch(1 0 0 / 10%)',
|
|
166
143
|
'--input': 'oklch(1 0 0 / 15%)',
|
|
167
|
-
'--ring': 'oklch(0.551 0.027 264.364)',
|
|
168
144
|
},
|
|
169
145
|
},
|
|
170
146
|
zinc: {
|
|
@@ -175,8 +151,6 @@ const baseColors = {
|
|
|
175
151
|
'--card-foreground': 'oklch(0.141 0.005 285.823)',
|
|
176
152
|
'--popover': 'oklch(1 0 0)',
|
|
177
153
|
'--popover-foreground': 'oklch(0.141 0.005 285.823)',
|
|
178
|
-
'--primary': 'oklch(0.21 0.006 285.885)',
|
|
179
|
-
'--primary-foreground': 'oklch(0.985 0 0)',
|
|
180
154
|
'--secondary': 'oklch(0.967 0.001 286.375)',
|
|
181
155
|
'--secondary-foreground': 'oklch(0.21 0.006 285.885)',
|
|
182
156
|
'--muted': 'oklch(0.967 0.001 286.375)',
|
|
@@ -186,7 +160,6 @@ const baseColors = {
|
|
|
186
160
|
'--destructive': 'oklch(0.577 0.245 27.325)',
|
|
187
161
|
'--border': 'oklch(0.92 0.004 286.32)',
|
|
188
162
|
'--input': 'oklch(0.92 0.004 286.32)',
|
|
189
|
-
'--ring': 'oklch(0.705 0.015 286.067)',
|
|
190
163
|
},
|
|
191
164
|
dark: {
|
|
192
165
|
'--background': 'oklch(0.141 0.005 285.823)',
|
|
@@ -195,8 +168,6 @@ const baseColors = {
|
|
|
195
168
|
'--card-foreground': 'oklch(0.985 0 0)',
|
|
196
169
|
'--popover': 'oklch(0.274 0.006 286.033)',
|
|
197
170
|
'--popover-foreground': 'oklch(0.985 0 0)',
|
|
198
|
-
'--primary': 'oklch(0.92 0.004 286.32)',
|
|
199
|
-
'--primary-foreground': 'oklch(0.21 0.006 285.885)',
|
|
200
171
|
'--secondary': 'oklch(0.274 0.006 286.033)',
|
|
201
172
|
'--secondary-foreground': 'oklch(0.985 0 0)',
|
|
202
173
|
'--muted': 'oklch(0.274 0.006 286.033)',
|
|
@@ -206,17 +177,73 @@ const baseColors = {
|
|
|
206
177
|
'--destructive': 'oklch(0.704 0.191 22.216)',
|
|
207
178
|
'--border': 'oklch(1 0 0 / 10%)',
|
|
208
179
|
'--input': 'oklch(1 0 0 / 15%)',
|
|
209
|
-
'--ring': 'oklch(0.552 0.016 285.938)',
|
|
210
180
|
},
|
|
211
181
|
},
|
|
212
182
|
};
|
|
183
|
+
const themeColors = {
|
|
184
|
+
neutral: {
|
|
185
|
+
light: { '--primary': 'oklch(0.205 0 0)', '--primary-foreground': 'oklch(0.985 0 0)', '--ring': 'oklch(0.708 0 0)' },
|
|
186
|
+
dark: { '--primary': 'oklch(0.985 0 0)', '--primary-foreground': 'oklch(0.205 0 0)', '--ring': 'oklch(0.708 0 0)' },
|
|
187
|
+
},
|
|
188
|
+
zinc: {
|
|
189
|
+
light: { '--primary': 'oklch(0.205 0 0)', '--primary-foreground': 'oklch(0.985 0 0)', '--ring': 'oklch(0.708 0 0)' },
|
|
190
|
+
dark: { '--primary': 'oklch(0.985 0 0)', '--primary-foreground': 'oklch(0.205 0 0)', '--ring': 'oklch(0.708 0 0)' },
|
|
191
|
+
},
|
|
192
|
+
slate: {
|
|
193
|
+
light: { '--primary': 'oklch(0.208 0.042 265.755)', '--primary-foreground': 'oklch(0.984 0.003 247.858)', '--ring': 'oklch(0.704 0.04 256.788)' },
|
|
194
|
+
dark: { '--primary': 'oklch(0.929 0.013 255.508)', '--primary-foreground': 'oklch(0.208 0.042 265.755)', '--ring': 'oklch(0.704 0.04 256.788)' },
|
|
195
|
+
},
|
|
196
|
+
stone: {
|
|
197
|
+
light: { '--primary': 'oklch(0.216 0.006 56.043)', '--primary-foreground': 'oklch(0.985 0.001 106.423)', '--ring': 'oklch(0.709 0.01 56.259)' },
|
|
198
|
+
dark: { '--primary': 'oklch(0.923 0.003 48.717)', '--primary-foreground': 'oklch(0.216 0.006 56.043)', '--ring': 'oklch(0.553 0.013 58.071)' },
|
|
199
|
+
},
|
|
200
|
+
gray: {
|
|
201
|
+
light: { '--primary': 'oklch(0.21 0.028 264.532)', '--primary-foreground': 'oklch(0.985 0.002 247.839)', '--ring': 'oklch(0.707 0.022 264.436)' },
|
|
202
|
+
dark: { '--primary': 'oklch(0.928 0.006 264.531)', '--primary-foreground': 'oklch(0.21 0.028 264.532)', '--ring': 'oklch(0.551 0.027 264.364)' },
|
|
203
|
+
},
|
|
204
|
+
red: {
|
|
205
|
+
light: { '--primary': 'oklch(0.577 0.245 27.325)', '--primary-foreground': 'oklch(0.985 0 0)', '--ring': 'oklch(0.577 0.245 27.325)' },
|
|
206
|
+
dark: { '--primary': 'oklch(0.577 0.245 27.325)', '--primary-foreground': 'oklch(0.985 0 0)', '--ring': 'oklch(0.577 0.245 27.325)' },
|
|
207
|
+
},
|
|
208
|
+
rose: {
|
|
209
|
+
light: { '--primary': 'oklch(0.645 0.246 16.439)', '--primary-foreground': 'oklch(0.985 0 0)', '--ring': 'oklch(0.645 0.246 16.439)' },
|
|
210
|
+
dark: { '--primary': 'oklch(0.645 0.246 16.439)', '--primary-foreground': 'oklch(0.985 0 0)', '--ring': 'oklch(0.645 0.246 16.439)' },
|
|
211
|
+
},
|
|
212
|
+
orange: {
|
|
213
|
+
light: { '--primary': 'oklch(0.646 0.222 41.116)', '--primary-foreground': 'oklch(0.985 0 0)', '--ring': 'oklch(0.646 0.222 41.116)' },
|
|
214
|
+
dark: { '--primary': 'oklch(0.646 0.222 41.116)', '--primary-foreground': 'oklch(0.985 0 0)', '--ring': 'oklch(0.646 0.222 41.116)' },
|
|
215
|
+
},
|
|
216
|
+
green: {
|
|
217
|
+
light: { '--primary': 'oklch(0.623 0.214 131.655)', '--primary-foreground': 'oklch(0.985 0 0)', '--ring': 'oklch(0.623 0.214 131.655)' },
|
|
218
|
+
dark: { '--primary': 'oklch(0.623 0.214 131.655)', '--primary-foreground': 'oklch(0.985 0 0)', '--ring': 'oklch(0.623 0.214 131.655)' },
|
|
219
|
+
},
|
|
220
|
+
blue: {
|
|
221
|
+
light: { '--primary': 'oklch(0.546 0.245 262.881)', '--primary-foreground': 'oklch(0.985 0 0)', '--ring': 'oklch(0.546 0.245 262.881)' },
|
|
222
|
+
dark: { '--primary': 'oklch(0.546 0.245 262.881)', '--primary-foreground': 'oklch(0.985 0 0)', '--ring': 'oklch(0.546 0.245 262.881)' },
|
|
223
|
+
},
|
|
224
|
+
yellow: {
|
|
225
|
+
light: { '--primary': 'oklch(0.82 0.185 84.67)', '--primary-foreground': 'oklch(0.205 0 0)', '--ring': 'oklch(0.82 0.185 84.67)' },
|
|
226
|
+
dark: { '--primary': 'oklch(0.82 0.185 84.67)', '--primary-foreground': 'oklch(0.205 0 0)', '--ring': 'oklch(0.82 0.185 84.67)' },
|
|
227
|
+
},
|
|
228
|
+
violet: {
|
|
229
|
+
light: { '--primary': 'oklch(0.558 0.288 302.321)', '--primary-foreground': 'oklch(0.985 0 0)', '--ring': 'oklch(0.558 0.288 302.321)' },
|
|
230
|
+
dark: { '--primary': 'oklch(0.558 0.288 302.321)', '--primary-foreground': 'oklch(0.985 0 0)', '--ring': 'oklch(0.558 0.288 302.321)' },
|
|
231
|
+
},
|
|
232
|
+
amber: {
|
|
233
|
+
light: { '--primary': 'oklch(0.77 0.16 70)', '--primary-foreground': 'oklch(0.145 0 0)', '--ring': 'oklch(0.77 0.16 70)' },
|
|
234
|
+
dark: { '--primary': 'oklch(0.77 0.16 70)', '--primary-foreground': 'oklch(0.145 0 0)', '--ring': 'oklch(0.77 0.16 70)' },
|
|
235
|
+
},
|
|
236
|
+
};
|
|
213
237
|
function generateCssVars(vars, indent = ' ') {
|
|
214
238
|
return Object.entries(vars)
|
|
215
239
|
.map(([key, value]) => `${indent}${key}: ${value};`)
|
|
216
240
|
.join('\n');
|
|
217
241
|
}
|
|
218
|
-
export function getStylesTemplate(baseColor = 'neutral') {
|
|
219
|
-
const
|
|
242
|
+
export function getStylesTemplate(baseColor = 'neutral', themeColor = 'zinc') {
|
|
243
|
+
const base = baseColors[baseColor];
|
|
244
|
+
const theme = themeColors[themeColor] || themeColors.neutral;
|
|
245
|
+
const lightVars = { ...base.light, ...theme.light };
|
|
246
|
+
const darkVars = { ...base.dark, ...theme.dark };
|
|
220
247
|
return `@import "tailwindcss";
|
|
221
248
|
|
|
222
249
|
/* Tell Tailwind v4 where to scan for classes */
|
|
@@ -227,7 +254,7 @@ export function getStylesTemplate(baseColor = 'neutral') {
|
|
|
227
254
|
|
|
228
255
|
:root {
|
|
229
256
|
--radius: 0.625rem;
|
|
230
|
-
${generateCssVars(
|
|
257
|
+
${generateCssVars(lightVars)}
|
|
231
258
|
--chart-1: oklch(0.646 0.222 41.116);
|
|
232
259
|
--chart-2: oklch(0.6 0.118 184.704);
|
|
233
260
|
--chart-3: oklch(0.398 0.07 227.392);
|
|
@@ -244,7 +271,7 @@ ${generateCssVars(colors.light)}
|
|
|
244
271
|
}
|
|
245
272
|
|
|
246
273
|
.dark {
|
|
247
|
-
${generateCssVars(
|
|
274
|
+
${generateCssVars(darkVars)}
|
|
248
275
|
--chart-1: oklch(0.488 0.243 264.376);
|
|
249
276
|
--chart-2: oklch(0.696 0.17 162.48);
|
|
250
277
|
--chart-3: oklch(0.769 0.188 70.08);
|
|
@@ -314,6 +341,7 @@ ${generateCssVars(colors.dark)}
|
|
|
314
341
|
}
|
|
315
342
|
html {
|
|
316
343
|
font-family: var(--font-sans);
|
|
344
|
+
font-size: 16px;
|
|
317
345
|
}
|
|
318
346
|
button:not(:disabled),
|
|
319
347
|
[role="button"]:not(:disabled) {
|
package/dist/templates/utils.js
CHANGED
|
@@ -8,5 +8,14 @@ import { twMerge } from 'tailwind-merge';
|
|
|
8
8
|
export function cn(...inputs: ClassValue[]): string {
|
|
9
9
|
return twMerge(clsx(inputs));
|
|
10
10
|
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Check if the current direction is RTL by reading the computed style of the element.
|
|
14
|
+
* This allows components to detect RTL without needing an explicit input.
|
|
15
|
+
*/
|
|
16
|
+
export function isRtl(el: HTMLElement): boolean {
|
|
17
|
+
return getComputedStyle(el).direction === 'rtl';
|
|
18
|
+
}
|
|
19
|
+
|
|
11
20
|
`;
|
|
12
21
|
}
|
package/dist/utils/config.d.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
export interface Config {
|
|
2
2
|
$schema: string;
|
|
3
|
-
style: 'default'
|
|
3
|
+
style: 'default';
|
|
4
4
|
tailwind: {
|
|
5
5
|
css: string;
|
|
6
6
|
baseColor: 'neutral' | 'slate' | 'stone' | 'gray' | 'zinc';
|
|
7
|
+
theme?: 'zinc' | 'slate' | 'stone' | 'gray' | 'neutral' | 'red' | 'rose' | 'orange' | 'green' | 'blue' | 'yellow' | 'violet' | 'amber';
|
|
7
8
|
cssVariables: boolean;
|
|
8
9
|
};
|
|
9
10
|
aliases: {
|
package/dist/utils/config.js
CHANGED
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
|
@@ -46,29 +46,70 @@ export async function init(options: InitOptions) {
|
|
|
46
46
|
if (options.defaults || options.yes) {
|
|
47
47
|
config = getDefaultConfig();
|
|
48
48
|
} else {
|
|
49
|
+
const THEME_COLORS: Record<string, string> = {
|
|
50
|
+
zinc: '#71717a',
|
|
51
|
+
slate: '#64748b',
|
|
52
|
+
stone: '#78716c',
|
|
53
|
+
gray: '#6b7280',
|
|
54
|
+
neutral: '#737373',
|
|
55
|
+
red: '#ef4444',
|
|
56
|
+
rose: '#f43f5e',
|
|
57
|
+
orange: '#f97316', // bright orange
|
|
58
|
+
green: '#22c55e',
|
|
59
|
+
blue: '#3b82f6',
|
|
60
|
+
yellow: '#eab308',
|
|
61
|
+
violet: '#8b5cf6',
|
|
62
|
+
amber: '#d97706', // warm amber for preview
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
const themeChoices = [
|
|
66
|
+
{ title: 'Zinc', value: 'zinc' },
|
|
67
|
+
{ title: 'Slate', value: 'slate' },
|
|
68
|
+
{ title: 'Stone', value: 'stone' },
|
|
69
|
+
{ title: 'Gray', value: 'gray' },
|
|
70
|
+
{ title: 'Neutral', value: 'neutral' },
|
|
71
|
+
{ title: 'Red', value: 'red' },
|
|
72
|
+
{ title: 'Rose', value: 'rose' },
|
|
73
|
+
{ title: 'Orange', value: 'orange' },
|
|
74
|
+
{ title: 'Green', value: 'green' },
|
|
75
|
+
{ title: 'Blue', value: 'blue' },
|
|
76
|
+
{ title: 'Yellow', value: 'yellow' },
|
|
77
|
+
{ title: 'Violet', value: 'violet' },
|
|
78
|
+
{ title: 'Amber', value: 'amber' },
|
|
79
|
+
].map(c => ({
|
|
80
|
+
...c,
|
|
81
|
+
title: `${chalk.hex(THEME_COLORS[c.value])('██')} ${c.title}`
|
|
82
|
+
}));
|
|
83
|
+
|
|
84
|
+
const baseColorChoices = [
|
|
85
|
+
{ title: 'Neutral', value: 'neutral' },
|
|
86
|
+
{ title: 'Slate', value: 'slate' },
|
|
87
|
+
{ title: 'Stone', value: 'stone' },
|
|
88
|
+
{ title: 'Gray', value: 'gray' },
|
|
89
|
+
{ title: 'Zinc', value: 'zinc' },
|
|
90
|
+
].map(c => ({
|
|
91
|
+
...c,
|
|
92
|
+
title: `${chalk.hex(THEME_COLORS[c.value])('██')} ${c.title}`
|
|
93
|
+
}));
|
|
94
|
+
|
|
49
95
|
const responses = await prompts([
|
|
96
|
+
|
|
50
97
|
{
|
|
51
98
|
type: 'select',
|
|
52
|
-
name: '
|
|
53
|
-
message: 'Which
|
|
54
|
-
choices:
|
|
55
|
-
{ title: 'Default', value: 'default' },
|
|
56
|
-
{ title: 'New York', value: 'new-york' },
|
|
57
|
-
],
|
|
99
|
+
name: 'baseColor',
|
|
100
|
+
message: 'Which color would you like to use as base color?',
|
|
101
|
+
choices: baseColorChoices,
|
|
58
102
|
initial: 0,
|
|
59
103
|
},
|
|
60
104
|
{
|
|
61
105
|
type: 'select',
|
|
62
|
-
name: '
|
|
63
|
-
message: 'Which color would you like to use
|
|
64
|
-
choices:
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
{ title: 'Zinc', value: 'zinc' },
|
|
70
|
-
],
|
|
71
|
-
initial: 0,
|
|
106
|
+
name: 'theme',
|
|
107
|
+
message: 'Which color would you like to use for the main theme?',
|
|
108
|
+
choices: themeChoices,
|
|
109
|
+
initial: (prev: string) => {
|
|
110
|
+
const index = themeChoices.findIndex(c => c.value === prev);
|
|
111
|
+
return index === -1 ? 0 : index;
|
|
112
|
+
},
|
|
72
113
|
},
|
|
73
114
|
{
|
|
74
115
|
type: 'text',
|
|
@@ -92,10 +133,11 @@ export async function init(options: InitOptions) {
|
|
|
92
133
|
|
|
93
134
|
config = {
|
|
94
135
|
$schema: 'https://shadcn-angular.dev/schema.json',
|
|
95
|
-
style:
|
|
136
|
+
style: 'default',
|
|
96
137
|
tailwind: {
|
|
97
138
|
css: responses.globalCss,
|
|
98
139
|
baseColor: responses.baseColor,
|
|
140
|
+
theme: responses.theme,
|
|
99
141
|
cssVariables: true,
|
|
100
142
|
},
|
|
101
143
|
aliases: {
|
|
@@ -133,7 +175,7 @@ export async function init(options: InitOptions) {
|
|
|
133
175
|
const tailwindCssPath = path.join(stylesDir, 'tailwind.css');
|
|
134
176
|
|
|
135
177
|
// Write the tailwind.css file with all Tailwind directives
|
|
136
|
-
await fs.writeFile(tailwindCssPath, getStylesTemplate(config.tailwind.baseColor));
|
|
178
|
+
await fs.writeFile(tailwindCssPath, getStylesTemplate(config.tailwind.baseColor, config.tailwind.theme));
|
|
137
179
|
spinner.text = 'Created tailwind.css';
|
|
138
180
|
|
|
139
181
|
// Add import to the user's global styles file if not already present
|
|
@@ -182,6 +224,44 @@ export async function init(options: InitOptions) {
|
|
|
182
224
|
await fs.writeJson(postcssrcPath, configContent, { spaces: 4 });
|
|
183
225
|
}
|
|
184
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
|
+
|
|
185
265
|
spinner.succeed(chalk.green('Project initialized successfully!'));
|
|
186
266
|
|
|
187
267
|
console.log('\n' + chalk.bold('Next steps:'));
|