create-bearnie 0.1.2 → 0.2.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/README.md +13 -2
- package/dist/index.js +216 -5
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
# create-bearnie
|
|
2
2
|
|
|
3
3
|
Create a new Astro project with Bearnie UI components pre-configured.
|
|
4
4
|
|
|
@@ -12,13 +12,23 @@ npx create-bearnie
|
|
|
12
12
|
npm create bearnie my-app
|
|
13
13
|
```
|
|
14
14
|
|
|
15
|
+
## Custom Theme
|
|
16
|
+
|
|
17
|
+
Create your own theme at [bearnie.dev/create](https://bearnie.dev/create), then use the generated command:
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
npm create bearnie my-app --theme=https://bearnie.dev/create#YOUR_THEME_HASH
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
This applies your custom colors, radius, and font to the project's CSS.
|
|
24
|
+
|
|
15
25
|
## What's included
|
|
16
26
|
|
|
17
27
|
- Astro 5 with TypeScript
|
|
18
28
|
- Tailwind CSS v4 (via `@tailwindcss/vite`)
|
|
19
29
|
- Bearnie CSS variables and theme
|
|
20
30
|
- Simple landing page to get started
|
|
21
|
-
- Ready for components via `npx
|
|
31
|
+
- Ready for components via `npx bearnie add`
|
|
22
32
|
|
|
23
33
|
## After creating your project
|
|
24
34
|
|
|
@@ -32,5 +42,6 @@ npm run dev
|
|
|
32
42
|
## Learn more
|
|
33
43
|
|
|
34
44
|
- [Bearnie Documentation](https://bearnie.dev/docs)
|
|
45
|
+
- [Theme Builder](https://bearnie.dev/create)
|
|
35
46
|
- [Browse Components](https://bearnie.dev/docs/components)
|
|
36
47
|
- [GitHub](https://github.com/michael-andreuzza/bearnie)
|
package/dist/index.js
CHANGED
|
@@ -10,13 +10,217 @@ var __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
|
10
10
|
var amber = (text) => pc.yellow(text);
|
|
11
11
|
var logo = `${amber("\u{1F43B}")} ${pc.bold("bearnie")}`;
|
|
12
12
|
var link = (text, url) => `\x1B]8;;${url}\x07${pc.cyan(text)}\x1B]8;;\x07`;
|
|
13
|
+
function parseThemeArg() {
|
|
14
|
+
const themeArg = process.argv.find((arg) => arg.startsWith("--theme="));
|
|
15
|
+
if (!themeArg) return null;
|
|
16
|
+
return themeArg.split("=")[1];
|
|
17
|
+
}
|
|
18
|
+
function extractThemeHash(themeUrl) {
|
|
19
|
+
try {
|
|
20
|
+
const hashIndex = themeUrl.indexOf("#");
|
|
21
|
+
if (hashIndex === -1) return null;
|
|
22
|
+
return themeUrl.slice(hashIndex + 1);
|
|
23
|
+
} catch {
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
function decodeThemeConfig(hash) {
|
|
28
|
+
try {
|
|
29
|
+
const decoded = Buffer.from(hash, "base64").toString("utf-8");
|
|
30
|
+
return JSON.parse(decoded);
|
|
31
|
+
} catch {
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
function oklch(l, c, h) {
|
|
36
|
+
return `oklch(${l} ${c} ${h})`;
|
|
37
|
+
}
|
|
38
|
+
function generateThemeCSS(config) {
|
|
39
|
+
const radiusRem = config.radius / 16;
|
|
40
|
+
const fontFamily = config.font === "geist" ? "'Geist', sans-serif" : "Inter, sans-serif";
|
|
41
|
+
const neutralChroma = config.neutralHue > 0 ? 0.01 : 0;
|
|
42
|
+
const lightPrimary = config.primaryHue === 0 ? "oklch(0.205 0 0)" : oklch(0.55, 0.2, config.primaryHue);
|
|
43
|
+
const lightPrimaryFg = "oklch(0.985 0 0)";
|
|
44
|
+
const darkPrimary = config.primaryHue === 0 ? "oklch(0.985 0 0)" : oklch(0.7, 0.2, config.primaryHue);
|
|
45
|
+
const darkPrimaryFg = "oklch(0.205 0 0)";
|
|
46
|
+
return `@import "tailwindcss";
|
|
47
|
+
@plugin "@tailwindcss/forms";
|
|
48
|
+
|
|
49
|
+
@theme {
|
|
50
|
+
/* Typography */
|
|
51
|
+
--font-sans: ${fontFamily};
|
|
52
|
+
--font-mono: Geist Mono, monospace;
|
|
53
|
+
|
|
54
|
+
/* Border Radius - Base: ${radiusRem}rem */
|
|
55
|
+
--radius-sm: calc(var(--radius) - 4px);
|
|
56
|
+
--radius-md: calc(var(--radius) - 2px);
|
|
57
|
+
--radius-lg: var(--radius);
|
|
58
|
+
--radius-xl: calc(var(--radius) + 4px);
|
|
59
|
+
--radius-2xl: calc(var(--radius) + 8px);
|
|
60
|
+
--radius-full: 9999px;
|
|
61
|
+
|
|
62
|
+
/* Shadows */
|
|
63
|
+
--shadow-sm: 0 1px 2px 0 rgb(0 0 0 / 0.05);
|
|
64
|
+
--shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);
|
|
65
|
+
--shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
@theme inline {
|
|
69
|
+
/* Semantic Colors */
|
|
70
|
+
--color-background: var(--background);
|
|
71
|
+
--color-foreground: var(--foreground);
|
|
72
|
+
--color-card: var(--card);
|
|
73
|
+
--color-card-foreground: var(--card-foreground);
|
|
74
|
+
--color-popover: var(--popover);
|
|
75
|
+
--color-popover-foreground: var(--popover-foreground);
|
|
76
|
+
--color-primary: var(--primary);
|
|
77
|
+
--color-primary-foreground: var(--primary-foreground);
|
|
78
|
+
--color-secondary: var(--secondary);
|
|
79
|
+
--color-secondary-foreground: var(--secondary-foreground);
|
|
80
|
+
--color-muted: var(--muted);
|
|
81
|
+
--color-muted-foreground: var(--muted-foreground);
|
|
82
|
+
--color-accent: var(--accent);
|
|
83
|
+
--color-accent-foreground: var(--accent-foreground);
|
|
84
|
+
--color-destructive: var(--destructive);
|
|
85
|
+
--color-destructive-foreground: var(--destructive-foreground);
|
|
86
|
+
--color-success: var(--success);
|
|
87
|
+
--color-success-foreground: var(--success-foreground);
|
|
88
|
+
--color-warning: var(--warning);
|
|
89
|
+
--color-warning-foreground: var(--warning-foreground);
|
|
90
|
+
--color-info: var(--info);
|
|
91
|
+
--color-info-foreground: var(--info-foreground);
|
|
92
|
+
--color-border: var(--border);
|
|
93
|
+
--color-input: var(--input);
|
|
94
|
+
--color-ring: var(--ring);
|
|
95
|
+
--color-chart-1: var(--chart-1);
|
|
96
|
+
--color-chart-2: var(--chart-2);
|
|
97
|
+
--color-chart-3: var(--chart-3);
|
|
98
|
+
--color-chart-4: var(--chart-4);
|
|
99
|
+
--color-chart-5: var(--chart-5);
|
|
100
|
+
|
|
101
|
+
/* Sidebar Colors */
|
|
102
|
+
--color-sidebar: var(--sidebar);
|
|
103
|
+
--color-sidebar-foreground: var(--sidebar-foreground);
|
|
104
|
+
--color-sidebar-primary: var(--sidebar-primary);
|
|
105
|
+
--color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
|
|
106
|
+
--color-sidebar-accent: var(--sidebar-accent);
|
|
107
|
+
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
|
|
108
|
+
--color-sidebar-border: var(--sidebar-border);
|
|
109
|
+
--color-sidebar-ring: var(--sidebar-ring);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
:root {
|
|
113
|
+
--radius: ${radiusRem}rem;
|
|
114
|
+
--background: ${oklch(1, neutralChroma, config.neutralHue)};
|
|
115
|
+
--foreground: ${oklch(0.145, neutralChroma, config.neutralHue)};
|
|
116
|
+
--card: ${oklch(1, neutralChroma, config.neutralHue)};
|
|
117
|
+
--card-foreground: ${oklch(0.145, neutralChroma, config.neutralHue)};
|
|
118
|
+
--popover: ${oklch(1, neutralChroma, config.neutralHue)};
|
|
119
|
+
--popover-foreground: ${oklch(0.145, neutralChroma, config.neutralHue)};
|
|
120
|
+
--primary: ${lightPrimary};
|
|
121
|
+
--primary-foreground: ${lightPrimaryFg};
|
|
122
|
+
--secondary: ${oklch(0.97, neutralChroma, config.neutralHue)};
|
|
123
|
+
--secondary-foreground: ${oklch(0.205, neutralChroma, config.neutralHue)};
|
|
124
|
+
--muted: ${oklch(0.97, neutralChroma, config.neutralHue)};
|
|
125
|
+
--muted-foreground: ${oklch(0.556, neutralChroma, config.neutralHue)};
|
|
126
|
+
--accent: ${oklch(0.97, neutralChroma, config.neutralHue)};
|
|
127
|
+
--accent-foreground: ${oklch(0.205, neutralChroma, config.neutralHue)};
|
|
128
|
+
--destructive: ${oklch(0.577, 0.245, config.destructiveHue)};
|
|
129
|
+
--destructive-foreground: ${oklch(0.577, 0.245, config.destructiveHue)};
|
|
130
|
+
--success: ${oklch(0.564, 0.168, config.successHue)};
|
|
131
|
+
--success-foreground: ${oklch(0.564, 0.168, config.successHue)};
|
|
132
|
+
--warning: ${oklch(0.681, 0.15, config.warningHue)};
|
|
133
|
+
--warning-foreground: ${oklch(0.681, 0.15, config.warningHue)};
|
|
134
|
+
--info: ${oklch(0.609, 0.202, config.infoHue)};
|
|
135
|
+
--info-foreground: ${oklch(0.609, 0.202, config.infoHue)};
|
|
136
|
+
--border: ${oklch(0.922, neutralChroma, config.neutralHue)};
|
|
137
|
+
--input: ${oklch(0.922, neutralChroma, config.neutralHue)};
|
|
138
|
+
--ring: ${oklch(0.708, neutralChroma, config.neutralHue)};
|
|
139
|
+
--chart-1: oklch(0.646 0.222 41.116);
|
|
140
|
+
--chart-2: oklch(0.6 0.118 184.704);
|
|
141
|
+
--chart-3: oklch(0.398 0.07 227.392);
|
|
142
|
+
--chart-4: oklch(0.828 0.189 84.429);
|
|
143
|
+
--chart-5: oklch(0.769 0.188 70.08);
|
|
144
|
+
|
|
145
|
+
/* Sidebar */
|
|
146
|
+
--sidebar: ${oklch(0.985, neutralChroma, config.neutralHue)};
|
|
147
|
+
--sidebar-foreground: ${oklch(0.145, neutralChroma, config.neutralHue)};
|
|
148
|
+
--sidebar-primary: ${lightPrimary};
|
|
149
|
+
--sidebar-primary-foreground: ${lightPrimaryFg};
|
|
150
|
+
--sidebar-accent: ${oklch(0.97, neutralChroma, config.neutralHue)};
|
|
151
|
+
--sidebar-accent-foreground: ${oklch(0.205, neutralChroma, config.neutralHue)};
|
|
152
|
+
--sidebar-border: ${oklch(0.922, neutralChroma, config.neutralHue)};
|
|
153
|
+
--sidebar-ring: ${oklch(0.708, neutralChroma, config.neutralHue)};
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
.dark {
|
|
157
|
+
--background: ${oklch(0.145, neutralChroma, config.neutralHue)};
|
|
158
|
+
--foreground: ${oklch(0.985, neutralChroma, config.neutralHue)};
|
|
159
|
+
--card: ${oklch(0.145, neutralChroma, config.neutralHue)};
|
|
160
|
+
--card-foreground: ${oklch(0.985, neutralChroma, config.neutralHue)};
|
|
161
|
+
--popover: ${oklch(0.145, neutralChroma, config.neutralHue)};
|
|
162
|
+
--popover-foreground: ${oklch(0.985, neutralChroma, config.neutralHue)};
|
|
163
|
+
--primary: ${darkPrimary};
|
|
164
|
+
--primary-foreground: ${darkPrimaryFg};
|
|
165
|
+
--secondary: ${oklch(0.269, neutralChroma, config.neutralHue)};
|
|
166
|
+
--secondary-foreground: ${oklch(0.985, neutralChroma, config.neutralHue)};
|
|
167
|
+
--muted: ${oklch(0.269, neutralChroma, config.neutralHue)};
|
|
168
|
+
--muted-foreground: ${oklch(0.708, neutralChroma, config.neutralHue)};
|
|
169
|
+
--accent: ${oklch(0.269, neutralChroma, config.neutralHue)};
|
|
170
|
+
--accent-foreground: ${oklch(0.985, neutralChroma, config.neutralHue)};
|
|
171
|
+
--destructive: ${oklch(0.65, 0.245, config.destructiveHue)};
|
|
172
|
+
--destructive-foreground: oklch(0.985 0 0);
|
|
173
|
+
--success: ${oklch(0.634, 0.168, config.successHue)};
|
|
174
|
+
--success-foreground: oklch(0.985 0 0);
|
|
175
|
+
--warning: ${oklch(0.785, 0.15, config.warningHue)};
|
|
176
|
+
--warning-foreground: oklch(0.985 0 0);
|
|
177
|
+
--info: ${oklch(0.701, 0.202, config.infoHue)};
|
|
178
|
+
--info-foreground: oklch(0.985 0 0);
|
|
179
|
+
--border: ${oklch(0.269, neutralChroma, config.neutralHue)};
|
|
180
|
+
--input: ${oklch(0.269, neutralChroma, config.neutralHue)};
|
|
181
|
+
--ring: ${oklch(0.439, neutralChroma, config.neutralHue)};
|
|
182
|
+
--chart-1: oklch(0.488 0.243 264.376);
|
|
183
|
+
--chart-2: oklch(0.696 0.17 162.48);
|
|
184
|
+
--chart-3: oklch(0.769 0.188 70.08);
|
|
185
|
+
--chart-4: oklch(0.627 0.265 303.9);
|
|
186
|
+
--chart-5: oklch(0.645 0.246 16.439);
|
|
187
|
+
|
|
188
|
+
/* Sidebar */
|
|
189
|
+
--sidebar: ${oklch(0.205, neutralChroma, config.neutralHue)};
|
|
190
|
+
--sidebar-foreground: ${oklch(0.985, neutralChroma, config.neutralHue)};
|
|
191
|
+
--sidebar-primary: ${config.primaryHue === 0 ? "oklch(0.488 0.243 264.376)" : oklch(0.7, 0.2, config.primaryHue)};
|
|
192
|
+
--sidebar-primary-foreground: oklch(0.985 0 0);
|
|
193
|
+
--sidebar-accent: ${oklch(0.269, neutralChroma, config.neutralHue)};
|
|
194
|
+
--sidebar-accent-foreground: ${oklch(0.985, neutralChroma, config.neutralHue)};
|
|
195
|
+
--sidebar-border: ${oklch(0.269, neutralChroma, config.neutralHue)};
|
|
196
|
+
--sidebar-ring: ${oklch(0.439, neutralChroma, config.neutralHue)};
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/* Base styles */
|
|
200
|
+
* {
|
|
201
|
+
border-color: var(--border);
|
|
202
|
+
}
|
|
203
|
+
`;
|
|
204
|
+
}
|
|
13
205
|
async function main() {
|
|
206
|
+
const themeUrl = parseThemeArg();
|
|
207
|
+
let themeConfig = null;
|
|
208
|
+
if (themeUrl) {
|
|
209
|
+
const hash = extractThemeHash(themeUrl);
|
|
210
|
+
if (hash) {
|
|
211
|
+
themeConfig = decodeThemeConfig(hash);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
14
214
|
console.log(`
|
|
15
215
|
${logo}
|
|
16
216
|
|
|
17
217
|
${amber("Hey!")} Let's create your Bearnie project.
|
|
218
|
+
${themeConfig ? ` ${pc.dim("Using custom theme from URL")}
|
|
219
|
+
` : ""}
|
|
18
220
|
`);
|
|
19
|
-
let projectName = process.argv
|
|
221
|
+
let projectName = process.argv.find(
|
|
222
|
+
(arg, index) => index >= 2 && !arg.startsWith("--")
|
|
223
|
+
);
|
|
20
224
|
if (!projectName) {
|
|
21
225
|
const response = await prompts({
|
|
22
226
|
type: "text",
|
|
@@ -38,12 +242,13 @@ async function main() {
|
|
|
38
242
|
}
|
|
39
243
|
projectName = response.projectName;
|
|
40
244
|
}
|
|
41
|
-
const
|
|
245
|
+
const finalName = projectName;
|
|
246
|
+
const targetDir = path.resolve(process.cwd(), finalName);
|
|
42
247
|
if (fs.existsSync(targetDir)) {
|
|
43
248
|
const { overwrite } = await prompts({
|
|
44
249
|
type: "confirm",
|
|
45
250
|
name: "overwrite",
|
|
46
|
-
message: `Directory ${pc.cyan(
|
|
251
|
+
message: `Directory ${pc.cyan(finalName)} already exists. Overwrite?`,
|
|
47
252
|
initial: false
|
|
48
253
|
});
|
|
49
254
|
if (!overwrite) {
|
|
@@ -61,8 +266,14 @@ async function main() {
|
|
|
61
266
|
await fs.copy(templateDir, targetDir);
|
|
62
267
|
const pkgPath = path.join(targetDir, "package.json");
|
|
63
268
|
const pkg = await fs.readJson(pkgPath);
|
|
64
|
-
pkg.name =
|
|
269
|
+
pkg.name = finalName;
|
|
65
270
|
await fs.writeJson(pkgPath, pkg, { spaces: 2 });
|
|
271
|
+
if (themeConfig) {
|
|
272
|
+
const globalCssPath = path.join(targetDir, "src", "styles", "global.css");
|
|
273
|
+
const customCSS = generateThemeCSS(themeConfig);
|
|
274
|
+
await fs.writeFile(globalCssPath, customCSS);
|
|
275
|
+
console.log(` ${pc.green("\u2713")} Applied custom theme`);
|
|
276
|
+
}
|
|
66
277
|
await fs.writeFile(
|
|
67
278
|
path.join(targetDir, ".gitignore"),
|
|
68
279
|
`# Dependencies
|
|
@@ -94,7 +305,7 @@ Thumbs.db
|
|
|
94
305
|
|
|
95
306
|
${pc.bold("Next steps:")}
|
|
96
307
|
|
|
97
|
-
${pc.dim("1.")} cd ${pc.cyan(
|
|
308
|
+
${pc.dim("1.")} cd ${pc.cyan(finalName)}
|
|
98
309
|
${pc.dim("2.")} npm install
|
|
99
310
|
${pc.dim("3.")} npx bearnie add button card
|
|
100
311
|
${pc.dim("4.")} npm run dev
|