@srcroot/ui 0.0.30 → 0.0.33
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/index.js +426 -594
- package/package.json +10 -9
- package/src/registry/analytics/google-analytics.tsx +36 -0
- package/src/registry/analytics/google-tag-manager.tsx +62 -0
- package/src/registry/analytics/meta-pixel.tsx +44 -0
- package/src/registry/analytics/microsoft-clarity.tsx +31 -0
- package/src/registry/analytics/tiktok-pixel.tsx +34 -0
- package/src/registry/lib/utils.ts +6 -0
- package/src/registry/themes/gradients.css +236 -0
- package/{registry/themes → src/registry/themes/v3}/gray.css +45 -1
- package/{registry/themes → src/registry/themes/v3}/neutral.css +45 -1
- package/{registry/themes → src/registry/themes/v3}/slate.css +45 -1
- package/{registry/themes → src/registry/themes/v3}/stone.css +45 -1
- package/{registry/themes → src/registry/themes/v3}/zinc.css +45 -1
- package/src/registry/themes/v4/gray.css +183 -0
- package/src/registry/themes/v4/neutral.css +183 -0
- package/src/registry/themes/v4/slate.css +183 -0
- package/src/registry/themes/v4/stone.css +183 -0
- package/src/registry/themes/v4/zinc.css +183 -0
- package/src/registry/ui/chatbot.tsx +96 -0
- package/registry/design-tokens.css +0 -217
- package/registry/themes/index.css +0 -19
- /package/{registry → src/registry/ui}/accordion.tsx +0 -0
- /package/{registry → src/registry/ui}/alert-dialog.tsx +0 -0
- /package/{registry → src/registry/ui}/alert.tsx +0 -0
- /package/{registry → src/registry/ui}/aspect-ratio.tsx +0 -0
- /package/{registry → src/registry/ui}/avatar.tsx +0 -0
- /package/{registry → src/registry/ui}/badge.tsx +0 -0
- /package/{registry → src/registry/ui}/breadcrumb.tsx +0 -0
- /package/{registry → src/registry/ui}/button-group.tsx +0 -0
- /package/{registry → src/registry/ui}/button.tsx +0 -0
- /package/{registry → src/registry/ui}/calendar.tsx +0 -0
- /package/{registry → src/registry/ui}/card.tsx +0 -0
- /package/{registry → src/registry/ui}/carousel.tsx +0 -0
- /package/{registry → src/registry/ui}/checkbox.tsx +0 -0
- /package/{registry → src/registry/ui}/collapsible.tsx +0 -0
- /package/{registry → src/registry/ui}/combobox.tsx +0 -0
- /package/{registry → src/registry/ui}/command.tsx +0 -0
- /package/{registry → src/registry/ui}/container.tsx +0 -0
- /package/{registry → src/registry/ui}/context-menu.tsx +0 -0
- /package/{registry → src/registry/ui}/date-picker.tsx +0 -0
- /package/{registry → src/registry/ui}/dialog.tsx +0 -0
- /package/{registry → src/registry/ui}/drawer.tsx +0 -0
- /package/{registry → src/registry/ui}/dropdown-menu.tsx +0 -0
- /package/{registry → src/registry/ui}/file-upload.tsx +0 -0
- /package/{registry → src/registry/ui}/hover-card.tsx +0 -0
- /package/{registry → src/registry/ui}/image.tsx +0 -0
- /package/{registry → src/registry/ui}/input.tsx +0 -0
- /package/{registry → src/registry/ui}/kbd.tsx +0 -0
- /package/{registry → src/registry/ui}/label.tsx +0 -0
- /package/{registry → src/registry/ui}/loading-spinner.tsx +0 -0
- /package/{registry → src/registry/ui}/menubar.tsx +0 -0
- /package/{registry → src/registry/ui}/native-select.tsx +0 -0
- /package/{registry → src/registry/ui}/otp-input.tsx +0 -0
- /package/{registry → src/registry/ui}/pagination.tsx +0 -0
- /package/{registry → src/registry/ui}/popover.tsx +0 -0
- /package/{registry → src/registry/ui}/progress.tsx +0 -0
- /package/{registry → src/registry/ui}/radio.tsx +0 -0
- /package/{registry → src/registry/ui}/resizable.tsx +0 -0
- /package/{registry → src/registry/ui}/scroll-area.tsx +0 -0
- /package/{registry → src/registry/ui}/search.tsx +0 -0
- /package/{registry → src/registry/ui}/select.tsx +0 -0
- /package/{registry → src/registry/ui}/separator.tsx +0 -0
- /package/{registry → src/registry/ui}/sheet.tsx +0 -0
- /package/{registry → src/registry/ui}/sidebar.tsx +0 -0
- /package/{registry → src/registry/ui}/skeleton.tsx +0 -0
- /package/{registry → src/registry/ui}/slider.tsx +0 -0
- /package/{registry → src/registry/ui}/star-rating.tsx +0 -0
- /package/{registry → src/registry/ui}/switch.tsx +0 -0
- /package/{registry → src/registry/ui}/table.tsx +0 -0
- /package/{registry → src/registry/ui}/tabs.tsx +0 -0
- /package/{registry → src/registry/ui}/text.tsx +0 -0
- /package/{registry → src/registry/ui}/textarea.tsx +0 -0
- /package/{registry → src/registry/ui}/toast.tsx +0 -0
- /package/{registry → src/registry/ui}/toggle-group.tsx +0 -0
- /package/{registry → src/registry/ui}/toggle.tsx +0 -0
- /package/{registry → src/registry/ui}/tooltip.tsx +0 -0
package/dist/index.js
CHANGED
|
@@ -2,425 +2,73 @@
|
|
|
2
2
|
|
|
3
3
|
// src/cli/index.ts
|
|
4
4
|
import { Command } from "commander";
|
|
5
|
+
import chalk3 from "chalk";
|
|
5
6
|
|
|
6
|
-
// src/cli/
|
|
7
|
-
import
|
|
8
|
-
import
|
|
9
|
-
import chalk from "chalk";
|
|
7
|
+
// src/cli/services/project-initializer.ts
|
|
8
|
+
import fs2 from "fs-extra";
|
|
9
|
+
import path2 from "path";
|
|
10
10
|
import ora from "ora";
|
|
11
11
|
import prompts from "prompts";
|
|
12
|
+
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
13
|
+
|
|
14
|
+
// src/cli/services/theme-service.ts
|
|
15
|
+
import fs from "fs-extra";
|
|
16
|
+
import path from "path";
|
|
12
17
|
import { fileURLToPath } from "url";
|
|
13
18
|
var __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
14
|
-
var
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
var
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
secondary: "210 40% 96.1%",
|
|
35
|
-
"secondary-foreground": "222.2 47.4% 11.2%",
|
|
36
|
-
muted: "210 40% 96.1%",
|
|
37
|
-
"muted-foreground": "215.4 16.3% 46.9%",
|
|
38
|
-
accent: "210 40% 96.1%",
|
|
39
|
-
"accent-foreground": "222.2 47.4% 11.2%",
|
|
40
|
-
destructive: "0 84.2% 60.2%",
|
|
41
|
-
"destructive-foreground": "210 40% 98%",
|
|
42
|
-
border: "214.3 31.8% 91.4%",
|
|
43
|
-
input: "214.3 31.8% 91.4%",
|
|
44
|
-
ring: "222.2 84% 4.9%"
|
|
45
|
-
},
|
|
46
|
-
dark: {
|
|
47
|
-
background: "222.2 84% 4.9%",
|
|
48
|
-
foreground: "210 40% 98%",
|
|
49
|
-
card: "222.2 84% 4.9%",
|
|
50
|
-
"card-foreground": "210 40% 98%",
|
|
51
|
-
popover: "222.2 84% 4.9%",
|
|
52
|
-
"popover-foreground": "210 40% 98%",
|
|
53
|
-
primary: "210 40% 98%",
|
|
54
|
-
"primary-foreground": "222.2 47.4% 11.2%",
|
|
55
|
-
secondary: "217.2 32.6% 17.5%",
|
|
56
|
-
"secondary-foreground": "210 40% 98%",
|
|
57
|
-
muted: "217.2 32.6% 17.5%",
|
|
58
|
-
"muted-foreground": "215 20.2% 65.1%",
|
|
59
|
-
accent: "217.2 32.6% 17.5%",
|
|
60
|
-
"accent-foreground": "210 40% 98%",
|
|
61
|
-
destructive: "0 62.8% 30.6%",
|
|
62
|
-
"destructive-foreground": "210 40% 98%",
|
|
63
|
-
border: "217.2 32.6% 17.5%",
|
|
64
|
-
input: "217.2 32.6% 17.5%",
|
|
65
|
-
ring: "212.7 26.8% 83.9%"
|
|
66
|
-
}
|
|
67
|
-
},
|
|
68
|
-
neutral: {
|
|
69
|
-
name: "Neutral",
|
|
70
|
-
description: "Pure gray, no undertones",
|
|
71
|
-
light: {
|
|
72
|
-
background: "0 0% 100%",
|
|
73
|
-
foreground: "0 0% 3.9%",
|
|
74
|
-
card: "0 0% 100%",
|
|
75
|
-
"card-foreground": "0 0% 3.9%",
|
|
76
|
-
popover: "0 0% 100%",
|
|
77
|
-
"popover-foreground": "0 0% 3.9%",
|
|
78
|
-
primary: "0 0% 9%",
|
|
79
|
-
"primary-foreground": "0 0% 98%",
|
|
80
|
-
secondary: "0 0% 96.1%",
|
|
81
|
-
"secondary-foreground": "0 0% 9%",
|
|
82
|
-
muted: "0 0% 96.1%",
|
|
83
|
-
"muted-foreground": "0 0% 45.1%",
|
|
84
|
-
accent: "0 0% 96.1%",
|
|
85
|
-
"accent-foreground": "0 0% 9%",
|
|
86
|
-
destructive: "0 84.2% 60.2%",
|
|
87
|
-
"destructive-foreground": "0 0% 98%",
|
|
88
|
-
border: "0 0% 89.8%",
|
|
89
|
-
input: "0 0% 89.8%",
|
|
90
|
-
ring: "0 0% 3.9%"
|
|
91
|
-
},
|
|
92
|
-
dark: {
|
|
93
|
-
background: "0 0% 3.9%",
|
|
94
|
-
foreground: "0 0% 98%",
|
|
95
|
-
card: "0 0% 3.9%",
|
|
96
|
-
"card-foreground": "0 0% 98%",
|
|
97
|
-
popover: "0 0% 3.9%",
|
|
98
|
-
"popover-foreground": "0 0% 98%",
|
|
99
|
-
primary: "0 0% 98%",
|
|
100
|
-
"primary-foreground": "0 0% 9%",
|
|
101
|
-
secondary: "0 0% 14.9%",
|
|
102
|
-
"secondary-foreground": "0 0% 98%",
|
|
103
|
-
muted: "0 0% 14.9%",
|
|
104
|
-
"muted-foreground": "0 0% 63.9%",
|
|
105
|
-
accent: "0 0% 14.9%",
|
|
106
|
-
"accent-foreground": "0 0% 98%",
|
|
107
|
-
destructive: "0 62.8% 30.6%",
|
|
108
|
-
"destructive-foreground": "0 0% 98%",
|
|
109
|
-
border: "0 0% 14.9%",
|
|
110
|
-
input: "0 0% 14.9%",
|
|
111
|
-
ring: "0 0% 83.1%"
|
|
112
|
-
}
|
|
113
|
-
},
|
|
114
|
-
stone: {
|
|
115
|
-
name: "Stone",
|
|
116
|
-
description: "Warm gray with brown undertones",
|
|
117
|
-
light: {
|
|
118
|
-
background: "0 0% 100%",
|
|
119
|
-
foreground: "24 9.8% 10%",
|
|
120
|
-
card: "0 0% 100%",
|
|
121
|
-
"card-foreground": "24 9.8% 10%",
|
|
122
|
-
popover: "0 0% 100%",
|
|
123
|
-
"popover-foreground": "24 9.8% 10%",
|
|
124
|
-
primary: "24 9.8% 10%",
|
|
125
|
-
"primary-foreground": "60 9.1% 97.8%",
|
|
126
|
-
secondary: "60 4.8% 95.9%",
|
|
127
|
-
"secondary-foreground": "24 9.8% 10%",
|
|
128
|
-
muted: "60 4.8% 95.9%",
|
|
129
|
-
"muted-foreground": "25 5.3% 44.7%",
|
|
130
|
-
accent: "60 4.8% 95.9%",
|
|
131
|
-
"accent-foreground": "24 9.8% 10%",
|
|
132
|
-
destructive: "0 84.2% 60.2%",
|
|
133
|
-
"destructive-foreground": "60 9.1% 97.8%",
|
|
134
|
-
border: "20 5.9% 90%",
|
|
135
|
-
input: "20 5.9% 90%",
|
|
136
|
-
ring: "24 9.8% 10%"
|
|
137
|
-
},
|
|
138
|
-
dark: {
|
|
139
|
-
background: "24 9.8% 10%",
|
|
140
|
-
foreground: "60 9.1% 97.8%",
|
|
141
|
-
card: "24 9.8% 10%",
|
|
142
|
-
"card-foreground": "60 9.1% 97.8%",
|
|
143
|
-
popover: "24 9.8% 10%",
|
|
144
|
-
"popover-foreground": "60 9.1% 97.8%",
|
|
145
|
-
primary: "60 9.1% 97.8%",
|
|
146
|
-
"primary-foreground": "24 9.8% 10%",
|
|
147
|
-
secondary: "12 6.5% 15.1%",
|
|
148
|
-
"secondary-foreground": "60 9.1% 97.8%",
|
|
149
|
-
muted: "12 6.5% 15.1%",
|
|
150
|
-
"muted-foreground": "24 5.4% 63.9%",
|
|
151
|
-
accent: "12 6.5% 15.1%",
|
|
152
|
-
"accent-foreground": "60 9.1% 97.8%",
|
|
153
|
-
destructive: "0 62.8% 30.6%",
|
|
154
|
-
"destructive-foreground": "60 9.1% 97.8%",
|
|
155
|
-
border: "12 6.5% 15.1%",
|
|
156
|
-
input: "12 6.5% 15.1%",
|
|
157
|
-
ring: "24 5.7% 82.9%"
|
|
19
|
+
var THEME_METADATA = {
|
|
20
|
+
slate: { name: "Slate", description: "Cool gray with strong blue undertones (default)" },
|
|
21
|
+
neutral: { name: "Neutral", description: "Pure gray, no undertones" },
|
|
22
|
+
stone: { name: "Stone", description: "Warm gray with brown undertones" },
|
|
23
|
+
zinc: { name: "Zinc", description: "Cool gray with subtle blue undertones" },
|
|
24
|
+
gray: { name: "Gray", description: "True neutral gray" }
|
|
25
|
+
};
|
|
26
|
+
var ThemeService = class {
|
|
27
|
+
registryThemesPath;
|
|
28
|
+
constructor() {
|
|
29
|
+
this.registryThemesPath = path.resolve(__dirname, "..", "src", "registry", "themes");
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Get list of available themes from registry/themes/v3/*.css (v3 as primary source)
|
|
33
|
+
*/
|
|
34
|
+
getAvailableThemes() {
|
|
35
|
+
const themes = [];
|
|
36
|
+
const v3Path = path.join(this.registryThemesPath, "v3");
|
|
37
|
+
if (!fs.existsSync(v3Path)) {
|
|
38
|
+
return themes;
|
|
158
39
|
}
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
"secondary-foreground": "240 5.9% 10%",
|
|
174
|
-
muted: "240 4.8% 95.9%",
|
|
175
|
-
"muted-foreground": "240 3.8% 46.1%",
|
|
176
|
-
accent: "240 4.8% 95.9%",
|
|
177
|
-
"accent-foreground": "240 5.9% 10%",
|
|
178
|
-
destructive: "0 84.2% 60.2%",
|
|
179
|
-
"destructive-foreground": "0 0% 98%",
|
|
180
|
-
border: "240 5.9% 90%",
|
|
181
|
-
input: "240 5.9% 90%",
|
|
182
|
-
ring: "240 10% 3.9%"
|
|
183
|
-
},
|
|
184
|
-
dark: {
|
|
185
|
-
background: "240 10% 3.9%",
|
|
186
|
-
foreground: "0 0% 98%",
|
|
187
|
-
card: "240 10% 3.9%",
|
|
188
|
-
"card-foreground": "0 0% 98%",
|
|
189
|
-
popover: "240 10% 3.9%",
|
|
190
|
-
"popover-foreground": "0 0% 98%",
|
|
191
|
-
primary: "0 0% 98%",
|
|
192
|
-
"primary-foreground": "240 5.9% 10%",
|
|
193
|
-
secondary: "240 3.7% 15.9%",
|
|
194
|
-
"secondary-foreground": "0 0% 98%",
|
|
195
|
-
muted: "240 3.7% 15.9%",
|
|
196
|
-
"muted-foreground": "240 5% 64.9%",
|
|
197
|
-
accent: "240 3.7% 15.9%",
|
|
198
|
-
"accent-foreground": "0 0% 98%",
|
|
199
|
-
destructive: "0 62.8% 30.6%",
|
|
200
|
-
"destructive-foreground": "0 0% 98%",
|
|
201
|
-
border: "240 3.7% 15.9%",
|
|
202
|
-
input: "240 3.7% 15.9%",
|
|
203
|
-
ring: "240 4.9% 83.9%"
|
|
40
|
+
const files = fs.readdirSync(v3Path);
|
|
41
|
+
for (const file of files) {
|
|
42
|
+
if (file.endsWith(".css")) {
|
|
43
|
+
const themeName = file.replace(".css", "");
|
|
44
|
+
const metadata = THEME_METADATA[themeName] || {
|
|
45
|
+
name: themeName.charAt(0).toUpperCase() + themeName.slice(1),
|
|
46
|
+
description: `${themeName} theme`
|
|
47
|
+
};
|
|
48
|
+
themes.push({
|
|
49
|
+
name: metadata.name,
|
|
50
|
+
description: metadata.description,
|
|
51
|
+
file
|
|
52
|
+
});
|
|
53
|
+
}
|
|
204
54
|
}
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
"popover-foreground": "224 71.4% 4.1%",
|
|
216
|
-
primary: "220.9 39.3% 11%",
|
|
217
|
-
"primary-foreground": "210 20% 98%",
|
|
218
|
-
secondary: "220 14.3% 95.9%",
|
|
219
|
-
"secondary-foreground": "220.9 39.3% 11%",
|
|
220
|
-
muted: "220 14.3% 95.9%",
|
|
221
|
-
"muted-foreground": "220 8.9% 46.1%",
|
|
222
|
-
accent: "220 14.3% 95.9%",
|
|
223
|
-
"accent-foreground": "220.9 39.3% 11%",
|
|
224
|
-
destructive: "0 84.2% 60.2%",
|
|
225
|
-
"destructive-foreground": "210 20% 98%",
|
|
226
|
-
border: "220 13% 91%",
|
|
227
|
-
input: "220 13% 91%",
|
|
228
|
-
ring: "224 71.4% 4.1%"
|
|
229
|
-
},
|
|
230
|
-
dark: {
|
|
231
|
-
background: "224 71.4% 4.1%",
|
|
232
|
-
foreground: "210 20% 98%",
|
|
233
|
-
card: "224 71.4% 4.1%",
|
|
234
|
-
"card-foreground": "210 20% 98%",
|
|
235
|
-
popover: "224 71.4% 4.1%",
|
|
236
|
-
"popover-foreground": "210 20% 98%",
|
|
237
|
-
primary: "210 20% 98%",
|
|
238
|
-
"primary-foreground": "220.9 39.3% 11%",
|
|
239
|
-
secondary: "215 27.9% 16.9%",
|
|
240
|
-
"secondary-foreground": "210 20% 98%",
|
|
241
|
-
muted: "215 27.9% 16.9%",
|
|
242
|
-
"muted-foreground": "217.9 10.6% 64.9%",
|
|
243
|
-
accent: "215 27.9% 16.9%",
|
|
244
|
-
"accent-foreground": "210 20% 98%",
|
|
245
|
-
destructive: "0 62.8% 30.6%",
|
|
246
|
-
"destructive-foreground": "210 20% 98%",
|
|
247
|
-
border: "215 27.9% 16.9%",
|
|
248
|
-
input: "215 27.9% 16.9%",
|
|
249
|
-
ring: "216 12.2% 83.9%"
|
|
55
|
+
return themes;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Get the complete CSS content for a theme from the appropriate v3 or v4 folder
|
|
59
|
+
*/
|
|
60
|
+
async getThemeCss(themeName, isTailwind4) {
|
|
61
|
+
const versionFolder = isTailwind4 ? "v4" : "v3";
|
|
62
|
+
const themeFilePath = path.join(this.registryThemesPath, versionFolder, `${themeName}.css`);
|
|
63
|
+
if (!fs.existsSync(themeFilePath)) {
|
|
64
|
+
throw new Error(`Theme file not found: ${themeFilePath}`);
|
|
250
65
|
}
|
|
66
|
+
const content = await fs.readFile(themeFilePath, "utf-8");
|
|
67
|
+
return content;
|
|
251
68
|
}
|
|
252
69
|
};
|
|
253
|
-
function generateCssVariablesV3(themeName) {
|
|
254
|
-
const theme = THEMES[themeName];
|
|
255
|
-
if (!theme) return "";
|
|
256
|
-
const lightVars = Object.entries(theme.light).map(([key, value]) => ` --${key}: ${value};`).join("\n");
|
|
257
|
-
const darkVars = Object.entries(theme.dark).map(([key, value]) => ` --${key}: ${value};`).join("\n");
|
|
258
|
-
return `@tailwind base;
|
|
259
|
-
@tailwind components;
|
|
260
|
-
@tailwind utilities;
|
|
261
70
|
|
|
262
|
-
|
|
263
|
-
:root {
|
|
264
|
-
${lightVars}
|
|
265
|
-
--radius: 0.5rem;
|
|
266
|
-
--sidebar-width: 16rem;
|
|
267
|
-
--sidebar-width-mobile: 18rem;
|
|
268
|
-
--sidebar-width-collapsed: 3rem;
|
|
269
|
-
--sidebar-width-icon: 3rem;
|
|
270
|
-
--header-height: 3.5rem;
|
|
271
|
-
--sidebar-background: 0 0% 98%;
|
|
272
|
-
--sidebar-foreground: 240 5.3% 26.1%;
|
|
273
|
-
--sidebar-primary: 240 5.9% 10%;
|
|
274
|
-
--sidebar-primary-foreground: 0 0% 98%;
|
|
275
|
-
--sidebar-accent: 240 4.8% 95.9%;
|
|
276
|
-
--sidebar-accent-foreground: 240 5.9% 10%;
|
|
277
|
-
--sidebar-border: 220 13% 91%;
|
|
278
|
-
--sidebar-ring: 217.2 91.2% 59.8%;
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
.dark {
|
|
282
|
-
${darkVars}
|
|
283
|
-
--sidebar-background: 240 5.9% 10%;
|
|
284
|
-
--sidebar-foreground: 240 4.8% 95.9%;
|
|
285
|
-
--sidebar-primary: 224.3 76.3% 48%;
|
|
286
|
-
--sidebar-primary-foreground: 0 0% 100%;
|
|
287
|
-
--sidebar-accent: 240 3.7% 15.9%;
|
|
288
|
-
--sidebar-accent-foreground: 240 4.8% 95.9%;
|
|
289
|
-
--sidebar-border: 240 3.7% 15.9%;
|
|
290
|
-
--sidebar-ring: 217.2 91.2% 59.8%;
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
@layer base {
|
|
295
|
-
* {
|
|
296
|
-
@apply border-border;
|
|
297
|
-
}
|
|
298
|
-
body {
|
|
299
|
-
@apply bg-background text-foreground;
|
|
300
|
-
}
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
@layer utilities {
|
|
304
|
-
@keyframes accordion-down {
|
|
305
|
-
from { height: 0; }
|
|
306
|
-
to { height: var(--radix-accordion-content-height); }
|
|
307
|
-
}
|
|
308
|
-
@keyframes accordion-up {
|
|
309
|
-
from { height: var(--radix-accordion-content-height); }
|
|
310
|
-
to { height: 0; }
|
|
311
|
-
}
|
|
312
|
-
.animate-accordion-down {
|
|
313
|
-
animation: accordion-down 0.2s ease-out;
|
|
314
|
-
}
|
|
315
|
-
.animate-accordion-up {
|
|
316
|
-
animation: accordion-up 0.2s ease-out;
|
|
317
|
-
}
|
|
318
|
-
}
|
|
319
|
-
`;
|
|
320
|
-
}
|
|
321
|
-
function generateCssVariablesV4(themeName) {
|
|
322
|
-
const theme = THEMES[themeName];
|
|
323
|
-
if (!theme) return "";
|
|
324
|
-
const lightVars = Object.entries(theme.light).map(([key, value]) => ` --${key}: ${value};`).join("\n");
|
|
325
|
-
const darkVars = Object.entries(theme.dark).map(([key, value]) => ` --${key}: ${value};`).join("\n");
|
|
326
|
-
const lightVarsHsl = Object.entries(theme.light).map(([key, value]) => ` --${key}: hsl(${value});`).join("\n");
|
|
327
|
-
const darkVarsHsl = Object.entries(theme.dark).map(([key, value]) => ` --${key}: hsl(${value});`).join("\n");
|
|
328
|
-
return `@import "tailwindcss";
|
|
329
|
-
|
|
330
|
-
:root {
|
|
331
|
-
${lightVarsHsl}
|
|
332
|
-
--radius: 0.5rem;
|
|
333
|
-
--sidebar-width: 16rem;
|
|
334
|
-
--sidebar-width-mobile: 18rem;
|
|
335
|
-
--sidebar-width-collapsed: 3rem;
|
|
336
|
-
--sidebar-width-icon: 3rem;
|
|
337
|
-
--header-height: 3.5rem;
|
|
338
|
-
--sidebar-background: 0 0% 98%;
|
|
339
|
-
--sidebar-foreground: 240 5.3% 26.1%;
|
|
340
|
-
--sidebar-primary: 240 5.9% 10%;
|
|
341
|
-
--sidebar-primary-foreground: 0 0% 98%;
|
|
342
|
-
--sidebar-accent: 240 4.8% 95.9%;
|
|
343
|
-
--sidebar-accent-foreground: 240 5.9% 10%;
|
|
344
|
-
--sidebar-border: 220 13% 91%;
|
|
345
|
-
--sidebar-ring: 217.2 91.2% 59.8%;
|
|
346
|
-
}
|
|
347
|
-
|
|
348
|
-
@theme inline {
|
|
349
|
-
--color-border: var(--border);
|
|
350
|
-
--color-input: var(--input);
|
|
351
|
-
--color-ring: var(--ring);
|
|
352
|
-
--color-background: var(--background);
|
|
353
|
-
--color-foreground: var(--foreground);
|
|
354
|
-
|
|
355
|
-
--color-primary: var(--primary);
|
|
356
|
-
--color-primary-foreground: var(--primary-foreground);
|
|
357
|
-
|
|
358
|
-
--color-secondary: var(--secondary);
|
|
359
|
-
--color-secondary-foreground: var(--secondary-foreground);
|
|
360
|
-
|
|
361
|
-
--color-destructive: var(--destructive);
|
|
362
|
-
--color-destructive-foreground: var(--destructive-foreground);
|
|
363
|
-
|
|
364
|
-
--color-muted: var(--muted);
|
|
365
|
-
--color-muted-foreground: var(--muted-foreground);
|
|
366
|
-
|
|
367
|
-
--color-accent: var(--accent);
|
|
368
|
-
--color-accent-foreground: var(--accent-foreground);
|
|
369
|
-
|
|
370
|
-
--color-popover: var(--popover);
|
|
371
|
-
--color-popover-foreground: var(--popover-foreground);
|
|
372
|
-
|
|
373
|
-
--color-card: var(--card);
|
|
374
|
-
--color-card-foreground: var(--card-foreground);
|
|
375
|
-
|
|
376
|
-
--color-sidebar: var(--sidebar-background);
|
|
377
|
-
--color-sidebar-foreground: var(--sidebar-foreground);
|
|
378
|
-
--color-sidebar-primary: var(--sidebar-primary);
|
|
379
|
-
--color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
|
|
380
|
-
--color-sidebar-accent: var(--sidebar-accent);
|
|
381
|
-
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
|
|
382
|
-
--color-sidebar-border: var(--sidebar-border);
|
|
383
|
-
--color-sidebar-ring: var(--sidebar-ring);
|
|
384
|
-
|
|
385
|
-
--radius-lg: var(--radius);
|
|
386
|
-
--radius-md: calc(var(--radius) - 2px);
|
|
387
|
-
--radius-sm: calc(var(--radius) - 4px);
|
|
388
|
-
|
|
389
|
-
/* Accordion Animations */
|
|
390
|
-
--animate-accordion-down: accordion-down 0.2s ease-out;
|
|
391
|
-
--animate-accordion-up: accordion-up 0.2s ease-out;
|
|
392
|
-
|
|
393
|
-
@keyframes accordion-down {
|
|
394
|
-
from { height: 0; }
|
|
395
|
-
to { height: var(--radix-accordion-content-height); }
|
|
396
|
-
}
|
|
397
|
-
@keyframes accordion-up {
|
|
398
|
-
from { height: var(--radix-accordion-content-height); }
|
|
399
|
-
to { height: 0; }
|
|
400
|
-
}
|
|
401
|
-
}
|
|
402
|
-
|
|
403
|
-
@media (prefers-color-scheme: dark) {
|
|
404
|
-
:root {
|
|
405
|
-
${darkVarsHsl}
|
|
406
|
-
--sidebar-background: 240 5.9% 10%;
|
|
407
|
-
--sidebar-foreground: 240 4.8% 95.9%;
|
|
408
|
-
--sidebar-primary: 224.3 76.3% 48%;
|
|
409
|
-
--sidebar-primary-foreground: 0 0% 100%;
|
|
410
|
-
--sidebar-accent: 240 3.7% 15.9%;
|
|
411
|
-
--sidebar-accent-foreground: 240 4.8% 95.9%;
|
|
412
|
-
--sidebar-border: 240 3.7% 15.9%;
|
|
413
|
-
--sidebar-ring: 217.2 91.2% 59.8%;
|
|
414
|
-
}
|
|
415
|
-
}
|
|
416
|
-
|
|
417
|
-
body {
|
|
418
|
-
background: var(--background);
|
|
419
|
-
color: var(--foreground);
|
|
420
|
-
font-family: Arial, Helvetica, sans-serif;
|
|
421
|
-
}
|
|
422
|
-
`;
|
|
423
|
-
}
|
|
71
|
+
// src/cli/utils/templates.ts
|
|
424
72
|
var TAILWIND_CONFIG = `import type { Config } from "tailwindcss"
|
|
425
73
|
|
|
426
74
|
const config: Config = {
|
|
@@ -493,473 +141,614 @@ const config: Config = {
|
|
|
493
141
|
|
|
494
142
|
export default config
|
|
495
143
|
`;
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
const
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
const packageManager = isPnpm ? "pnpm" : isYarn ? "yarn" : isBun ? "bun" : "npm";
|
|
503
|
-
const installCmd = isPnpm ? "add" : isYarn ? "add" : isBun ? "add" : "install";
|
|
504
|
-
console.log(chalk.cyan("\n\u{1F680} Initializing @srcroot/ui...\n"));
|
|
505
|
-
const packageJsonPath = path.join(cwd, "package.json");
|
|
506
|
-
if (!fs.existsSync(packageJsonPath)) {
|
|
507
|
-
console.log(chalk.red("Error: No package.json found. Please run this in a project directory."));
|
|
508
|
-
process.exit(1);
|
|
144
|
+
|
|
145
|
+
// src/cli/utils/get-package-manager.ts
|
|
146
|
+
function getPackageManager() {
|
|
147
|
+
const userAgent = process.env.npm_config_user_agent;
|
|
148
|
+
if (!userAgent) {
|
|
149
|
+
return "npm";
|
|
509
150
|
}
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
151
|
+
if (userAgent.startsWith("yarn")) {
|
|
152
|
+
return "yarn";
|
|
153
|
+
}
|
|
154
|
+
if (userAgent.startsWith("pnpm")) {
|
|
155
|
+
return "pnpm";
|
|
156
|
+
}
|
|
157
|
+
if (userAgent.startsWith("bun")) {
|
|
158
|
+
return "bun";
|
|
159
|
+
}
|
|
160
|
+
return "npm";
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// src/cli/utils/logger.ts
|
|
164
|
+
import chalk from "chalk";
|
|
165
|
+
var logger = {
|
|
166
|
+
error(...args) {
|
|
167
|
+
console.log(chalk.red(...args));
|
|
168
|
+
},
|
|
169
|
+
warn(...args) {
|
|
170
|
+
console.log(chalk.yellow(...args));
|
|
171
|
+
},
|
|
172
|
+
info(...args) {
|
|
173
|
+
console.log(chalk.cyan(...args));
|
|
174
|
+
},
|
|
175
|
+
success(...args) {
|
|
176
|
+
console.log(chalk.green(...args));
|
|
177
|
+
}
|
|
178
|
+
};
|
|
179
|
+
|
|
180
|
+
// src/cli/services/project-initializer.ts
|
|
181
|
+
var __dirname3 = path2.dirname(fileURLToPath2(import.meta.url));
|
|
182
|
+
var ProjectInitializer = class {
|
|
183
|
+
options;
|
|
184
|
+
config = {};
|
|
185
|
+
themeService;
|
|
186
|
+
constructor(options) {
|
|
187
|
+
this.options = options;
|
|
188
|
+
this.themeService = new ThemeService();
|
|
189
|
+
}
|
|
190
|
+
async run() {
|
|
191
|
+
logger.info("\n\u{1F680} Initializing @srcroot/ui...\n");
|
|
192
|
+
await this.validateEnvironment();
|
|
193
|
+
await this.detectConfiguration();
|
|
194
|
+
await this.promptUser();
|
|
195
|
+
await this.scaffold();
|
|
196
|
+
this.printSuccess();
|
|
197
|
+
}
|
|
198
|
+
async validateEnvironment() {
|
|
199
|
+
const cwd = path2.resolve(this.options.cwd);
|
|
200
|
+
const packageJsonPath = path2.join(cwd, "package.json");
|
|
201
|
+
if (!fs2.existsSync(packageJsonPath)) {
|
|
202
|
+
logger.error("Error: No package.json found. Please run this in a project directory.");
|
|
203
|
+
process.exit(1);
|
|
530
204
|
}
|
|
531
|
-
|
|
532
|
-
const
|
|
533
|
-
if (
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
205
|
+
const pkg = await fs2.readJson(packageJsonPath);
|
|
206
|
+
const allDeps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
207
|
+
if (!allDeps["react"]) {
|
|
208
|
+
logger.error("Error: React not found in dependencies. Please initialize this in a React project.");
|
|
209
|
+
process.exit(1);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
async detectConfiguration() {
|
|
213
|
+
const cwd = path2.resolve(this.options.cwd);
|
|
214
|
+
const packageManager = getPackageManager();
|
|
215
|
+
const installCmd = packageManager === "npm" ? "install" : "add";
|
|
216
|
+
const pkg = await fs2.readJson(path2.join(cwd, "package.json"));
|
|
217
|
+
const allDeps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
218
|
+
const tailwindVersion = allDeps["tailwindcss"] || "";
|
|
219
|
+
const isTailwind4 = tailwindVersion.includes("^4") || tailwindVersion.startsWith("4") || allDeps["@tailwindcss/postcss"];
|
|
220
|
+
const hasSrc = fs2.existsSync(path2.join(cwd, "src"));
|
|
221
|
+
const srcPath = hasSrc ? path2.join(cwd, "src") : cwd;
|
|
222
|
+
const appPath = path2.join(srcPath, "app");
|
|
223
|
+
const pagesPath = path2.join(srcPath, "pages");
|
|
224
|
+
const hasAppDir = fs2.existsSync(appPath);
|
|
225
|
+
const hasPagesDir = fs2.existsSync(pagesPath);
|
|
226
|
+
const libDir = path2.join(srcPath, "lib");
|
|
227
|
+
const componentsDir = path2.join(srcPath, "components", "ui");
|
|
228
|
+
let globalsPath = "";
|
|
229
|
+
if (hasAppDir) {
|
|
230
|
+
if (fs2.existsSync(path2.join(appPath, "globals.css"))) globalsPath = path2.join(appPath, "globals.css");
|
|
231
|
+
else if (fs2.existsSync(path2.join(appPath, "global.css"))) globalsPath = path2.join(appPath, "global.css");
|
|
232
|
+
else globalsPath = path2.join(appPath, "globals.css");
|
|
233
|
+
} else if (hasPagesDir) {
|
|
234
|
+
const stylesPath = path2.join(srcPath, "styles");
|
|
235
|
+
if (fs2.existsSync(path2.join(stylesPath, "globals.css"))) globalsPath = path2.join(stylesPath, "globals.css");
|
|
236
|
+
else if (fs2.existsSync(path2.join(stylesPath, "global.css"))) globalsPath = path2.join(stylesPath, "global.css");
|
|
237
|
+
else globalsPath = path2.join(stylesPath, "globals.css");
|
|
537
238
|
} else {
|
|
538
|
-
globalsPath =
|
|
239
|
+
globalsPath = path2.join(srcPath, "globals.css");
|
|
539
240
|
}
|
|
540
|
-
|
|
541
|
-
|
|
241
|
+
this.config = {
|
|
242
|
+
cwd,
|
|
243
|
+
packageManager,
|
|
244
|
+
installCmd,
|
|
245
|
+
isTailwind4,
|
|
246
|
+
hasSrc,
|
|
247
|
+
srcPath,
|
|
248
|
+
appPath,
|
|
249
|
+
pagesPath,
|
|
250
|
+
hasAppDir,
|
|
251
|
+
hasPagesDir,
|
|
252
|
+
libDir,
|
|
253
|
+
componentsDir,
|
|
254
|
+
globalsPath
|
|
255
|
+
};
|
|
542
256
|
}
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
257
|
+
async promptUser() {
|
|
258
|
+
let selectedTheme = this.options.theme || "slate";
|
|
259
|
+
if (!this.options.yes && !this.options.theme) {
|
|
260
|
+
const availableThemes = this.themeService.getAvailableThemes();
|
|
261
|
+
if (availableThemes.length === 0) {
|
|
262
|
+
logger.warn("Warning: No themes found in registry. Using default.");
|
|
263
|
+
this.config.selectedTheme = selectedTheme;
|
|
264
|
+
return;
|
|
265
|
+
}
|
|
266
|
+
const themeChoices = availableThemes.map((theme) => ({
|
|
267
|
+
title: `${theme.name} - ${theme.description}`,
|
|
268
|
+
value: theme.file.replace(".css", "")
|
|
269
|
+
}));
|
|
270
|
+
const themeResponse = await prompts({
|
|
271
|
+
type: "select",
|
|
272
|
+
name: "theme",
|
|
273
|
+
message: "Which color theme would you like to use?",
|
|
274
|
+
choices: themeChoices,
|
|
275
|
+
initial: 0
|
|
276
|
+
});
|
|
277
|
+
if (themeResponse.theme) {
|
|
278
|
+
selectedTheme = themeResponse.theme;
|
|
279
|
+
}
|
|
559
280
|
}
|
|
281
|
+
this.config.selectedTheme = selectedTheme;
|
|
560
282
|
}
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
283
|
+
async scaffold() {
|
|
284
|
+
const spinner = ora("Creating project structure...").start();
|
|
285
|
+
const cfg = this.config;
|
|
286
|
+
try {
|
|
287
|
+
await fs2.ensureDir(cfg.libDir);
|
|
288
|
+
await fs2.ensureDir(cfg.componentsDir);
|
|
289
|
+
const utilsPath = path2.join(cfg.libDir, "utils.ts");
|
|
290
|
+
const registryUtilsPath = path2.resolve(__dirname3, "..", "src", "registry", "lib", "utils.ts");
|
|
291
|
+
let utilsContent = "";
|
|
292
|
+
if (fs2.existsSync(registryUtilsPath)) {
|
|
293
|
+
utilsContent = await fs2.readFile(registryUtilsPath, "utf-8");
|
|
294
|
+
} else {
|
|
295
|
+
utilsContent = `import { type ClassValue, clsx } from "clsx"
|
|
296
|
+
import { twMerge } from "tailwind-merge"
|
|
297
|
+
|
|
298
|
+
export function cn(...inputs: ClassValue[]) {
|
|
299
|
+
return twMerge(clsx(inputs))
|
|
300
|
+
}
|
|
301
|
+
`;
|
|
302
|
+
spinner.warn(`Could not find registry/utils.ts, using fallback content.`);
|
|
303
|
+
}
|
|
304
|
+
await fs2.writeFile(utilsPath, utilsContent);
|
|
305
|
+
spinner.succeed(`Created ${path2.relative(cfg.cwd, utilsPath)}`);
|
|
306
|
+
spinner.start(`Setting up ${cfg.selectedTheme} theme...`);
|
|
307
|
+
const stylesDir = path2.dirname(cfg.globalsPath);
|
|
308
|
+
await fs2.ensureDir(stylesDir);
|
|
309
|
+
try {
|
|
310
|
+
const cssContent = await this.themeService.getThemeCss(cfg.selectedTheme, cfg.isTailwind4);
|
|
311
|
+
await fs2.writeFile(cfg.globalsPath, cssContent);
|
|
312
|
+
spinner.succeed(`Updated ${path2.relative(cfg.cwd, cfg.globalsPath)} with ${cfg.selectedTheme} theme (${cfg.isTailwind4 ? "Tailwind 4" : "Tailwind 3"})`);
|
|
313
|
+
} catch (error) {
|
|
314
|
+
spinner.fail(`Failed to load theme: ${cfg.selectedTheme}`);
|
|
315
|
+
console.error(error);
|
|
316
|
+
process.exit(1);
|
|
317
|
+
}
|
|
318
|
+
if (!cfg.isTailwind4) {
|
|
319
|
+
spinner.start("Setting up Tailwind config...");
|
|
320
|
+
const tailwindConfigPath = path2.join(cfg.cwd, "tailwind.config.ts");
|
|
321
|
+
await fs2.writeFile(tailwindConfigPath, TAILWIND_CONFIG);
|
|
322
|
+
spinner.succeed(`Created tailwind.config.ts`);
|
|
323
|
+
} else {
|
|
324
|
+
spinner.info(`Tailwind 4 detected - skipping tailwind.config.ts`);
|
|
325
|
+
}
|
|
326
|
+
} catch (error) {
|
|
327
|
+
spinner.fail("Failed to initialize project");
|
|
328
|
+
console.error(error);
|
|
329
|
+
process.exit(1);
|
|
581
330
|
}
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
331
|
+
}
|
|
332
|
+
printSuccess() {
|
|
333
|
+
const cfg = this.config;
|
|
334
|
+
logger.success("\n\u2705 Project initialized successfully!\n");
|
|
335
|
+
console.log(`Theme: ${cfg.selectedTheme}`);
|
|
336
|
+
console.log(`Tailwind: ${cfg.isTailwind4 ? "v4" : "v3"}`);
|
|
585
337
|
const requiredDeps = [
|
|
586
338
|
"clsx",
|
|
587
339
|
"tailwind-merge",
|
|
588
340
|
"class-variance-authority",
|
|
589
341
|
"react-icons"
|
|
590
342
|
];
|
|
591
|
-
if (!isTailwind4) {
|
|
343
|
+
if (!cfg.isTailwind4) {
|
|
592
344
|
requiredDeps.push("tailwindcss-animate");
|
|
593
345
|
}
|
|
594
|
-
|
|
595
|
-
console.log(
|
|
346
|
+
logger.info("\n\u{1F4E6} Required dependencies:");
|
|
347
|
+
console.log(` ${cfg.packageManager} ${cfg.installCmd} ${requiredDeps.join(" ")}`);
|
|
596
348
|
console.log("\n\u2728 Next steps:");
|
|
597
|
-
console.log(
|
|
598
|
-
console.log(
|
|
599
|
-
console.log(
|
|
349
|
+
console.log(" 1. Install dependencies (command above)");
|
|
350
|
+
console.log(" 2. npx @srcroot/ui add button");
|
|
351
|
+
console.log(" 3. npx @srcroot/ui add --all");
|
|
600
352
|
console.log();
|
|
601
|
-
} catch (error) {
|
|
602
|
-
spinner.fail("Failed to initialize project");
|
|
603
|
-
console.error(error);
|
|
604
|
-
process.exit(1);
|
|
605
353
|
}
|
|
354
|
+
};
|
|
355
|
+
|
|
356
|
+
// src/cli/commands/init.ts
|
|
357
|
+
async function init(options) {
|
|
358
|
+
const initializer = new ProjectInitializer(options);
|
|
359
|
+
await initializer.run();
|
|
606
360
|
}
|
|
607
361
|
|
|
608
362
|
// src/cli/commands/add.ts
|
|
609
|
-
import
|
|
610
|
-
import
|
|
611
|
-
import chalk2 from "chalk";
|
|
363
|
+
import fs3 from "fs-extra";
|
|
364
|
+
import path3 from "path";
|
|
612
365
|
import ora2 from "ora";
|
|
613
366
|
import prompts2 from "prompts";
|
|
614
|
-
import { fileURLToPath as
|
|
367
|
+
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
615
368
|
|
|
616
369
|
// src/cli/registry.ts
|
|
617
370
|
var REGISTRY = {
|
|
618
371
|
// Core
|
|
619
372
|
button: {
|
|
620
|
-
file: "button.tsx",
|
|
373
|
+
file: "ui/button.tsx",
|
|
621
374
|
description: "Polymorphic button with variants",
|
|
622
375
|
category: "Core",
|
|
623
376
|
dependencies: []
|
|
624
377
|
},
|
|
625
378
|
badge: {
|
|
626
|
-
file: "badge.tsx",
|
|
379
|
+
file: "ui/badge.tsx",
|
|
627
380
|
description: "Status indicator",
|
|
628
381
|
category: "Core",
|
|
629
382
|
dependencies: []
|
|
630
383
|
},
|
|
631
384
|
avatar: {
|
|
632
|
-
file: "avatar.tsx",
|
|
385
|
+
file: "ui/avatar.tsx",
|
|
633
386
|
description: "User avatar with fallback",
|
|
634
387
|
category: "Core",
|
|
635
388
|
dependencies: []
|
|
636
389
|
},
|
|
637
390
|
separator: {
|
|
638
|
-
file: "separator.tsx",
|
|
391
|
+
file: "ui/separator.tsx",
|
|
639
392
|
description: "Visual divider",
|
|
640
393
|
category: "Core",
|
|
641
394
|
dependencies: []
|
|
642
395
|
},
|
|
643
396
|
// Typography
|
|
644
397
|
text: {
|
|
645
|
-
file: "text.tsx",
|
|
398
|
+
file: "ui/text.tsx",
|
|
646
399
|
description: "Polymorphic typography",
|
|
647
400
|
category: "Typography",
|
|
648
401
|
dependencies: []
|
|
649
402
|
},
|
|
650
403
|
label: {
|
|
651
|
-
file: "label.tsx",
|
|
404
|
+
file: "ui/label.tsx",
|
|
652
405
|
description: "Form label",
|
|
653
406
|
category: "Typography",
|
|
654
407
|
dependencies: []
|
|
655
408
|
},
|
|
656
409
|
// Forms
|
|
657
410
|
input: {
|
|
658
|
-
file: "input.tsx",
|
|
411
|
+
file: "ui/input.tsx",
|
|
659
412
|
description: "Text input field",
|
|
660
413
|
category: "Forms",
|
|
661
414
|
dependencies: []
|
|
662
415
|
},
|
|
663
416
|
textarea: {
|
|
664
|
-
file: "textarea.tsx",
|
|
417
|
+
file: "ui/textarea.tsx",
|
|
665
418
|
description: "Multi-line text input",
|
|
666
419
|
category: "Forms",
|
|
667
420
|
dependencies: []
|
|
668
421
|
},
|
|
669
422
|
checkbox: {
|
|
670
|
-
file: "checkbox.tsx",
|
|
423
|
+
file: "ui/checkbox.tsx",
|
|
671
424
|
description: "Checkbox input",
|
|
672
425
|
category: "Forms",
|
|
673
426
|
dependencies: []
|
|
674
427
|
},
|
|
675
428
|
radio: {
|
|
676
|
-
file: "radio.tsx",
|
|
429
|
+
file: "ui/radio.tsx",
|
|
677
430
|
description: "Radio button group",
|
|
678
431
|
category: "Forms",
|
|
679
432
|
dependencies: []
|
|
680
433
|
},
|
|
681
434
|
switch: {
|
|
682
|
-
file: "switch.tsx",
|
|
435
|
+
file: "ui/switch.tsx",
|
|
683
436
|
description: "Toggle switch",
|
|
684
437
|
category: "Forms",
|
|
685
438
|
dependencies: []
|
|
686
439
|
},
|
|
687
440
|
slider: {
|
|
688
|
-
file: "slider.tsx",
|
|
441
|
+
file: "ui/slider.tsx",
|
|
689
442
|
description: "Range slider",
|
|
690
443
|
category: "Forms",
|
|
691
444
|
dependencies: []
|
|
692
445
|
},
|
|
693
446
|
select: {
|
|
694
|
-
file: "select.tsx",
|
|
447
|
+
file: "ui/select.tsx",
|
|
695
448
|
description: "Custom select dropdown",
|
|
696
449
|
category: "Forms",
|
|
697
450
|
dependencies: []
|
|
698
451
|
},
|
|
699
452
|
// Layout
|
|
700
453
|
card: {
|
|
701
|
-
file: "card.tsx",
|
|
454
|
+
file: "ui/card.tsx",
|
|
702
455
|
description: "Card container",
|
|
703
456
|
category: "Layout",
|
|
704
457
|
dependencies: []
|
|
705
458
|
},
|
|
706
459
|
container: {
|
|
707
|
-
file: "container.tsx",
|
|
460
|
+
file: "ui/container.tsx",
|
|
708
461
|
description: "Max-width container",
|
|
709
462
|
category: "Layout",
|
|
710
463
|
dependencies: []
|
|
711
464
|
},
|
|
712
465
|
"aspect-ratio": {
|
|
713
|
-
file: "aspect-ratio.tsx",
|
|
466
|
+
file: "ui/aspect-ratio.tsx",
|
|
714
467
|
description: "Maintain aspect ratio",
|
|
715
468
|
category: "Layout",
|
|
716
469
|
dependencies: []
|
|
717
470
|
},
|
|
718
471
|
// Data Display
|
|
719
472
|
accordion: {
|
|
720
|
-
file: "accordion.tsx",
|
|
473
|
+
file: "ui/accordion.tsx",
|
|
721
474
|
description: "Expandable sections",
|
|
722
475
|
category: "Data Display",
|
|
723
476
|
dependencies: []
|
|
724
477
|
},
|
|
725
478
|
tabs: {
|
|
726
|
-
file: "tabs.tsx",
|
|
479
|
+
file: "ui/tabs.tsx",
|
|
727
480
|
description: "Tab navigation",
|
|
728
481
|
category: "Data Display",
|
|
729
482
|
dependencies: []
|
|
730
483
|
},
|
|
731
484
|
table: {
|
|
732
|
-
file: "table.tsx",
|
|
485
|
+
file: "ui/table.tsx",
|
|
733
486
|
description: "Data table",
|
|
734
487
|
category: "Data Display",
|
|
735
488
|
dependencies: []
|
|
736
489
|
},
|
|
737
490
|
progress: {
|
|
738
|
-
file: "progress.tsx",
|
|
491
|
+
file: "ui/progress.tsx",
|
|
739
492
|
description: "Progress indicator",
|
|
740
493
|
category: "Data Display",
|
|
741
494
|
dependencies: []
|
|
742
495
|
},
|
|
743
496
|
skeleton: {
|
|
744
|
-
file: "skeleton.tsx",
|
|
497
|
+
file: "ui/skeleton.tsx",
|
|
745
498
|
description: "Loading placeholder",
|
|
746
499
|
category: "Data Display",
|
|
747
500
|
dependencies: []
|
|
748
501
|
},
|
|
749
502
|
// Overlay / Feedback
|
|
750
503
|
dialog: {
|
|
751
|
-
file: "dialog.tsx",
|
|
504
|
+
file: "ui/dialog.tsx",
|
|
752
505
|
description: "Modal dialog",
|
|
753
506
|
category: "Overlay / Feedback",
|
|
754
507
|
dependencies: []
|
|
755
508
|
},
|
|
756
509
|
"alert-dialog": {
|
|
757
|
-
file: "alert-dialog.tsx",
|
|
510
|
+
file: "ui/alert-dialog.tsx",
|
|
758
511
|
description: "Confirmation dialog",
|
|
759
512
|
category: "Overlay / Feedback",
|
|
760
513
|
dependencies: ["dialog"]
|
|
761
514
|
},
|
|
762
515
|
sheet: {
|
|
763
|
-
file: "sheet.tsx",
|
|
516
|
+
file: "ui/sheet.tsx",
|
|
764
517
|
description: "Slide-in panel",
|
|
765
518
|
category: "Overlay / Feedback",
|
|
766
519
|
dependencies: []
|
|
767
520
|
},
|
|
768
521
|
popover: {
|
|
769
|
-
file: "popover.tsx",
|
|
522
|
+
file: "ui/popover.tsx",
|
|
770
523
|
description: "Floating content",
|
|
771
524
|
category: "Overlay / Feedback",
|
|
772
525
|
dependencies: []
|
|
773
526
|
},
|
|
774
527
|
tooltip: {
|
|
775
|
-
file: "tooltip.tsx",
|
|
528
|
+
file: "ui/tooltip.tsx",
|
|
776
529
|
description: "Hover tooltip",
|
|
777
530
|
category: "Overlay / Feedback",
|
|
778
531
|
dependencies: []
|
|
779
532
|
},
|
|
780
533
|
"dropdown-menu": {
|
|
781
|
-
file: "dropdown-menu.tsx",
|
|
534
|
+
file: "ui/dropdown-menu.tsx",
|
|
782
535
|
description: "Action dropdown",
|
|
783
536
|
category: "Overlay / Feedback",
|
|
784
537
|
dependencies: []
|
|
785
538
|
},
|
|
786
539
|
toast: {
|
|
787
|
-
file: "toast.tsx",
|
|
540
|
+
file: "ui/toast.tsx",
|
|
788
541
|
description: "Notification toast",
|
|
789
542
|
category: "Overlay / Feedback",
|
|
790
543
|
dependencies: []
|
|
791
544
|
},
|
|
792
545
|
alert: {
|
|
793
|
-
file: "alert.tsx",
|
|
546
|
+
file: "ui/alert.tsx",
|
|
794
547
|
description: "Inline alert",
|
|
795
548
|
category: "Overlay / Feedback",
|
|
796
549
|
dependencies: []
|
|
797
550
|
},
|
|
798
551
|
// Navigation
|
|
799
552
|
breadcrumb: {
|
|
800
|
-
file: "breadcrumb.tsx",
|
|
553
|
+
file: "ui/breadcrumb.tsx",
|
|
801
554
|
description: "Breadcrumb navigation",
|
|
802
555
|
category: "Navigation",
|
|
803
556
|
dependencies: []
|
|
804
557
|
},
|
|
805
558
|
pagination: {
|
|
806
|
-
file: "pagination.tsx",
|
|
559
|
+
file: "ui/pagination.tsx",
|
|
807
560
|
description: "Page navigation",
|
|
808
561
|
category: "Navigation",
|
|
809
562
|
dependencies: ["button"]
|
|
810
563
|
},
|
|
811
564
|
// New Components
|
|
812
565
|
"loading-spinner": {
|
|
813
|
-
file: "loading-spinner.tsx",
|
|
566
|
+
file: "ui/loading-spinner.tsx",
|
|
814
567
|
description: "Loading spinner with variants",
|
|
815
568
|
category: "Feedback",
|
|
816
569
|
dependencies: []
|
|
817
570
|
},
|
|
818
571
|
image: {
|
|
819
|
-
file: "image.tsx",
|
|
572
|
+
file: "ui/image.tsx",
|
|
820
573
|
description: "Enhanced image with loading",
|
|
821
574
|
category: "Data Display",
|
|
822
575
|
dependencies: []
|
|
823
576
|
},
|
|
824
577
|
"button-group": {
|
|
825
|
-
file: "button-group.tsx",
|
|
578
|
+
file: "ui/button-group.tsx",
|
|
826
579
|
description: "Group buttons together",
|
|
827
580
|
category: "Core",
|
|
828
581
|
dependencies: ["button"]
|
|
829
582
|
},
|
|
830
583
|
"otp-input": {
|
|
831
|
-
file: "otp-input.tsx",
|
|
584
|
+
file: "ui/otp-input.tsx",
|
|
832
585
|
description: "OTP verification input",
|
|
833
586
|
category: "Forms",
|
|
834
587
|
dependencies: []
|
|
835
588
|
},
|
|
836
589
|
search: {
|
|
837
|
-
file: "search.tsx",
|
|
590
|
+
file: "ui/search.tsx",
|
|
838
591
|
description: "Search input with debounce",
|
|
839
592
|
category: "Forms",
|
|
840
593
|
dependencies: []
|
|
841
594
|
},
|
|
842
595
|
"star-rating": {
|
|
843
|
-
file: "star-rating.tsx",
|
|
596
|
+
file: "ui/star-rating.tsx",
|
|
844
597
|
description: "Star rating input",
|
|
845
598
|
category: "Feedback",
|
|
846
599
|
dependencies: []
|
|
847
600
|
},
|
|
848
601
|
collapsible: {
|
|
849
|
-
file: "collapsible.tsx",
|
|
602
|
+
file: "ui/collapsible.tsx",
|
|
850
603
|
description: "Expandable section",
|
|
851
604
|
category: "Data Display",
|
|
852
605
|
dependencies: []
|
|
853
606
|
},
|
|
854
607
|
carousel: {
|
|
855
|
-
file: "carousel.tsx",
|
|
608
|
+
file: "ui/carousel.tsx",
|
|
856
609
|
description: "Image/content slider",
|
|
857
610
|
category: "Data Display",
|
|
858
611
|
dependencies: []
|
|
859
612
|
},
|
|
860
613
|
calendar: {
|
|
861
|
-
file: "calendar.tsx",
|
|
614
|
+
file: "ui/calendar.tsx",
|
|
862
615
|
description: "Date picker",
|
|
863
616
|
category: "Forms",
|
|
864
617
|
dependencies: []
|
|
865
618
|
},
|
|
866
619
|
sidebar: {
|
|
867
|
-
file: "sidebar.tsx",
|
|
620
|
+
file: "ui/sidebar.tsx",
|
|
868
621
|
description: "Responsive sidebar with mobile drawer",
|
|
869
622
|
category: "Layout",
|
|
870
623
|
dependencies: ["sheet", "button"]
|
|
871
624
|
},
|
|
872
625
|
// Added Components
|
|
873
626
|
combobox: {
|
|
874
|
-
file: "combobox.tsx",
|
|
627
|
+
file: "ui/combobox.tsx",
|
|
875
628
|
description: "Searchable select with autocomplete",
|
|
876
629
|
category: "Forms",
|
|
877
630
|
dependencies: ["popover"]
|
|
878
631
|
},
|
|
879
632
|
command: {
|
|
880
|
-
file: "command.tsx",
|
|
633
|
+
file: "ui/command.tsx",
|
|
881
634
|
description: "Command palette / search menu",
|
|
882
635
|
category: "Navigation",
|
|
883
636
|
dependencies: []
|
|
884
637
|
},
|
|
885
638
|
"context-menu": {
|
|
886
|
-
file: "context-menu.tsx",
|
|
639
|
+
file: "ui/context-menu.tsx",
|
|
887
640
|
description: "Right-click context menu",
|
|
888
641
|
category: "Overlay / Feedback",
|
|
889
642
|
dependencies: []
|
|
890
643
|
},
|
|
891
644
|
"date-picker": {
|
|
892
|
-
file: "date-picker.tsx",
|
|
645
|
+
file: "ui/date-picker.tsx",
|
|
893
646
|
description: "Date picker with calendar",
|
|
894
647
|
category: "Forms",
|
|
895
648
|
dependencies: ["calendar", "popover", "button"]
|
|
896
649
|
},
|
|
897
650
|
drawer: {
|
|
898
|
-
file: "drawer.tsx",
|
|
651
|
+
file: "ui/drawer.tsx",
|
|
899
652
|
description: "Bottom/top sheet drawer",
|
|
900
653
|
category: "Overlay / Feedback",
|
|
901
654
|
dependencies: []
|
|
902
655
|
},
|
|
903
656
|
"file-upload": {
|
|
904
|
-
file: "file-upload.tsx",
|
|
657
|
+
file: "ui/file-upload.tsx",
|
|
905
658
|
description: "Drag-and-drop file upload",
|
|
906
659
|
category: "Forms",
|
|
907
660
|
dependencies: []
|
|
908
661
|
},
|
|
909
662
|
"hover-card": {
|
|
910
|
-
file: "hover-card.tsx",
|
|
663
|
+
file: "ui/hover-card.tsx",
|
|
911
664
|
description: "Hover-triggered popover",
|
|
912
665
|
category: "Overlay / Feedback",
|
|
913
666
|
dependencies: []
|
|
914
667
|
},
|
|
915
668
|
kbd: {
|
|
916
|
-
file: "kbd.tsx",
|
|
669
|
+
file: "ui/kbd.tsx",
|
|
917
670
|
description: "Keyboard shortcut display",
|
|
918
671
|
category: "Typography",
|
|
919
672
|
dependencies: []
|
|
920
673
|
},
|
|
921
674
|
menubar: {
|
|
922
|
-
file: "menubar.tsx",
|
|
675
|
+
file: "ui/menubar.tsx",
|
|
923
676
|
description: "Horizontal menu with dropdowns",
|
|
924
677
|
category: "Navigation",
|
|
925
678
|
dependencies: []
|
|
926
679
|
},
|
|
927
680
|
"native-select": {
|
|
928
|
-
file: "native-select.tsx",
|
|
681
|
+
file: "ui/native-select.tsx",
|
|
929
682
|
description: "Styled browser-native select",
|
|
930
683
|
category: "Forms",
|
|
931
684
|
dependencies: []
|
|
932
685
|
},
|
|
933
686
|
resizable: {
|
|
934
|
-
file: "resizable.tsx",
|
|
687
|
+
file: "ui/resizable.tsx",
|
|
935
688
|
description: "Resizable panel layout",
|
|
936
689
|
category: "Layout",
|
|
937
690
|
dependencies: []
|
|
938
691
|
},
|
|
939
692
|
"scroll-area": {
|
|
940
|
-
file: "scroll-area.tsx",
|
|
693
|
+
file: "ui/scroll-area.tsx",
|
|
941
694
|
description: "Custom scrollbar container",
|
|
942
695
|
category: "Layout",
|
|
943
696
|
dependencies: []
|
|
944
697
|
},
|
|
945
698
|
toggle: {
|
|
946
|
-
file: "toggle.tsx",
|
|
699
|
+
file: "ui/toggle.tsx",
|
|
947
700
|
description: "Toggle button",
|
|
948
701
|
category: "Forms",
|
|
949
702
|
dependencies: []
|
|
950
703
|
},
|
|
951
704
|
"toggle-group": {
|
|
952
|
-
file: "toggle-group.tsx",
|
|
705
|
+
file: "ui/toggle-group.tsx",
|
|
953
706
|
description: "Grouped toggle buttons",
|
|
954
707
|
category: "Forms",
|
|
955
708
|
dependencies: ["toggle"]
|
|
709
|
+
},
|
|
710
|
+
"google-analytics": {
|
|
711
|
+
file: "analytics/google-analytics.tsx",
|
|
712
|
+
description: "Google Analytics 4 tracking",
|
|
713
|
+
category: "Analytics",
|
|
714
|
+
dependencies: []
|
|
715
|
+
},
|
|
716
|
+
"google-tag-manager": {
|
|
717
|
+
file: "analytics/google-tag-manager.tsx",
|
|
718
|
+
description: "Google Tag Manager integration",
|
|
719
|
+
category: "Analytics",
|
|
720
|
+
dependencies: []
|
|
721
|
+
},
|
|
722
|
+
"meta-pixel": {
|
|
723
|
+
file: "analytics/meta-pixel.tsx",
|
|
724
|
+
description: "Meta (Facebook) Pixel tracking",
|
|
725
|
+
category: "Analytics",
|
|
726
|
+
dependencies: []
|
|
727
|
+
},
|
|
728
|
+
"microsoft-clarity": {
|
|
729
|
+
file: "analytics/microsoft-clarity.tsx",
|
|
730
|
+
description: "Microsoft Clarity heatmap tracking",
|
|
731
|
+
category: "Analytics",
|
|
732
|
+
dependencies: []
|
|
733
|
+
},
|
|
734
|
+
"tiktok-pixel": {
|
|
735
|
+
file: "analytics/tiktok-pixel.tsx",
|
|
736
|
+
description: "TikTok Pixel tracking",
|
|
737
|
+
category: "Analytics",
|
|
738
|
+
dependencies: []
|
|
739
|
+
},
|
|
740
|
+
chatbot: {
|
|
741
|
+
file: "ui/chatbot.tsx",
|
|
742
|
+
description: "AI chat interface",
|
|
743
|
+
category: "Data Display",
|
|
744
|
+
dependencies: ["button", "input", "scroll-area", "avatar"]
|
|
956
745
|
}
|
|
957
746
|
};
|
|
958
747
|
|
|
959
748
|
// src/cli/commands/add.ts
|
|
960
|
-
var
|
|
749
|
+
var __dirname4 = path3.dirname(fileURLToPath3(import.meta.url));
|
|
961
750
|
async function add(components, options) {
|
|
962
|
-
const cwd =
|
|
751
|
+
const cwd = path3.resolve(options.cwd);
|
|
963
752
|
if (options.all) {
|
|
964
753
|
components = Object.keys(REGISTRY);
|
|
965
754
|
}
|
|
@@ -976,7 +765,7 @@ async function add(components, options) {
|
|
|
976
765
|
}))
|
|
977
766
|
});
|
|
978
767
|
if (!items || items.length === 0) {
|
|
979
|
-
|
|
768
|
+
logger.warn("No components selected.");
|
|
980
769
|
process.exit(0);
|
|
981
770
|
}
|
|
982
771
|
components = items;
|
|
@@ -991,8 +780,8 @@ async function add(components, options) {
|
|
|
991
780
|
}
|
|
992
781
|
}
|
|
993
782
|
if (invalidComponents.length > 0) {
|
|
994
|
-
|
|
995
|
-
console.log(
|
|
783
|
+
logger.error(`Unknown components: ${invalidComponents.join(", ")}`);
|
|
784
|
+
console.log("\nRun '@srcroot/ui list' to see available components.");
|
|
996
785
|
process.exit(1);
|
|
997
786
|
}
|
|
998
787
|
const toInstall = /* @__PURE__ */ new Set();
|
|
@@ -1011,57 +800,58 @@ async function add(components, options) {
|
|
|
1011
800
|
}
|
|
1012
801
|
const componentsToAdd = Array.from(toInstall);
|
|
1013
802
|
if (componentsToAdd.length > 10) {
|
|
1014
|
-
|
|
803
|
+
logger.info(`
|
|
1015
804
|
\u{1F4E6} Adding ${componentsToAdd.length} components...
|
|
1016
|
-
`)
|
|
805
|
+
`);
|
|
1017
806
|
} else {
|
|
1018
|
-
|
|
807
|
+
logger.info("\n\u{1F4E6} Adding components:\n");
|
|
1019
808
|
componentsToAdd.forEach((name) => {
|
|
1020
|
-
console.log(
|
|
809
|
+
console.log(` - ${name}`);
|
|
1021
810
|
});
|
|
1022
811
|
}
|
|
1023
812
|
console.log();
|
|
1024
813
|
const spinner = ora2("Adding components...").start();
|
|
1025
|
-
const hasSrc =
|
|
1026
|
-
const srcPath = hasSrc ?
|
|
1027
|
-
const componentsDir =
|
|
814
|
+
const hasSrc = fs3.existsSync(path3.join(cwd, "src"));
|
|
815
|
+
const srcPath = hasSrc ? path3.join(cwd, "src") : cwd;
|
|
816
|
+
const componentsDir = path3.join(srcPath, "components", "ui");
|
|
1028
817
|
try {
|
|
1029
|
-
await
|
|
818
|
+
await fs3.ensureDir(componentsDir);
|
|
1030
819
|
for (const name of componentsToAdd) {
|
|
1031
820
|
const comp = REGISTRY[name];
|
|
1032
|
-
const
|
|
1033
|
-
|
|
821
|
+
const fileName = path3.basename(comp.file);
|
|
822
|
+
const targetPath = path3.join(componentsDir, fileName);
|
|
823
|
+
if (fs3.existsSync(targetPath) && !options.overwrite) {
|
|
1034
824
|
spinner.stop();
|
|
1035
825
|
const { overwrite } = await prompts2({
|
|
1036
826
|
type: "confirm",
|
|
1037
827
|
name: "overwrite",
|
|
1038
|
-
message: `${
|
|
828
|
+
message: `${fileName} already exists. Overwrite?`,
|
|
1039
829
|
initial: false
|
|
1040
830
|
});
|
|
1041
831
|
if (!overwrite) {
|
|
1042
|
-
spinner.info(`Skipped ${
|
|
832
|
+
spinner.info(`Skipped ${fileName}`);
|
|
1043
833
|
spinner.start("Adding components...");
|
|
1044
834
|
continue;
|
|
1045
835
|
}
|
|
1046
836
|
spinner.start("Adding components...");
|
|
1047
837
|
}
|
|
1048
|
-
const registryPath =
|
|
1049
|
-
if (!
|
|
838
|
+
const registryPath = path3.resolve(__dirname4, "..", "src", "registry", comp.file);
|
|
839
|
+
if (!fs3.existsSync(registryPath)) {
|
|
1050
840
|
spinner.warn(`Registry file not found for ${name}: ${registryPath}`);
|
|
1051
841
|
continue;
|
|
1052
842
|
}
|
|
1053
|
-
const content = await
|
|
1054
|
-
await
|
|
843
|
+
const content = await fs3.readFile(registryPath, "utf-8");
|
|
844
|
+
await fs3.writeFile(targetPath, content);
|
|
1055
845
|
if (componentsToAdd.length > 10) {
|
|
1056
|
-
spinner.text = `Adding ${
|
|
846
|
+
spinner.text = `Adding ${fileName}...`;
|
|
1057
847
|
} else {
|
|
1058
|
-
spinner.succeed(`Added ${
|
|
848
|
+
spinner.succeed(`Added ${fileName}`);
|
|
1059
849
|
}
|
|
1060
850
|
}
|
|
1061
851
|
if (componentsToAdd.length > 10) {
|
|
1062
852
|
spinner.succeed(`Added ${componentsToAdd.length} components`);
|
|
1063
853
|
}
|
|
1064
|
-
|
|
854
|
+
logger.success("\n\u2705 Components added successfully!\n");
|
|
1065
855
|
} catch (error) {
|
|
1066
856
|
spinner.fail("Failed to add components");
|
|
1067
857
|
console.error(error);
|
|
@@ -1070,9 +860,9 @@ async function add(components, options) {
|
|
|
1070
860
|
}
|
|
1071
861
|
|
|
1072
862
|
// src/cli/commands/list.ts
|
|
1073
|
-
import
|
|
863
|
+
import chalk2 from "chalk";
|
|
1074
864
|
async function list() {
|
|
1075
|
-
console.log(
|
|
865
|
+
console.log(chalk2.cyan("\n\u{1F4E6} Available components:\n"));
|
|
1076
866
|
const categories = {
|
|
1077
867
|
"Core": [],
|
|
1078
868
|
"Typography": [],
|
|
@@ -1080,7 +870,8 @@ async function list() {
|
|
|
1080
870
|
"Layout": [],
|
|
1081
871
|
"Data Display": [],
|
|
1082
872
|
"Overlay / Feedback": [],
|
|
1083
|
-
"Navigation": []
|
|
873
|
+
"Navigation": [],
|
|
874
|
+
"Analytics": []
|
|
1084
875
|
};
|
|
1085
876
|
for (const [name, comp] of Object.entries(REGISTRY)) {
|
|
1086
877
|
if (categories[comp.category]) {
|
|
@@ -1089,20 +880,61 @@ async function list() {
|
|
|
1089
880
|
}
|
|
1090
881
|
for (const [category, components] of Object.entries(categories)) {
|
|
1091
882
|
if (components.length === 0) continue;
|
|
1092
|
-
console.log(
|
|
883
|
+
console.log(chalk2.bold.white(` ${category}`));
|
|
1093
884
|
components.forEach((name) => {
|
|
1094
885
|
const comp = REGISTRY[name];
|
|
1095
|
-
console.log(
|
|
886
|
+
console.log(chalk2.dim(` - ${name}`) + chalk2.gray(` (${comp.description})`));
|
|
1096
887
|
});
|
|
1097
888
|
console.log();
|
|
1098
889
|
}
|
|
1099
|
-
console.log(
|
|
890
|
+
console.log(chalk2.dim("Usage: npx @srcroot/ui add <component>\n"));
|
|
891
|
+
}
|
|
892
|
+
|
|
893
|
+
// src/cli/utils/get-package-info.ts
|
|
894
|
+
import path4 from "path";
|
|
895
|
+
import fs4 from "fs-extra";
|
|
896
|
+
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
897
|
+
function getPackageInfo() {
|
|
898
|
+
const __filename2 = fileURLToPath4(import.meta.url);
|
|
899
|
+
const __dirname5 = path4.dirname(__filename2);
|
|
900
|
+
const pathsToCheck = [
|
|
901
|
+
path4.resolve(__dirname5, "..", "package.json"),
|
|
902
|
+
path4.resolve(__dirname5, "..", "..", "..", "package.json")
|
|
903
|
+
];
|
|
904
|
+
for (const pkgPath of pathsToCheck) {
|
|
905
|
+
if (fs4.existsSync(pkgPath)) {
|
|
906
|
+
return fs4.readJSONSync(pkgPath);
|
|
907
|
+
}
|
|
908
|
+
}
|
|
909
|
+
return { version: "0.0.0" };
|
|
1100
910
|
}
|
|
1101
911
|
|
|
1102
912
|
// src/cli/index.ts
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
program.
|
|
1108
|
-
|
|
913
|
+
process.on("SIGINT", () => process.exit(0));
|
|
914
|
+
process.on("SIGTERM", () => process.exit(0));
|
|
915
|
+
async function main() {
|
|
916
|
+
const packageInfo = getPackageInfo();
|
|
917
|
+
const program = new Command().name("@srcroot/ui").description("Add polymorphic, accessible UI components to your project").version(
|
|
918
|
+
packageInfo.version || "0.0.1",
|
|
919
|
+
"-v, --version",
|
|
920
|
+
"display the version number"
|
|
921
|
+
);
|
|
922
|
+
program.command("init").description("Initialize your project with @srcroot/ui").option("-y, --yes", "Skip confirmation prompts", false).option("-t, --theme <theme>", "Color theme (slate, neutral, stone, zinc, gray)").option("--cwd <path>", "Working directory", process.cwd()).action(init);
|
|
923
|
+
program.command("add").description("Add components to your project").argument("[components...]", "Components to add").option("-y, --yes", "Skip confirmation prompts", false).option("-o, --overwrite", "Overwrite existing files", false).option("-a, --all", "Add all available components", false).option("--cwd <path>", "Working directory", process.cwd()).action(add);
|
|
924
|
+
program.command("list").description("List all available components").action(list);
|
|
925
|
+
if (process.argv.length < 3) {
|
|
926
|
+
console.log(chalk3.cyan(`
|
|
927
|
+
@srcroot/ui v${packageInfo.version}
|
|
928
|
+
|
|
929
|
+
A UI library with polymorphic, accessible components.
|
|
930
|
+
`));
|
|
931
|
+
program.outputHelp();
|
|
932
|
+
console.log();
|
|
933
|
+
return;
|
|
934
|
+
}
|
|
935
|
+
program.parse();
|
|
936
|
+
}
|
|
937
|
+
main().catch((err) => {
|
|
938
|
+
console.error("Results: ", err);
|
|
939
|
+
process.exit(1);
|
|
940
|
+
});
|