@proto.ui/cli 0.0.1 → 0.0.2
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 +7 -0
- package/package.json +1 -1
- package/src/cli.mjs +262 -12
package/README.md
CHANGED
|
@@ -4,6 +4,13 @@ Local CLI package for generating Proto UI Tailwind assets.
|
|
|
4
4
|
|
|
5
5
|
## Commands
|
|
6
6
|
|
|
7
|
+
- `proto-ui shadcn [--styles-dir <dir>]`
|
|
7
8
|
- `proto-ui tokens --input <dir> --out <file>`
|
|
8
9
|
- `proto-ui tailwindcss --out <file> [--theme-import <path>] [--tokens-import <path>]`
|
|
9
10
|
- `proto-ui theme shadcn --out <file>`
|
|
11
|
+
|
|
12
|
+
`proto-ui shadcn` writes these preset files directly:
|
|
13
|
+
|
|
14
|
+
- `prototype-tokens.generated.css`
|
|
15
|
+
- `tailwindcss.css`
|
|
16
|
+
- `shadcn-theme.css`
|
package/package.json
CHANGED
package/src/cli.mjs
CHANGED
|
@@ -7,6 +7,203 @@ const DEFAULT_THEME_NAME = 'shadcn';
|
|
|
7
7
|
const DEFAULT_THEME_IMPORT = './shadcn-theme.css';
|
|
8
8
|
const DEFAULT_TOKENS_IMPORT = './prototype-tokens.generated.css';
|
|
9
9
|
|
|
10
|
+
const SHADCN_TOKENS_CSS = `/* This file is auto-generated by apps/www/scripts/generate-prototype-tailwind-sources.mjs. */
|
|
11
|
+
/* Do not edit by hand. */
|
|
12
|
+
|
|
13
|
+
@source inline("absolute");
|
|
14
|
+
@source inline("active:bg-background");
|
|
15
|
+
@source inline("active:bg-muted");
|
|
16
|
+
@source inline("active:bg-muted/80");
|
|
17
|
+
@source inline("active:scale-[0.98]");
|
|
18
|
+
@source inline("active:scale-[0.99]");
|
|
19
|
+
@source inline("active:shadow-xs");
|
|
20
|
+
@source inline("active:text-foreground");
|
|
21
|
+
@source inline("active:translate-y-px");
|
|
22
|
+
@source inline("aria-checked:bg-accent");
|
|
23
|
+
@source inline("aria-checked:bg-muted");
|
|
24
|
+
@source inline("aria-checked:bg-primary");
|
|
25
|
+
@source inline("aria-checked:pl-[22px]");
|
|
26
|
+
@source inline("aria-checked:pr-0.5");
|
|
27
|
+
@source inline("aria-checked:text-accent-foreground");
|
|
28
|
+
@source inline("aria-checked:text-muted-foreground");
|
|
29
|
+
@source inline("aria-checked:text-primary-foreground");
|
|
30
|
+
@source inline("aria-current:hidden");
|
|
31
|
+
@source inline("aria-expanded:bg-muted");
|
|
32
|
+
@source inline("aria-expanded:bg-secondary");
|
|
33
|
+
@source inline("aria-expanded:text-foreground");
|
|
34
|
+
@source inline("aria-expanded:text-secondary-foreground");
|
|
35
|
+
@source inline("aria-invalid:border-destructive");
|
|
36
|
+
@source inline("aria-invalid:ring-3");
|
|
37
|
+
@source inline("aria-invalid:ring-destructive/20");
|
|
38
|
+
@source inline("aria-selected:bg-background");
|
|
39
|
+
@source inline("aria-selected:shadow-xs");
|
|
40
|
+
@source inline("aria-selected:text-foreground");
|
|
41
|
+
@source inline("backdrop-blur-xs");
|
|
42
|
+
@source inline("bg-accent");
|
|
43
|
+
@source inline("bg-background");
|
|
44
|
+
@source inline("bg-background/70");
|
|
45
|
+
@source inline("bg-clip-padding");
|
|
46
|
+
@source inline("bg-destructive/10");
|
|
47
|
+
@source inline("bg-destructive/20");
|
|
48
|
+
@source inline("bg-destructive/30");
|
|
49
|
+
@source inline("bg-input");
|
|
50
|
+
@source inline("bg-input/30");
|
|
51
|
+
@source inline("bg-input/50");
|
|
52
|
+
@source inline("bg-input/80");
|
|
53
|
+
@source inline("bg-muted");
|
|
54
|
+
@source inline("bg-muted/60");
|
|
55
|
+
@source inline("bg-muted/80");
|
|
56
|
+
@source inline("bg-primary");
|
|
57
|
+
@source inline("bg-primary/80");
|
|
58
|
+
@source inline("bg-primary/90");
|
|
59
|
+
@source inline("bg-secondary");
|
|
60
|
+
@source inline("bg-secondary/80");
|
|
61
|
+
@source inline("bg-transparent");
|
|
62
|
+
@source inline("block");
|
|
63
|
+
@source inline("border");
|
|
64
|
+
@source inline("border-border");
|
|
65
|
+
@source inline("border-border/50");
|
|
66
|
+
@source inline("border-border/60");
|
|
67
|
+
@source inline("border-destructive");
|
|
68
|
+
@source inline("border-destructive/40");
|
|
69
|
+
@source inline("border-destructive/50");
|
|
70
|
+
@source inline("border-input");
|
|
71
|
+
@source inline("border-ring");
|
|
72
|
+
@source inline("border-transparent");
|
|
73
|
+
@source inline("cursor-default");
|
|
74
|
+
@source inline("dark:aria-checked:bg-input/50");
|
|
75
|
+
@source inline("dark:aria-checked:bg-primary");
|
|
76
|
+
@source inline("dark:aria-invalid:border-destructive/50");
|
|
77
|
+
@source inline("dark:aria-invalid:ring-destructive/40");
|
|
78
|
+
@source inline("dark:bg-destructive/20");
|
|
79
|
+
@source inline("dark:bg-input/30");
|
|
80
|
+
@source inline("dark:border-input");
|
|
81
|
+
@source inline("dark:data-[focus-visible]:ring-destructive/40");
|
|
82
|
+
@source inline("dark:hover:bg-destructive/30");
|
|
83
|
+
@source inline("dark:hover:bg-input/50");
|
|
84
|
+
@source inline("data-[disabled]:opacity-50");
|
|
85
|
+
@source inline("data-[disabled]:pointer-events-none");
|
|
86
|
+
@source inline("data-[focus-visible]:bg-background");
|
|
87
|
+
@source inline("data-[focus-visible]:border-destructive/40");
|
|
88
|
+
@source inline("data-[focus-visible]:border-ring");
|
|
89
|
+
@source inline("data-[focus-visible]:ring-2");
|
|
90
|
+
@source inline("data-[focus-visible]:ring-3");
|
|
91
|
+
@source inline("data-[focus-visible]:ring-destructive/20");
|
|
92
|
+
@source inline("data-[focus-visible]:ring-inset");
|
|
93
|
+
@source inline("data-[focus-visible]:ring-offset-2");
|
|
94
|
+
@source inline("data-[focus-visible]:ring-offset-background");
|
|
95
|
+
@source inline("data-[focus-visible]:ring-ring/40");
|
|
96
|
+
@source inline("data-[focus-visible]:ring-ring/50");
|
|
97
|
+
@source inline("data-[focus-visible]:shadow-xs");
|
|
98
|
+
@source inline("data-[focus-visible]:text-foreground");
|
|
99
|
+
@source inline("duration-200");
|
|
100
|
+
@source inline("ease-in-out");
|
|
101
|
+
@source inline("flex");
|
|
102
|
+
@source inline("flex-col");
|
|
103
|
+
@source inline("font-medium");
|
|
104
|
+
@source inline("gap-1");
|
|
105
|
+
@source inline("gap-1.5");
|
|
106
|
+
@source inline("gap-2");
|
|
107
|
+
@source inline("gap-3");
|
|
108
|
+
@source inline("group/button");
|
|
109
|
+
@source inline("h-10");
|
|
110
|
+
@source inline("h-6");
|
|
111
|
+
@source inline("h-7");
|
|
112
|
+
@source inline("h-8");
|
|
113
|
+
@source inline("h-9");
|
|
114
|
+
@source inline("hidden");
|
|
115
|
+
@source inline("hover:aria-checked:bg-input");
|
|
116
|
+
@source inline("hover:aria-checked:bg-muted/60");
|
|
117
|
+
@source inline("hover:aria-checked:bg-primary/90");
|
|
118
|
+
@source inline("hover:aria-checked:text-foreground");
|
|
119
|
+
@source inline("hover:aria-selected:bg-background/70");
|
|
120
|
+
@source inline("hover:aria-selected:shadow-xs");
|
|
121
|
+
@source inline("hover:aria-selected:text-foreground");
|
|
122
|
+
@source inline("hover:bg-destructive/20");
|
|
123
|
+
@source inline("hover:bg-muted");
|
|
124
|
+
@source inline("hover:bg-primary/80");
|
|
125
|
+
@source inline("hover:bg-secondary/80");
|
|
126
|
+
@source inline("hover:data-[focus-visible]:data-[focused]:bg-muted");
|
|
127
|
+
@source inline("hover:data-[focus-visible]:data-[focused]:text-foreground");
|
|
128
|
+
@source inline("hover:text-foreground");
|
|
129
|
+
@source inline("hover:underline");
|
|
130
|
+
@source inline("inline-flex");
|
|
131
|
+
@source inline("items-center");
|
|
132
|
+
@source inline("items-start");
|
|
133
|
+
@source inline("justify-center");
|
|
134
|
+
@source inline("leading-6");
|
|
135
|
+
@source inline("left-0");
|
|
136
|
+
@source inline("min-h-28");
|
|
137
|
+
@source inline("min-w-10");
|
|
138
|
+
@source inline("min-w-56");
|
|
139
|
+
@source inline("min-w-8");
|
|
140
|
+
@source inline("min-w-9");
|
|
141
|
+
@source inline("mt-2");
|
|
142
|
+
@source inline("opacity-50");
|
|
143
|
+
@source inline("outline-none");
|
|
144
|
+
@source inline("overflow-hidden");
|
|
145
|
+
@source inline("p-1");
|
|
146
|
+
@source inline("p-4");
|
|
147
|
+
@source inline("peer");
|
|
148
|
+
@source inline("pl-0.5");
|
|
149
|
+
@source inline("pl-[22px]");
|
|
150
|
+
@source inline("pointer-events-none");
|
|
151
|
+
@source inline("pr-0.5");
|
|
152
|
+
@source inline("pr-[22px]");
|
|
153
|
+
@source inline("px-2.5");
|
|
154
|
+
@source inline("px-3");
|
|
155
|
+
@source inline("px-5");
|
|
156
|
+
@source inline("py-1.5");
|
|
157
|
+
@source inline("py-2");
|
|
158
|
+
@source inline("relative");
|
|
159
|
+
@source inline("ring-0");
|
|
160
|
+
@source inline("ring-2");
|
|
161
|
+
@source inline("ring-3");
|
|
162
|
+
@source inline("ring-destructive/20");
|
|
163
|
+
@source inline("ring-destructive/40");
|
|
164
|
+
@source inline("ring-inset");
|
|
165
|
+
@source inline("ring-offset-2");
|
|
166
|
+
@source inline("ring-offset-background");
|
|
167
|
+
@source inline("ring-ring/40");
|
|
168
|
+
@source inline("ring-ring/50");
|
|
169
|
+
@source inline("rounded-[min(var(--radius-md),12px)]");
|
|
170
|
+
@source inline("rounded-full");
|
|
171
|
+
@source inline("rounded-lg");
|
|
172
|
+
@source inline("rounded-md");
|
|
173
|
+
@source inline("rounded-xl");
|
|
174
|
+
@source inline("scale-[0.98]");
|
|
175
|
+
@source inline("scale-[0.99]");
|
|
176
|
+
@source inline("select-none");
|
|
177
|
+
@source inline("shadow-lg");
|
|
178
|
+
@source inline("shadow-xs");
|
|
179
|
+
@source inline("shrink-0");
|
|
180
|
+
@source inline("size-5");
|
|
181
|
+
@source inline("size-8");
|
|
182
|
+
@source inline("text-[0.8rem]");
|
|
183
|
+
@source inline("text-accent-foreground");
|
|
184
|
+
@source inline("text-destructive");
|
|
185
|
+
@source inline("text-foreground");
|
|
186
|
+
@source inline("text-left");
|
|
187
|
+
@source inline("text-muted-foreground");
|
|
188
|
+
@source inline("text-primary");
|
|
189
|
+
@source inline("text-primary-foreground");
|
|
190
|
+
@source inline("text-secondary-foreground");
|
|
191
|
+
@source inline("text-sm");
|
|
192
|
+
@source inline("top-full");
|
|
193
|
+
@source inline("transition-all");
|
|
194
|
+
@source inline("transition-colors");
|
|
195
|
+
@source inline("translate-x-0");
|
|
196
|
+
@source inline("translate-y-px");
|
|
197
|
+
@source inline("underline");
|
|
198
|
+
@source inline("underline-offset-4");
|
|
199
|
+
@source inline("w-11");
|
|
200
|
+
@source inline("w-80");
|
|
201
|
+
@source inline("w-full");
|
|
202
|
+
@source inline("whitespace-nowrap");
|
|
203
|
+
@source inline("will-change-transform");
|
|
204
|
+
@source inline("z-50");
|
|
205
|
+
`;
|
|
206
|
+
|
|
10
207
|
const SHADCN_THEME_CSS = `:root {
|
|
11
208
|
--radius: 0.625rem;
|
|
12
209
|
--background: lab(100% 0 0);
|
|
@@ -150,6 +347,11 @@ const TAILWIND_BASE_TEMPLATE = `@import 'tailwindcss';
|
|
|
150
347
|
--color-selection-foreground: var(--selection-foreground);
|
|
151
348
|
}
|
|
152
349
|
|
|
350
|
+
@font-face {
|
|
351
|
+
font-family: 'GeistSans';
|
|
352
|
+
src: url('./assets/font/GeistVF.woff2') format('woff2-variations');
|
|
353
|
+
}
|
|
354
|
+
|
|
153
355
|
@layer base {
|
|
154
356
|
:root {
|
|
155
357
|
--radius-xl: calc(var(--radius) + 4px);
|
|
@@ -166,6 +368,31 @@ const TAILWIND_BASE_TEMPLATE = `@import 'tailwindcss';
|
|
|
166
368
|
body {
|
|
167
369
|
background-color: var(--color-background);
|
|
168
370
|
color: var(--color-foreground);
|
|
371
|
+
font-family:
|
|
372
|
+
var(--color-font-geist-sans),
|
|
373
|
+
ui-sans-serif,
|
|
374
|
+
system-ui,
|
|
375
|
+
-apple-system,
|
|
376
|
+
BlinkMacSystemFont,
|
|
377
|
+
'Segoe UI',
|
|
378
|
+
Roboto,
|
|
379
|
+
'Helvetica Neue',
|
|
380
|
+
Arial,
|
|
381
|
+
'Noto Sans',
|
|
382
|
+
sans-serif,
|
|
383
|
+
'Apple Color Emoji',
|
|
384
|
+
'Segoe UI Emoji',
|
|
385
|
+
'Segoe UI Symbol',
|
|
386
|
+
'Noto Color Emoji';
|
|
387
|
+
text-rendering: optimizeLegibility;
|
|
388
|
+
-webkit-font-smoothing: antialiased;
|
|
389
|
+
-moz-osx-font-smoothing: grayscale;
|
|
390
|
+
unicode-bidi: isolate;
|
|
391
|
+
font-feature-settings: normal;
|
|
392
|
+
font-synthesis-weight: none;
|
|
393
|
+
font-variation-settings: normal;
|
|
394
|
+
text-size-adjust: 100%;
|
|
395
|
+
-webkit-text-size-adjust: 100%;
|
|
169
396
|
}
|
|
170
397
|
`;
|
|
171
398
|
|
|
@@ -199,13 +426,13 @@ function printHelp() {
|
|
|
199
426
|
console.log(`proto-ui
|
|
200
427
|
|
|
201
428
|
Usage:
|
|
202
|
-
proto-ui <theme> [--
|
|
429
|
+
proto-ui <theme> [--styles-dir <dir>]
|
|
203
430
|
proto-ui tokens --input <dir> --out <file>
|
|
204
431
|
proto-ui tailwindcss [--theme-import <path>] [--tokens-import <path>] --out <file>
|
|
205
432
|
proto-ui theme <name> --out <file>
|
|
206
433
|
|
|
207
434
|
Examples:
|
|
208
|
-
proto-ui shadcn --
|
|
435
|
+
proto-ui shadcn --styles-dir ./src/styles
|
|
209
436
|
proto-ui tokens --input ./packages/prototypes --out ./src/styles/prototype-tokens.generated.css
|
|
210
437
|
proto-ui tailwindcss --out ./src/styles/tailwindcss.css
|
|
211
438
|
proto-ui theme shadcn --out ./src/styles/shadcn-theme.css
|
|
@@ -214,18 +441,27 @@ Examples:
|
|
|
214
441
|
|
|
215
442
|
async function runPreset(themeName, args) {
|
|
216
443
|
const options = parseOptions(args);
|
|
217
|
-
const
|
|
444
|
+
const normalizedTheme = themeName.toLowerCase();
|
|
445
|
+
if (normalizedTheme !== DEFAULT_THEME_NAME) {
|
|
446
|
+
throw new Error(
|
|
447
|
+
`unsupported theme "${themeName}". currently supported: ${DEFAULT_THEME_NAME}.`
|
|
448
|
+
);
|
|
449
|
+
}
|
|
218
450
|
const stylesDir = options['styles-dir'] ?? './src/styles';
|
|
219
451
|
const tokensFileName = options['tokens-file'] ?? 'prototype-tokens.generated.css';
|
|
220
452
|
const tailwindFileName = options['tailwind-file'] ?? 'tailwindcss.css';
|
|
221
|
-
const themeFileName = options['theme-file'] ?? `${
|
|
453
|
+
const themeFileName = options['theme-file'] ?? `${normalizedTheme}-theme.css`;
|
|
222
454
|
|
|
223
455
|
const tokensOut = path.join(stylesDir, tokensFileName);
|
|
224
456
|
const themeOut = path.join(stylesDir, themeFileName);
|
|
225
457
|
const tailwindOut = path.join(stylesDir, tailwindFileName);
|
|
226
458
|
|
|
227
|
-
|
|
228
|
-
await
|
|
459
|
+
const tokensOutputFile = path.resolve(process.cwd(), tokensOut);
|
|
460
|
+
await ensureDirectory(tokensOutputFile);
|
|
461
|
+
await fs.writeFile(tokensOutputFile, SHADCN_TOKENS_CSS, 'utf8');
|
|
462
|
+
console.log(`[proto-ui] tokens(preset): wrote ${relativeToCwd(tokensOutputFile)}`);
|
|
463
|
+
|
|
464
|
+
await runGenerateTheme([normalizedTheme, '--out', themeOut]);
|
|
229
465
|
|
|
230
466
|
const tailwindAbs = path.resolve(process.cwd(), tailwindOut);
|
|
231
467
|
const themeImport = toCssImportPath(tailwindAbs, path.resolve(process.cwd(), themeOut));
|
|
@@ -241,7 +477,7 @@ async function runPreset(themeName, args) {
|
|
|
241
477
|
]);
|
|
242
478
|
|
|
243
479
|
console.log(
|
|
244
|
-
`[proto-ui] setup(${
|
|
480
|
+
`[proto-ui] setup(${normalizedTheme}): completed tokens + theme + tailwindcss in ${stylesDir}`
|
|
245
481
|
);
|
|
246
482
|
}
|
|
247
483
|
|
|
@@ -252,7 +488,7 @@ async function runGenerateTokens(args) {
|
|
|
252
488
|
const root = path.resolve(process.cwd(), input);
|
|
253
489
|
const outputFile = path.resolve(process.cwd(), outFile);
|
|
254
490
|
|
|
255
|
-
const files = await
|
|
491
|
+
const files = await collectSourceFiles(root);
|
|
256
492
|
const tokens = new Set();
|
|
257
493
|
|
|
258
494
|
for (const file of files) {
|
|
@@ -262,7 +498,7 @@ async function runGenerateTokens(args) {
|
|
|
262
498
|
sourceText,
|
|
263
499
|
ts.ScriptTarget.Latest,
|
|
264
500
|
true,
|
|
265
|
-
file
|
|
501
|
+
scriptKindForFile(file)
|
|
266
502
|
);
|
|
267
503
|
const scope = createScope();
|
|
268
504
|
walk(sourceFile, scope, tokens);
|
|
@@ -775,17 +1011,31 @@ function escapeForCss(token) {
|
|
|
775
1011
|
return token.replace(/\\/g, '\\\\').replace(/"/g, '\\"');
|
|
776
1012
|
}
|
|
777
1013
|
|
|
778
|
-
|
|
1014
|
+
function scriptKindForFile(file) {
|
|
1015
|
+
const ext = path.extname(file).toLowerCase();
|
|
1016
|
+
if (ext === '.tsx') return ts.ScriptKind.TSX;
|
|
1017
|
+
if (ext === '.jsx') return ts.ScriptKind.JSX;
|
|
1018
|
+
if (ext === '.js' || ext === '.mjs' || ext === '.cjs') return ts.ScriptKind.JS;
|
|
1019
|
+
return ts.ScriptKind.TS;
|
|
1020
|
+
}
|
|
1021
|
+
|
|
1022
|
+
async function collectSourceFiles(dir) {
|
|
779
1023
|
const out = [];
|
|
780
1024
|
const entries = await fs.readdir(dir, { withFileTypes: true });
|
|
781
1025
|
for (const entry of entries) {
|
|
782
1026
|
const fullPath = path.join(dir, entry.name);
|
|
783
1027
|
if (entry.isDirectory()) {
|
|
784
1028
|
if (entry.name === 'dist' || entry.name === 'test' || entry.name === 'node_modules') continue;
|
|
785
|
-
out.push(...(await
|
|
1029
|
+
out.push(...(await collectSourceFiles(fullPath)));
|
|
786
1030
|
continue;
|
|
787
1031
|
}
|
|
788
|
-
if (
|
|
1032
|
+
if (
|
|
1033
|
+
entry.isFile() &&
|
|
1034
|
+
/\.(ts|tsx|mts|cts|js|jsx|mjs|cjs)$/.test(entry.name) &&
|
|
1035
|
+
!/\.d\.ts$/i.test(entry.name)
|
|
1036
|
+
) {
|
|
1037
|
+
out.push(fullPath);
|
|
1038
|
+
}
|
|
789
1039
|
}
|
|
790
1040
|
return out;
|
|
791
1041
|
}
|