myoperator-ui 0.0.152-beta.2 → 0.0.152-beta.3
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 +301 -189
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -5,9 +5,9 @@ import { Command } from "commander";
|
|
|
5
5
|
import { createRequire } from "module";
|
|
6
6
|
|
|
7
7
|
// src/commands/add.ts
|
|
8
|
-
import
|
|
9
|
-
import
|
|
10
|
-
import
|
|
8
|
+
import chalk2 from "chalk";
|
|
9
|
+
import fs3 from "fs-extra";
|
|
10
|
+
import path3 from "path";
|
|
11
11
|
import prompts from "prompts";
|
|
12
12
|
import ora from "ora";
|
|
13
13
|
|
|
@@ -8442,17 +8442,64 @@ async function detectTailwindPrefix(configFile, cwd = process.cwd()) {
|
|
|
8442
8442
|
return "";
|
|
8443
8443
|
}
|
|
8444
8444
|
|
|
8445
|
+
// src/utils/tailwind-fix.ts
|
|
8446
|
+
import fs2 from "fs-extra";
|
|
8447
|
+
import path2 from "path";
|
|
8448
|
+
import chalk from "chalk";
|
|
8449
|
+
var CUSTOM_COMPONENTS_PATH = "./src/components/custom/**/*.{js,ts,jsx,tsx}";
|
|
8450
|
+
async function ensureCustomComponentsInTailwindConfig(cwd) {
|
|
8451
|
+
const tailwindConfigOptions = [
|
|
8452
|
+
"tailwind.config.js",
|
|
8453
|
+
"tailwind.config.ts",
|
|
8454
|
+
"tailwind.config.mjs",
|
|
8455
|
+
"tailwind.config.cjs"
|
|
8456
|
+
];
|
|
8457
|
+
let tailwindConfigPath = null;
|
|
8458
|
+
for (const configFile of tailwindConfigOptions) {
|
|
8459
|
+
const fullPath = path2.join(cwd, configFile);
|
|
8460
|
+
if (await fs2.pathExists(fullPath)) {
|
|
8461
|
+
tailwindConfigPath = fullPath;
|
|
8462
|
+
break;
|
|
8463
|
+
}
|
|
8464
|
+
}
|
|
8465
|
+
if (!tailwindConfigPath) {
|
|
8466
|
+
return false;
|
|
8467
|
+
}
|
|
8468
|
+
const tailwindConfig = await fs2.readFile(tailwindConfigPath, "utf-8");
|
|
8469
|
+
if (tailwindConfig.includes("./src/components/custom/")) {
|
|
8470
|
+
return false;
|
|
8471
|
+
}
|
|
8472
|
+
const contentMatch = tailwindConfig.match(/content\s*:\s*\[([^\]]*)\]/s);
|
|
8473
|
+
if (!contentMatch) {
|
|
8474
|
+
return false;
|
|
8475
|
+
}
|
|
8476
|
+
const existingContent = contentMatch[1];
|
|
8477
|
+
const existingPaths = existingContent.split(",").map((p) => p.trim()).filter((p) => p.length > 0);
|
|
8478
|
+
const newPaths = [...existingPaths.map((p) => p.replace(/["']/g, "")), CUSTOM_COMPONENTS_PATH];
|
|
8479
|
+
const newContentArray = newPaths.map((p) => ` "${p}"`).join(",\n");
|
|
8480
|
+
const updatedConfig = tailwindConfig.replace(
|
|
8481
|
+
/content\s*:\s*\[([^\]]*)\]/s,
|
|
8482
|
+
`content: [
|
|
8483
|
+
${newContentArray},
|
|
8484
|
+
]`
|
|
8485
|
+
);
|
|
8486
|
+
await fs2.writeFile(tailwindConfigPath, updatedConfig);
|
|
8487
|
+
console.log(chalk.green(`
|
|
8488
|
+
\u2713 Updated ${path2.basename(tailwindConfigPath)} with custom components path`));
|
|
8489
|
+
return true;
|
|
8490
|
+
}
|
|
8491
|
+
|
|
8445
8492
|
// src/commands/add.ts
|
|
8446
8493
|
async function add(components, options) {
|
|
8447
8494
|
const cwd = process.cwd();
|
|
8448
8495
|
if (!await configExists(cwd)) {
|
|
8449
|
-
console.log(
|
|
8450
|
-
console.log(
|
|
8496
|
+
console.log(chalk2.red("\n Error: Project not initialized."));
|
|
8497
|
+
console.log(chalk2.yellow(" Run `npx myoperator-ui init` first.\n"));
|
|
8451
8498
|
process.exit(1);
|
|
8452
8499
|
}
|
|
8453
8500
|
const prefix = await getTailwindPrefix(cwd);
|
|
8454
8501
|
if (prefix) {
|
|
8455
|
-
console.log(
|
|
8502
|
+
console.log(chalk2.blue(`
|
|
8456
8503
|
\u2139 Applying Tailwind prefix: "${prefix}"
|
|
8457
8504
|
`));
|
|
8458
8505
|
}
|
|
@@ -8460,27 +8507,27 @@ async function add(components, options) {
|
|
|
8460
8507
|
const availableComponents = Object.keys(registry);
|
|
8461
8508
|
if (options.all) {
|
|
8462
8509
|
components = availableComponents;
|
|
8463
|
-
console.log(
|
|
8510
|
+
console.log(chalk2.blue(` Adding all ${components.length} components...
|
|
8464
8511
|
`));
|
|
8465
8512
|
}
|
|
8466
8513
|
if (options.category) {
|
|
8467
8514
|
const validCategories = ["core", "form", "data", "overlay", "feedback", "layout", "custom"];
|
|
8468
8515
|
const categoryLower = options.category.toLowerCase();
|
|
8469
8516
|
if (!validCategories.includes(categoryLower)) {
|
|
8470
|
-
console.log(
|
|
8517
|
+
console.log(chalk2.red(`
|
|
8471
8518
|
Error: Unknown category: ${options.category}`));
|
|
8472
|
-
console.log(
|
|
8519
|
+
console.log(chalk2.yellow(` Available categories: ${validCategories.join(", ")}
|
|
8473
8520
|
`));
|
|
8474
8521
|
process.exit(1);
|
|
8475
8522
|
}
|
|
8476
8523
|
components = availableComponents.filter((name) => registry[name].category === categoryLower);
|
|
8477
8524
|
if (components.length === 0) {
|
|
8478
|
-
console.log(
|
|
8525
|
+
console.log(chalk2.yellow(`
|
|
8479
8526
|
No components found in category: ${categoryLower}
|
|
8480
8527
|
`));
|
|
8481
8528
|
process.exit(0);
|
|
8482
8529
|
}
|
|
8483
|
-
console.log(
|
|
8530
|
+
console.log(chalk2.blue(` Adding all ${components.length} ${categoryLower} components...
|
|
8484
8531
|
`));
|
|
8485
8532
|
}
|
|
8486
8533
|
if (!components || components.length === 0) {
|
|
@@ -8496,7 +8543,7 @@ async function add(components, options) {
|
|
|
8496
8543
|
min: 1
|
|
8497
8544
|
});
|
|
8498
8545
|
if (!selectedComponents || selectedComponents.length === 0) {
|
|
8499
|
-
console.log(
|
|
8546
|
+
console.log(chalk2.yellow("\n No components selected.\n"));
|
|
8500
8547
|
process.exit(0);
|
|
8501
8548
|
}
|
|
8502
8549
|
components = selectedComponents;
|
|
@@ -8516,13 +8563,13 @@ async function add(components, options) {
|
|
|
8516
8563
|
});
|
|
8517
8564
|
const invalidComponents = components.filter((c) => !availableComponents.includes(c));
|
|
8518
8565
|
if (invalidComponents.length > 0) {
|
|
8519
|
-
console.log(
|
|
8566
|
+
console.log(chalk2.red(`
|
|
8520
8567
|
Error: Unknown components: ${invalidComponents.join(", ")}`));
|
|
8521
|
-
console.log(
|
|
8568
|
+
console.log(chalk2.yellow(` Available: ${availableComponents.join(", ")}
|
|
8522
8569
|
`));
|
|
8523
8570
|
process.exit(1);
|
|
8524
8571
|
}
|
|
8525
|
-
const componentsDir =
|
|
8572
|
+
const componentsDir = path3.join(cwd, options.path);
|
|
8526
8573
|
if (!options.yes) {
|
|
8527
8574
|
const { confirm } = await prompts({
|
|
8528
8575
|
type: "confirm",
|
|
@@ -8531,7 +8578,7 @@ async function add(components, options) {
|
|
|
8531
8578
|
initial: true
|
|
8532
8579
|
});
|
|
8533
8580
|
if (!confirm) {
|
|
8534
|
-
console.log(
|
|
8581
|
+
console.log(chalk2.yellow("\n Installation cancelled.\n"));
|
|
8535
8582
|
process.exit(0);
|
|
8536
8583
|
}
|
|
8537
8584
|
}
|
|
@@ -8558,18 +8605,18 @@ async function add(components, options) {
|
|
|
8558
8605
|
}
|
|
8559
8606
|
spinner.text = `Installing ${componentName}...`;
|
|
8560
8607
|
const isCustomComponent = component.category === "custom";
|
|
8561
|
-
const baseDir = isCustomComponent ?
|
|
8562
|
-
const targetDir = component.isMultiFile ?
|
|
8608
|
+
const baseDir = isCustomComponent ? path3.join(cwd, "src/components/custom") : componentsDir;
|
|
8609
|
+
const targetDir = component.isMultiFile ? path3.join(baseDir, component.directory) : baseDir;
|
|
8563
8610
|
for (const file of component.files) {
|
|
8564
|
-
const filePath =
|
|
8565
|
-
if (await
|
|
8611
|
+
const filePath = path3.join(targetDir, file.name);
|
|
8612
|
+
if (await fs3.pathExists(filePath)) {
|
|
8566
8613
|
if (!options.overwrite) {
|
|
8567
8614
|
spinner.warn(`${file.name} already exists. Use --overwrite to replace.`);
|
|
8568
8615
|
continue;
|
|
8569
8616
|
}
|
|
8570
8617
|
}
|
|
8571
|
-
await
|
|
8572
|
-
await
|
|
8618
|
+
await fs3.ensureDir(path3.dirname(filePath));
|
|
8619
|
+
await fs3.writeFile(filePath, file.content);
|
|
8573
8620
|
const basePath = isCustomComponent ? "src/components/custom" : options.path;
|
|
8574
8621
|
const relativePath = component.isMultiFile ? `${component.directory}/${file.name}` : file.name;
|
|
8575
8622
|
installed.push({ path: relativePath, basePath });
|
|
@@ -8584,23 +8631,18 @@ async function add(components, options) {
|
|
|
8584
8631
|
}
|
|
8585
8632
|
spinner.succeed("Components installed successfully!");
|
|
8586
8633
|
if (installed.length > 0) {
|
|
8587
|
-
console.log(
|
|
8634
|
+
console.log(chalk2.green("\n Installed files:"));
|
|
8588
8635
|
installed.forEach((file) => {
|
|
8589
|
-
console.log(
|
|
8636
|
+
console.log(chalk2.green(` \u2713 ${file.basePath}/${file.path}`));
|
|
8590
8637
|
});
|
|
8591
8638
|
}
|
|
8592
8639
|
if (dependencies.size > 0) {
|
|
8593
|
-
console.log(
|
|
8594
|
-
console.log(
|
|
8640
|
+
console.log(chalk2.yellow("\n Required dependencies:"));
|
|
8641
|
+
console.log(chalk2.cyan(` npm install ${Array.from(dependencies).join(" ")}`));
|
|
8595
8642
|
}
|
|
8596
8643
|
const hasCustomComponents = installed.some((file) => file.basePath.includes("custom"));
|
|
8597
8644
|
if (hasCustomComponents) {
|
|
8598
|
-
|
|
8599
|
-
console.log(chalk.white(" Make sure your tailwind.config.js includes:"));
|
|
8600
|
-
console.log(chalk.cyan(" content: ["));
|
|
8601
|
-
console.log(chalk.cyan(' "./src/components/ui/**/*.{js,ts,jsx,tsx}",'));
|
|
8602
|
-
console.log(chalk.cyan(' "./src/components/custom/**/*.{js,ts,jsx,tsx}", // Add this line'));
|
|
8603
|
-
console.log(chalk.cyan(" ]"));
|
|
8645
|
+
await ensureCustomComponentsInTailwindConfig(cwd);
|
|
8604
8646
|
}
|
|
8605
8647
|
console.log("");
|
|
8606
8648
|
} catch (error) {
|
|
@@ -8610,12 +8652,85 @@ async function add(components, options) {
|
|
|
8610
8652
|
}
|
|
8611
8653
|
}
|
|
8612
8654
|
|
|
8655
|
+
// src/commands/fix.ts
|
|
8656
|
+
import chalk3 from "chalk";
|
|
8657
|
+
import fs4 from "fs-extra";
|
|
8658
|
+
import path4 from "path";
|
|
8659
|
+
import ora2 from "ora";
|
|
8660
|
+
async function fix() {
|
|
8661
|
+
const cwd = process.cwd();
|
|
8662
|
+
console.log(chalk3.bold("\n myOperator UI - Fix Configuration\n"));
|
|
8663
|
+
if (!await configExists(cwd)) {
|
|
8664
|
+
console.log(chalk3.red(" Error: Project not initialized."));
|
|
8665
|
+
console.log(chalk3.yellow(" Run `npx myoperator-ui init` first.\n"));
|
|
8666
|
+
process.exit(1);
|
|
8667
|
+
}
|
|
8668
|
+
const spinner = ora2("Checking configuration...").start();
|
|
8669
|
+
let fixesApplied = 0;
|
|
8670
|
+
try {
|
|
8671
|
+
const prefix = await getTailwindPrefix(cwd);
|
|
8672
|
+
const tailwindConfigOptions = [
|
|
8673
|
+
"tailwind.config.js",
|
|
8674
|
+
"tailwind.config.ts",
|
|
8675
|
+
"tailwind.config.mjs",
|
|
8676
|
+
"tailwind.config.cjs"
|
|
8677
|
+
];
|
|
8678
|
+
let tailwindConfigPath = null;
|
|
8679
|
+
for (const configFile of tailwindConfigOptions) {
|
|
8680
|
+
const fullPath = path4.join(cwd, configFile);
|
|
8681
|
+
if (await fs4.pathExists(fullPath)) {
|
|
8682
|
+
tailwindConfigPath = fullPath;
|
|
8683
|
+
break;
|
|
8684
|
+
}
|
|
8685
|
+
}
|
|
8686
|
+
if (!tailwindConfigPath) {
|
|
8687
|
+
spinner.warn("No tailwind.config found - skipping Tailwind config check");
|
|
8688
|
+
} else {
|
|
8689
|
+
spinner.text = "Checking Tailwind content paths...";
|
|
8690
|
+
const customPathFixed = await ensureCustomComponentsInTailwindConfig(cwd);
|
|
8691
|
+
if (customPathFixed) {
|
|
8692
|
+
fixesApplied++;
|
|
8693
|
+
}
|
|
8694
|
+
const tailwindConfig = await fs4.readFile(tailwindConfigPath, "utf-8");
|
|
8695
|
+
if (!tailwindConfig.includes("semantic-text-primary")) {
|
|
8696
|
+
console.log(chalk3.yellow("\n \u26A0\uFE0F Tailwind config missing semantic color tokens"));
|
|
8697
|
+
console.log(chalk3.white(" Run `npx myoperator-ui init` to regenerate with full color set"));
|
|
8698
|
+
}
|
|
8699
|
+
}
|
|
8700
|
+
const themeFilePath = path4.join(cwd, "src/lib/myoperator-ui-theme.css");
|
|
8701
|
+
if (!await fs4.pathExists(themeFilePath)) {
|
|
8702
|
+
console.log(chalk3.yellow("\n \u26A0\uFE0F Theme file missing: src/lib/myoperator-ui-theme.css"));
|
|
8703
|
+
console.log(chalk3.white(" Run `npx myoperator-ui init` to create it"));
|
|
8704
|
+
} else {
|
|
8705
|
+
const themeContent = await fs4.readFile(themeFilePath, "utf-8");
|
|
8706
|
+
if (!themeContent.includes("--semantic-info-surface")) {
|
|
8707
|
+
console.log(chalk3.yellow("\n \u26A0\uFE0F Theme file outdated - missing semantic variables"));
|
|
8708
|
+
console.log(chalk3.white(" Run `npx myoperator-ui init` to update it"));
|
|
8709
|
+
}
|
|
8710
|
+
}
|
|
8711
|
+
if (fixesApplied > 0) {
|
|
8712
|
+
spinner.succeed(`Applied ${fixesApplied} fix(es)!`);
|
|
8713
|
+
} else {
|
|
8714
|
+
spinner.succeed("Configuration looks good!");
|
|
8715
|
+
}
|
|
8716
|
+
if (prefix) {
|
|
8717
|
+
console.log(chalk3.blue(`
|
|
8718
|
+
\u2139 Tailwind prefix: "${prefix}"`));
|
|
8719
|
+
}
|
|
8720
|
+
console.log("");
|
|
8721
|
+
} catch (error) {
|
|
8722
|
+
spinner.fail("Fix check failed");
|
|
8723
|
+
console.error(error);
|
|
8724
|
+
process.exit(1);
|
|
8725
|
+
}
|
|
8726
|
+
}
|
|
8727
|
+
|
|
8613
8728
|
// src/commands/init.ts
|
|
8614
|
-
import
|
|
8615
|
-
import
|
|
8616
|
-
import
|
|
8729
|
+
import chalk4 from "chalk";
|
|
8730
|
+
import fs5 from "fs-extra";
|
|
8731
|
+
import path5 from "path";
|
|
8617
8732
|
import prompts2 from "prompts";
|
|
8618
|
-
import
|
|
8733
|
+
import ora3 from "ora";
|
|
8619
8734
|
import { execSync } from "child_process";
|
|
8620
8735
|
var MYOPERATOR_THEME_CSS = `/* myOperator UI Theme - Design System Variables
|
|
8621
8736
|
* Auto-generated by myoperator-ui CLI
|
|
@@ -8916,6 +9031,7 @@ export default {
|
|
|
8916
9031
|
important: true, // Required to override Bootstrap styles` : ""}
|
|
8917
9032
|
content: [
|
|
8918
9033
|
"./src/components/ui/**/*.{js,ts,jsx,tsx}",
|
|
9034
|
+
"./src/components/custom/**/*.{js,ts,jsx,tsx}",
|
|
8919
9035
|
"./src/modules/Shadcn/**/*.{js,ts,jsx,tsx}",
|
|
8920
9036
|
],
|
|
8921
9037
|
theme: {
|
|
@@ -9053,10 +9169,10 @@ export default {
|
|
|
9053
9169
|
}
|
|
9054
9170
|
`;
|
|
9055
9171
|
async function init() {
|
|
9056
|
-
console.log(
|
|
9172
|
+
console.log(chalk4.bold("\n Welcome to myOperator UI!\n"));
|
|
9057
9173
|
const cwd = process.cwd();
|
|
9058
|
-
const configPath =
|
|
9059
|
-
if (await
|
|
9174
|
+
const configPath = path5.join(cwd, "components.json");
|
|
9175
|
+
if (await fs5.pathExists(configPath)) {
|
|
9060
9176
|
const { overwrite } = await prompts2({
|
|
9061
9177
|
type: "confirm",
|
|
9062
9178
|
name: "overwrite",
|
|
@@ -9064,16 +9180,16 @@ async function init() {
|
|
|
9064
9180
|
initial: false
|
|
9065
9181
|
});
|
|
9066
9182
|
if (!overwrite) {
|
|
9067
|
-
console.log(
|
|
9183
|
+
console.log(chalk4.yellow(" Initialization cancelled.\n"));
|
|
9068
9184
|
process.exit(0);
|
|
9069
9185
|
}
|
|
9070
9186
|
}
|
|
9071
|
-
const packageJsonPath =
|
|
9187
|
+
const packageJsonPath = path5.join(cwd, "package.json");
|
|
9072
9188
|
let hasBootstrap = false;
|
|
9073
9189
|
let isESM = false;
|
|
9074
9190
|
let detectedTailwindVersion = null;
|
|
9075
|
-
if (await
|
|
9076
|
-
const packageJson2 = await
|
|
9191
|
+
if (await fs5.pathExists(packageJsonPath)) {
|
|
9192
|
+
const packageJson2 = await fs5.readJson(packageJsonPath);
|
|
9077
9193
|
hasBootstrap = !!(packageJson2.dependencies?.bootstrap || packageJson2.devDependencies?.bootstrap);
|
|
9078
9194
|
isESM = packageJson2.type === "module";
|
|
9079
9195
|
const tailwindDep = packageJson2.dependencies?.tailwindcss || packageJson2.devDependencies?.tailwindcss;
|
|
@@ -9088,10 +9204,10 @@ async function init() {
|
|
|
9088
9204
|
detectedTailwindVersion = "v4";
|
|
9089
9205
|
}
|
|
9090
9206
|
if (hasBootstrap) {
|
|
9091
|
-
console.log(
|
|
9207
|
+
console.log(chalk4.blue(" \u2139 Bootstrap detected - will configure Tailwind to avoid conflicts\n"));
|
|
9092
9208
|
}
|
|
9093
9209
|
if (detectedTailwindVersion) {
|
|
9094
|
-
console.log(
|
|
9210
|
+
console.log(chalk4.blue(` \u2139 Tailwind CSS ${detectedTailwindVersion} detected
|
|
9095
9211
|
`));
|
|
9096
9212
|
}
|
|
9097
9213
|
}
|
|
@@ -9106,7 +9222,7 @@ async function init() {
|
|
|
9106
9222
|
"styles/globals.css"
|
|
9107
9223
|
];
|
|
9108
9224
|
for (const css of cssOptions) {
|
|
9109
|
-
if (await
|
|
9225
|
+
if (await fs5.pathExists(path5.join(cwd, css))) {
|
|
9110
9226
|
return css;
|
|
9111
9227
|
}
|
|
9112
9228
|
}
|
|
@@ -9120,7 +9236,7 @@ async function init() {
|
|
|
9120
9236
|
"tailwind.config.cjs"
|
|
9121
9237
|
];
|
|
9122
9238
|
for (const config of configOptions) {
|
|
9123
|
-
if (await
|
|
9239
|
+
if (await fs5.pathExists(path5.join(cwd, config))) {
|
|
9124
9240
|
return config;
|
|
9125
9241
|
}
|
|
9126
9242
|
}
|
|
@@ -9130,7 +9246,7 @@ async function init() {
|
|
|
9130
9246
|
const detectedTailwindConfig = await detectTailwindConfig();
|
|
9131
9247
|
const detectedPrefix = await detectTailwindPrefix(detectedTailwindConfig, cwd);
|
|
9132
9248
|
if (detectedPrefix) {
|
|
9133
|
-
console.log(
|
|
9249
|
+
console.log(chalk4.blue(` \u2139 Tailwind prefix "${detectedPrefix}" detected - components will use prefixed classes
|
|
9134
9250
|
`));
|
|
9135
9251
|
}
|
|
9136
9252
|
let tailwindVersion = detectedTailwindVersion;
|
|
@@ -9171,7 +9287,7 @@ async function init() {
|
|
|
9171
9287
|
const utilsPath = "src/lib/utils.ts";
|
|
9172
9288
|
const tailwindConfig = detectedTailwindConfig;
|
|
9173
9289
|
const globalCss = detectedCss;
|
|
9174
|
-
const spinner =
|
|
9290
|
+
const spinner = ora3("Initializing project...").start();
|
|
9175
9291
|
try {
|
|
9176
9292
|
const config = {
|
|
9177
9293
|
...DEFAULT_CONFIG,
|
|
@@ -9186,8 +9302,8 @@ async function init() {
|
|
|
9186
9302
|
ui: `@/${componentsPath.replace("src/", "")}`
|
|
9187
9303
|
}
|
|
9188
9304
|
};
|
|
9189
|
-
await
|
|
9190
|
-
const utilsFullPath =
|
|
9305
|
+
await fs5.writeJson(configPath, config, { spaces: 2 });
|
|
9306
|
+
const utilsFullPath = path5.join(cwd, utilsPath);
|
|
9191
9307
|
const getCnUtilsContent = (prefix) => {
|
|
9192
9308
|
if (prefix) {
|
|
9193
9309
|
return `import { type ClassValue, clsx } from "clsx"
|
|
@@ -9214,12 +9330,12 @@ export function cn(...inputs: ClassValue[]) {
|
|
|
9214
9330
|
const cnUtilsContent = getCnUtilsContent(userPrefix);
|
|
9215
9331
|
let utilsCreated = false;
|
|
9216
9332
|
let utilsUpdated = false;
|
|
9217
|
-
if (!await
|
|
9218
|
-
await
|
|
9219
|
-
await
|
|
9333
|
+
if (!await fs5.pathExists(utilsFullPath)) {
|
|
9334
|
+
await fs5.ensureDir(path5.dirname(utilsFullPath));
|
|
9335
|
+
await fs5.writeFile(utilsFullPath, cnUtilsContent);
|
|
9220
9336
|
utilsCreated = true;
|
|
9221
9337
|
} else {
|
|
9222
|
-
const existingUtils = await
|
|
9338
|
+
const existingUtils = await fs5.readFile(utilsFullPath, "utf-8");
|
|
9223
9339
|
if (!existingUtils.includes("export function cn") && !existingUtils.includes("export const cn")) {
|
|
9224
9340
|
let updatedContent = existingUtils;
|
|
9225
9341
|
const hasClsxImport = existingUtils.includes('from "clsx"') || existingUtils.includes("from 'clsx'");
|
|
@@ -9262,26 +9378,26 @@ export function cn(...inputs: ClassValue[]) {
|
|
|
9262
9378
|
`;
|
|
9263
9379
|
}
|
|
9264
9380
|
updatedContent = updatedContent.trimEnd() + "\n" + cnFunction;
|
|
9265
|
-
await
|
|
9381
|
+
await fs5.writeFile(utilsFullPath, updatedContent);
|
|
9266
9382
|
utilsUpdated = true;
|
|
9267
9383
|
}
|
|
9268
9384
|
}
|
|
9269
|
-
const componentsFullPath =
|
|
9270
|
-
await
|
|
9271
|
-
const themeFilePath =
|
|
9385
|
+
const componentsFullPath = path5.join(cwd, componentsPath);
|
|
9386
|
+
await fs5.ensureDir(componentsFullPath);
|
|
9387
|
+
const themeFilePath = path5.join(cwd, "src/lib/myoperator-ui-theme.css");
|
|
9272
9388
|
let themeCreated = false;
|
|
9273
|
-
if (!await
|
|
9274
|
-
await
|
|
9275
|
-
await
|
|
9389
|
+
if (!await fs5.pathExists(themeFilePath)) {
|
|
9390
|
+
await fs5.ensureDir(path5.dirname(themeFilePath));
|
|
9391
|
+
await fs5.writeFile(themeFilePath, MYOPERATOR_THEME_CSS);
|
|
9276
9392
|
themeCreated = true;
|
|
9277
9393
|
} else {
|
|
9278
|
-
const existingTheme = await
|
|
9394
|
+
const existingTheme = await fs5.readFile(themeFilePath, "utf-8");
|
|
9279
9395
|
if (!existingTheme.includes("--semantic-text-primary")) {
|
|
9280
|
-
await
|
|
9396
|
+
await fs5.writeFile(themeFilePath, MYOPERATOR_THEME_CSS);
|
|
9281
9397
|
themeCreated = true;
|
|
9282
9398
|
}
|
|
9283
9399
|
}
|
|
9284
|
-
const globalCssPath =
|
|
9400
|
+
const globalCssPath = path5.join(cwd, globalCss);
|
|
9285
9401
|
let cssContent;
|
|
9286
9402
|
if (tailwindVersion === "v4") {
|
|
9287
9403
|
cssContent = hasBootstrap ? CSS_VARIABLES_V4_BOOTSTRAP : CSS_VARIABLES_V4;
|
|
@@ -9289,12 +9405,12 @@ export function cn(...inputs: ClassValue[]) {
|
|
|
9289
9405
|
cssContent = CSS_VARIABLES_V3;
|
|
9290
9406
|
}
|
|
9291
9407
|
let cssUpdated = false;
|
|
9292
|
-
if (!await
|
|
9293
|
-
await
|
|
9294
|
-
await
|
|
9408
|
+
if (!await fs5.pathExists(globalCssPath)) {
|
|
9409
|
+
await fs5.ensureDir(path5.dirname(globalCssPath));
|
|
9410
|
+
await fs5.writeFile(globalCssPath, cssContent);
|
|
9295
9411
|
cssUpdated = true;
|
|
9296
9412
|
} else {
|
|
9297
|
-
const existingCss = await
|
|
9413
|
+
const existingCss = await fs5.readFile(globalCssPath, "utf-8");
|
|
9298
9414
|
const hasThemeImport = existingCss.includes("myoperator-ui-theme.css");
|
|
9299
9415
|
if (!hasThemeImport) {
|
|
9300
9416
|
spinner.stop();
|
|
@@ -9311,9 +9427,9 @@ export function cn(...inputs: ClassValue[]) {
|
|
|
9311
9427
|
(imp) => !imp.includes("tailwindcss") && !imp.includes("@tailwind")
|
|
9312
9428
|
).join("\n");
|
|
9313
9429
|
if (importsToKeep) {
|
|
9314
|
-
await
|
|
9430
|
+
await fs5.writeFile(globalCssPath, cssContent + "\n" + importsToKeep + "\n");
|
|
9315
9431
|
} else {
|
|
9316
|
-
await
|
|
9432
|
+
await fs5.writeFile(globalCssPath, cssContent);
|
|
9317
9433
|
}
|
|
9318
9434
|
cssUpdated = true;
|
|
9319
9435
|
}
|
|
@@ -9321,16 +9437,16 @@ export function cn(...inputs: ClassValue[]) {
|
|
|
9321
9437
|
}
|
|
9322
9438
|
let tailwindUpdated = false;
|
|
9323
9439
|
if (tailwindVersion === "v3" && tailwindConfig) {
|
|
9324
|
-
const tailwindConfigPath =
|
|
9325
|
-
if (!await
|
|
9326
|
-
await
|
|
9440
|
+
const tailwindConfigPath = path5.join(cwd, tailwindConfig);
|
|
9441
|
+
if (!await fs5.pathExists(tailwindConfigPath)) {
|
|
9442
|
+
await fs5.writeFile(tailwindConfigPath, getTailwindConfig(userPrefix, hasBootstrap));
|
|
9327
9443
|
tailwindUpdated = true;
|
|
9328
9444
|
} else {
|
|
9329
|
-
const existingConfig = await
|
|
9445
|
+
const existingConfig = await fs5.readFile(tailwindConfigPath, "utf-8");
|
|
9330
9446
|
const hasLegacyColors = existingConfig.includes("hsl(var(--destructive))") || existingConfig.includes("hsl(var(--ring))");
|
|
9331
9447
|
const hasSemanticColors = existingConfig.includes("semantic-text-primary");
|
|
9332
9448
|
if (!hasLegacyColors && !hasSemanticColors) {
|
|
9333
|
-
await
|
|
9449
|
+
await fs5.writeFile(tailwindConfigPath, getTailwindConfig(userPrefix, hasBootstrap));
|
|
9334
9450
|
tailwindUpdated = true;
|
|
9335
9451
|
} else if (hasLegacyColors && !hasSemanticColors) {
|
|
9336
9452
|
spinner.stop();
|
|
@@ -9342,13 +9458,13 @@ export function cn(...inputs: ClassValue[]) {
|
|
|
9342
9458
|
});
|
|
9343
9459
|
spinner.start("Initializing project...");
|
|
9344
9460
|
if (result.updateTailwind) {
|
|
9345
|
-
await
|
|
9461
|
+
await fs5.writeFile(tailwindConfigPath, getTailwindConfig(userPrefix, hasBootstrap));
|
|
9346
9462
|
tailwindUpdated = true;
|
|
9347
9463
|
}
|
|
9348
9464
|
}
|
|
9349
9465
|
}
|
|
9350
9466
|
}
|
|
9351
|
-
const postcssConfigPath =
|
|
9467
|
+
const postcssConfigPath = path5.join(cwd, "postcss.config.js");
|
|
9352
9468
|
let postcssConfigContent;
|
|
9353
9469
|
if (tailwindVersion === "v4") {
|
|
9354
9470
|
postcssConfigContent = isESM ? `export default {
|
|
@@ -9378,8 +9494,8 @@ export function cn(...inputs: ClassValue[]) {
|
|
|
9378
9494
|
`;
|
|
9379
9495
|
}
|
|
9380
9496
|
let postcssCreated = false;
|
|
9381
|
-
if (!await
|
|
9382
|
-
await
|
|
9497
|
+
if (!await fs5.pathExists(postcssConfigPath)) {
|
|
9498
|
+
await fs5.writeFile(postcssConfigPath, postcssConfigContent);
|
|
9383
9499
|
postcssCreated = true;
|
|
9384
9500
|
} else {
|
|
9385
9501
|
spinner.stop();
|
|
@@ -9391,7 +9507,7 @@ export function cn(...inputs: ClassValue[]) {
|
|
|
9391
9507
|
});
|
|
9392
9508
|
spinner.start("Initializing project...");
|
|
9393
9509
|
if (updatePostcss) {
|
|
9394
|
-
await
|
|
9510
|
+
await fs5.writeFile(postcssConfigPath, postcssConfigContent);
|
|
9395
9511
|
postcssCreated = true;
|
|
9396
9512
|
}
|
|
9397
9513
|
}
|
|
@@ -9399,47 +9515,47 @@ export function cn(...inputs: ClassValue[]) {
|
|
|
9399
9515
|
const deps = tailwindVersion === "v4" ? "clsx tailwind-merge class-variance-authority @radix-ui/react-slot lucide-react" : "clsx tailwind-merge class-variance-authority @radix-ui/react-slot lucide-react tailwindcss-animate tailwindcss@^3.4.0 autoprefixer";
|
|
9400
9516
|
try {
|
|
9401
9517
|
execSync(`npm install ${deps}`, { cwd, stdio: "pipe" });
|
|
9402
|
-
console.log(
|
|
9518
|
+
console.log(chalk4.green("\n \u2713 Installed dependencies"));
|
|
9403
9519
|
} catch {
|
|
9404
9520
|
spinner.warn("Could not install dependencies automatically");
|
|
9405
|
-
console.log(
|
|
9521
|
+
console.log(chalk4.yellow(`
|
|
9406
9522
|
Required dependencies:`));
|
|
9407
|
-
console.log(
|
|
9523
|
+
console.log(chalk4.cyan(` npm install ${deps}
|
|
9408
9524
|
`));
|
|
9409
9525
|
}
|
|
9410
9526
|
spinner.succeed("Project initialized successfully!");
|
|
9411
|
-
console.log(
|
|
9527
|
+
console.log(chalk4.green("\n \u2713 Created components.json"));
|
|
9412
9528
|
if (userPrefix) {
|
|
9413
|
-
console.log(
|
|
9529
|
+
console.log(chalk4.blue(` \u2139 Components will use prefix: "${userPrefix}"`));
|
|
9414
9530
|
} else {
|
|
9415
|
-
console.log(
|
|
9531
|
+
console.log(chalk4.blue(` \u2139 Components will use no prefix`));
|
|
9416
9532
|
}
|
|
9417
9533
|
if (utilsCreated) {
|
|
9418
|
-
console.log(
|
|
9534
|
+
console.log(chalk4.green(` \u2713 Created ${utilsPath}`));
|
|
9419
9535
|
} else if (utilsUpdated) {
|
|
9420
|
-
console.log(
|
|
9536
|
+
console.log(chalk4.green(` \u2713 Added cn() function to ${utilsPath}`));
|
|
9421
9537
|
} else {
|
|
9422
|
-
console.log(
|
|
9538
|
+
console.log(chalk4.green(` \u2713 ${utilsPath} already has cn() function`));
|
|
9423
9539
|
}
|
|
9424
|
-
console.log(
|
|
9540
|
+
console.log(chalk4.green(` \u2713 Created ${componentsPath}`));
|
|
9425
9541
|
if (themeCreated) {
|
|
9426
|
-
console.log(
|
|
9542
|
+
console.log(chalk4.green(` \u2713 Created src/lib/myoperator-ui-theme.css (CSS variables)`));
|
|
9427
9543
|
}
|
|
9428
9544
|
if (cssUpdated) {
|
|
9429
|
-
console.log(
|
|
9545
|
+
console.log(chalk4.green(` \u2713 Updated ${globalCss} with theme import`));
|
|
9430
9546
|
}
|
|
9431
9547
|
if (tailwindUpdated) {
|
|
9432
|
-
console.log(
|
|
9548
|
+
console.log(chalk4.green(` \u2713 Updated ${tailwindConfig} with theme colors`));
|
|
9433
9549
|
}
|
|
9434
9550
|
if (postcssCreated) {
|
|
9435
|
-
console.log(
|
|
9551
|
+
console.log(chalk4.green(" \u2713 Created postcss.config.js"));
|
|
9436
9552
|
}
|
|
9437
9553
|
console.log("");
|
|
9438
|
-
console.log(
|
|
9554
|
+
console.log(chalk4.bold(" Next steps:\n"));
|
|
9439
9555
|
console.log(" 1. Add your first component:");
|
|
9440
|
-
console.log(
|
|
9556
|
+
console.log(chalk4.cyan(" npx myoperator-ui add button\n"));
|
|
9441
9557
|
console.log(" 2. Browse all components:");
|
|
9442
|
-
console.log(
|
|
9558
|
+
console.log(chalk4.cyan(" https://myoperator-ui.vercel.app\n"));
|
|
9443
9559
|
} catch (error) {
|
|
9444
9560
|
spinner.fail("Failed to initialize project");
|
|
9445
9561
|
console.error(error);
|
|
@@ -9448,27 +9564,27 @@ export function cn(...inputs: ClassValue[]) {
|
|
|
9448
9564
|
}
|
|
9449
9565
|
|
|
9450
9566
|
// src/commands/sync.ts
|
|
9451
|
-
import
|
|
9452
|
-
import
|
|
9453
|
-
import
|
|
9567
|
+
import chalk5 from "chalk";
|
|
9568
|
+
import fs6 from "fs-extra";
|
|
9569
|
+
import path6 from "path";
|
|
9454
9570
|
import prompts3 from "prompts";
|
|
9455
|
-
import
|
|
9571
|
+
import ora4 from "ora";
|
|
9456
9572
|
async function sync(options) {
|
|
9457
9573
|
const cwd = process.cwd();
|
|
9458
9574
|
if (!await configExists(cwd)) {
|
|
9459
|
-
console.log(
|
|
9460
|
-
console.log(
|
|
9575
|
+
console.log(chalk5.red("\n Error: Project not initialized."));
|
|
9576
|
+
console.log(chalk5.yellow(" Run `npx myoperator-ui init` first.\n"));
|
|
9461
9577
|
process.exit(1);
|
|
9462
9578
|
}
|
|
9463
9579
|
const prefix = await getTailwindPrefix(cwd);
|
|
9464
9580
|
if (prefix) {
|
|
9465
|
-
console.log(
|
|
9581
|
+
console.log(chalk5.blue(`
|
|
9466
9582
|
\u2139 Applying Tailwind prefix: "${prefix}"
|
|
9467
9583
|
`));
|
|
9468
9584
|
}
|
|
9469
9585
|
const registry = await getRegistry(prefix);
|
|
9470
9586
|
const availableComponents = Object.keys(registry);
|
|
9471
|
-
console.log(
|
|
9587
|
+
console.log(chalk5.blue(` Scanning for ${availableComponents.length} components...
|
|
9472
9588
|
`));
|
|
9473
9589
|
const toAdd = [];
|
|
9474
9590
|
const toUpdate = [];
|
|
@@ -9476,25 +9592,25 @@ async function sync(options) {
|
|
|
9476
9592
|
for (const componentName of availableComponents) {
|
|
9477
9593
|
const component = registry[componentName];
|
|
9478
9594
|
const isCustomComponent = component.category === "custom";
|
|
9479
|
-
const baseDir = isCustomComponent ?
|
|
9480
|
-
const targetDir = component.isMultiFile ?
|
|
9595
|
+
const baseDir = isCustomComponent ? path6.join(cwd, "src/components/custom") : path6.join(cwd, options.path);
|
|
9596
|
+
const targetDir = component.isMultiFile ? path6.join(baseDir, component.directory) : baseDir;
|
|
9481
9597
|
const mainFileName = component.isMultiFile ? component.mainFile : component.files[0]?.name;
|
|
9482
9598
|
if (!mainFileName) continue;
|
|
9483
|
-
const mainFilePath =
|
|
9484
|
-
const exists = await
|
|
9599
|
+
const mainFilePath = path6.join(targetDir, mainFileName);
|
|
9600
|
+
const exists = await fs6.pathExists(mainFilePath);
|
|
9485
9601
|
if (!exists) {
|
|
9486
9602
|
toAdd.push(componentName);
|
|
9487
9603
|
} else {
|
|
9488
9604
|
const normalizeForComparison = (content) => content.replace(/\r\n/g, "\n").split("\n").map((line) => line.trimEnd()).join("\n").trim();
|
|
9489
9605
|
let needsUpdate = false;
|
|
9490
9606
|
for (const registryFile of component.files) {
|
|
9491
|
-
const filePath =
|
|
9492
|
-
const fileExists = await
|
|
9607
|
+
const filePath = path6.join(targetDir, registryFile.name);
|
|
9608
|
+
const fileExists = await fs6.pathExists(filePath);
|
|
9493
9609
|
if (!fileExists) {
|
|
9494
9610
|
needsUpdate = true;
|
|
9495
9611
|
break;
|
|
9496
9612
|
}
|
|
9497
|
-
const existingContent = await
|
|
9613
|
+
const existingContent = await fs6.readFile(filePath, "utf-8");
|
|
9498
9614
|
const existingNormalized = normalizeForComparison(existingContent);
|
|
9499
9615
|
const registryNormalized = normalizeForComparison(registryFile.content);
|
|
9500
9616
|
if (existingNormalized !== registryNormalized) {
|
|
@@ -9509,23 +9625,23 @@ async function sync(options) {
|
|
|
9509
9625
|
}
|
|
9510
9626
|
}
|
|
9511
9627
|
}
|
|
9512
|
-
console.log(
|
|
9513
|
-
console.log(
|
|
9514
|
-
console.log(
|
|
9515
|
-
console.log(
|
|
9628
|
+
console.log(chalk5.cyan(" Summary:"));
|
|
9629
|
+
console.log(chalk5.green(` New components to add: ${toAdd.length}`));
|
|
9630
|
+
console.log(chalk5.yellow(` Components to update: ${toUpdate.length}`));
|
|
9631
|
+
console.log(chalk5.gray(` Already up to date: ${upToDate.length}`));
|
|
9516
9632
|
console.log("");
|
|
9517
9633
|
if (toAdd.length === 0 && toUpdate.length === 0) {
|
|
9518
|
-
console.log(
|
|
9634
|
+
console.log(chalk5.green(" \u2713 All components are up to date!\n"));
|
|
9519
9635
|
return;
|
|
9520
9636
|
}
|
|
9521
9637
|
if (toAdd.length > 0) {
|
|
9522
|
-
console.log(
|
|
9523
|
-
toAdd.forEach((c) => console.log(
|
|
9638
|
+
console.log(chalk5.green(" Will add:"));
|
|
9639
|
+
toAdd.forEach((c) => console.log(chalk5.green(` + ${c}`)));
|
|
9524
9640
|
console.log("");
|
|
9525
9641
|
}
|
|
9526
9642
|
if (toUpdate.length > 0) {
|
|
9527
|
-
console.log(
|
|
9528
|
-
toUpdate.forEach((c) => console.log(
|
|
9643
|
+
console.log(chalk5.yellow(" Will update:"));
|
|
9644
|
+
toUpdate.forEach((c) => console.log(chalk5.yellow(` ~ ${c}`)));
|
|
9529
9645
|
console.log("");
|
|
9530
9646
|
}
|
|
9531
9647
|
if (!options.yes) {
|
|
@@ -9536,11 +9652,11 @@ async function sync(options) {
|
|
|
9536
9652
|
initial: true
|
|
9537
9653
|
});
|
|
9538
9654
|
if (!confirm) {
|
|
9539
|
-
console.log(
|
|
9655
|
+
console.log(chalk5.yellow("\n Sync cancelled.\n"));
|
|
9540
9656
|
process.exit(0);
|
|
9541
9657
|
}
|
|
9542
9658
|
}
|
|
9543
|
-
const spinner =
|
|
9659
|
+
const spinner = ora4("Syncing components...").start();
|
|
9544
9660
|
try {
|
|
9545
9661
|
const installed = [];
|
|
9546
9662
|
const dependencies = /* @__PURE__ */ new Set();
|
|
@@ -9554,11 +9670,11 @@ async function sync(options) {
|
|
|
9554
9670
|
const depComponent = registry[depName];
|
|
9555
9671
|
if (depComponent) {
|
|
9556
9672
|
const depIsCustom = depComponent.category === "custom";
|
|
9557
|
-
const depBaseDir = depIsCustom ?
|
|
9558
|
-
const depTargetDir = depComponent.isMultiFile ?
|
|
9673
|
+
const depBaseDir = depIsCustom ? path6.join(cwd, "src/components/custom") : path6.join(cwd, options.path);
|
|
9674
|
+
const depTargetDir = depComponent.isMultiFile ? path6.join(depBaseDir, depComponent.directory) : depBaseDir;
|
|
9559
9675
|
const depMainFile = depComponent.isMultiFile ? depComponent.mainFile : depComponent.files[0]?.name;
|
|
9560
9676
|
if (depMainFile) {
|
|
9561
|
-
const depExists = await
|
|
9677
|
+
const depExists = await fs6.pathExists(path6.join(depTargetDir, depMainFile));
|
|
9562
9678
|
if (!depExists) {
|
|
9563
9679
|
await installComponent(depName, "added");
|
|
9564
9680
|
}
|
|
@@ -9568,12 +9684,12 @@ async function sync(options) {
|
|
|
9568
9684
|
}
|
|
9569
9685
|
spinner.text = `${action === "added" ? "Adding" : "Updating"} ${componentName}...`;
|
|
9570
9686
|
const isCustomComponent = component.category === "custom";
|
|
9571
|
-
const baseDir = isCustomComponent ?
|
|
9572
|
-
const targetDir = component.isMultiFile ?
|
|
9687
|
+
const baseDir = isCustomComponent ? path6.join(cwd, "src/components/custom") : path6.join(cwd, options.path);
|
|
9688
|
+
const targetDir = component.isMultiFile ? path6.join(baseDir, component.directory) : baseDir;
|
|
9573
9689
|
for (const file of component.files) {
|
|
9574
|
-
const filePath =
|
|
9575
|
-
await
|
|
9576
|
-
await
|
|
9690
|
+
const filePath = path6.join(targetDir, file.name);
|
|
9691
|
+
await fs6.ensureDir(path6.dirname(filePath));
|
|
9692
|
+
await fs6.writeFile(filePath, file.content);
|
|
9577
9693
|
const basePath = isCustomComponent ? "src/components/custom" : options.path;
|
|
9578
9694
|
const relativePath = component.isMultiFile ? `${component.directory}/${file.name}` : file.name;
|
|
9579
9695
|
installed.push({ path: relativePath, basePath, action });
|
|
@@ -9593,29 +9709,24 @@ async function sync(options) {
|
|
|
9593
9709
|
const added = installed.filter((f) => f.action === "added");
|
|
9594
9710
|
const updated = installed.filter((f) => f.action === "updated");
|
|
9595
9711
|
if (added.length > 0) {
|
|
9596
|
-
console.log(
|
|
9712
|
+
console.log(chalk5.green("\n Added:"));
|
|
9597
9713
|
added.forEach((file) => {
|
|
9598
|
-
console.log(
|
|
9714
|
+
console.log(chalk5.green(` + ${file.basePath}/${file.path}`));
|
|
9599
9715
|
});
|
|
9600
9716
|
}
|
|
9601
9717
|
if (updated.length > 0) {
|
|
9602
|
-
console.log(
|
|
9718
|
+
console.log(chalk5.yellow("\n Updated:"));
|
|
9603
9719
|
updated.forEach((file) => {
|
|
9604
|
-
console.log(
|
|
9720
|
+
console.log(chalk5.yellow(` ~ ${file.basePath}/${file.path}`));
|
|
9605
9721
|
});
|
|
9606
9722
|
}
|
|
9607
9723
|
if (dependencies.size > 0) {
|
|
9608
|
-
console.log(
|
|
9609
|
-
console.log(
|
|
9724
|
+
console.log(chalk5.yellow("\n Required dependencies:"));
|
|
9725
|
+
console.log(chalk5.cyan(` npm install ${Array.from(dependencies).join(" ")}`));
|
|
9610
9726
|
}
|
|
9611
9727
|
const hasCustomComponents = installed.some((file) => file.basePath.includes("custom"));
|
|
9612
9728
|
if (hasCustomComponents) {
|
|
9613
|
-
|
|
9614
|
-
console.log(chalk3.white(" Make sure your tailwind.config.js includes:"));
|
|
9615
|
-
console.log(chalk3.cyan(" content: ["));
|
|
9616
|
-
console.log(chalk3.cyan(' "./src/components/ui/**/*.{js,ts,jsx,tsx}",'));
|
|
9617
|
-
console.log(chalk3.cyan(' "./src/components/custom/**/*.{js,ts,jsx,tsx}", // Add this line'));
|
|
9618
|
-
console.log(chalk3.cyan(" ]"));
|
|
9729
|
+
await ensureCustomComponentsInTailwindConfig(cwd);
|
|
9619
9730
|
}
|
|
9620
9731
|
console.log("");
|
|
9621
9732
|
} catch (error) {
|
|
@@ -9626,11 +9737,11 @@ async function sync(options) {
|
|
|
9626
9737
|
}
|
|
9627
9738
|
|
|
9628
9739
|
// src/commands/update.ts
|
|
9629
|
-
import
|
|
9630
|
-
import
|
|
9631
|
-
import
|
|
9740
|
+
import chalk6 from "chalk";
|
|
9741
|
+
import fs7 from "fs-extra";
|
|
9742
|
+
import path7 from "path";
|
|
9632
9743
|
import prompts4 from "prompts";
|
|
9633
|
-
import
|
|
9744
|
+
import ora5 from "ora";
|
|
9634
9745
|
function normalizeContent(content) {
|
|
9635
9746
|
return content.split("\n").map((line) => line.trimEnd()).join("\n").replace(/\r\n/g, "\n").trimEnd();
|
|
9636
9747
|
}
|
|
@@ -9641,12 +9752,12 @@ function generateDiff(oldContent, newContent, filename) {
|
|
|
9641
9752
|
const oldLines = oldContent.split("\n");
|
|
9642
9753
|
const newLines = newContent.split("\n");
|
|
9643
9754
|
if (!hasRealChanges(oldContent, newContent)) {
|
|
9644
|
-
return
|
|
9755
|
+
return chalk6.gray(` ${filename}: No changes`);
|
|
9645
9756
|
}
|
|
9646
9757
|
const changes = [];
|
|
9647
|
-
changes.push(
|
|
9758
|
+
changes.push(chalk6.cyan(`
|
|
9648
9759
|
--- ${filename} (current)`));
|
|
9649
|
-
changes.push(
|
|
9760
|
+
changes.push(chalk6.cyan(` +++ ${filename} (new)
|
|
9650
9761
|
`));
|
|
9651
9762
|
const maxLines = Math.max(oldLines.length, newLines.length);
|
|
9652
9763
|
let hasChanges = false;
|
|
@@ -9660,20 +9771,20 @@ function generateDiff(oldContent, newContent, filename) {
|
|
|
9660
9771
|
if (contextBuffer.length > 0 && !inChange) {
|
|
9661
9772
|
const startContext = Math.max(0, contextBuffer.length - 2);
|
|
9662
9773
|
for (let j = startContext; j < contextBuffer.length; j++) {
|
|
9663
|
-
changes.push(
|
|
9774
|
+
changes.push(chalk6.gray(` ${i - contextBuffer.length + j + 1}: ${contextBuffer[j]}`));
|
|
9664
9775
|
}
|
|
9665
9776
|
}
|
|
9666
9777
|
inChange = true;
|
|
9667
9778
|
contextBuffer = [];
|
|
9668
9779
|
if (oldLine !== void 0) {
|
|
9669
|
-
changes.push(
|
|
9780
|
+
changes.push(chalk6.red(` - ${i + 1}: ${oldLine}`));
|
|
9670
9781
|
}
|
|
9671
9782
|
if (newLine !== void 0) {
|
|
9672
|
-
changes.push(
|
|
9783
|
+
changes.push(chalk6.green(` + ${i + 1}: ${newLine}`));
|
|
9673
9784
|
}
|
|
9674
9785
|
} else {
|
|
9675
9786
|
if (inChange) {
|
|
9676
|
-
changes.push(
|
|
9787
|
+
changes.push(chalk6.gray(` ${i + 1}: ${oldLine}`));
|
|
9677
9788
|
inChange = false;
|
|
9678
9789
|
}
|
|
9679
9790
|
contextBuffer.push(oldLine || "");
|
|
@@ -9683,47 +9794,47 @@ function generateDiff(oldContent, newContent, filename) {
|
|
|
9683
9794
|
}
|
|
9684
9795
|
}
|
|
9685
9796
|
if (!hasChanges) {
|
|
9686
|
-
return
|
|
9797
|
+
return chalk6.gray(` ${filename}: No changes`);
|
|
9687
9798
|
}
|
|
9688
9799
|
return changes.join("\n");
|
|
9689
9800
|
}
|
|
9690
9801
|
async function update(components, options) {
|
|
9691
9802
|
const cwd = process.cwd();
|
|
9692
9803
|
if (!await configExists(cwd)) {
|
|
9693
|
-
console.log(
|
|
9694
|
-
console.log(
|
|
9804
|
+
console.log(chalk6.red("\n Error: Project not initialized."));
|
|
9805
|
+
console.log(chalk6.yellow(" Run `npx myoperator-ui init` first.\n"));
|
|
9695
9806
|
process.exit(1);
|
|
9696
9807
|
}
|
|
9697
9808
|
const prefix = await getTailwindPrefix(cwd);
|
|
9698
9809
|
if (prefix) {
|
|
9699
|
-
console.log(
|
|
9810
|
+
console.log(chalk6.blue(`
|
|
9700
9811
|
\u2139 Using Tailwind prefix: "${prefix}"
|
|
9701
9812
|
`));
|
|
9702
9813
|
}
|
|
9703
9814
|
const registry = await getRegistry(prefix);
|
|
9704
9815
|
const availableComponents = Object.keys(registry);
|
|
9705
|
-
const componentsDir =
|
|
9816
|
+
const componentsDir = path7.join(cwd, options.path);
|
|
9706
9817
|
const getComponentFilePath = (component) => {
|
|
9707
9818
|
if (component.isMultiFile && component.directory) {
|
|
9708
|
-
return
|
|
9819
|
+
return path7.join(componentsDir, component.directory, component.files[0].name);
|
|
9709
9820
|
}
|
|
9710
|
-
return
|
|
9821
|
+
return path7.join(componentsDir, component.files[0].name);
|
|
9711
9822
|
};
|
|
9712
9823
|
if (options.all) {
|
|
9713
9824
|
const installedComponents = [];
|
|
9714
9825
|
for (const name of availableComponents) {
|
|
9715
9826
|
const component = registry[name];
|
|
9716
9827
|
const filePath = getComponentFilePath(component);
|
|
9717
|
-
if (await
|
|
9828
|
+
if (await fs7.pathExists(filePath)) {
|
|
9718
9829
|
installedComponents.push(name);
|
|
9719
9830
|
}
|
|
9720
9831
|
}
|
|
9721
9832
|
if (installedComponents.length === 0) {
|
|
9722
|
-
console.log(
|
|
9833
|
+
console.log(chalk6.yellow("\n No installed components found to update.\n"));
|
|
9723
9834
|
process.exit(0);
|
|
9724
9835
|
}
|
|
9725
9836
|
components = installedComponents;
|
|
9726
|
-
console.log(
|
|
9837
|
+
console.log(chalk6.blue(` Found ${installedComponents.length} installed component(s)
|
|
9727
9838
|
`));
|
|
9728
9839
|
}
|
|
9729
9840
|
if (!components || components.length === 0) {
|
|
@@ -9731,12 +9842,12 @@ async function update(components, options) {
|
|
|
9731
9842
|
for (const name of availableComponents) {
|
|
9732
9843
|
const component = registry[name];
|
|
9733
9844
|
const filePath = getComponentFilePath(component);
|
|
9734
|
-
if (await
|
|
9845
|
+
if (await fs7.pathExists(filePath)) {
|
|
9735
9846
|
installedComponents.push(name);
|
|
9736
9847
|
}
|
|
9737
9848
|
}
|
|
9738
9849
|
if (installedComponents.length === 0) {
|
|
9739
|
-
console.log(
|
|
9850
|
+
console.log(chalk6.yellow("\n No installed components found to update.\n"));
|
|
9740
9851
|
process.exit(0);
|
|
9741
9852
|
}
|
|
9742
9853
|
const { selectedComponents } = await prompts4({
|
|
@@ -9751,16 +9862,16 @@ async function update(components, options) {
|
|
|
9751
9862
|
min: 1
|
|
9752
9863
|
});
|
|
9753
9864
|
if (!selectedComponents || selectedComponents.length === 0) {
|
|
9754
|
-
console.log(
|
|
9865
|
+
console.log(chalk6.yellow("\n No components selected.\n"));
|
|
9755
9866
|
process.exit(0);
|
|
9756
9867
|
}
|
|
9757
9868
|
components = selectedComponents;
|
|
9758
9869
|
}
|
|
9759
9870
|
const invalidComponents = components.filter((c) => !availableComponents.includes(c));
|
|
9760
9871
|
if (invalidComponents.length > 0) {
|
|
9761
|
-
console.log(
|
|
9872
|
+
console.log(chalk6.red(`
|
|
9762
9873
|
Error: Unknown components: ${invalidComponents.join(", ")}`));
|
|
9763
|
-
console.log(
|
|
9874
|
+
console.log(chalk6.yellow(` Available: ${availableComponents.join(", ")}
|
|
9764
9875
|
`));
|
|
9765
9876
|
process.exit(1);
|
|
9766
9877
|
}
|
|
@@ -9769,29 +9880,29 @@ async function update(components, options) {
|
|
|
9769
9880
|
for (const name of components) {
|
|
9770
9881
|
const component = registry[name];
|
|
9771
9882
|
const filePath = getComponentFilePath(component);
|
|
9772
|
-
if (await
|
|
9883
|
+
if (await fs7.pathExists(filePath)) {
|
|
9773
9884
|
toUpdate.push(name);
|
|
9774
9885
|
} else {
|
|
9775
9886
|
notInstalled.push(name);
|
|
9776
9887
|
}
|
|
9777
9888
|
}
|
|
9778
9889
|
if (notInstalled.length > 0) {
|
|
9779
|
-
console.log(
|
|
9890
|
+
console.log(chalk6.yellow(`
|
|
9780
9891
|
Components not installed (use 'add' instead): ${notInstalled.join(", ")}`));
|
|
9781
9892
|
}
|
|
9782
9893
|
if (toUpdate.length === 0) {
|
|
9783
|
-
console.log(
|
|
9894
|
+
console.log(chalk6.yellow("\n No installed components to update.\n"));
|
|
9784
9895
|
process.exit(0);
|
|
9785
9896
|
}
|
|
9786
|
-
console.log(
|
|
9897
|
+
console.log(chalk6.bold("\n Changes to be applied:\n"));
|
|
9787
9898
|
const changesInfo = [];
|
|
9788
9899
|
for (const componentName of toUpdate) {
|
|
9789
9900
|
const component = registry[componentName];
|
|
9790
9901
|
const subDir = component.isMultiFile && component.directory ? component.directory : "";
|
|
9791
9902
|
for (const file of component.files) {
|
|
9792
|
-
const relativePath = subDir ?
|
|
9793
|
-
const filePath =
|
|
9794
|
-
const oldContent = await
|
|
9903
|
+
const relativePath = subDir ? path7.join(subDir, file.name) : file.name;
|
|
9904
|
+
const filePath = path7.join(componentsDir, relativePath);
|
|
9905
|
+
const oldContent = await fs7.readFile(filePath, "utf-8");
|
|
9795
9906
|
const newContent = file.content;
|
|
9796
9907
|
const hasChanges = hasRealChanges(oldContent, newContent);
|
|
9797
9908
|
changesInfo.push({ name: componentName, file: file.name, relativePath, oldContent, newContent, hasChanges });
|
|
@@ -9801,14 +9912,14 @@ async function update(components, options) {
|
|
|
9801
9912
|
}
|
|
9802
9913
|
const componentsWithChanges = changesInfo.filter((c) => c.hasChanges);
|
|
9803
9914
|
if (componentsWithChanges.length === 0) {
|
|
9804
|
-
console.log(
|
|
9915
|
+
console.log(chalk6.green("\n \u2713 All components are already up to date!\n"));
|
|
9805
9916
|
process.exit(0);
|
|
9806
9917
|
}
|
|
9807
|
-
console.log(
|
|
9918
|
+
console.log(chalk6.bold(`
|
|
9808
9919
|
${componentsWithChanges.length} file(s) will be updated.
|
|
9809
9920
|
`));
|
|
9810
9921
|
if (options.dryRun) {
|
|
9811
|
-
console.log(
|
|
9922
|
+
console.log(chalk6.blue(" Dry run complete. No files were modified.\n"));
|
|
9812
9923
|
process.exit(0);
|
|
9813
9924
|
}
|
|
9814
9925
|
if (!options.yes) {
|
|
@@ -9819,35 +9930,35 @@ async function update(components, options) {
|
|
|
9819
9930
|
initial: true
|
|
9820
9931
|
});
|
|
9821
9932
|
if (!confirm) {
|
|
9822
|
-
console.log(
|
|
9933
|
+
console.log(chalk6.yellow("\n Update cancelled.\n"));
|
|
9823
9934
|
process.exit(0);
|
|
9824
9935
|
}
|
|
9825
9936
|
}
|
|
9826
|
-
const spinner =
|
|
9937
|
+
const spinner = ora5("Updating components...").start();
|
|
9827
9938
|
try {
|
|
9828
9939
|
const updated = [];
|
|
9829
9940
|
const backedUp = [];
|
|
9830
9941
|
for (const change of componentsWithChanges) {
|
|
9831
|
-
const filePath =
|
|
9942
|
+
const filePath = path7.join(componentsDir, change.relativePath);
|
|
9832
9943
|
if (options.backup) {
|
|
9833
9944
|
const backupPath = `${filePath}.backup.${Date.now()}`;
|
|
9834
|
-
await
|
|
9945
|
+
await fs7.copy(filePath, backupPath);
|
|
9835
9946
|
backedUp.push(change.relativePath);
|
|
9836
9947
|
}
|
|
9837
|
-
await
|
|
9948
|
+
await fs7.writeFile(filePath, change.newContent);
|
|
9838
9949
|
updated.push(change.relativePath);
|
|
9839
9950
|
}
|
|
9840
9951
|
spinner.succeed("Components updated successfully!");
|
|
9841
9952
|
if (backedUp.length > 0) {
|
|
9842
|
-
console.log(
|
|
9953
|
+
console.log(chalk6.blue("\n Backed up files:"));
|
|
9843
9954
|
backedUp.forEach((file) => {
|
|
9844
|
-
console.log(
|
|
9955
|
+
console.log(chalk6.blue(` \u{1F4C1} ${options.path}/${file}.backup.*`));
|
|
9845
9956
|
});
|
|
9846
9957
|
}
|
|
9847
9958
|
if (updated.length > 0) {
|
|
9848
|
-
console.log(
|
|
9959
|
+
console.log(chalk6.green("\n Updated files:"));
|
|
9849
9960
|
updated.forEach((file) => {
|
|
9850
|
-
console.log(
|
|
9961
|
+
console.log(chalk6.green(` \u2713 ${options.path}/${file}`));
|
|
9851
9962
|
});
|
|
9852
9963
|
}
|
|
9853
9964
|
console.log("");
|
|
@@ -9867,4 +9978,5 @@ program.command("init").description("Initialize your project with myOperator UI"
|
|
|
9867
9978
|
program.command("add").description("Add a component to your project").argument("[components...]", "Components to add").option("-a, --all", "Add all available components", false).option("-c, --category <category>", "Add all components from a category (core, form, data, overlay, feedback, layout, custom)").option("-y, --yes", "Skip confirmation prompt", false).option("-o, --overwrite", "Overwrite existing files", false).option("-p, --path <path>", "Path to add components to", "src/components/ui").action(add);
|
|
9868
9979
|
program.command("update").description("Update installed components to the latest version").argument("[components...]", "Components to update (leave empty to select)").option("-y, --yes", "Skip confirmation prompt", false).option("-a, --all", "Update all installed components", false).option("-d, --dry-run", "Show what would change without making changes", false).option("-b, --backup", "Create backup files before updating", false).option("-p, --path <path>", "Path to components directory", "src/components/ui").action(update);
|
|
9869
9980
|
program.command("sync").description("Add new components and update existing ones in one command").option("-y, --yes", "Skip confirmation prompt", false).option("-p, --path <path>", "Path to components directory", "src/components/ui").action(sync);
|
|
9981
|
+
program.command("fix").description("Fix configuration issues (e.g., missing Tailwind content paths)").action(fix);
|
|
9870
9982
|
program.parse();
|