@bison-lab/create-theme 0.1.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.mjs +399 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +30 -0
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,399 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import * as p from "@clack/prompts";
|
|
3
|
+
import pc from "picocolors";
|
|
4
|
+
import { existsSync, readFileSync, writeFileSync } from "fs";
|
|
5
|
+
import { resolve } from "path";
|
|
6
|
+
//#region src/preview.ts
|
|
7
|
+
function hexToRgb(hex) {
|
|
8
|
+
hex = hex.replace("#", "");
|
|
9
|
+
return [
|
|
10
|
+
parseInt(hex.substring(0, 2), 16),
|
|
11
|
+
parseInt(hex.substring(2, 4), 16),
|
|
12
|
+
parseInt(hex.substring(4, 6), 16)
|
|
13
|
+
];
|
|
14
|
+
}
|
|
15
|
+
function previewHexColor(hex) {
|
|
16
|
+
const [r, g, b] = hexToRgb(hex);
|
|
17
|
+
return `\x1b[48;2;${r};${g};${b}m \x1b[0m ${pc.dim(hex)}`;
|
|
18
|
+
}
|
|
19
|
+
//#endregion
|
|
20
|
+
//#region src/prompts.ts
|
|
21
|
+
function isValidHex(hex) {
|
|
22
|
+
return hex != null && /^#[0-9A-Fa-f]{6}$/.test(hex);
|
|
23
|
+
}
|
|
24
|
+
async function runPrompts(existing) {
|
|
25
|
+
p.log.info(pc.bold("Brand Colors"));
|
|
26
|
+
if (existing) p.log.message(`Current: Primary ${previewHexColor(existing.brandPrimary)} Secondary ${previewHexColor(existing.brandSecondary)} Accent ${previewHexColor(existing.brandAccent)}`);
|
|
27
|
+
const brandPrimary = await p.text({
|
|
28
|
+
message: "Primary brand color (hex)",
|
|
29
|
+
placeholder: "#1e3a5f",
|
|
30
|
+
...existing?.brandPrimary && { defaultValue: existing.brandPrimary },
|
|
31
|
+
validate: (v) => !isValidHex(v) ? "Enter a valid hex color (e.g. #1e3a5f)" : void 0
|
|
32
|
+
});
|
|
33
|
+
if (p.isCancel(brandPrimary)) return null;
|
|
34
|
+
p.log.message(` ${previewHexColor(brandPrimary)} Primary`);
|
|
35
|
+
const brandSecondary = await p.text({
|
|
36
|
+
message: "Secondary brand color (hex)",
|
|
37
|
+
placeholder: "#2d9d6e",
|
|
38
|
+
...existing?.brandSecondary && { defaultValue: existing.brandSecondary },
|
|
39
|
+
validate: (v) => !isValidHex(v) ? "Enter a valid hex color (e.g. #2d9d6e)" : void 0
|
|
40
|
+
});
|
|
41
|
+
if (p.isCancel(brandSecondary)) return null;
|
|
42
|
+
p.log.message(` ${previewHexColor(brandSecondary)} Secondary`);
|
|
43
|
+
const brandAccent = await p.text({
|
|
44
|
+
message: "Accent brand color (hex)",
|
|
45
|
+
placeholder: "#e89b20",
|
|
46
|
+
...existing?.brandAccent && { defaultValue: existing.brandAccent },
|
|
47
|
+
validate: (v) => !isValidHex(v) ? "Enter a valid hex color (e.g. #e89b20)" : void 0
|
|
48
|
+
});
|
|
49
|
+
if (p.isCancel(brandAccent)) return null;
|
|
50
|
+
p.log.message(` ${previewHexColor(brandAccent)} Accent`);
|
|
51
|
+
const radius = await p.select({
|
|
52
|
+
message: "Border radius preset",
|
|
53
|
+
initialValue: existing?.radius ?? "rounded",
|
|
54
|
+
options: [
|
|
55
|
+
{
|
|
56
|
+
value: "sharp",
|
|
57
|
+
label: "Sharp",
|
|
58
|
+
hint: "0px — square corners"
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
value: "subtle",
|
|
62
|
+
label: "Subtle",
|
|
63
|
+
hint: "6px — barely rounded"
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
value: "rounded",
|
|
67
|
+
label: "Rounded",
|
|
68
|
+
hint: "8px — balanced (default)"
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
value: "pill",
|
|
72
|
+
label: "Pill",
|
|
73
|
+
hint: "12px — soft, bubbly"
|
|
74
|
+
}
|
|
75
|
+
]
|
|
76
|
+
});
|
|
77
|
+
if (p.isCancel(radius)) return null;
|
|
78
|
+
const shadow = await p.select({
|
|
79
|
+
message: "Shadow preset",
|
|
80
|
+
initialValue: existing?.shadow ?? "subtle",
|
|
81
|
+
options: [
|
|
82
|
+
{
|
|
83
|
+
value: "flat",
|
|
84
|
+
label: "Flat",
|
|
85
|
+
hint: "No shadows — clean, modern"
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
value: "subtle",
|
|
89
|
+
label: "Subtle",
|
|
90
|
+
hint: "Soft low-opacity shadows (default)"
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
value: "elevated",
|
|
94
|
+
label: "Elevated",
|
|
95
|
+
hint: "Prominent layered shadows"
|
|
96
|
+
}
|
|
97
|
+
]
|
|
98
|
+
});
|
|
99
|
+
if (p.isCancel(shadow)) return null;
|
|
100
|
+
const motion = await p.select({
|
|
101
|
+
message: "Motion preset",
|
|
102
|
+
initialValue: existing?.motion ?? "smooth",
|
|
103
|
+
options: [
|
|
104
|
+
{
|
|
105
|
+
value: "snappy",
|
|
106
|
+
label: "Snappy",
|
|
107
|
+
hint: "Fast, spring-like (150ms)"
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
value: "smooth",
|
|
111
|
+
label: "Smooth",
|
|
112
|
+
hint: "Balanced ease-out (200ms, default)"
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
value: "minimal",
|
|
116
|
+
label: "Minimal",
|
|
117
|
+
hint: "Barely-there, linear (100ms)"
|
|
118
|
+
}
|
|
119
|
+
]
|
|
120
|
+
});
|
|
121
|
+
if (p.isCancel(motion)) return null;
|
|
122
|
+
const density = await p.select({
|
|
123
|
+
message: "Component density",
|
|
124
|
+
initialValue: existing?.density ?? "default",
|
|
125
|
+
options: [
|
|
126
|
+
{
|
|
127
|
+
value: "compact",
|
|
128
|
+
label: "Compact",
|
|
129
|
+
hint: "Tight padding, smaller components"
|
|
130
|
+
},
|
|
131
|
+
{
|
|
132
|
+
value: "default",
|
|
133
|
+
label: "Default",
|
|
134
|
+
hint: "Balanced spacing"
|
|
135
|
+
},
|
|
136
|
+
{
|
|
137
|
+
value: "spacious",
|
|
138
|
+
label: "Spacious",
|
|
139
|
+
hint: "Generous padding, larger components"
|
|
140
|
+
}
|
|
141
|
+
]
|
|
142
|
+
});
|
|
143
|
+
if (p.isCancel(density)) return null;
|
|
144
|
+
p.log.info(pc.bold("Typography"));
|
|
145
|
+
const fontFamily = await p.text({
|
|
146
|
+
message: "Font family name",
|
|
147
|
+
placeholder: "Inter",
|
|
148
|
+
defaultValue: existing?.fontFamily ?? "Inter"
|
|
149
|
+
});
|
|
150
|
+
if (p.isCancel(fontFamily)) return null;
|
|
151
|
+
const customizeWeights = await p.confirm({
|
|
152
|
+
message: "Customize font weights? (default: 400/500/600/700)",
|
|
153
|
+
initialValue: false
|
|
154
|
+
});
|
|
155
|
+
if (p.isCancel(customizeWeights)) return null;
|
|
156
|
+
let fontWeights = existing?.fontWeights ?? {
|
|
157
|
+
normal: 400,
|
|
158
|
+
medium: 500,
|
|
159
|
+
semibold: 600,
|
|
160
|
+
bold: 700
|
|
161
|
+
};
|
|
162
|
+
if (customizeWeights) {
|
|
163
|
+
const normal = await p.text({
|
|
164
|
+
message: "Normal weight",
|
|
165
|
+
defaultValue: String(fontWeights.normal),
|
|
166
|
+
validate: (v) => isNaN(Number(v)) ? "Must be a number" : void 0
|
|
167
|
+
});
|
|
168
|
+
if (p.isCancel(normal)) return null;
|
|
169
|
+
const medium = await p.text({
|
|
170
|
+
message: "Medium weight",
|
|
171
|
+
defaultValue: String(fontWeights.medium),
|
|
172
|
+
validate: (v) => isNaN(Number(v)) ? "Must be a number" : void 0
|
|
173
|
+
});
|
|
174
|
+
if (p.isCancel(medium)) return null;
|
|
175
|
+
const semibold = await p.text({
|
|
176
|
+
message: "Semibold weight",
|
|
177
|
+
defaultValue: String(fontWeights.semibold),
|
|
178
|
+
validate: (v) => isNaN(Number(v)) ? "Must be a number" : void 0
|
|
179
|
+
});
|
|
180
|
+
if (p.isCancel(semibold)) return null;
|
|
181
|
+
const bold = await p.text({
|
|
182
|
+
message: "Bold weight",
|
|
183
|
+
defaultValue: String(fontWeights.bold),
|
|
184
|
+
validate: (v) => isNaN(Number(v)) ? "Must be a number" : void 0
|
|
185
|
+
});
|
|
186
|
+
if (p.isCancel(bold)) return null;
|
|
187
|
+
fontWeights = {
|
|
188
|
+
normal: Number(normal),
|
|
189
|
+
medium: Number(medium),
|
|
190
|
+
semibold: Number(semibold),
|
|
191
|
+
bold: Number(bold)
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
return {
|
|
195
|
+
brandPrimary,
|
|
196
|
+
brandSecondary,
|
|
197
|
+
brandAccent,
|
|
198
|
+
radius,
|
|
199
|
+
shadow,
|
|
200
|
+
motion,
|
|
201
|
+
density,
|
|
202
|
+
fontFamily,
|
|
203
|
+
fontWeights
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
//#endregion
|
|
207
|
+
//#region src/generate.ts
|
|
208
|
+
function hexToHSL(hex) {
|
|
209
|
+
hex = hex.replace("#", "");
|
|
210
|
+
const r = parseInt(hex.substring(0, 2), 16) / 255;
|
|
211
|
+
const g = parseInt(hex.substring(2, 4), 16) / 255;
|
|
212
|
+
const b = parseInt(hex.substring(4, 6), 16) / 255;
|
|
213
|
+
const max = Math.max(r, g, b);
|
|
214
|
+
const min = Math.min(r, g, b);
|
|
215
|
+
const l = (max + min) / 2;
|
|
216
|
+
let h = 0;
|
|
217
|
+
let s = 0;
|
|
218
|
+
if (max !== min) {
|
|
219
|
+
const d = max - min;
|
|
220
|
+
s = l > .5 ? d / (2 - max - min) : d / (max + min);
|
|
221
|
+
switch (max) {
|
|
222
|
+
case r:
|
|
223
|
+
h = ((g - b) / d + (g < b ? 6 : 0)) / 6;
|
|
224
|
+
break;
|
|
225
|
+
case g:
|
|
226
|
+
h = ((b - r) / d + 2) / 6;
|
|
227
|
+
break;
|
|
228
|
+
case b:
|
|
229
|
+
h = ((r - g) / d + 4) / 6;
|
|
230
|
+
break;
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
return {
|
|
234
|
+
h: Math.round(h * 360),
|
|
235
|
+
s: Math.round(s * 100),
|
|
236
|
+
l: Math.round(l * 100)
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
function hsl(h, s, l) {
|
|
240
|
+
return `${h} ${s}% ${l}%`;
|
|
241
|
+
}
|
|
242
|
+
function clamp(v, min, max) {
|
|
243
|
+
return Math.min(Math.max(v, min), max);
|
|
244
|
+
}
|
|
245
|
+
function deriveLight(primary, secondary, accent) {
|
|
246
|
+
return {
|
|
247
|
+
background: hsl(primary.h, clamp(primary.s - 30, 0, 100), 100),
|
|
248
|
+
foreground: hsl(primary.h, clamp(primary.s - 20, 0, 100), 10),
|
|
249
|
+
card: hsl(primary.h, clamp(primary.s - 30, 0, 100), 100),
|
|
250
|
+
"card-foreground": hsl(primary.h, clamp(primary.s - 20, 0, 100), 10),
|
|
251
|
+
popover: hsl(primary.h, clamp(primary.s - 30, 0, 100), 100),
|
|
252
|
+
"popover-foreground": hsl(primary.h, clamp(primary.s - 20, 0, 100), 10),
|
|
253
|
+
primary: hsl(primary.h, primary.s, primary.l),
|
|
254
|
+
"primary-foreground": hsl(primary.h, clamp(primary.s - 30, 0, 100), primary.l > 50 ? 10 : 98),
|
|
255
|
+
secondary: hsl(secondary.h, clamp(secondary.s - 30, 0, 100), clamp(secondary.l + 40, 0, 100)),
|
|
256
|
+
"secondary-foreground": hsl(secondary.h, secondary.s, clamp(secondary.l - 30, 0, 100)),
|
|
257
|
+
accent: hsl(accent.h, accent.s, clamp(accent.l + 10, 0, 100)),
|
|
258
|
+
"accent-foreground": hsl(accent.h, accent.s, clamp(accent.l - 60, 0, 100)),
|
|
259
|
+
muted: hsl(primary.h, clamp(primary.s - 30, 0, 100), 96),
|
|
260
|
+
"muted-foreground": hsl(primary.h, clamp(primary.s - 25, 0, 100), 45),
|
|
261
|
+
destructive: "0 84% 60%",
|
|
262
|
+
"destructive-foreground": "0 0% 98%",
|
|
263
|
+
border: hsl(primary.h, clamp(primary.s - 25, 0, 100), 91),
|
|
264
|
+
input: hsl(primary.h, clamp(primary.s - 25, 0, 100), 91),
|
|
265
|
+
ring: hsl(primary.h, primary.s, primary.l)
|
|
266
|
+
};
|
|
267
|
+
}
|
|
268
|
+
function deriveDark(primary, secondary, accent) {
|
|
269
|
+
const darkPrimary = {
|
|
270
|
+
...primary,
|
|
271
|
+
l: primary.l < 50 ? primary.l + 20 : primary.l
|
|
272
|
+
};
|
|
273
|
+
return {
|
|
274
|
+
background: hsl(primary.h, clamp(primary.s - 25, 0, 100), 7),
|
|
275
|
+
foreground: hsl(primary.h, clamp(primary.s - 30, 0, 100), 98),
|
|
276
|
+
card: hsl(primary.h, clamp(primary.s - 25, 0, 100), 10),
|
|
277
|
+
"card-foreground": hsl(primary.h, clamp(primary.s - 30, 0, 100), 98),
|
|
278
|
+
popover: hsl(primary.h, clamp(primary.s - 25, 0, 100), 10),
|
|
279
|
+
"popover-foreground": hsl(primary.h, clamp(primary.s - 30, 0, 100), 98),
|
|
280
|
+
primary: hsl(darkPrimary.h, darkPrimary.s, darkPrimary.l),
|
|
281
|
+
"primary-foreground": hsl(primary.h, clamp(primary.s - 30, 0, 100), darkPrimary.l > 50 ? 10 : 98),
|
|
282
|
+
secondary: hsl(secondary.h, clamp(secondary.s - 20, 0, 100), 18),
|
|
283
|
+
"secondary-foreground": hsl(secondary.h, secondary.s, clamp(secondary.l + 30, 0, 100)),
|
|
284
|
+
accent: hsl(accent.h, clamp(accent.s - 10, 0, 100), 20),
|
|
285
|
+
"accent-foreground": hsl(accent.h, accent.s, clamp(accent.l + 40, 0, 100)),
|
|
286
|
+
muted: hsl(primary.h, clamp(primary.s - 25, 0, 100), 18),
|
|
287
|
+
"muted-foreground": hsl(primary.h, clamp(primary.s - 20, 0, 100), 65),
|
|
288
|
+
destructive: "0 62% 30%",
|
|
289
|
+
"destructive-foreground": "0 0% 98%",
|
|
290
|
+
border: hsl(primary.h, clamp(primary.s - 25, 0, 100), 18),
|
|
291
|
+
input: hsl(primary.h, clamp(primary.s - 25, 0, 100), 18),
|
|
292
|
+
ring: hsl(darkPrimary.h, darkPrimary.s, darkPrimary.l)
|
|
293
|
+
};
|
|
294
|
+
}
|
|
295
|
+
function generateThemeCSS(config) {
|
|
296
|
+
const primary = hexToHSL(config.brandPrimary);
|
|
297
|
+
const secondary = hexToHSL(config.brandSecondary);
|
|
298
|
+
const accent = hexToHSL(config.brandAccent);
|
|
299
|
+
const light = deriveLight(primary, secondary, accent);
|
|
300
|
+
const dark = deriveDark(primary, secondary, accent);
|
|
301
|
+
return [
|
|
302
|
+
`/* Bison Lab Theme — Generated by @bison-lab/create-theme */`,
|
|
303
|
+
`/* Brand: ${config.brandPrimary} / ${config.brandSecondary} / ${config.brandAccent} */`,
|
|
304
|
+
``,
|
|
305
|
+
`:root {`,
|
|
306
|
+
...Object.entries(light).map(([k, v]) => ` --${k}: ${v};`),
|
|
307
|
+
``,
|
|
308
|
+
` /* Typography */`,
|
|
309
|
+
` --font-sans: '${config.fontFamily}', ui-sans-serif, system-ui, sans-serif;`,
|
|
310
|
+
` --font-weight-normal: ${config.fontWeights.normal};`,
|
|
311
|
+
` --font-weight-medium: ${config.fontWeights.medium};`,
|
|
312
|
+
` --font-weight-semibold: ${config.fontWeights.semibold};`,
|
|
313
|
+
` --font-weight-bold: ${config.fontWeights.bold};`,
|
|
314
|
+
`}`,
|
|
315
|
+
``,
|
|
316
|
+
`.dark {`,
|
|
317
|
+
...Object.entries(dark).map(([k, v]) => ` --${k}: ${v};`),
|
|
318
|
+
`}`,
|
|
319
|
+
``
|
|
320
|
+
].join("\n");
|
|
321
|
+
}
|
|
322
|
+
function generateTailwindConfig(config) {
|
|
323
|
+
return [
|
|
324
|
+
`import bisonPreset from '@bison-lab/tailwind-preset';`,
|
|
325
|
+
``,
|
|
326
|
+
`export default {`,
|
|
327
|
+
` presets: [bisonPreset],`,
|
|
328
|
+
` content: [`,
|
|
329
|
+
` './app/**/*.{ts,tsx}',`,
|
|
330
|
+
` './components/**/*.{ts,tsx}',`,
|
|
331
|
+
` './node_modules/@bison-lab/ui/dist/**/*.js',`,
|
|
332
|
+
` ],`,
|
|
333
|
+
`};`
|
|
334
|
+
].join("\n");
|
|
335
|
+
}
|
|
336
|
+
//#endregion
|
|
337
|
+
//#region src/index.ts
|
|
338
|
+
const CONFIG_FILE = "bison.config.json";
|
|
339
|
+
const THEME_FILE = "bison-theme.css";
|
|
340
|
+
async function main() {
|
|
341
|
+
p.intro(pc.bgCyan(pc.black(" Bison Lab Theme Generator ")));
|
|
342
|
+
const configPath = resolve(process.cwd(), CONFIG_FILE);
|
|
343
|
+
let existingConfig;
|
|
344
|
+
if (existsSync(configPath)) {
|
|
345
|
+
existingConfig = JSON.parse(readFileSync(configPath, "utf-8"));
|
|
346
|
+
const mode = await p.select({
|
|
347
|
+
message: "An existing theme was found. What would you like to do?",
|
|
348
|
+
options: [{
|
|
349
|
+
value: "update",
|
|
350
|
+
label: "Update existing theme",
|
|
351
|
+
hint: "Modify individual properties"
|
|
352
|
+
}, {
|
|
353
|
+
value: "fresh",
|
|
354
|
+
label: "Start fresh",
|
|
355
|
+
hint: "Overwrite everything"
|
|
356
|
+
}]
|
|
357
|
+
});
|
|
358
|
+
if (p.isCancel(mode)) {
|
|
359
|
+
p.cancel("Cancelled.");
|
|
360
|
+
process.exit(0);
|
|
361
|
+
}
|
|
362
|
+
if (mode === "fresh") existingConfig = void 0;
|
|
363
|
+
}
|
|
364
|
+
const config = await runPrompts(existingConfig);
|
|
365
|
+
if (!config) {
|
|
366
|
+
p.cancel("Cancelled.");
|
|
367
|
+
process.exit(0);
|
|
368
|
+
}
|
|
369
|
+
const s = p.spinner();
|
|
370
|
+
s.start("Generating theme files...");
|
|
371
|
+
const themeCSS = generateThemeCSS(config);
|
|
372
|
+
writeFileSync(resolve(process.cwd(), THEME_FILE), themeCSS, "utf-8");
|
|
373
|
+
writeFileSync(configPath, JSON.stringify(config, null, 2), "utf-8");
|
|
374
|
+
const tailwindSnippet = generateTailwindConfig(config);
|
|
375
|
+
s.stop("Theme files generated!");
|
|
376
|
+
p.note([
|
|
377
|
+
`${pc.green("Created:")} ${THEME_FILE}`,
|
|
378
|
+
`${pc.green("Created:")} ${CONFIG_FILE}`,
|
|
379
|
+
"",
|
|
380
|
+
`${pc.bold("Add to your tailwind.config.ts:")}`,
|
|
381
|
+
"",
|
|
382
|
+
tailwindSnippet,
|
|
383
|
+
"",
|
|
384
|
+
`${pc.bold("Import in your app/layout.tsx:")}`,
|
|
385
|
+
"",
|
|
386
|
+
`import '@bison-lab/tokens/css/globals.css';`,
|
|
387
|
+
`import '@bison-lab/tokens/css/themes/radius-${config.radius}.css';`,
|
|
388
|
+
`import '@bison-lab/tokens/css/themes/shadow-${config.shadow}.css';`,
|
|
389
|
+
`import '@bison-lab/tokens/css/themes/motion-${config.motion}.css';`,
|
|
390
|
+
`import '@bison-lab/tokens/css/themes/density-${config.density}.css';`,
|
|
391
|
+
`import './${THEME_FILE}';`
|
|
392
|
+
].join("\n"), "Next steps");
|
|
393
|
+
p.outro(pc.green("Done! Your Bison Lab theme is ready."));
|
|
394
|
+
}
|
|
395
|
+
main().catch(console.error);
|
|
396
|
+
//#endregion
|
|
397
|
+
export {};
|
|
398
|
+
|
|
399
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../src/preview.ts","../src/prompts.ts","../src/generate.ts","../src/index.ts"],"sourcesContent":["import pc from \"picocolors\";\n\nexport function hexToRgb(hex: string): [number, number, number] {\n hex = hex.replace(\"#\", \"\");\n return [\n parseInt(hex.substring(0, 2), 16),\n parseInt(hex.substring(2, 4), 16),\n parseInt(hex.substring(4, 6), 16),\n ];\n}\n\nexport function previewHexColor(hex: string): string {\n const [r, g, b] = hexToRgb(hex);\n // Use ANSI 24-bit color for background\n return `\\x1b[48;2;${r};${g};${b}m \\x1b[0m ${pc.dim(hex)}`;\n}\n","import * as p from \"@clack/prompts\";\nimport pc from \"picocolors\";\nimport { previewHexColor } from \"./preview\";\n\nexport interface ThemeConfig {\n brandPrimary: string;\n brandSecondary: string;\n brandAccent: string;\n radius: \"sharp\" | \"subtle\" | \"rounded\" | \"pill\";\n shadow: \"flat\" | \"subtle\" | \"elevated\";\n motion: \"snappy\" | \"smooth\" | \"minimal\";\n density: \"compact\" | \"default\" | \"spacious\";\n fontFamily: string;\n fontWeights: {\n normal: number;\n medium: number;\n semibold: number;\n bold: number;\n };\n}\n\nfunction isValidHex(hex: string | undefined): boolean {\n return hex != null && /^#[0-9A-Fa-f]{6}$/.test(hex);\n}\n\nexport async function runPrompts(existing?: ThemeConfig): Promise<ThemeConfig | null> {\n // Brand colors\n p.log.info(pc.bold(\"Brand Colors\"));\n\n if (existing) {\n p.log.message(\n `Current: Primary ${previewHexColor(existing.brandPrimary)} Secondary ${previewHexColor(existing.brandSecondary)} Accent ${previewHexColor(existing.brandAccent)}`\n );\n }\n\n const brandPrimary = await p.text({\n message: \"Primary brand color (hex)\",\n placeholder: \"#1e3a5f\",\n ...(existing?.brandPrimary && { defaultValue: existing.brandPrimary }),\n validate: (v) => (!isValidHex(v) ? \"Enter a valid hex color (e.g. #1e3a5f)\" : undefined),\n });\n if (p.isCancel(brandPrimary)) return null;\n\n p.log.message(` ${previewHexColor(brandPrimary as string)} Primary`);\n\n const brandSecondary = await p.text({\n message: \"Secondary brand color (hex)\",\n placeholder: \"#2d9d6e\",\n ...(existing?.brandSecondary && { defaultValue: existing.brandSecondary }),\n validate: (v) => (!isValidHex(v) ? \"Enter a valid hex color (e.g. #2d9d6e)\" : undefined),\n });\n if (p.isCancel(brandSecondary)) return null;\n\n p.log.message(` ${previewHexColor(brandSecondary as string)} Secondary`);\n\n const brandAccent = await p.text({\n message: \"Accent brand color (hex)\",\n placeholder: \"#e89b20\",\n ...(existing?.brandAccent && { defaultValue: existing.brandAccent }),\n validate: (v) => (!isValidHex(v) ? \"Enter a valid hex color (e.g. #e89b20)\" : undefined),\n });\n if (p.isCancel(brandAccent)) return null;\n\n p.log.message(` ${previewHexColor(brandAccent as string)} Accent`);\n\n // Radius\n const radius = await p.select({\n message: \"Border radius preset\",\n initialValue: existing?.radius ?? \"rounded\",\n options: [\n { value: \"sharp\" as const, label: \"Sharp\", hint: \"0px — square corners\" },\n { value: \"subtle\" as const, label: \"Subtle\", hint: \"6px — barely rounded\" },\n { value: \"rounded\" as const, label: \"Rounded\", hint: \"8px — balanced (default)\" },\n { value: \"pill\" as const, label: \"Pill\", hint: \"12px — soft, bubbly\" },\n ],\n });\n if (p.isCancel(radius)) return null;\n\n // Shadow\n const shadow = await p.select({\n message: \"Shadow preset\",\n initialValue: existing?.shadow ?? \"subtle\",\n options: [\n { value: \"flat\" as const, label: \"Flat\", hint: \"No shadows — clean, modern\" },\n { value: \"subtle\" as const, label: \"Subtle\", hint: \"Soft low-opacity shadows (default)\" },\n { value: \"elevated\" as const, label: \"Elevated\", hint: \"Prominent layered shadows\" },\n ],\n });\n if (p.isCancel(shadow)) return null;\n\n // Motion\n const motion = await p.select({\n message: \"Motion preset\",\n initialValue: existing?.motion ?? \"smooth\",\n options: [\n { value: \"snappy\" as const, label: \"Snappy\", hint: \"Fast, spring-like (150ms)\" },\n { value: \"smooth\" as const, label: \"Smooth\", hint: \"Balanced ease-out (200ms, default)\" },\n { value: \"minimal\" as const, label: \"Minimal\", hint: \"Barely-there, linear (100ms)\" },\n ],\n });\n if (p.isCancel(motion)) return null;\n\n // Density\n const density = await p.select({\n message: \"Component density\",\n initialValue: existing?.density ?? \"default\",\n options: [\n { value: \"compact\" as const, label: \"Compact\", hint: \"Tight padding, smaller components\" },\n { value: \"default\" as const, label: \"Default\", hint: \"Balanced spacing\" },\n { value: \"spacious\" as const, label: \"Spacious\", hint: \"Generous padding, larger components\" },\n ],\n });\n if (p.isCancel(density)) return null;\n\n // Font\n p.log.info(pc.bold(\"Typography\"));\n\n const fontFamily = await p.text({\n message: \"Font family name\",\n placeholder: \"Inter\",\n defaultValue: existing?.fontFamily ?? \"Inter\",\n });\n if (p.isCancel(fontFamily)) return null;\n\n // Font weights\n const customizeWeights = await p.confirm({\n message: \"Customize font weights? (default: 400/500/600/700)\",\n initialValue: false,\n });\n if (p.isCancel(customizeWeights)) return null;\n\n let fontWeights = existing?.fontWeights ?? { normal: 400, medium: 500, semibold: 600, bold: 700 };\n\n if (customizeWeights) {\n const normal = await p.text({\n message: \"Normal weight\",\n defaultValue: String(fontWeights.normal),\n validate: (v) => (isNaN(Number(v)) ? \"Must be a number\" : undefined),\n });\n if (p.isCancel(normal)) return null;\n\n const medium = await p.text({\n message: \"Medium weight\",\n defaultValue: String(fontWeights.medium),\n validate: (v) => (isNaN(Number(v)) ? \"Must be a number\" : undefined),\n });\n if (p.isCancel(medium)) return null;\n\n const semibold = await p.text({\n message: \"Semibold weight\",\n defaultValue: String(fontWeights.semibold),\n validate: (v) => (isNaN(Number(v)) ? \"Must be a number\" : undefined),\n });\n if (p.isCancel(semibold)) return null;\n\n const bold = await p.text({\n message: \"Bold weight\",\n defaultValue: String(fontWeights.bold),\n validate: (v) => (isNaN(Number(v)) ? \"Must be a number\" : undefined),\n });\n if (p.isCancel(bold)) return null;\n\n fontWeights = {\n normal: Number(normal),\n medium: Number(medium),\n semibold: Number(semibold),\n bold: Number(bold),\n };\n }\n\n return {\n brandPrimary: brandPrimary as string,\n brandSecondary: brandSecondary as string,\n brandAccent: brandAccent as string,\n radius: radius as ThemeConfig[\"radius\"],\n shadow: shadow as ThemeConfig[\"shadow\"],\n motion: motion as ThemeConfig[\"motion\"],\n density: density as ThemeConfig[\"density\"],\n fontFamily: fontFamily as string,\n fontWeights,\n };\n}\n","import type { ThemeConfig } from \"./prompts\";\n\nfunction hexToHSL(hex: string): { h: number; s: number; l: number } {\n hex = hex.replace(\"#\", \"\");\n const r = parseInt(hex.substring(0, 2), 16) / 255;\n const g = parseInt(hex.substring(2, 4), 16) / 255;\n const b = parseInt(hex.substring(4, 6), 16) / 255;\n\n const max = Math.max(r, g, b);\n const min = Math.min(r, g, b);\n const l = (max + min) / 2;\n let h = 0;\n let s = 0;\n\n if (max !== min) {\n const d = max - min;\n s = l > 0.5 ? d / (2 - max - min) : d / (max + min);\n switch (max) {\n case r:\n h = ((g - b) / d + (g < b ? 6 : 0)) / 6;\n break;\n case g:\n h = ((b - r) / d + 2) / 6;\n break;\n case b:\n h = ((r - g) / d + 4) / 6;\n break;\n }\n }\n\n return {\n h: Math.round(h * 360),\n s: Math.round(s * 100),\n l: Math.round(l * 100),\n };\n}\n\nfunction hsl(h: number, s: number, l: number): string {\n return `${h} ${s}% ${l}%`;\n}\n\nfunction clamp(v: number, min: number, max: number): number {\n return Math.min(Math.max(v, min), max);\n}\n\ninterface HSL {\n h: number;\n s: number;\n l: number;\n}\n\nfunction deriveLight(primary: HSL, secondary: HSL, accent: HSL): Record<string, string> {\n return {\n background: hsl(primary.h, clamp(primary.s - 30, 0, 100), 100),\n foreground: hsl(primary.h, clamp(primary.s - 20, 0, 100), 10),\n card: hsl(primary.h, clamp(primary.s - 30, 0, 100), 100),\n \"card-foreground\": hsl(primary.h, clamp(primary.s - 20, 0, 100), 10),\n popover: hsl(primary.h, clamp(primary.s - 30, 0, 100), 100),\n \"popover-foreground\": hsl(primary.h, clamp(primary.s - 20, 0, 100), 10),\n primary: hsl(primary.h, primary.s, primary.l),\n \"primary-foreground\": hsl(primary.h, clamp(primary.s - 30, 0, 100), primary.l > 50 ? 10 : 98),\n secondary: hsl(secondary.h, clamp(secondary.s - 30, 0, 100), clamp(secondary.l + 40, 0, 100)),\n \"secondary-foreground\": hsl(secondary.h, secondary.s, clamp(secondary.l - 30, 0, 100)),\n accent: hsl(accent.h, accent.s, clamp(accent.l + 10, 0, 100)),\n \"accent-foreground\": hsl(accent.h, accent.s, clamp(accent.l - 60, 0, 100)),\n muted: hsl(primary.h, clamp(primary.s - 30, 0, 100), 96),\n \"muted-foreground\": hsl(primary.h, clamp(primary.s - 25, 0, 100), 45),\n destructive: \"0 84% 60%\",\n \"destructive-foreground\": \"0 0% 98%\",\n border: hsl(primary.h, clamp(primary.s - 25, 0, 100), 91),\n input: hsl(primary.h, clamp(primary.s - 25, 0, 100), 91),\n ring: hsl(primary.h, primary.s, primary.l),\n };\n}\n\nfunction deriveDark(primary: HSL, secondary: HSL, accent: HSL): Record<string, string> {\n const darkPrimary = { ...primary, l: primary.l < 50 ? primary.l + 20 : primary.l };\n\n return {\n background: hsl(primary.h, clamp(primary.s - 25, 0, 100), 7),\n foreground: hsl(primary.h, clamp(primary.s - 30, 0, 100), 98),\n card: hsl(primary.h, clamp(primary.s - 25, 0, 100), 10),\n \"card-foreground\": hsl(primary.h, clamp(primary.s - 30, 0, 100), 98),\n popover: hsl(primary.h, clamp(primary.s - 25, 0, 100), 10),\n \"popover-foreground\": hsl(primary.h, clamp(primary.s - 30, 0, 100), 98),\n primary: hsl(darkPrimary.h, darkPrimary.s, darkPrimary.l),\n \"primary-foreground\": hsl(primary.h, clamp(primary.s - 30, 0, 100), darkPrimary.l > 50 ? 10 : 98),\n secondary: hsl(secondary.h, clamp(secondary.s - 20, 0, 100), 18),\n \"secondary-foreground\": hsl(secondary.h, secondary.s, clamp(secondary.l + 30, 0, 100)),\n accent: hsl(accent.h, clamp(accent.s - 10, 0, 100), 20),\n \"accent-foreground\": hsl(accent.h, accent.s, clamp(accent.l + 40, 0, 100)),\n muted: hsl(primary.h, clamp(primary.s - 25, 0, 100), 18),\n \"muted-foreground\": hsl(primary.h, clamp(primary.s - 20, 0, 100), 65),\n destructive: \"0 62% 30%\",\n \"destructive-foreground\": \"0 0% 98%\",\n border: hsl(primary.h, clamp(primary.s - 25, 0, 100), 18),\n input: hsl(primary.h, clamp(primary.s - 25, 0, 100), 18),\n ring: hsl(darkPrimary.h, darkPrimary.s, darkPrimary.l),\n };\n}\n\nexport function generateThemeCSS(config: ThemeConfig): string {\n const primary = hexToHSL(config.brandPrimary);\n const secondary = hexToHSL(config.brandSecondary);\n const accent = hexToHSL(config.brandAccent);\n\n const light = deriveLight(primary, secondary, accent);\n const dark = deriveDark(primary, secondary, accent);\n\n const lines: string[] = [\n `/* Bison Lab Theme — Generated by @bison-lab/create-theme */`,\n `/* Brand: ${config.brandPrimary} / ${config.brandSecondary} / ${config.brandAccent} */`,\n ``,\n `:root {`,\n ...Object.entries(light).map(([k, v]) => ` --${k}: ${v};`),\n ``,\n ` /* Typography */`,\n ` --font-sans: '${config.fontFamily}', ui-sans-serif, system-ui, sans-serif;`,\n ` --font-weight-normal: ${config.fontWeights.normal};`,\n ` --font-weight-medium: ${config.fontWeights.medium};`,\n ` --font-weight-semibold: ${config.fontWeights.semibold};`,\n ` --font-weight-bold: ${config.fontWeights.bold};`,\n `}`,\n ``,\n `.dark {`,\n ...Object.entries(dark).map(([k, v]) => ` --${k}: ${v};`),\n `}`,\n ``,\n ];\n\n return lines.join(\"\\n\");\n}\n\nexport function generateTailwindConfig(config: ThemeConfig): string {\n return [\n `import bisonPreset from '@bison-lab/tailwind-preset';`,\n ``,\n `export default {`,\n ` presets: [bisonPreset],`,\n ` content: [`,\n ` './app/**/*.{ts,tsx}',`,\n ` './components/**/*.{ts,tsx}',`,\n ` './node_modules/@bison-lab/ui/dist/**/*.js',`,\n ` ],`,\n `};`,\n ].join(\"\\n\");\n}\n","import * as p from \"@clack/prompts\";\nimport pc from \"picocolors\";\nimport { existsSync, readFileSync, writeFileSync } from \"fs\";\nimport { resolve } from \"path\";\nimport { runPrompts, type ThemeConfig } from \"./prompts\";\nimport { generateThemeCSS, generateTailwindConfig } from \"./generate\";\n\nconst CONFIG_FILE = \"bison.config.json\";\nconst THEME_FILE = \"bison-theme.css\";\n\nasync function main() {\n p.intro(pc.bgCyan(pc.black(\" Bison Lab Theme Generator \")));\n\n const configPath = resolve(process.cwd(), CONFIG_FILE);\n let existingConfig: ThemeConfig | undefined;\n\n if (existsSync(configPath)) {\n const raw = JSON.parse(readFileSync(configPath, \"utf-8\")) as ThemeConfig;\n existingConfig = raw;\n\n const mode = await p.select({\n message: \"An existing theme was found. What would you like to do?\",\n options: [\n { value: \"update\", label: \"Update existing theme\", hint: \"Modify individual properties\" },\n { value: \"fresh\", label: \"Start fresh\", hint: \"Overwrite everything\" },\n ],\n });\n\n if (p.isCancel(mode)) {\n p.cancel(\"Cancelled.\");\n process.exit(0);\n }\n\n if (mode === \"fresh\") {\n existingConfig = undefined;\n }\n }\n\n const config = await runPrompts(existingConfig);\n\n if (!config) {\n p.cancel(\"Cancelled.\");\n process.exit(0);\n }\n\n const s = p.spinner();\n s.start(\"Generating theme files...\");\n\n const themeCSS = generateThemeCSS(config);\n const themePath = resolve(process.cwd(), THEME_FILE);\n writeFileSync(themePath, themeCSS, \"utf-8\");\n\n writeFileSync(configPath, JSON.stringify(config, null, 2), \"utf-8\");\n\n const tailwindSnippet = generateTailwindConfig(config);\n\n s.stop(\"Theme files generated!\");\n\n p.note(\n [\n `${pc.green(\"Created:\")} ${THEME_FILE}`,\n `${pc.green(\"Created:\")} ${CONFIG_FILE}`,\n \"\",\n `${pc.bold(\"Add to your tailwind.config.ts:\")}`,\n \"\",\n tailwindSnippet,\n \"\",\n `${pc.bold(\"Import in your app/layout.tsx:\")}`,\n \"\",\n `import '@bison-lab/tokens/css/globals.css';`,\n `import '@bison-lab/tokens/css/themes/radius-${config.radius}.css';`,\n `import '@bison-lab/tokens/css/themes/shadow-${config.shadow}.css';`,\n `import '@bison-lab/tokens/css/themes/motion-${config.motion}.css';`,\n `import '@bison-lab/tokens/css/themes/density-${config.density}.css';`,\n `import './${THEME_FILE}';`,\n ].join(\"\\n\"),\n \"Next steps\"\n );\n\n p.outro(pc.green(\"Done! Your Bison Lab theme is ready.\"));\n}\n\nmain().catch(console.error);\n"],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@bison-lab/create-theme",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Interactive CLI for generating and updating Bison Lab theme files",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"create-theme": "./dist/index.mjs"
|
|
8
|
+
},
|
|
9
|
+
"files": [
|
|
10
|
+
"dist"
|
|
11
|
+
],
|
|
12
|
+
"dependencies": {
|
|
13
|
+
"@clack/prompts": "^1.1.0",
|
|
14
|
+
"picocolors": "^1.1.1"
|
|
15
|
+
},
|
|
16
|
+
"devDependencies": {
|
|
17
|
+
"@types/node": "^25.5.0",
|
|
18
|
+
"tsdown": "^0.21.0",
|
|
19
|
+
"typescript": "^5.9.3"
|
|
20
|
+
},
|
|
21
|
+
"publishConfig": {
|
|
22
|
+
"access": "public"
|
|
23
|
+
},
|
|
24
|
+
"scripts": {
|
|
25
|
+
"build": "tsdown",
|
|
26
|
+
"dev": "tsdown --watch",
|
|
27
|
+
"clean": "rm -rf dist",
|
|
28
|
+
"typecheck": "tsc --noEmit"
|
|
29
|
+
}
|
|
30
|
+
}
|