myoperator-ui 0.0.152-beta.2 → 0.0.152-beta.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 +357 -222
- 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,27 +9169,39 @@ 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
|
-
|
|
9060
|
-
|
|
9061
|
-
|
|
9062
|
-
|
|
9063
|
-
|
|
9064
|
-
|
|
9174
|
+
const configPath = path5.join(cwd, "components.json");
|
|
9175
|
+
let skipConfigCreation = false;
|
|
9176
|
+
let existingConfig = null;
|
|
9177
|
+
if (await fs5.pathExists(configPath)) {
|
|
9178
|
+
existingConfig = await fs5.readJson(configPath);
|
|
9179
|
+
const { action } = await prompts2({
|
|
9180
|
+
type: "select",
|
|
9181
|
+
name: "action",
|
|
9182
|
+
message: "components.json already exists. What would you like to do?",
|
|
9183
|
+
choices: [
|
|
9184
|
+
{ title: "Update missing files only (theme, CSS)", value: "update" },
|
|
9185
|
+
{ title: "Overwrite everything", value: "overwrite" },
|
|
9186
|
+
{ title: "Cancel", value: "cancel" }
|
|
9187
|
+
],
|
|
9188
|
+
initial: 0
|
|
9065
9189
|
});
|
|
9066
|
-
if (
|
|
9067
|
-
console.log(
|
|
9190
|
+
if (action === "cancel") {
|
|
9191
|
+
console.log(chalk4.yellow(" Initialization cancelled.\n"));
|
|
9068
9192
|
process.exit(0);
|
|
9069
9193
|
}
|
|
9194
|
+
skipConfigCreation = action === "update";
|
|
9195
|
+
if (skipConfigCreation) {
|
|
9196
|
+
console.log(chalk4.blue(" \u2139 Keeping existing config, updating missing files...\n"));
|
|
9197
|
+
}
|
|
9070
9198
|
}
|
|
9071
|
-
const packageJsonPath =
|
|
9199
|
+
const packageJsonPath = path5.join(cwd, "package.json");
|
|
9072
9200
|
let hasBootstrap = false;
|
|
9073
9201
|
let isESM = false;
|
|
9074
9202
|
let detectedTailwindVersion = null;
|
|
9075
|
-
if (await
|
|
9076
|
-
const packageJson2 = await
|
|
9203
|
+
if (await fs5.pathExists(packageJsonPath)) {
|
|
9204
|
+
const packageJson2 = await fs5.readJson(packageJsonPath);
|
|
9077
9205
|
hasBootstrap = !!(packageJson2.dependencies?.bootstrap || packageJson2.devDependencies?.bootstrap);
|
|
9078
9206
|
isESM = packageJson2.type === "module";
|
|
9079
9207
|
const tailwindDep = packageJson2.dependencies?.tailwindcss || packageJson2.devDependencies?.tailwindcss;
|
|
@@ -9088,10 +9216,10 @@ async function init() {
|
|
|
9088
9216
|
detectedTailwindVersion = "v4";
|
|
9089
9217
|
}
|
|
9090
9218
|
if (hasBootstrap) {
|
|
9091
|
-
console.log(
|
|
9219
|
+
console.log(chalk4.blue(" \u2139 Bootstrap detected - will configure Tailwind to avoid conflicts\n"));
|
|
9092
9220
|
}
|
|
9093
9221
|
if (detectedTailwindVersion) {
|
|
9094
|
-
console.log(
|
|
9222
|
+
console.log(chalk4.blue(` \u2139 Tailwind CSS ${detectedTailwindVersion} detected
|
|
9095
9223
|
`));
|
|
9096
9224
|
}
|
|
9097
9225
|
}
|
|
@@ -9106,7 +9234,7 @@ async function init() {
|
|
|
9106
9234
|
"styles/globals.css"
|
|
9107
9235
|
];
|
|
9108
9236
|
for (const css of cssOptions) {
|
|
9109
|
-
if (await
|
|
9237
|
+
if (await fs5.pathExists(path5.join(cwd, css))) {
|
|
9110
9238
|
return css;
|
|
9111
9239
|
}
|
|
9112
9240
|
}
|
|
@@ -9120,7 +9248,7 @@ async function init() {
|
|
|
9120
9248
|
"tailwind.config.cjs"
|
|
9121
9249
|
];
|
|
9122
9250
|
for (const config of configOptions) {
|
|
9123
|
-
if (await
|
|
9251
|
+
if (await fs5.pathExists(path5.join(cwd, config))) {
|
|
9124
9252
|
return config;
|
|
9125
9253
|
}
|
|
9126
9254
|
}
|
|
@@ -9130,7 +9258,7 @@ async function init() {
|
|
|
9130
9258
|
const detectedTailwindConfig = await detectTailwindConfig();
|
|
9131
9259
|
const detectedPrefix = await detectTailwindPrefix(detectedTailwindConfig, cwd);
|
|
9132
9260
|
if (detectedPrefix) {
|
|
9133
|
-
console.log(
|
|
9261
|
+
console.log(chalk4.blue(` \u2139 Tailwind prefix "${detectedPrefix}" detected - components will use prefixed classes
|
|
9134
9262
|
`));
|
|
9135
9263
|
}
|
|
9136
9264
|
let tailwindVersion = detectedTailwindVersion;
|
|
@@ -9148,18 +9276,20 @@ async function init() {
|
|
|
9148
9276
|
initial: 0
|
|
9149
9277
|
});
|
|
9150
9278
|
}
|
|
9151
|
-
|
|
9152
|
-
|
|
9153
|
-
|
|
9154
|
-
|
|
9155
|
-
|
|
9156
|
-
|
|
9157
|
-
|
|
9158
|
-
|
|
9279
|
+
if (!skipConfigCreation) {
|
|
9280
|
+
questions.push({
|
|
9281
|
+
type: "text",
|
|
9282
|
+
name: "prefix",
|
|
9283
|
+
message: detectedPrefix ? `Confirm Tailwind prefix (detected: "${detectedPrefix}"):` : "Enter Tailwind CSS prefix (default: tw-):",
|
|
9284
|
+
initial: detectedPrefix || "tw-",
|
|
9285
|
+
validate: (value) => {
|
|
9286
|
+
if (value === "" || /^[a-zA-Z_-][a-zA-Z0-9_-]*$/.test(value)) {
|
|
9287
|
+
return true;
|
|
9288
|
+
}
|
|
9289
|
+
return "Prefix must be a valid CSS identifier (letters, numbers, hyphens, underscores)";
|
|
9159
9290
|
}
|
|
9160
|
-
|
|
9161
|
-
|
|
9162
|
-
});
|
|
9291
|
+
});
|
|
9292
|
+
}
|
|
9163
9293
|
if (questions.length > 0) {
|
|
9164
9294
|
const response = await prompts2(questions);
|
|
9165
9295
|
if (!tailwindVersion) {
|
|
@@ -9171,23 +9301,28 @@ async function init() {
|
|
|
9171
9301
|
const utilsPath = "src/lib/utils.ts";
|
|
9172
9302
|
const tailwindConfig = detectedTailwindConfig;
|
|
9173
9303
|
const globalCss = detectedCss;
|
|
9174
|
-
const spinner =
|
|
9304
|
+
const spinner = ora3("Initializing project...").start();
|
|
9175
9305
|
try {
|
|
9176
|
-
|
|
9177
|
-
|
|
9178
|
-
|
|
9179
|
-
|
|
9180
|
-
|
|
9181
|
-
|
|
9182
|
-
|
|
9183
|
-
|
|
9184
|
-
|
|
9185
|
-
|
|
9186
|
-
|
|
9187
|
-
|
|
9188
|
-
|
|
9189
|
-
|
|
9190
|
-
|
|
9306
|
+
if (!skipConfigCreation) {
|
|
9307
|
+
const config = {
|
|
9308
|
+
...DEFAULT_CONFIG,
|
|
9309
|
+
tailwind: {
|
|
9310
|
+
...DEFAULT_CONFIG.tailwind,
|
|
9311
|
+
config: tailwindConfig,
|
|
9312
|
+
css: globalCss,
|
|
9313
|
+
prefix: userPrefix
|
|
9314
|
+
},
|
|
9315
|
+
aliases: {
|
|
9316
|
+
...DEFAULT_CONFIG.aliases,
|
|
9317
|
+
ui: `@/${componentsPath.replace("src/", "")}`
|
|
9318
|
+
}
|
|
9319
|
+
};
|
|
9320
|
+
await fs5.writeJson(configPath, config, { spaces: 2 });
|
|
9321
|
+
} else if (existingConfig) {
|
|
9322
|
+
const existingTailwind = existingConfig.tailwind;
|
|
9323
|
+
userPrefix = existingTailwind?.prefix || "";
|
|
9324
|
+
}
|
|
9325
|
+
const utilsFullPath = path5.join(cwd, utilsPath);
|
|
9191
9326
|
const getCnUtilsContent = (prefix) => {
|
|
9192
9327
|
if (prefix) {
|
|
9193
9328
|
return `import { type ClassValue, clsx } from "clsx"
|
|
@@ -9214,12 +9349,12 @@ export function cn(...inputs: ClassValue[]) {
|
|
|
9214
9349
|
const cnUtilsContent = getCnUtilsContent(userPrefix);
|
|
9215
9350
|
let utilsCreated = false;
|
|
9216
9351
|
let utilsUpdated = false;
|
|
9217
|
-
if (!await
|
|
9218
|
-
await
|
|
9219
|
-
await
|
|
9352
|
+
if (!await fs5.pathExists(utilsFullPath)) {
|
|
9353
|
+
await fs5.ensureDir(path5.dirname(utilsFullPath));
|
|
9354
|
+
await fs5.writeFile(utilsFullPath, cnUtilsContent);
|
|
9220
9355
|
utilsCreated = true;
|
|
9221
9356
|
} else {
|
|
9222
|
-
const existingUtils = await
|
|
9357
|
+
const existingUtils = await fs5.readFile(utilsFullPath, "utf-8");
|
|
9223
9358
|
if (!existingUtils.includes("export function cn") && !existingUtils.includes("export const cn")) {
|
|
9224
9359
|
let updatedContent = existingUtils;
|
|
9225
9360
|
const hasClsxImport = existingUtils.includes('from "clsx"') || existingUtils.includes("from 'clsx'");
|
|
@@ -9262,26 +9397,26 @@ export function cn(...inputs: ClassValue[]) {
|
|
|
9262
9397
|
`;
|
|
9263
9398
|
}
|
|
9264
9399
|
updatedContent = updatedContent.trimEnd() + "\n" + cnFunction;
|
|
9265
|
-
await
|
|
9400
|
+
await fs5.writeFile(utilsFullPath, updatedContent);
|
|
9266
9401
|
utilsUpdated = true;
|
|
9267
9402
|
}
|
|
9268
9403
|
}
|
|
9269
|
-
const componentsFullPath =
|
|
9270
|
-
await
|
|
9271
|
-
const themeFilePath =
|
|
9404
|
+
const componentsFullPath = path5.join(cwd, componentsPath);
|
|
9405
|
+
await fs5.ensureDir(componentsFullPath);
|
|
9406
|
+
const themeFilePath = path5.join(cwd, "src/lib/myoperator-ui-theme.css");
|
|
9272
9407
|
let themeCreated = false;
|
|
9273
|
-
if (!await
|
|
9274
|
-
await
|
|
9275
|
-
await
|
|
9408
|
+
if (!await fs5.pathExists(themeFilePath)) {
|
|
9409
|
+
await fs5.ensureDir(path5.dirname(themeFilePath));
|
|
9410
|
+
await fs5.writeFile(themeFilePath, MYOPERATOR_THEME_CSS);
|
|
9276
9411
|
themeCreated = true;
|
|
9277
9412
|
} else {
|
|
9278
|
-
const existingTheme = await
|
|
9413
|
+
const existingTheme = await fs5.readFile(themeFilePath, "utf-8");
|
|
9279
9414
|
if (!existingTheme.includes("--semantic-text-primary")) {
|
|
9280
|
-
await
|
|
9415
|
+
await fs5.writeFile(themeFilePath, MYOPERATOR_THEME_CSS);
|
|
9281
9416
|
themeCreated = true;
|
|
9282
9417
|
}
|
|
9283
9418
|
}
|
|
9284
|
-
const globalCssPath =
|
|
9419
|
+
const globalCssPath = path5.join(cwd, globalCss);
|
|
9285
9420
|
let cssContent;
|
|
9286
9421
|
if (tailwindVersion === "v4") {
|
|
9287
9422
|
cssContent = hasBootstrap ? CSS_VARIABLES_V4_BOOTSTRAP : CSS_VARIABLES_V4;
|
|
@@ -9289,12 +9424,12 @@ export function cn(...inputs: ClassValue[]) {
|
|
|
9289
9424
|
cssContent = CSS_VARIABLES_V3;
|
|
9290
9425
|
}
|
|
9291
9426
|
let cssUpdated = false;
|
|
9292
|
-
if (!await
|
|
9293
|
-
await
|
|
9294
|
-
await
|
|
9427
|
+
if (!await fs5.pathExists(globalCssPath)) {
|
|
9428
|
+
await fs5.ensureDir(path5.dirname(globalCssPath));
|
|
9429
|
+
await fs5.writeFile(globalCssPath, cssContent);
|
|
9295
9430
|
cssUpdated = true;
|
|
9296
9431
|
} else {
|
|
9297
|
-
const existingCss = await
|
|
9432
|
+
const existingCss = await fs5.readFile(globalCssPath, "utf-8");
|
|
9298
9433
|
const hasThemeImport = existingCss.includes("myoperator-ui-theme.css");
|
|
9299
9434
|
if (!hasThemeImport) {
|
|
9300
9435
|
spinner.stop();
|
|
@@ -9311,9 +9446,9 @@ export function cn(...inputs: ClassValue[]) {
|
|
|
9311
9446
|
(imp) => !imp.includes("tailwindcss") && !imp.includes("@tailwind")
|
|
9312
9447
|
).join("\n");
|
|
9313
9448
|
if (importsToKeep) {
|
|
9314
|
-
await
|
|
9449
|
+
await fs5.writeFile(globalCssPath, cssContent + "\n" + importsToKeep + "\n");
|
|
9315
9450
|
} else {
|
|
9316
|
-
await
|
|
9451
|
+
await fs5.writeFile(globalCssPath, cssContent);
|
|
9317
9452
|
}
|
|
9318
9453
|
cssUpdated = true;
|
|
9319
9454
|
}
|
|
@@ -9321,16 +9456,16 @@ export function cn(...inputs: ClassValue[]) {
|
|
|
9321
9456
|
}
|
|
9322
9457
|
let tailwindUpdated = false;
|
|
9323
9458
|
if (tailwindVersion === "v3" && tailwindConfig) {
|
|
9324
|
-
const tailwindConfigPath =
|
|
9325
|
-
if (!await
|
|
9326
|
-
await
|
|
9459
|
+
const tailwindConfigPath = path5.join(cwd, tailwindConfig);
|
|
9460
|
+
if (!await fs5.pathExists(tailwindConfigPath)) {
|
|
9461
|
+
await fs5.writeFile(tailwindConfigPath, getTailwindConfig(userPrefix, hasBootstrap));
|
|
9327
9462
|
tailwindUpdated = true;
|
|
9328
9463
|
} else {
|
|
9329
|
-
const
|
|
9330
|
-
const hasLegacyColors =
|
|
9331
|
-
const hasSemanticColors =
|
|
9464
|
+
const existingConfig2 = await fs5.readFile(tailwindConfigPath, "utf-8");
|
|
9465
|
+
const hasLegacyColors = existingConfig2.includes("hsl(var(--destructive))") || existingConfig2.includes("hsl(var(--ring))");
|
|
9466
|
+
const hasSemanticColors = existingConfig2.includes("semantic-text-primary");
|
|
9332
9467
|
if (!hasLegacyColors && !hasSemanticColors) {
|
|
9333
|
-
await
|
|
9468
|
+
await fs5.writeFile(tailwindConfigPath, getTailwindConfig(userPrefix, hasBootstrap));
|
|
9334
9469
|
tailwindUpdated = true;
|
|
9335
9470
|
} else if (hasLegacyColors && !hasSemanticColors) {
|
|
9336
9471
|
spinner.stop();
|
|
@@ -9342,13 +9477,13 @@ export function cn(...inputs: ClassValue[]) {
|
|
|
9342
9477
|
});
|
|
9343
9478
|
spinner.start("Initializing project...");
|
|
9344
9479
|
if (result.updateTailwind) {
|
|
9345
|
-
await
|
|
9480
|
+
await fs5.writeFile(tailwindConfigPath, getTailwindConfig(userPrefix, hasBootstrap));
|
|
9346
9481
|
tailwindUpdated = true;
|
|
9347
9482
|
}
|
|
9348
9483
|
}
|
|
9349
9484
|
}
|
|
9350
9485
|
}
|
|
9351
|
-
const postcssConfigPath =
|
|
9486
|
+
const postcssConfigPath = path5.join(cwd, "postcss.config.js");
|
|
9352
9487
|
let postcssConfigContent;
|
|
9353
9488
|
if (tailwindVersion === "v4") {
|
|
9354
9489
|
postcssConfigContent = isESM ? `export default {
|
|
@@ -9378,8 +9513,8 @@ export function cn(...inputs: ClassValue[]) {
|
|
|
9378
9513
|
`;
|
|
9379
9514
|
}
|
|
9380
9515
|
let postcssCreated = false;
|
|
9381
|
-
if (!await
|
|
9382
|
-
await
|
|
9516
|
+
if (!await fs5.pathExists(postcssConfigPath)) {
|
|
9517
|
+
await fs5.writeFile(postcssConfigPath, postcssConfigContent);
|
|
9383
9518
|
postcssCreated = true;
|
|
9384
9519
|
} else {
|
|
9385
9520
|
spinner.stop();
|
|
@@ -9391,7 +9526,7 @@ export function cn(...inputs: ClassValue[]) {
|
|
|
9391
9526
|
});
|
|
9392
9527
|
spinner.start("Initializing project...");
|
|
9393
9528
|
if (updatePostcss) {
|
|
9394
|
-
await
|
|
9529
|
+
await fs5.writeFile(postcssConfigPath, postcssConfigContent);
|
|
9395
9530
|
postcssCreated = true;
|
|
9396
9531
|
}
|
|
9397
9532
|
}
|
|
@@ -9399,47 +9534,51 @@ export function cn(...inputs: ClassValue[]) {
|
|
|
9399
9534
|
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
9535
|
try {
|
|
9401
9536
|
execSync(`npm install ${deps}`, { cwd, stdio: "pipe" });
|
|
9402
|
-
console.log(
|
|
9537
|
+
console.log(chalk4.green("\n \u2713 Installed dependencies"));
|
|
9403
9538
|
} catch {
|
|
9404
9539
|
spinner.warn("Could not install dependencies automatically");
|
|
9405
|
-
console.log(
|
|
9540
|
+
console.log(chalk4.yellow(`
|
|
9406
9541
|
Required dependencies:`));
|
|
9407
|
-
console.log(
|
|
9542
|
+
console.log(chalk4.cyan(` npm install ${deps}
|
|
9408
9543
|
`));
|
|
9409
9544
|
}
|
|
9410
|
-
spinner.succeed("Project initialized successfully!");
|
|
9411
|
-
|
|
9545
|
+
spinner.succeed(skipConfigCreation ? "Project updated successfully!" : "Project initialized successfully!");
|
|
9546
|
+
if (!skipConfigCreation) {
|
|
9547
|
+
console.log(chalk4.green("\n \u2713 Created components.json"));
|
|
9548
|
+
} else {
|
|
9549
|
+
console.log(chalk4.green("\n \u2713 Using existing components.json"));
|
|
9550
|
+
}
|
|
9412
9551
|
if (userPrefix) {
|
|
9413
|
-
console.log(
|
|
9552
|
+
console.log(chalk4.blue(` \u2139 Components will use prefix: "${userPrefix}"`));
|
|
9414
9553
|
} else {
|
|
9415
|
-
console.log(
|
|
9554
|
+
console.log(chalk4.blue(` \u2139 Components will use no prefix`));
|
|
9416
9555
|
}
|
|
9417
9556
|
if (utilsCreated) {
|
|
9418
|
-
console.log(
|
|
9557
|
+
console.log(chalk4.green(` \u2713 Created ${utilsPath}`));
|
|
9419
9558
|
} else if (utilsUpdated) {
|
|
9420
|
-
console.log(
|
|
9559
|
+
console.log(chalk4.green(` \u2713 Added cn() function to ${utilsPath}`));
|
|
9421
9560
|
} else {
|
|
9422
|
-
console.log(
|
|
9561
|
+
console.log(chalk4.green(` \u2713 ${utilsPath} already has cn() function`));
|
|
9423
9562
|
}
|
|
9424
|
-
console.log(
|
|
9563
|
+
console.log(chalk4.green(` \u2713 Created ${componentsPath}`));
|
|
9425
9564
|
if (themeCreated) {
|
|
9426
|
-
console.log(
|
|
9565
|
+
console.log(chalk4.green(` \u2713 Created src/lib/myoperator-ui-theme.css (CSS variables)`));
|
|
9427
9566
|
}
|
|
9428
9567
|
if (cssUpdated) {
|
|
9429
|
-
console.log(
|
|
9568
|
+
console.log(chalk4.green(` \u2713 Updated ${globalCss} with theme import`));
|
|
9430
9569
|
}
|
|
9431
9570
|
if (tailwindUpdated) {
|
|
9432
|
-
console.log(
|
|
9571
|
+
console.log(chalk4.green(` \u2713 Updated ${tailwindConfig} with theme colors`));
|
|
9433
9572
|
}
|
|
9434
9573
|
if (postcssCreated) {
|
|
9435
|
-
console.log(
|
|
9574
|
+
console.log(chalk4.green(" \u2713 Created postcss.config.js"));
|
|
9436
9575
|
}
|
|
9437
9576
|
console.log("");
|
|
9438
|
-
console.log(
|
|
9577
|
+
console.log(chalk4.bold(" Next steps:\n"));
|
|
9439
9578
|
console.log(" 1. Add your first component:");
|
|
9440
|
-
console.log(
|
|
9579
|
+
console.log(chalk4.cyan(" npx myoperator-ui add button\n"));
|
|
9441
9580
|
console.log(" 2. Browse all components:");
|
|
9442
|
-
console.log(
|
|
9581
|
+
console.log(chalk4.cyan(" https://myoperator-ui.vercel.app\n"));
|
|
9443
9582
|
} catch (error) {
|
|
9444
9583
|
spinner.fail("Failed to initialize project");
|
|
9445
9584
|
console.error(error);
|
|
@@ -9448,27 +9587,27 @@ export function cn(...inputs: ClassValue[]) {
|
|
|
9448
9587
|
}
|
|
9449
9588
|
|
|
9450
9589
|
// src/commands/sync.ts
|
|
9451
|
-
import
|
|
9452
|
-
import
|
|
9453
|
-
import
|
|
9590
|
+
import chalk5 from "chalk";
|
|
9591
|
+
import fs6 from "fs-extra";
|
|
9592
|
+
import path6 from "path";
|
|
9454
9593
|
import prompts3 from "prompts";
|
|
9455
|
-
import
|
|
9594
|
+
import ora4 from "ora";
|
|
9456
9595
|
async function sync(options) {
|
|
9457
9596
|
const cwd = process.cwd();
|
|
9458
9597
|
if (!await configExists(cwd)) {
|
|
9459
|
-
console.log(
|
|
9460
|
-
console.log(
|
|
9598
|
+
console.log(chalk5.red("\n Error: Project not initialized."));
|
|
9599
|
+
console.log(chalk5.yellow(" Run `npx myoperator-ui init` first.\n"));
|
|
9461
9600
|
process.exit(1);
|
|
9462
9601
|
}
|
|
9463
9602
|
const prefix = await getTailwindPrefix(cwd);
|
|
9464
9603
|
if (prefix) {
|
|
9465
|
-
console.log(
|
|
9604
|
+
console.log(chalk5.blue(`
|
|
9466
9605
|
\u2139 Applying Tailwind prefix: "${prefix}"
|
|
9467
9606
|
`));
|
|
9468
9607
|
}
|
|
9469
9608
|
const registry = await getRegistry(prefix);
|
|
9470
9609
|
const availableComponents = Object.keys(registry);
|
|
9471
|
-
console.log(
|
|
9610
|
+
console.log(chalk5.blue(` Scanning for ${availableComponents.length} components...
|
|
9472
9611
|
`));
|
|
9473
9612
|
const toAdd = [];
|
|
9474
9613
|
const toUpdate = [];
|
|
@@ -9476,25 +9615,25 @@ async function sync(options) {
|
|
|
9476
9615
|
for (const componentName of availableComponents) {
|
|
9477
9616
|
const component = registry[componentName];
|
|
9478
9617
|
const isCustomComponent = component.category === "custom";
|
|
9479
|
-
const baseDir = isCustomComponent ?
|
|
9480
|
-
const targetDir = component.isMultiFile ?
|
|
9618
|
+
const baseDir = isCustomComponent ? path6.join(cwd, "src/components/custom") : path6.join(cwd, options.path);
|
|
9619
|
+
const targetDir = component.isMultiFile ? path6.join(baseDir, component.directory) : baseDir;
|
|
9481
9620
|
const mainFileName = component.isMultiFile ? component.mainFile : component.files[0]?.name;
|
|
9482
9621
|
if (!mainFileName) continue;
|
|
9483
|
-
const mainFilePath =
|
|
9484
|
-
const exists = await
|
|
9622
|
+
const mainFilePath = path6.join(targetDir, mainFileName);
|
|
9623
|
+
const exists = await fs6.pathExists(mainFilePath);
|
|
9485
9624
|
if (!exists) {
|
|
9486
9625
|
toAdd.push(componentName);
|
|
9487
9626
|
} else {
|
|
9488
9627
|
const normalizeForComparison = (content) => content.replace(/\r\n/g, "\n").split("\n").map((line) => line.trimEnd()).join("\n").trim();
|
|
9489
9628
|
let needsUpdate = false;
|
|
9490
9629
|
for (const registryFile of component.files) {
|
|
9491
|
-
const filePath =
|
|
9492
|
-
const fileExists = await
|
|
9630
|
+
const filePath = path6.join(targetDir, registryFile.name);
|
|
9631
|
+
const fileExists = await fs6.pathExists(filePath);
|
|
9493
9632
|
if (!fileExists) {
|
|
9494
9633
|
needsUpdate = true;
|
|
9495
9634
|
break;
|
|
9496
9635
|
}
|
|
9497
|
-
const existingContent = await
|
|
9636
|
+
const existingContent = await fs6.readFile(filePath, "utf-8");
|
|
9498
9637
|
const existingNormalized = normalizeForComparison(existingContent);
|
|
9499
9638
|
const registryNormalized = normalizeForComparison(registryFile.content);
|
|
9500
9639
|
if (existingNormalized !== registryNormalized) {
|
|
@@ -9509,23 +9648,23 @@ async function sync(options) {
|
|
|
9509
9648
|
}
|
|
9510
9649
|
}
|
|
9511
9650
|
}
|
|
9512
|
-
console.log(
|
|
9513
|
-
console.log(
|
|
9514
|
-
console.log(
|
|
9515
|
-
console.log(
|
|
9651
|
+
console.log(chalk5.cyan(" Summary:"));
|
|
9652
|
+
console.log(chalk5.green(` New components to add: ${toAdd.length}`));
|
|
9653
|
+
console.log(chalk5.yellow(` Components to update: ${toUpdate.length}`));
|
|
9654
|
+
console.log(chalk5.gray(` Already up to date: ${upToDate.length}`));
|
|
9516
9655
|
console.log("");
|
|
9517
9656
|
if (toAdd.length === 0 && toUpdate.length === 0) {
|
|
9518
|
-
console.log(
|
|
9657
|
+
console.log(chalk5.green(" \u2713 All components are up to date!\n"));
|
|
9519
9658
|
return;
|
|
9520
9659
|
}
|
|
9521
9660
|
if (toAdd.length > 0) {
|
|
9522
|
-
console.log(
|
|
9523
|
-
toAdd.forEach((c) => console.log(
|
|
9661
|
+
console.log(chalk5.green(" Will add:"));
|
|
9662
|
+
toAdd.forEach((c) => console.log(chalk5.green(` + ${c}`)));
|
|
9524
9663
|
console.log("");
|
|
9525
9664
|
}
|
|
9526
9665
|
if (toUpdate.length > 0) {
|
|
9527
|
-
console.log(
|
|
9528
|
-
toUpdate.forEach((c) => console.log(
|
|
9666
|
+
console.log(chalk5.yellow(" Will update:"));
|
|
9667
|
+
toUpdate.forEach((c) => console.log(chalk5.yellow(` ~ ${c}`)));
|
|
9529
9668
|
console.log("");
|
|
9530
9669
|
}
|
|
9531
9670
|
if (!options.yes) {
|
|
@@ -9536,11 +9675,11 @@ async function sync(options) {
|
|
|
9536
9675
|
initial: true
|
|
9537
9676
|
});
|
|
9538
9677
|
if (!confirm) {
|
|
9539
|
-
console.log(
|
|
9678
|
+
console.log(chalk5.yellow("\n Sync cancelled.\n"));
|
|
9540
9679
|
process.exit(0);
|
|
9541
9680
|
}
|
|
9542
9681
|
}
|
|
9543
|
-
const spinner =
|
|
9682
|
+
const spinner = ora4("Syncing components...").start();
|
|
9544
9683
|
try {
|
|
9545
9684
|
const installed = [];
|
|
9546
9685
|
const dependencies = /* @__PURE__ */ new Set();
|
|
@@ -9554,11 +9693,11 @@ async function sync(options) {
|
|
|
9554
9693
|
const depComponent = registry[depName];
|
|
9555
9694
|
if (depComponent) {
|
|
9556
9695
|
const depIsCustom = depComponent.category === "custom";
|
|
9557
|
-
const depBaseDir = depIsCustom ?
|
|
9558
|
-
const depTargetDir = depComponent.isMultiFile ?
|
|
9696
|
+
const depBaseDir = depIsCustom ? path6.join(cwd, "src/components/custom") : path6.join(cwd, options.path);
|
|
9697
|
+
const depTargetDir = depComponent.isMultiFile ? path6.join(depBaseDir, depComponent.directory) : depBaseDir;
|
|
9559
9698
|
const depMainFile = depComponent.isMultiFile ? depComponent.mainFile : depComponent.files[0]?.name;
|
|
9560
9699
|
if (depMainFile) {
|
|
9561
|
-
const depExists = await
|
|
9700
|
+
const depExists = await fs6.pathExists(path6.join(depTargetDir, depMainFile));
|
|
9562
9701
|
if (!depExists) {
|
|
9563
9702
|
await installComponent(depName, "added");
|
|
9564
9703
|
}
|
|
@@ -9568,12 +9707,12 @@ async function sync(options) {
|
|
|
9568
9707
|
}
|
|
9569
9708
|
spinner.text = `${action === "added" ? "Adding" : "Updating"} ${componentName}...`;
|
|
9570
9709
|
const isCustomComponent = component.category === "custom";
|
|
9571
|
-
const baseDir = isCustomComponent ?
|
|
9572
|
-
const targetDir = component.isMultiFile ?
|
|
9710
|
+
const baseDir = isCustomComponent ? path6.join(cwd, "src/components/custom") : path6.join(cwd, options.path);
|
|
9711
|
+
const targetDir = component.isMultiFile ? path6.join(baseDir, component.directory) : baseDir;
|
|
9573
9712
|
for (const file of component.files) {
|
|
9574
|
-
const filePath =
|
|
9575
|
-
await
|
|
9576
|
-
await
|
|
9713
|
+
const filePath = path6.join(targetDir, file.name);
|
|
9714
|
+
await fs6.ensureDir(path6.dirname(filePath));
|
|
9715
|
+
await fs6.writeFile(filePath, file.content);
|
|
9577
9716
|
const basePath = isCustomComponent ? "src/components/custom" : options.path;
|
|
9578
9717
|
const relativePath = component.isMultiFile ? `${component.directory}/${file.name}` : file.name;
|
|
9579
9718
|
installed.push({ path: relativePath, basePath, action });
|
|
@@ -9593,29 +9732,24 @@ async function sync(options) {
|
|
|
9593
9732
|
const added = installed.filter((f) => f.action === "added");
|
|
9594
9733
|
const updated = installed.filter((f) => f.action === "updated");
|
|
9595
9734
|
if (added.length > 0) {
|
|
9596
|
-
console.log(
|
|
9735
|
+
console.log(chalk5.green("\n Added:"));
|
|
9597
9736
|
added.forEach((file) => {
|
|
9598
|
-
console.log(
|
|
9737
|
+
console.log(chalk5.green(` + ${file.basePath}/${file.path}`));
|
|
9599
9738
|
});
|
|
9600
9739
|
}
|
|
9601
9740
|
if (updated.length > 0) {
|
|
9602
|
-
console.log(
|
|
9741
|
+
console.log(chalk5.yellow("\n Updated:"));
|
|
9603
9742
|
updated.forEach((file) => {
|
|
9604
|
-
console.log(
|
|
9743
|
+
console.log(chalk5.yellow(` ~ ${file.basePath}/${file.path}`));
|
|
9605
9744
|
});
|
|
9606
9745
|
}
|
|
9607
9746
|
if (dependencies.size > 0) {
|
|
9608
|
-
console.log(
|
|
9609
|
-
console.log(
|
|
9747
|
+
console.log(chalk5.yellow("\n Required dependencies:"));
|
|
9748
|
+
console.log(chalk5.cyan(` npm install ${Array.from(dependencies).join(" ")}`));
|
|
9610
9749
|
}
|
|
9611
9750
|
const hasCustomComponents = installed.some((file) => file.basePath.includes("custom"));
|
|
9612
9751
|
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(" ]"));
|
|
9752
|
+
await ensureCustomComponentsInTailwindConfig(cwd);
|
|
9619
9753
|
}
|
|
9620
9754
|
console.log("");
|
|
9621
9755
|
} catch (error) {
|
|
@@ -9626,11 +9760,11 @@ async function sync(options) {
|
|
|
9626
9760
|
}
|
|
9627
9761
|
|
|
9628
9762
|
// src/commands/update.ts
|
|
9629
|
-
import
|
|
9630
|
-
import
|
|
9631
|
-
import
|
|
9763
|
+
import chalk6 from "chalk";
|
|
9764
|
+
import fs7 from "fs-extra";
|
|
9765
|
+
import path7 from "path";
|
|
9632
9766
|
import prompts4 from "prompts";
|
|
9633
|
-
import
|
|
9767
|
+
import ora5 from "ora";
|
|
9634
9768
|
function normalizeContent(content) {
|
|
9635
9769
|
return content.split("\n").map((line) => line.trimEnd()).join("\n").replace(/\r\n/g, "\n").trimEnd();
|
|
9636
9770
|
}
|
|
@@ -9641,12 +9775,12 @@ function generateDiff(oldContent, newContent, filename) {
|
|
|
9641
9775
|
const oldLines = oldContent.split("\n");
|
|
9642
9776
|
const newLines = newContent.split("\n");
|
|
9643
9777
|
if (!hasRealChanges(oldContent, newContent)) {
|
|
9644
|
-
return
|
|
9778
|
+
return chalk6.gray(` ${filename}: No changes`);
|
|
9645
9779
|
}
|
|
9646
9780
|
const changes = [];
|
|
9647
|
-
changes.push(
|
|
9781
|
+
changes.push(chalk6.cyan(`
|
|
9648
9782
|
--- ${filename} (current)`));
|
|
9649
|
-
changes.push(
|
|
9783
|
+
changes.push(chalk6.cyan(` +++ ${filename} (new)
|
|
9650
9784
|
`));
|
|
9651
9785
|
const maxLines = Math.max(oldLines.length, newLines.length);
|
|
9652
9786
|
let hasChanges = false;
|
|
@@ -9660,20 +9794,20 @@ function generateDiff(oldContent, newContent, filename) {
|
|
|
9660
9794
|
if (contextBuffer.length > 0 && !inChange) {
|
|
9661
9795
|
const startContext = Math.max(0, contextBuffer.length - 2);
|
|
9662
9796
|
for (let j = startContext; j < contextBuffer.length; j++) {
|
|
9663
|
-
changes.push(
|
|
9797
|
+
changes.push(chalk6.gray(` ${i - contextBuffer.length + j + 1}: ${contextBuffer[j]}`));
|
|
9664
9798
|
}
|
|
9665
9799
|
}
|
|
9666
9800
|
inChange = true;
|
|
9667
9801
|
contextBuffer = [];
|
|
9668
9802
|
if (oldLine !== void 0) {
|
|
9669
|
-
changes.push(
|
|
9803
|
+
changes.push(chalk6.red(` - ${i + 1}: ${oldLine}`));
|
|
9670
9804
|
}
|
|
9671
9805
|
if (newLine !== void 0) {
|
|
9672
|
-
changes.push(
|
|
9806
|
+
changes.push(chalk6.green(` + ${i + 1}: ${newLine}`));
|
|
9673
9807
|
}
|
|
9674
9808
|
} else {
|
|
9675
9809
|
if (inChange) {
|
|
9676
|
-
changes.push(
|
|
9810
|
+
changes.push(chalk6.gray(` ${i + 1}: ${oldLine}`));
|
|
9677
9811
|
inChange = false;
|
|
9678
9812
|
}
|
|
9679
9813
|
contextBuffer.push(oldLine || "");
|
|
@@ -9683,47 +9817,47 @@ function generateDiff(oldContent, newContent, filename) {
|
|
|
9683
9817
|
}
|
|
9684
9818
|
}
|
|
9685
9819
|
if (!hasChanges) {
|
|
9686
|
-
return
|
|
9820
|
+
return chalk6.gray(` ${filename}: No changes`);
|
|
9687
9821
|
}
|
|
9688
9822
|
return changes.join("\n");
|
|
9689
9823
|
}
|
|
9690
9824
|
async function update(components, options) {
|
|
9691
9825
|
const cwd = process.cwd();
|
|
9692
9826
|
if (!await configExists(cwd)) {
|
|
9693
|
-
console.log(
|
|
9694
|
-
console.log(
|
|
9827
|
+
console.log(chalk6.red("\n Error: Project not initialized."));
|
|
9828
|
+
console.log(chalk6.yellow(" Run `npx myoperator-ui init` first.\n"));
|
|
9695
9829
|
process.exit(1);
|
|
9696
9830
|
}
|
|
9697
9831
|
const prefix = await getTailwindPrefix(cwd);
|
|
9698
9832
|
if (prefix) {
|
|
9699
|
-
console.log(
|
|
9833
|
+
console.log(chalk6.blue(`
|
|
9700
9834
|
\u2139 Using Tailwind prefix: "${prefix}"
|
|
9701
9835
|
`));
|
|
9702
9836
|
}
|
|
9703
9837
|
const registry = await getRegistry(prefix);
|
|
9704
9838
|
const availableComponents = Object.keys(registry);
|
|
9705
|
-
const componentsDir =
|
|
9839
|
+
const componentsDir = path7.join(cwd, options.path);
|
|
9706
9840
|
const getComponentFilePath = (component) => {
|
|
9707
9841
|
if (component.isMultiFile && component.directory) {
|
|
9708
|
-
return
|
|
9842
|
+
return path7.join(componentsDir, component.directory, component.files[0].name);
|
|
9709
9843
|
}
|
|
9710
|
-
return
|
|
9844
|
+
return path7.join(componentsDir, component.files[0].name);
|
|
9711
9845
|
};
|
|
9712
9846
|
if (options.all) {
|
|
9713
9847
|
const installedComponents = [];
|
|
9714
9848
|
for (const name of availableComponents) {
|
|
9715
9849
|
const component = registry[name];
|
|
9716
9850
|
const filePath = getComponentFilePath(component);
|
|
9717
|
-
if (await
|
|
9851
|
+
if (await fs7.pathExists(filePath)) {
|
|
9718
9852
|
installedComponents.push(name);
|
|
9719
9853
|
}
|
|
9720
9854
|
}
|
|
9721
9855
|
if (installedComponents.length === 0) {
|
|
9722
|
-
console.log(
|
|
9856
|
+
console.log(chalk6.yellow("\n No installed components found to update.\n"));
|
|
9723
9857
|
process.exit(0);
|
|
9724
9858
|
}
|
|
9725
9859
|
components = installedComponents;
|
|
9726
|
-
console.log(
|
|
9860
|
+
console.log(chalk6.blue(` Found ${installedComponents.length} installed component(s)
|
|
9727
9861
|
`));
|
|
9728
9862
|
}
|
|
9729
9863
|
if (!components || components.length === 0) {
|
|
@@ -9731,12 +9865,12 @@ async function update(components, options) {
|
|
|
9731
9865
|
for (const name of availableComponents) {
|
|
9732
9866
|
const component = registry[name];
|
|
9733
9867
|
const filePath = getComponentFilePath(component);
|
|
9734
|
-
if (await
|
|
9868
|
+
if (await fs7.pathExists(filePath)) {
|
|
9735
9869
|
installedComponents.push(name);
|
|
9736
9870
|
}
|
|
9737
9871
|
}
|
|
9738
9872
|
if (installedComponents.length === 0) {
|
|
9739
|
-
console.log(
|
|
9873
|
+
console.log(chalk6.yellow("\n No installed components found to update.\n"));
|
|
9740
9874
|
process.exit(0);
|
|
9741
9875
|
}
|
|
9742
9876
|
const { selectedComponents } = await prompts4({
|
|
@@ -9751,16 +9885,16 @@ async function update(components, options) {
|
|
|
9751
9885
|
min: 1
|
|
9752
9886
|
});
|
|
9753
9887
|
if (!selectedComponents || selectedComponents.length === 0) {
|
|
9754
|
-
console.log(
|
|
9888
|
+
console.log(chalk6.yellow("\n No components selected.\n"));
|
|
9755
9889
|
process.exit(0);
|
|
9756
9890
|
}
|
|
9757
9891
|
components = selectedComponents;
|
|
9758
9892
|
}
|
|
9759
9893
|
const invalidComponents = components.filter((c) => !availableComponents.includes(c));
|
|
9760
9894
|
if (invalidComponents.length > 0) {
|
|
9761
|
-
console.log(
|
|
9895
|
+
console.log(chalk6.red(`
|
|
9762
9896
|
Error: Unknown components: ${invalidComponents.join(", ")}`));
|
|
9763
|
-
console.log(
|
|
9897
|
+
console.log(chalk6.yellow(` Available: ${availableComponents.join(", ")}
|
|
9764
9898
|
`));
|
|
9765
9899
|
process.exit(1);
|
|
9766
9900
|
}
|
|
@@ -9769,29 +9903,29 @@ async function update(components, options) {
|
|
|
9769
9903
|
for (const name of components) {
|
|
9770
9904
|
const component = registry[name];
|
|
9771
9905
|
const filePath = getComponentFilePath(component);
|
|
9772
|
-
if (await
|
|
9906
|
+
if (await fs7.pathExists(filePath)) {
|
|
9773
9907
|
toUpdate.push(name);
|
|
9774
9908
|
} else {
|
|
9775
9909
|
notInstalled.push(name);
|
|
9776
9910
|
}
|
|
9777
9911
|
}
|
|
9778
9912
|
if (notInstalled.length > 0) {
|
|
9779
|
-
console.log(
|
|
9913
|
+
console.log(chalk6.yellow(`
|
|
9780
9914
|
Components not installed (use 'add' instead): ${notInstalled.join(", ")}`));
|
|
9781
9915
|
}
|
|
9782
9916
|
if (toUpdate.length === 0) {
|
|
9783
|
-
console.log(
|
|
9917
|
+
console.log(chalk6.yellow("\n No installed components to update.\n"));
|
|
9784
9918
|
process.exit(0);
|
|
9785
9919
|
}
|
|
9786
|
-
console.log(
|
|
9920
|
+
console.log(chalk6.bold("\n Changes to be applied:\n"));
|
|
9787
9921
|
const changesInfo = [];
|
|
9788
9922
|
for (const componentName of toUpdate) {
|
|
9789
9923
|
const component = registry[componentName];
|
|
9790
9924
|
const subDir = component.isMultiFile && component.directory ? component.directory : "";
|
|
9791
9925
|
for (const file of component.files) {
|
|
9792
|
-
const relativePath = subDir ?
|
|
9793
|
-
const filePath =
|
|
9794
|
-
const oldContent = await
|
|
9926
|
+
const relativePath = subDir ? path7.join(subDir, file.name) : file.name;
|
|
9927
|
+
const filePath = path7.join(componentsDir, relativePath);
|
|
9928
|
+
const oldContent = await fs7.readFile(filePath, "utf-8");
|
|
9795
9929
|
const newContent = file.content;
|
|
9796
9930
|
const hasChanges = hasRealChanges(oldContent, newContent);
|
|
9797
9931
|
changesInfo.push({ name: componentName, file: file.name, relativePath, oldContent, newContent, hasChanges });
|
|
@@ -9801,14 +9935,14 @@ async function update(components, options) {
|
|
|
9801
9935
|
}
|
|
9802
9936
|
const componentsWithChanges = changesInfo.filter((c) => c.hasChanges);
|
|
9803
9937
|
if (componentsWithChanges.length === 0) {
|
|
9804
|
-
console.log(
|
|
9938
|
+
console.log(chalk6.green("\n \u2713 All components are already up to date!\n"));
|
|
9805
9939
|
process.exit(0);
|
|
9806
9940
|
}
|
|
9807
|
-
console.log(
|
|
9941
|
+
console.log(chalk6.bold(`
|
|
9808
9942
|
${componentsWithChanges.length} file(s) will be updated.
|
|
9809
9943
|
`));
|
|
9810
9944
|
if (options.dryRun) {
|
|
9811
|
-
console.log(
|
|
9945
|
+
console.log(chalk6.blue(" Dry run complete. No files were modified.\n"));
|
|
9812
9946
|
process.exit(0);
|
|
9813
9947
|
}
|
|
9814
9948
|
if (!options.yes) {
|
|
@@ -9819,35 +9953,35 @@ async function update(components, options) {
|
|
|
9819
9953
|
initial: true
|
|
9820
9954
|
});
|
|
9821
9955
|
if (!confirm) {
|
|
9822
|
-
console.log(
|
|
9956
|
+
console.log(chalk6.yellow("\n Update cancelled.\n"));
|
|
9823
9957
|
process.exit(0);
|
|
9824
9958
|
}
|
|
9825
9959
|
}
|
|
9826
|
-
const spinner =
|
|
9960
|
+
const spinner = ora5("Updating components...").start();
|
|
9827
9961
|
try {
|
|
9828
9962
|
const updated = [];
|
|
9829
9963
|
const backedUp = [];
|
|
9830
9964
|
for (const change of componentsWithChanges) {
|
|
9831
|
-
const filePath =
|
|
9965
|
+
const filePath = path7.join(componentsDir, change.relativePath);
|
|
9832
9966
|
if (options.backup) {
|
|
9833
9967
|
const backupPath = `${filePath}.backup.${Date.now()}`;
|
|
9834
|
-
await
|
|
9968
|
+
await fs7.copy(filePath, backupPath);
|
|
9835
9969
|
backedUp.push(change.relativePath);
|
|
9836
9970
|
}
|
|
9837
|
-
await
|
|
9971
|
+
await fs7.writeFile(filePath, change.newContent);
|
|
9838
9972
|
updated.push(change.relativePath);
|
|
9839
9973
|
}
|
|
9840
9974
|
spinner.succeed("Components updated successfully!");
|
|
9841
9975
|
if (backedUp.length > 0) {
|
|
9842
|
-
console.log(
|
|
9976
|
+
console.log(chalk6.blue("\n Backed up files:"));
|
|
9843
9977
|
backedUp.forEach((file) => {
|
|
9844
|
-
console.log(
|
|
9978
|
+
console.log(chalk6.blue(` \u{1F4C1} ${options.path}/${file}.backup.*`));
|
|
9845
9979
|
});
|
|
9846
9980
|
}
|
|
9847
9981
|
if (updated.length > 0) {
|
|
9848
|
-
console.log(
|
|
9982
|
+
console.log(chalk6.green("\n Updated files:"));
|
|
9849
9983
|
updated.forEach((file) => {
|
|
9850
|
-
console.log(
|
|
9984
|
+
console.log(chalk6.green(` \u2713 ${options.path}/${file}`));
|
|
9851
9985
|
});
|
|
9852
9986
|
}
|
|
9853
9987
|
console.log("");
|
|
@@ -9867,4 +10001,5 @@ program.command("init").description("Initialize your project with myOperator UI"
|
|
|
9867
10001
|
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
10002
|
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
10003
|
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);
|
|
10004
|
+
program.command("fix").description("Fix configuration issues (e.g., missing Tailwind content paths)").action(fix);
|
|
9870
10005
|
program.parse();
|