myoperator-ui 0.0.2 → 0.0.4
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 +231 -50
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -11,22 +11,70 @@ import prompts from "prompts";
|
|
|
11
11
|
import ora from "ora";
|
|
12
12
|
|
|
13
13
|
// src/utils/registry.ts
|
|
14
|
-
|
|
15
|
-
return
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
14
|
+
function prefixTailwindClasses(content, prefix) {
|
|
15
|
+
if (!prefix) return content;
|
|
16
|
+
const patterns = [
|
|
17
|
+
// Layout & Display
|
|
18
|
+
/\b(flex|inline-flex|block|inline-block|grid|inline-grid|hidden|table|contents)\b/g,
|
|
19
|
+
// Flexbox & Grid
|
|
20
|
+
/\b(items-|justify-|gap-|flex-|grid-|col-|row-|place-|self-|order-)/g,
|
|
21
|
+
// Spacing
|
|
22
|
+
/\b([mp][trblxy]?-\d+|[mp][trblxy]?-\[)/g,
|
|
23
|
+
/\b(space-[xy]-)/g,
|
|
24
|
+
// Sizing
|
|
25
|
+
/\b([wh]-(full|screen|auto|min|max|fit|\d+|px|\[))/g,
|
|
26
|
+
/\b(min-[wh]-|max-[wh]-)/g,
|
|
27
|
+
// Typography
|
|
28
|
+
/\b(text-(?:xs|sm|base|lg|xl|2xl|3xl|4xl|5xl|6xl|7xl|8xl|9xl|left|center|right|justify|wrap|nowrap|ellipsis|clip))\b/g,
|
|
29
|
+
/\b(font-(?:sans|serif|mono|thin|extralight|light|normal|medium|semibold|bold|extrabold|black))\b/g,
|
|
30
|
+
/\b(leading-|tracking-|whitespace-)/g,
|
|
31
|
+
// Colors (bg, text, border colors)
|
|
32
|
+
/\b(bg-|text-|border-|ring-|from-|via-|to-|fill-|stroke-)(?!\[)/g,
|
|
33
|
+
// Borders & Rings
|
|
34
|
+
/\b(border|rounded|ring|outline)(?:-|$)/g,
|
|
35
|
+
// Effects
|
|
36
|
+
/\b(shadow|opacity-|blur-|brightness-|contrast-|grayscale|invert|saturate|sepia)/g,
|
|
37
|
+
// Transitions & Animations
|
|
38
|
+
/\b(transition|duration-|ease-|delay-|animate-)/g,
|
|
39
|
+
// Transforms
|
|
40
|
+
/\b(scale-|rotate-|translate-|skew-|origin-|transform)/g,
|
|
41
|
+
// Interactivity
|
|
42
|
+
/\b(cursor-|pointer-events-|resize|select-|scroll-)/g,
|
|
43
|
+
// Pseudo-classes prefixes
|
|
44
|
+
/\b(hover:|focus:|active:|disabled:|focus-visible:|focus-within:|group-hover:|peer-)/g,
|
|
45
|
+
// Responsive prefixes
|
|
46
|
+
/\b(sm:|md:|lg:|xl:|2xl:)/g,
|
|
47
|
+
// Dark mode
|
|
48
|
+
/\b(dark:)/g,
|
|
49
|
+
// Other common utilities
|
|
50
|
+
/\b(overflow-|z-|relative|absolute|fixed|sticky|inset-|top-|right-|bottom-|left-)/g,
|
|
51
|
+
/\b(underline|line-through|no-underline|underline-offset-)/g,
|
|
52
|
+
/\b(sr-only|not-sr-only)\b/g
|
|
53
|
+
];
|
|
54
|
+
let result = content;
|
|
55
|
+
result = result.replace(
|
|
56
|
+
/(className=["'`{]|cn\(["'`])([^"'`}]+)(["'`}])/g,
|
|
57
|
+
(match, start, classes, end) => {
|
|
58
|
+
let prefixedClasses = classes;
|
|
59
|
+
prefixedClasses = prefixedClasses.replace(
|
|
60
|
+
/(?<=^|\s)([a-z])/g,
|
|
61
|
+
(m, char) => `${prefix}${char}`
|
|
62
|
+
);
|
|
63
|
+
prefixedClasses = prefixedClasses.replace(
|
|
64
|
+
/(?<=^|\s)-([a-z])/g,
|
|
65
|
+
(m, char) => `-${prefix}${char}`
|
|
66
|
+
);
|
|
67
|
+
prefixedClasses = prefixedClasses.replace(
|
|
68
|
+
new RegExp(`${prefix}(hover|focus|active|disabled|focus-visible|focus-within|group-hover|sm|md|lg|xl|2xl|dark):${prefix}`, "g"),
|
|
69
|
+
`${prefix}$1:`
|
|
70
|
+
);
|
|
71
|
+
return start + prefixedClasses + end;
|
|
72
|
+
}
|
|
73
|
+
);
|
|
74
|
+
return result;
|
|
75
|
+
}
|
|
76
|
+
async function getRegistry(prefix = "") {
|
|
77
|
+
const buttonContent = prefixTailwindClasses(`import * as React from "react"
|
|
30
78
|
import { Slot } from "@radix-ui/react-slot"
|
|
31
79
|
import { cva, type VariantProps } from "class-variance-authority"
|
|
32
80
|
import { Loader2 } from "lucide-react"
|
|
@@ -114,7 +162,22 @@ const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
|
|
|
114
162
|
Button.displayName = "Button"
|
|
115
163
|
|
|
116
164
|
export { Button, buttonVariants }
|
|
117
|
-
|
|
165
|
+
`, prefix);
|
|
166
|
+
return {
|
|
167
|
+
button: {
|
|
168
|
+
name: "button",
|
|
169
|
+
description: "A customizable button component with variants, sizes, and icons",
|
|
170
|
+
dependencies: [
|
|
171
|
+
"@radix-ui/react-slot",
|
|
172
|
+
"class-variance-authority",
|
|
173
|
+
"clsx",
|
|
174
|
+
"tailwind-merge",
|
|
175
|
+
"lucide-react"
|
|
176
|
+
],
|
|
177
|
+
files: [
|
|
178
|
+
{
|
|
179
|
+
name: "button.tsx",
|
|
180
|
+
content: buttonContent
|
|
118
181
|
}
|
|
119
182
|
]
|
|
120
183
|
}
|
|
@@ -130,7 +193,9 @@ async function add(components, options) {
|
|
|
130
193
|
console.log(chalk.yellow(" Run `npx myoperator-ui init` first.\n"));
|
|
131
194
|
process.exit(1);
|
|
132
195
|
}
|
|
133
|
-
const
|
|
196
|
+
const config = await fs.readJson(configPath);
|
|
197
|
+
const prefix = config.tailwind?.prefix || "";
|
|
198
|
+
const registry = await getRegistry(prefix);
|
|
134
199
|
const availableComponents = Object.keys(registry);
|
|
135
200
|
if (!components || components.length === 0) {
|
|
136
201
|
const { selectedComponents } = await prompts({
|
|
@@ -158,7 +223,6 @@ async function add(components, options) {
|
|
|
158
223
|
`));
|
|
159
224
|
process.exit(1);
|
|
160
225
|
}
|
|
161
|
-
const config = await fs.readJson(configPath);
|
|
162
226
|
const componentsDir = path.join(cwd, options.path);
|
|
163
227
|
if (!options.yes) {
|
|
164
228
|
const { confirm } = await prompts({
|
|
@@ -220,7 +284,86 @@ import fs2 from "fs-extra";
|
|
|
220
284
|
import path2 from "path";
|
|
221
285
|
import prompts2 from "prompts";
|
|
222
286
|
import ora2 from "ora";
|
|
223
|
-
var
|
|
287
|
+
var CSS_VARIABLES_V4 = `@import "tailwindcss";
|
|
288
|
+
|
|
289
|
+
@theme {
|
|
290
|
+
--color-background: hsl(0 0% 100%);
|
|
291
|
+
--color-foreground: hsl(222.2 84% 4.9%);
|
|
292
|
+
--color-card: hsl(0 0% 100%);
|
|
293
|
+
--color-card-foreground: hsl(222.2 84% 4.9%);
|
|
294
|
+
--color-popover: hsl(0 0% 100%);
|
|
295
|
+
--color-popover-foreground: hsl(222.2 84% 4.9%);
|
|
296
|
+
--color-primary: hsl(222.2 47.4% 11.2%);
|
|
297
|
+
--color-primary-foreground: hsl(210 40% 98%);
|
|
298
|
+
--color-secondary: hsl(210 40% 96.1%);
|
|
299
|
+
--color-secondary-foreground: hsl(222.2 47.4% 11.2%);
|
|
300
|
+
--color-muted: hsl(210 40% 96.1%);
|
|
301
|
+
--color-muted-foreground: hsl(215.4 16.3% 46.9%);
|
|
302
|
+
--color-accent: hsl(210 40% 96.1%);
|
|
303
|
+
--color-accent-foreground: hsl(222.2 47.4% 11.2%);
|
|
304
|
+
--color-destructive: hsl(0 84.2% 60.2%);
|
|
305
|
+
--color-destructive-foreground: hsl(210 40% 98%);
|
|
306
|
+
--color-border: hsl(214.3 31.8% 91.4%);
|
|
307
|
+
--color-input: hsl(214.3 31.8% 91.4%);
|
|
308
|
+
--color-ring: hsl(222.2 84% 4.9%);
|
|
309
|
+
--radius: 0.5rem;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
:root {
|
|
313
|
+
--background: 0 0% 100%;
|
|
314
|
+
--foreground: 222.2 84% 4.9%;
|
|
315
|
+
--card: 0 0% 100%;
|
|
316
|
+
--card-foreground: 222.2 84% 4.9%;
|
|
317
|
+
--popover: 0 0% 100%;
|
|
318
|
+
--popover-foreground: 222.2 84% 4.9%;
|
|
319
|
+
--primary: 222.2 47.4% 11.2%;
|
|
320
|
+
--primary-foreground: 210 40% 98%;
|
|
321
|
+
--secondary: 210 40% 96.1%;
|
|
322
|
+
--secondary-foreground: 222.2 47.4% 11.2%;
|
|
323
|
+
--muted: 210 40% 96.1%;
|
|
324
|
+
--muted-foreground: 215.4 16.3% 46.9%;
|
|
325
|
+
--accent: 210 40% 96.1%;
|
|
326
|
+
--accent-foreground: 222.2 47.4% 11.2%;
|
|
327
|
+
--destructive: 0 84.2% 60.2%;
|
|
328
|
+
--destructive-foreground: 210 40% 98%;
|
|
329
|
+
--border: 214.3 31.8% 91.4%;
|
|
330
|
+
--input: 214.3 31.8% 91.4%;
|
|
331
|
+
--ring: 222.2 84% 4.9%;
|
|
332
|
+
--radius: 0.5rem;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
.dark {
|
|
336
|
+
--background: 222.2 84% 4.9%;
|
|
337
|
+
--foreground: 210 40% 98%;
|
|
338
|
+
--card: 222.2 84% 4.9%;
|
|
339
|
+
--card-foreground: 210 40% 98%;
|
|
340
|
+
--popover: 222.2 84% 4.9%;
|
|
341
|
+
--popover-foreground: 210 40% 98%;
|
|
342
|
+
--primary: 210 40% 98%;
|
|
343
|
+
--primary-foreground: 222.2 47.4% 11.2%;
|
|
344
|
+
--secondary: 217.2 32.6% 17.5%;
|
|
345
|
+
--secondary-foreground: 210 40% 98%;
|
|
346
|
+
--muted: 217.2 32.6% 17.5%;
|
|
347
|
+
--muted-foreground: 215 20.2% 65.1%;
|
|
348
|
+
--accent: 217.2 32.6% 17.5%;
|
|
349
|
+
--accent-foreground: 210 40% 98%;
|
|
350
|
+
--destructive: 0 62.8% 30.6%;
|
|
351
|
+
--destructive-foreground: 210 40% 98%;
|
|
352
|
+
--border: 217.2 32.6% 17.5%;
|
|
353
|
+
--input: 217.2 32.6% 17.5%;
|
|
354
|
+
--ring: 212.7 26.8% 83.9%;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
* {
|
|
358
|
+
border-color: hsl(var(--border));
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
body {
|
|
362
|
+
background-color: hsl(var(--background));
|
|
363
|
+
color: hsl(var(--foreground));
|
|
364
|
+
}
|
|
365
|
+
`;
|
|
366
|
+
var CSS_VARIABLES_V3 = `@tailwind base;
|
|
224
367
|
@tailwind components;
|
|
225
368
|
@tailwind utilities;
|
|
226
369
|
|
|
@@ -280,9 +423,10 @@ var CSS_VARIABLES = `@tailwind base;
|
|
|
280
423
|
}
|
|
281
424
|
}
|
|
282
425
|
`;
|
|
283
|
-
var
|
|
426
|
+
var getTailwindConfig = (prefix) => `/** @type {import('tailwindcss').Config} */
|
|
284
427
|
export default {
|
|
285
428
|
darkMode: ["class"],
|
|
429
|
+
${prefix ? `prefix: "${prefix}",` : ""}
|
|
286
430
|
content: [
|
|
287
431
|
"./index.html",
|
|
288
432
|
"./src/**/*.{js,ts,jsx,tsx}",
|
|
@@ -362,7 +506,8 @@ var DEFAULT_CONFIG = {
|
|
|
362
506
|
config: "tailwind.config.js",
|
|
363
507
|
css: "src/index.css",
|
|
364
508
|
baseColor: "slate",
|
|
365
|
-
cssVariables: true
|
|
509
|
+
cssVariables: true,
|
|
510
|
+
prefix: ""
|
|
366
511
|
},
|
|
367
512
|
aliases: {
|
|
368
513
|
components: "@/components",
|
|
@@ -387,6 +532,28 @@ async function init() {
|
|
|
387
532
|
}
|
|
388
533
|
}
|
|
389
534
|
const response = await prompts2([
|
|
535
|
+
{
|
|
536
|
+
type: "select",
|
|
537
|
+
name: "tailwindVersion",
|
|
538
|
+
message: "Which Tailwind CSS version are you using?",
|
|
539
|
+
choices: [
|
|
540
|
+
{ title: "Tailwind CSS v4 (latest)", value: "v4" },
|
|
541
|
+
{ title: "Tailwind CSS v3", value: "v3" }
|
|
542
|
+
],
|
|
543
|
+
initial: 0
|
|
544
|
+
},
|
|
545
|
+
{
|
|
546
|
+
type: "confirm",
|
|
547
|
+
name: "usePrefix",
|
|
548
|
+
message: "Use a prefix for Tailwind classes? (recommended if using Bootstrap/other CSS frameworks)",
|
|
549
|
+
initial: false
|
|
550
|
+
},
|
|
551
|
+
{
|
|
552
|
+
type: (prev) => prev ? "text" : null,
|
|
553
|
+
name: "prefix",
|
|
554
|
+
message: "Enter prefix for Tailwind classes:",
|
|
555
|
+
initial: "tw-"
|
|
556
|
+
},
|
|
390
557
|
{
|
|
391
558
|
type: "text",
|
|
392
559
|
name: "componentsPath",
|
|
@@ -400,7 +567,7 @@ async function init() {
|
|
|
400
567
|
initial: "src/lib/utils.ts"
|
|
401
568
|
},
|
|
402
569
|
{
|
|
403
|
-
type: "text",
|
|
570
|
+
type: (prev, values) => values.tailwindVersion === "v3" ? "text" : null,
|
|
404
571
|
name: "tailwindConfig",
|
|
405
572
|
message: "Where is your tailwind.config.js?",
|
|
406
573
|
initial: "tailwind.config.js"
|
|
@@ -414,12 +581,14 @@ async function init() {
|
|
|
414
581
|
]);
|
|
415
582
|
const spinner = ora2("Initializing project...").start();
|
|
416
583
|
try {
|
|
584
|
+
const prefix = response.usePrefix ? response.prefix : "";
|
|
417
585
|
const config = {
|
|
418
586
|
...DEFAULT_CONFIG,
|
|
419
587
|
tailwind: {
|
|
420
588
|
...DEFAULT_CONFIG.tailwind,
|
|
421
|
-
config: response.tailwindConfig,
|
|
422
|
-
css: response.globalCss
|
|
589
|
+
config: response.tailwindConfig || "tailwind.config.js",
|
|
590
|
+
css: response.globalCss,
|
|
591
|
+
prefix
|
|
423
592
|
},
|
|
424
593
|
aliases: {
|
|
425
594
|
...DEFAULT_CONFIG.aliases,
|
|
@@ -444,10 +613,11 @@ export function cn(...inputs: ClassValue[]) {
|
|
|
444
613
|
const componentsPath = path2.join(cwd, response.componentsPath);
|
|
445
614
|
await fs2.ensureDir(componentsPath);
|
|
446
615
|
const globalCssPath = path2.join(cwd, response.globalCss);
|
|
616
|
+
const cssContent = response.tailwindVersion === "v4" ? CSS_VARIABLES_V4 : CSS_VARIABLES_V3;
|
|
447
617
|
let cssUpdated = false;
|
|
448
618
|
if (!await fs2.pathExists(globalCssPath)) {
|
|
449
619
|
await fs2.ensureDir(path2.dirname(globalCssPath));
|
|
450
|
-
await fs2.writeFile(globalCssPath,
|
|
620
|
+
await fs2.writeFile(globalCssPath, cssContent);
|
|
451
621
|
cssUpdated = true;
|
|
452
622
|
} else {
|
|
453
623
|
const existingCss = await fs2.readFile(globalCssPath, "utf-8");
|
|
@@ -461,30 +631,32 @@ export function cn(...inputs: ClassValue[]) {
|
|
|
461
631
|
});
|
|
462
632
|
spinner.start("Initializing project...");
|
|
463
633
|
if (updateCss) {
|
|
464
|
-
await fs2.writeFile(globalCssPath,
|
|
634
|
+
await fs2.writeFile(globalCssPath, cssContent);
|
|
465
635
|
cssUpdated = true;
|
|
466
636
|
}
|
|
467
637
|
}
|
|
468
638
|
}
|
|
469
|
-
const tailwindConfigPath = path2.join(cwd, response.tailwindConfig);
|
|
470
639
|
let tailwindUpdated = false;
|
|
471
|
-
if (
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
640
|
+
if (response.tailwindVersion === "v3" && response.tailwindConfig) {
|
|
641
|
+
const tailwindConfigPath = path2.join(cwd, response.tailwindConfig);
|
|
642
|
+
if (!await fs2.pathExists(tailwindConfigPath)) {
|
|
643
|
+
await fs2.writeFile(tailwindConfigPath, getTailwindConfig(prefix));
|
|
644
|
+
tailwindUpdated = true;
|
|
645
|
+
} else {
|
|
646
|
+
const existingConfig = await fs2.readFile(tailwindConfigPath, "utf-8");
|
|
647
|
+
if (!existingConfig.includes("hsl(var(--destructive))") && !existingConfig.includes("hsl(var(--ring))")) {
|
|
648
|
+
spinner.stop();
|
|
649
|
+
const { updateTailwind } = await prompts2({
|
|
650
|
+
type: "confirm",
|
|
651
|
+
name: "updateTailwind",
|
|
652
|
+
message: `${response.tailwindConfig} exists. Update with myOperator UI theme colors?`,
|
|
653
|
+
initial: true
|
|
654
|
+
});
|
|
655
|
+
spinner.start("Initializing project...");
|
|
656
|
+
if (updateTailwind) {
|
|
657
|
+
await fs2.writeFile(tailwindConfigPath, getTailwindConfig(prefix));
|
|
658
|
+
tailwindUpdated = true;
|
|
659
|
+
}
|
|
488
660
|
}
|
|
489
661
|
}
|
|
490
662
|
}
|
|
@@ -529,11 +701,20 @@ export function cn(...inputs: ClassValue[]) {
|
|
|
529
701
|
console.log("");
|
|
530
702
|
console.log(chalk2.bold(" Next steps:\n"));
|
|
531
703
|
console.log(" 1. Install core dependencies:");
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
704
|
+
if (response.tailwindVersion === "v4") {
|
|
705
|
+
console.log(chalk2.cyan(" npm install clsx tailwind-merge class-variance-authority @radix-ui/react-slot lucide-react\n"));
|
|
706
|
+
} else {
|
|
707
|
+
console.log(chalk2.cyan(" npm install clsx tailwind-merge class-variance-authority @radix-ui/react-slot lucide-react tailwindcss-animate\n"));
|
|
708
|
+
}
|
|
709
|
+
if (response.tailwindVersion === "v4") {
|
|
710
|
+
console.log(" 2. Add your first component:");
|
|
711
|
+
console.log(chalk2.cyan(" npx myoperator-ui add button\n"));
|
|
712
|
+
} else {
|
|
713
|
+
console.log(" 2. Install PostCSS plugin (if not already installed):");
|
|
714
|
+
console.log(chalk2.cyan(" npm install -D @tailwindcss/postcss\n"));
|
|
715
|
+
console.log(" 3. Add your first component:");
|
|
716
|
+
console.log(chalk2.cyan(" npx myoperator-ui add button\n"));
|
|
717
|
+
}
|
|
537
718
|
} catch (error) {
|
|
538
719
|
spinner.fail("Failed to initialize project");
|
|
539
720
|
console.error(error);
|