myoperator-ui 0.0.3 → 0.0.5

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.
Files changed (2) hide show
  1. package/dist/index.js +178 -32
  2. 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
- async function getRegistry() {
15
- return {
16
- button: {
17
- name: "button",
18
- description: "A customizable button component with variants, sizes, and icons",
19
- dependencies: [
20
- "@radix-ui/react-slot",
21
- "class-variance-authority",
22
- "clsx",
23
- "tailwind-merge",
24
- "lucide-react"
25
- ],
26
- files: [
27
- {
28
- name: "button.tsx",
29
- content: `import * as React from "react"
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 registry = await getRegistry();
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({
@@ -289,14 +353,75 @@ var CSS_VARIABLES_V4 = `@import "tailwindcss";
289
353
  --input: 217.2 32.6% 17.5%;
290
354
  --ring: 212.7 26.8% 83.9%;
291
355
  }
356
+ `;
357
+ var CSS_VARIABLES_V4_PREFIXED = `@import "tailwindcss/utilities" layer(utilities);
358
+
359
+ @theme {
360
+ --color-background: hsl(0 0% 100%);
361
+ --color-foreground: hsl(222.2 84% 4.9%);
362
+ --color-card: hsl(0 0% 100%);
363
+ --color-card-foreground: hsl(222.2 84% 4.9%);
364
+ --color-popover: hsl(0 0% 100%);
365
+ --color-popover-foreground: hsl(222.2 84% 4.9%);
366
+ --color-primary: hsl(222.2 47.4% 11.2%);
367
+ --color-primary-foreground: hsl(210 40% 98%);
368
+ --color-secondary: hsl(210 40% 96.1%);
369
+ --color-secondary-foreground: hsl(222.2 47.4% 11.2%);
370
+ --color-muted: hsl(210 40% 96.1%);
371
+ --color-muted-foreground: hsl(215.4 16.3% 46.9%);
372
+ --color-accent: hsl(210 40% 96.1%);
373
+ --color-accent-foreground: hsl(222.2 47.4% 11.2%);
374
+ --color-destructive: hsl(0 84.2% 60.2%);
375
+ --color-destructive-foreground: hsl(210 40% 98%);
376
+ --color-border: hsl(214.3 31.8% 91.4%);
377
+ --color-input: hsl(214.3 31.8% 91.4%);
378
+ --color-ring: hsl(222.2 84% 4.9%);
379
+ --radius: 0.5rem;
380
+ }
292
381
 
293
- * {
294
- border-color: hsl(var(--border));
382
+ :root {
383
+ --background: 0 0% 100%;
384
+ --foreground: 222.2 84% 4.9%;
385
+ --card: 0 0% 100%;
386
+ --card-foreground: 222.2 84% 4.9%;
387
+ --popover: 0 0% 100%;
388
+ --popover-foreground: 222.2 84% 4.9%;
389
+ --primary: 222.2 47.4% 11.2%;
390
+ --primary-foreground: 210 40% 98%;
391
+ --secondary: 210 40% 96.1%;
392
+ --secondary-foreground: 222.2 47.4% 11.2%;
393
+ --muted: 210 40% 96.1%;
394
+ --muted-foreground: 215.4 16.3% 46.9%;
395
+ --accent: 210 40% 96.1%;
396
+ --accent-foreground: 222.2 47.4% 11.2%;
397
+ --destructive: 0 84.2% 60.2%;
398
+ --destructive-foreground: 210 40% 98%;
399
+ --border: 214.3 31.8% 91.4%;
400
+ --input: 214.3 31.8% 91.4%;
401
+ --ring: 222.2 84% 4.9%;
402
+ --radius: 0.5rem;
295
403
  }
296
404
 
297
- body {
298
- background-color: hsl(var(--background));
299
- color: hsl(var(--foreground));
405
+ .dark {
406
+ --background: 222.2 84% 4.9%;
407
+ --foreground: 210 40% 98%;
408
+ --card: 222.2 84% 4.9%;
409
+ --card-foreground: 210 40% 98%;
410
+ --popover: 222.2 84% 4.9%;
411
+ --popover-foreground: 210 40% 98%;
412
+ --primary: 210 40% 98%;
413
+ --primary-foreground: 222.2 47.4% 11.2%;
414
+ --secondary: 217.2 32.6% 17.5%;
415
+ --secondary-foreground: 210 40% 98%;
416
+ --muted: 217.2 32.6% 17.5%;
417
+ --muted-foreground: 215 20.2% 65.1%;
418
+ --accent: 217.2 32.6% 17.5%;
419
+ --accent-foreground: 210 40% 98%;
420
+ --destructive: 0 62.8% 30.6%;
421
+ --destructive-foreground: 210 40% 98%;
422
+ --border: 217.2 32.6% 17.5%;
423
+ --input: 217.2 32.6% 17.5%;
424
+ --ring: 212.7 26.8% 83.9%;
300
425
  }
301
426
  `;
302
427
  var CSS_VARIABLES_V3 = `@tailwind base;
@@ -359,9 +484,10 @@ var CSS_VARIABLES_V3 = `@tailwind base;
359
484
  }
360
485
  }
361
486
  `;
362
- var TAILWIND_CONFIG = `/** @type {import('tailwindcss').Config} */
487
+ var getTailwindConfig = (prefix) => `/** @type {import('tailwindcss').Config} */
363
488
  export default {
364
489
  darkMode: ["class"],
490
+ ${prefix ? `prefix: "${prefix}",` : ""}
365
491
  content: [
366
492
  "./index.html",
367
493
  "./src/**/*.{js,ts,jsx,tsx}",
@@ -441,7 +567,8 @@ var DEFAULT_CONFIG = {
441
567
  config: "tailwind.config.js",
442
568
  css: "src/index.css",
443
569
  baseColor: "slate",
444
- cssVariables: true
570
+ cssVariables: true,
571
+ prefix: ""
445
572
  },
446
573
  aliases: {
447
574
  components: "@/components",
@@ -476,6 +603,18 @@ async function init() {
476
603
  ],
477
604
  initial: 0
478
605
  },
606
+ {
607
+ type: "confirm",
608
+ name: "usePrefix",
609
+ message: "Use a prefix for Tailwind classes? (recommended if using Bootstrap/other CSS frameworks)",
610
+ initial: false
611
+ },
612
+ {
613
+ type: (prev) => prev ? "text" : null,
614
+ name: "prefix",
615
+ message: "Enter prefix for Tailwind classes:",
616
+ initial: "tw-"
617
+ },
479
618
  {
480
619
  type: "text",
481
620
  name: "componentsPath",
@@ -503,12 +642,14 @@ async function init() {
503
642
  ]);
504
643
  const spinner = ora2("Initializing project...").start();
505
644
  try {
645
+ const prefix = response.usePrefix ? response.prefix : "";
506
646
  const config = {
507
647
  ...DEFAULT_CONFIG,
508
648
  tailwind: {
509
649
  ...DEFAULT_CONFIG.tailwind,
510
- config: response.tailwindConfig,
511
- css: response.globalCss
650
+ config: response.tailwindConfig || "tailwind.config.js",
651
+ css: response.globalCss,
652
+ prefix
512
653
  },
513
654
  aliases: {
514
655
  ...DEFAULT_CONFIG.aliases,
@@ -533,7 +674,12 @@ export function cn(...inputs: ClassValue[]) {
533
674
  const componentsPath = path2.join(cwd, response.componentsPath);
534
675
  await fs2.ensureDir(componentsPath);
535
676
  const globalCssPath = path2.join(cwd, response.globalCss);
536
- const cssContent = response.tailwindVersion === "v4" ? CSS_VARIABLES_V4 : CSS_VARIABLES_V3;
677
+ let cssContent;
678
+ if (response.tailwindVersion === "v4") {
679
+ cssContent = prefix ? CSS_VARIABLES_V4_PREFIXED : CSS_VARIABLES_V4;
680
+ } else {
681
+ cssContent = CSS_VARIABLES_V3;
682
+ }
537
683
  let cssUpdated = false;
538
684
  if (!await fs2.pathExists(globalCssPath)) {
539
685
  await fs2.ensureDir(path2.dirname(globalCssPath));
@@ -560,7 +706,7 @@ export function cn(...inputs: ClassValue[]) {
560
706
  if (response.tailwindVersion === "v3" && response.tailwindConfig) {
561
707
  const tailwindConfigPath = path2.join(cwd, response.tailwindConfig);
562
708
  if (!await fs2.pathExists(tailwindConfigPath)) {
563
- await fs2.writeFile(tailwindConfigPath, TAILWIND_CONFIG);
709
+ await fs2.writeFile(tailwindConfigPath, getTailwindConfig(prefix));
564
710
  tailwindUpdated = true;
565
711
  } else {
566
712
  const existingConfig = await fs2.readFile(tailwindConfigPath, "utf-8");
@@ -574,14 +720,14 @@ export function cn(...inputs: ClassValue[]) {
574
720
  });
575
721
  spinner.start("Initializing project...");
576
722
  if (updateTailwind) {
577
- await fs2.writeFile(tailwindConfigPath, TAILWIND_CONFIG);
723
+ await fs2.writeFile(tailwindConfigPath, getTailwindConfig(prefix));
578
724
  tailwindUpdated = true;
579
725
  }
580
726
  }
581
727
  }
582
728
  }
583
729
  const postcssConfigPath = path2.join(cwd, "postcss.config.js");
584
- const postcssConfigContent = `module.exports = {
730
+ const postcssConfigContent = `export default {
585
731
  plugins: {
586
732
  '@tailwindcss/postcss': {},
587
733
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "myoperator-ui",
3
- "version": "0.0.3",
3
+ "version": "0.0.5",
4
4
  "description": "CLI for adding myOperator UI components to your project",
5
5
  "type": "module",
6
6
  "exports": "./dist/index.js",