create-bearnie 0.4.4 → 0.6.0
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 +132 -29
- package/package.json +7 -3
package/dist/index.js
CHANGED
|
@@ -13,6 +13,39 @@ var link = (text, url) => `\x1B]8;;${url}\x07${pc.cyan(text)}\x1B]8;;\x07`;
|
|
|
13
13
|
function parseFullArg() {
|
|
14
14
|
return process.argv.includes("--full");
|
|
15
15
|
}
|
|
16
|
+
function parseThemeArg() {
|
|
17
|
+
const argv = process.argv;
|
|
18
|
+
for (let i = 2; i < argv.length; i++) {
|
|
19
|
+
if (argv[i].startsWith("--theme=")) {
|
|
20
|
+
return argv[i].slice("--theme=".length) || null;
|
|
21
|
+
}
|
|
22
|
+
if (argv[i] === "--theme") {
|
|
23
|
+
return argv[i + 1] && !argv[i + 1].startsWith("--") ? argv[i + 1] : null;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
function isThemeEntry(name) {
|
|
29
|
+
return name === "styles" || name.startsWith("styles-");
|
|
30
|
+
}
|
|
31
|
+
function composeThemeName(base, accent) {
|
|
32
|
+
if (base === "neutral") return accent;
|
|
33
|
+
if (accent === "default") return base;
|
|
34
|
+
return `${base}-${accent}`;
|
|
35
|
+
}
|
|
36
|
+
function detectPackageManager() {
|
|
37
|
+
const userAgent = process.env.npm_config_user_agent ?? "";
|
|
38
|
+
if (userAgent.startsWith("pnpm")) return "pnpm";
|
|
39
|
+
if (userAgent.startsWith("yarn")) return "yarn";
|
|
40
|
+
if (userAgent.startsWith("bun")) return "bun";
|
|
41
|
+
return "npm";
|
|
42
|
+
}
|
|
43
|
+
var PM_COMMANDS = {
|
|
44
|
+
npm: { install: "npm install", dev: "npm run dev", dlx: "npx" },
|
|
45
|
+
pnpm: { install: "pnpm install", dev: "pnpm dev", dlx: "pnpm dlx" },
|
|
46
|
+
yarn: { install: "yarn", dev: "yarn dev", dlx: "yarn dlx" },
|
|
47
|
+
bun: { install: "bun install", dev: "bun run dev", dlx: "bunx" }
|
|
48
|
+
};
|
|
16
49
|
var REGISTRY_URL = process.env.BEARNIE_REGISTRY_URL || "https://bearnie.dev/registry";
|
|
17
50
|
var REGISTRY_PATH = process.env.BEARNIE_REGISTRY_PATH;
|
|
18
51
|
var BEARNIE_CONFIG = {
|
|
@@ -22,15 +55,24 @@ var BEARNIE_CONFIG = {
|
|
|
22
55
|
tailwindConfig: "tailwind.config.mjs",
|
|
23
56
|
typescript: true
|
|
24
57
|
};
|
|
25
|
-
var
|
|
58
|
+
var FALLBACK_UTILITY_NAMES = [
|
|
59
|
+
"cn",
|
|
26
60
|
"focus-trap",
|
|
27
61
|
"ui-runtime-loader",
|
|
28
|
-
"ui-runtime-
|
|
62
|
+
"ui-runtime-dialog",
|
|
29
63
|
"ui-runtime-disclosure-triggers",
|
|
64
|
+
"ui-runtime-dropdown-menu",
|
|
30
65
|
"ui-runtime-popover",
|
|
31
66
|
"ui-runtime-command",
|
|
32
|
-
"ui-runtime-combobox"
|
|
67
|
+
"ui-runtime-combobox",
|
|
68
|
+
"ui-runtime-tabs"
|
|
33
69
|
];
|
|
70
|
+
var DEP_VERSIONS = {
|
|
71
|
+
clsx: "^2.1.1",
|
|
72
|
+
"tailwind-merge": "^3.6.0",
|
|
73
|
+
"keen-slider": "^6.8.6",
|
|
74
|
+
"@hugeicons/core-free-icons": "^4.2.3"
|
|
75
|
+
};
|
|
34
76
|
function resolveInstallPath(targetDir, filePath, type) {
|
|
35
77
|
if (type === "utility" || filePath.startsWith("utils/")) {
|
|
36
78
|
return path.join(targetDir, "src/utils", filePath.replace(/^utils\//, ""));
|
|
@@ -70,10 +112,12 @@ async function fetchRegistryIndex() {
|
|
|
70
112
|
}
|
|
71
113
|
return await response.json();
|
|
72
114
|
}
|
|
73
|
-
async function writeBearnieConfig(targetDir) {
|
|
74
|
-
await fs.writeJson(
|
|
75
|
-
|
|
76
|
-
|
|
115
|
+
async function writeBearnieConfig(targetDir, theme) {
|
|
116
|
+
await fs.writeJson(
|
|
117
|
+
path.join(targetDir, "bearnie.json"),
|
|
118
|
+
{ ...BEARNIE_CONFIG, theme },
|
|
119
|
+
{ spaces: 2 }
|
|
120
|
+
);
|
|
77
121
|
}
|
|
78
122
|
async function writeRegistryFiles(targetDir, entry) {
|
|
79
123
|
for (const file of entry.files) {
|
|
@@ -117,6 +161,54 @@ ${fullInstall ? ` ${pc.dim("Full install: including all components")}
|
|
|
117
161
|
}
|
|
118
162
|
const finalName = projectName;
|
|
119
163
|
const targetDir = path.resolve(process.cwd(), finalName);
|
|
164
|
+
let availableThemes = ["default"];
|
|
165
|
+
let themeBases = ["neutral"];
|
|
166
|
+
let themeAccents = ["default"];
|
|
167
|
+
try {
|
|
168
|
+
const index = await fetchRegistryIndex();
|
|
169
|
+
if (index.themes?.length) availableThemes = index.themes;
|
|
170
|
+
if (index.themeBases?.length) themeBases = index.themeBases;
|
|
171
|
+
if (index.themeAccents?.length) themeAccents = index.themeAccents;
|
|
172
|
+
} catch {
|
|
173
|
+
}
|
|
174
|
+
let theme = parseThemeArg();
|
|
175
|
+
if (theme && !availableThemes.includes(theme)) {
|
|
176
|
+
console.log(
|
|
177
|
+
`
|
|
178
|
+
${pc.red("Unknown theme:")} ${theme}
|
|
179
|
+
Themes combine a base and an accent, e.g. ${pc.cyan("slate-blue")}.
|
|
180
|
+
Bases: ${themeBases.join(", ")}
|
|
181
|
+
Accents: ${themeAccents.join(", ")}
|
|
182
|
+
`
|
|
183
|
+
);
|
|
184
|
+
process.exit(1);
|
|
185
|
+
}
|
|
186
|
+
if (!theme && (themeBases.length > 1 || themeAccents.length > 1) && process.stdin.isTTY) {
|
|
187
|
+
const response = await prompts([
|
|
188
|
+
{
|
|
189
|
+
type: "select",
|
|
190
|
+
name: "base",
|
|
191
|
+
message: "Base color (grays and surfaces)",
|
|
192
|
+
choices: themeBases.map((name) => ({ title: name, value: name })),
|
|
193
|
+
initial: 0
|
|
194
|
+
},
|
|
195
|
+
{
|
|
196
|
+
type: "select",
|
|
197
|
+
name: "accent",
|
|
198
|
+
message: "Accent color (buttons, focus rings)",
|
|
199
|
+
choices: themeAccents.map((name) => ({
|
|
200
|
+
title: name === "default" ? "default (neutral)" : name,
|
|
201
|
+
value: name
|
|
202
|
+
})),
|
|
203
|
+
initial: 0
|
|
204
|
+
}
|
|
205
|
+
]);
|
|
206
|
+
theme = composeThemeName(
|
|
207
|
+
response.base ?? "neutral",
|
|
208
|
+
response.accent ?? "default"
|
|
209
|
+
);
|
|
210
|
+
}
|
|
211
|
+
theme = theme ?? "default";
|
|
120
212
|
if (fs.existsSync(targetDir)) {
|
|
121
213
|
const { overwrite } = await prompts({
|
|
122
214
|
type: "confirm",
|
|
@@ -141,39 +233,45 @@ ${fullInstall ? ` ${pc.dim("Full install: including all components")}
|
|
|
141
233
|
const pkg = await fs.readJson(pkgPath);
|
|
142
234
|
pkg.name = finalName;
|
|
143
235
|
await fs.writeJson(pkgPath, pkg, { spaces: 2 });
|
|
144
|
-
await writeBearnieConfig(targetDir);
|
|
236
|
+
await writeBearnieConfig(targetDir, theme);
|
|
237
|
+
if (theme !== "default") {
|
|
238
|
+
const themeEntry = await fetchRegistryEntry(`styles-${theme}`);
|
|
239
|
+
if (themeEntry?.files) {
|
|
240
|
+
await writeRegistryFiles(targetDir, themeEntry);
|
|
241
|
+
console.log(` ${pc.green("\u2713")} Applied ${theme} theme`);
|
|
242
|
+
} else {
|
|
243
|
+
console.log(
|
|
244
|
+
` ${pc.yellow("!")} Couldn't fetch the ${theme} theme \u2014 using default`
|
|
245
|
+
);
|
|
246
|
+
}
|
|
247
|
+
}
|
|
145
248
|
if (fullInstall) {
|
|
146
249
|
console.log(`
|
|
147
250
|
${pc.dim("Fetching components from registry...")}
|
|
148
251
|
`);
|
|
149
252
|
await fs.ensureDir(path.join(targetDir, "src", "components", "bearnie"));
|
|
150
253
|
await fs.ensureDir(path.join(targetDir, "src", "utils"));
|
|
151
|
-
|
|
254
|
+
const registryIndex = await fetchRegistryIndex();
|
|
255
|
+
const npmDependencies = /* @__PURE__ */ new Set(["clsx", "tailwind-merge"]);
|
|
256
|
+
const utilityNames = registryIndex.utilities?.length ? registryIndex.utilities.map((utility) => utility.name) : FALLBACK_UTILITY_NAMES;
|
|
257
|
+
for (const utilityName of utilityNames) {
|
|
152
258
|
const utility = await fetchRegistryEntry(utilityName);
|
|
153
259
|
if (utility?.files) {
|
|
154
260
|
await writeRegistryFiles(targetDir, utility);
|
|
261
|
+
utility.dependencies?.forEach((dep) => npmDependencies.add(dep));
|
|
155
262
|
console.log(` ${pc.green("\u2713")} Added ${utilityName} utility`);
|
|
156
263
|
} else {
|
|
157
264
|
console.log(` ${pc.yellow("!")} Failed to fetch ${utilityName} utility`);
|
|
158
265
|
}
|
|
159
266
|
}
|
|
160
|
-
const
|
|
161
|
-
import { twMerge } from "tailwind-merge";
|
|
162
|
-
|
|
163
|
-
export function cn(...inputs: ClassValue[]) {
|
|
164
|
-
return twMerge(clsx(inputs));
|
|
165
|
-
}
|
|
166
|
-
`;
|
|
167
|
-
await fs.writeFile(path.join(targetDir, "src", "utils", "cn.ts"), cnContent);
|
|
168
|
-
console.log(` ${pc.green("\u2713")} Added cn utility`);
|
|
169
|
-
const registryIndex = await fetchRegistryIndex();
|
|
170
|
-
const componentNames = registryIndex.components.map((component) => component.name).filter((name) => name !== "styles" && name !== "barrel");
|
|
267
|
+
const componentNames = registryIndex.components.map((component) => component.name).filter((name) => !isThemeEntry(name) && name !== "barrel");
|
|
171
268
|
let installed = 0;
|
|
172
269
|
let failed = 0;
|
|
173
270
|
for (const componentName of componentNames) {
|
|
174
271
|
const component = await fetchRegistryEntry(componentName);
|
|
175
272
|
if (component?.files) {
|
|
176
273
|
await writeRegistryFiles(targetDir, component);
|
|
274
|
+
component.dependencies?.forEach((dep) => npmDependencies.add(dep));
|
|
177
275
|
installed++;
|
|
178
276
|
process.stdout.write(
|
|
179
277
|
`\r ${pc.green("\u2713")} Installed ${installed}/${componentNames.length} components`
|
|
@@ -195,13 +293,17 @@ export function cn(...inputs: ClassValue[]) {
|
|
|
195
293
|
}
|
|
196
294
|
const pkgPath2 = path.join(targetDir, "package.json");
|
|
197
295
|
const pkg2 = await fs.readJson(pkgPath2);
|
|
296
|
+
const addedDeps = Object.fromEntries(
|
|
297
|
+
[...npmDependencies].sort().map((dep) => [dep, DEP_VERSIONS[dep] ?? "latest"])
|
|
298
|
+
);
|
|
198
299
|
pkg2.dependencies = {
|
|
199
300
|
...pkg2.dependencies,
|
|
200
|
-
|
|
201
|
-
"tailwind-merge": "^3.3.0"
|
|
301
|
+
...addedDeps
|
|
202
302
|
};
|
|
203
303
|
await fs.writeJson(pkgPath2, pkg2, { spaces: 2 });
|
|
204
|
-
console.log(
|
|
304
|
+
console.log(
|
|
305
|
+
` ${pc.green("\u2713")} Added ${Object.keys(addedDeps).length} npm dependencies (${Object.keys(addedDeps).join(", ")})`
|
|
306
|
+
);
|
|
205
307
|
}
|
|
206
308
|
await fs.writeFile(
|
|
207
309
|
path.join(targetDir, ".gitignore"),
|
|
@@ -229,6 +331,7 @@ Thumbs.db
|
|
|
229
331
|
`
|
|
230
332
|
);
|
|
231
333
|
console.log(` ${pc.green("\u2713")} Created project files`);
|
|
334
|
+
const pmCommands = PM_COMMANDS[detectPackageManager()];
|
|
232
335
|
if (fullInstall) {
|
|
233
336
|
console.log(`
|
|
234
337
|
${pc.green("Done!")} Your Bearnie project is ready with all components.
|
|
@@ -236,8 +339,8 @@ Thumbs.db
|
|
|
236
339
|
${pc.bold("Next steps:")}
|
|
237
340
|
|
|
238
341
|
${pc.dim("1.")} cd ${pc.cyan(finalName)}
|
|
239
|
-
${pc.dim("2.")}
|
|
240
|
-
${pc.dim("3.")}
|
|
342
|
+
${pc.dim("2.")} ${pmCommands.install}
|
|
343
|
+
${pc.dim("3.")} ${pmCommands.dev}
|
|
241
344
|
|
|
242
345
|
${pc.dim("All components are in")} ${pc.cyan("src/components/bearnie/")}
|
|
243
346
|
${pc.dim("Import from")} ${pc.cyan("@/components/bearnie")} ${pc.dim("via")} ${pc.cyan("index.ts")}
|
|
@@ -253,12 +356,12 @@ Thumbs.db
|
|
|
253
356
|
${pc.bold("Next steps:")}
|
|
254
357
|
|
|
255
358
|
${pc.dim("1.")} cd ${pc.cyan(finalName)}
|
|
256
|
-
${pc.dim("2.")}
|
|
257
|
-
${pc.dim("3.")}
|
|
258
|
-
${pc.dim("4.")}
|
|
359
|
+
${pc.dim("2.")} ${pmCommands.install}
|
|
360
|
+
${pc.dim("3.")} ${pmCommands.dlx} bearnie add button card
|
|
361
|
+
${pc.dim("4.")} ${pmCommands.dev}
|
|
259
362
|
|
|
260
363
|
${pc.dim("Or use")} ${pc.cyan("--full")} ${pc.dim("to include all components:")}
|
|
261
|
-
|
|
364
|
+
${pmCommands.dlx} create-bearnie my-app --full
|
|
262
365
|
|
|
263
366
|
${pc.dim("Browse components at")} ${link("bearnie.dev/docs/components", "https://bearnie.dev/docs/components")}
|
|
264
367
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-bearnie",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "Create a new Astro project with Bearnie UI components",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -23,13 +23,13 @@
|
|
|
23
23
|
},
|
|
24
24
|
"devDependencies": {
|
|
25
25
|
"@types/fs-extra": "^11.0.4",
|
|
26
|
-
"@types/node": "^
|
|
26
|
+
"@types/node": "^22.10.0",
|
|
27
27
|
"@types/prompts": "^2.4.9",
|
|
28
28
|
"tsup": "^8.1.0",
|
|
29
29
|
"typescript": "^5.7.3"
|
|
30
30
|
},
|
|
31
31
|
"engines": {
|
|
32
|
-
"node": ">=
|
|
32
|
+
"node": ">=22.12.0"
|
|
33
33
|
},
|
|
34
34
|
"author": "Michael Andreuzza",
|
|
35
35
|
"repository": {
|
|
@@ -37,6 +37,10 @@
|
|
|
37
37
|
"url": "https://github.com/michael-andreuzza/bearnie.git",
|
|
38
38
|
"directory": "packages/create-bearnie"
|
|
39
39
|
},
|
|
40
|
+
"homepage": "https://bearnie.dev",
|
|
41
|
+
"bugs": {
|
|
42
|
+
"url": "https://github.com/michael-andreuzza/bearnie/issues"
|
|
43
|
+
},
|
|
40
44
|
"keywords": [
|
|
41
45
|
"create",
|
|
42
46
|
"bearnie",
|