reend-components 1.1.0 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +172 -98
- package/dist/bin/cli.cjs +289 -228
- package/dist/lib/index.cjs +2 -2
- package/dist/lib/index.cjs.map +1 -1
- package/dist/lib/index.mjs +386 -273
- package/dist/lib/index.mjs.map +1 -1
- package/dist/tailwind/index.cjs +492 -0
- package/dist/tailwind/index.mjs +462 -0
- package/package.json +20 -10
- package/src/tailwind-preset.ts +0 -1
package/dist/bin/cli.cjs
CHANGED
|
@@ -8813,201 +8813,10 @@ var chalk = createChalk();
|
|
|
8813
8813
|
var chalkStderr = createChalk({ level: stderrColor ? stderrColor.level : 0 });
|
|
8814
8814
|
var source_default = chalk;
|
|
8815
8815
|
|
|
8816
|
-
// src/cli/commands/init.ts
|
|
8817
|
-
var import_node_fs2 = require("node:fs");
|
|
8818
|
-
var import_node_path2 = require("node:path");
|
|
8819
|
-
var import_prompts = __toESM(require_prompts3(), 1);
|
|
8820
|
-
|
|
8821
|
-
// src/cli/utils.ts
|
|
8822
|
-
var import_node_fs = require("node:fs");
|
|
8823
|
-
var import_node_path = require("node:path");
|
|
8824
|
-
var CONFIG_FILE = "reend-ui.config.json";
|
|
8825
|
-
function readConfig(cwd2) {
|
|
8826
|
-
const configPath = (0, import_node_path.join)(cwd2, CONFIG_FILE);
|
|
8827
|
-
if (!(0, import_node_fs.existsSync)(configPath)) return null;
|
|
8828
|
-
try {
|
|
8829
|
-
return JSON.parse((0, import_node_fs.readFileSync)(configPath, "utf-8"));
|
|
8830
|
-
} catch {
|
|
8831
|
-
return null;
|
|
8832
|
-
}
|
|
8833
|
-
}
|
|
8834
|
-
function writeConfig(cwd2, config) {
|
|
8835
|
-
const configPath = (0, import_node_path.join)(cwd2, CONFIG_FILE);
|
|
8836
|
-
(0, import_node_fs.writeFileSync)(configPath, JSON.stringify(config, null, 2) + "\n", "utf-8");
|
|
8837
|
-
}
|
|
8838
|
-
function detectFramework(cwd2) {
|
|
8839
|
-
const pkgPath = (0, import_node_path.join)(cwd2, "package.json");
|
|
8840
|
-
if (!(0, import_node_fs.existsSync)(pkgPath)) return "vite";
|
|
8841
|
-
try {
|
|
8842
|
-
const pkg = JSON.parse((0, import_node_fs.readFileSync)(pkgPath, "utf-8"));
|
|
8843
|
-
const allDeps = {
|
|
8844
|
-
...pkg.dependencies,
|
|
8845
|
-
...pkg.devDependencies
|
|
8846
|
-
};
|
|
8847
|
-
if (allDeps["next"]) return "next";
|
|
8848
|
-
if (allDeps["@remix-run/react"]) return "remix";
|
|
8849
|
-
if (allDeps["gatsby"]) return "gatsby";
|
|
8850
|
-
return "vite";
|
|
8851
|
-
} catch {
|
|
8852
|
-
return "vite";
|
|
8853
|
-
}
|
|
8854
|
-
}
|
|
8855
|
-
function detectTypeScript(cwd2) {
|
|
8856
|
-
return (0, import_node_fs.existsSync)((0, import_node_path.join)(cwd2, "tsconfig.json")) || (0, import_node_fs.existsSync)((0, import_node_path.join)(cwd2, "tsconfig.app.json"));
|
|
8857
|
-
}
|
|
8858
|
-
function detectTailwindConfig(cwd2) {
|
|
8859
|
-
const candidates = [
|
|
8860
|
-
"tailwind.config.ts",
|
|
8861
|
-
"tailwind.config.js",
|
|
8862
|
-
"tailwind.config.mjs"
|
|
8863
|
-
];
|
|
8864
|
-
for (const f of candidates) {
|
|
8865
|
-
if ((0, import_node_fs.existsSync)((0, import_node_path.join)(cwd2, f))) return f;
|
|
8866
|
-
}
|
|
8867
|
-
return void 0;
|
|
8868
|
-
}
|
|
8869
|
-
async function fetchText(url) {
|
|
8870
|
-
const res = await fetch(url);
|
|
8871
|
-
if (!res.ok) {
|
|
8872
|
-
throw new Error(`HTTP ${res.status} ${res.statusText} \u2014 ${url}`);
|
|
8873
|
-
}
|
|
8874
|
-
return res.text();
|
|
8875
|
-
}
|
|
8876
|
-
var log = {
|
|
8877
|
-
info: (msg) => console.log(` ${source_default.cyan("\u25C6")} ${msg}`),
|
|
8878
|
-
success: (msg) => console.log(` ${source_default.green("\u25C6")} ${source_default.green(msg)}`),
|
|
8879
|
-
warn: (msg) => console.log(` ${source_default.yellow("\u25C7")} ${source_default.yellow(msg)}`),
|
|
8880
|
-
error: (msg) => console.error(` ${source_default.red("\u2715")} ${source_default.red(msg)}`),
|
|
8881
|
-
step: (msg) => console.log(` ${source_default.dim("\u203A")} ${msg}`),
|
|
8882
|
-
blank: () => console.log(),
|
|
8883
|
-
header: (msg) => console.log(
|
|
8884
|
-
`
|
|
8885
|
-
${source_default.bold.white("\u25C6")} ${source_default.bold.white(msg.toUpperCase())}
|
|
8886
|
-
`
|
|
8887
|
-
)
|
|
8888
|
-
};
|
|
8889
|
-
|
|
8890
|
-
// src/cli/commands/init.ts
|
|
8891
|
-
async function runInit(cwd2) {
|
|
8892
|
-
log.header("ReEnd UI \u2014 Initialize");
|
|
8893
|
-
if ((0, import_node_fs2.existsSync)((0, import_node_path2.join)(cwd2, "reend-ui.config.json"))) {
|
|
8894
|
-
log.warn("reend-ui.config.json already exists.");
|
|
8895
|
-
const { overwrite } = await (0, import_prompts.default)({
|
|
8896
|
-
type: "confirm",
|
|
8897
|
-
name: "overwrite",
|
|
8898
|
-
message: "Overwrite existing config?",
|
|
8899
|
-
initial: false
|
|
8900
|
-
});
|
|
8901
|
-
if (!overwrite) {
|
|
8902
|
-
log.info("Init cancelled.");
|
|
8903
|
-
return;
|
|
8904
|
-
}
|
|
8905
|
-
}
|
|
8906
|
-
const framework = detectFramework(cwd2);
|
|
8907
|
-
const isTypescript = detectTypeScript(cwd2);
|
|
8908
|
-
const tailwindCfg = detectTailwindConfig(cwd2);
|
|
8909
|
-
log.step(`Detected framework: ${source_default.cyan(framework)}`);
|
|
8910
|
-
log.step(
|
|
8911
|
-
`TypeScript: ${isTypescript ? source_default.green("yes") : source_default.yellow("no")}`
|
|
8912
|
-
);
|
|
8913
|
-
if (tailwindCfg) log.step(`Tailwind config: ${source_default.cyan(tailwindCfg)}`);
|
|
8914
|
-
log.blank();
|
|
8915
|
-
const response = await (0, import_prompts.default)([
|
|
8916
|
-
{
|
|
8917
|
-
type: "text",
|
|
8918
|
-
name: "outputDir",
|
|
8919
|
-
message: "Component output directory:",
|
|
8920
|
-
initial: "components/ui"
|
|
8921
|
-
},
|
|
8922
|
-
{
|
|
8923
|
-
type: "confirm",
|
|
8924
|
-
name: "cssVariables",
|
|
8925
|
-
message: "Copy CSS design tokens (variables.css)?",
|
|
8926
|
-
initial: true
|
|
8927
|
-
}
|
|
8928
|
-
]);
|
|
8929
|
-
if (!response.outputDir) {
|
|
8930
|
-
log.error("Init cancelled.");
|
|
8931
|
-
return;
|
|
8932
|
-
}
|
|
8933
|
-
writeConfig(cwd2, {
|
|
8934
|
-
version: "1.0",
|
|
8935
|
-
framework,
|
|
8936
|
-
typescript: isTypescript,
|
|
8937
|
-
outputDir: response.outputDir,
|
|
8938
|
-
cssVariables: response.cssVariables,
|
|
8939
|
-
tailwindConfig: tailwindCfg
|
|
8940
|
-
});
|
|
8941
|
-
log.success("Created reend-ui.config.json");
|
|
8942
|
-
const outDir = (0, import_node_path2.join)(cwd2, response.outputDir);
|
|
8943
|
-
if (!(0, import_node_fs2.existsSync)(outDir)) {
|
|
8944
|
-
(0, import_node_fs2.mkdirSync)(outDir, { recursive: true });
|
|
8945
|
-
log.success(`Created directory: ${response.outputDir}`);
|
|
8946
|
-
}
|
|
8947
|
-
if (response.cssVariables) {
|
|
8948
|
-
await copyVariablesCss(cwd2, response.outputDir);
|
|
8949
|
-
}
|
|
8950
|
-
log.blank();
|
|
8951
|
-
console.log(source_default.bold.white(" \u25C6 NEXT STEPS\n"));
|
|
8952
|
-
console.log(
|
|
8953
|
-
source_default.dim(" Add the ReEnd Tailwind preset to your tailwind config:\n")
|
|
8954
|
-
);
|
|
8955
|
-
console.log(
|
|
8956
|
-
source_default.cyan(` // ${tailwindCfg ?? "tailwind.config.ts"}`) + "\n" + source_default.white(" import reendPreset from 'reend-components/tailwind'\n") + source_default.white(" export default {\n") + source_default.white(" presets: [reendPreset],\n") + source_default.white(" // ...your config\n") + source_default.white(" }") + "\n"
|
|
8957
|
-
);
|
|
8958
|
-
console.log(source_default.dim(" Import CSS variables in your global CSS:\n"));
|
|
8959
|
-
console.log(source_default.white(` @import 'reend-components/styles.css';`) + "\n");
|
|
8960
|
-
console.log(source_default.dim(" Add components:\n"));
|
|
8961
|
-
console.log(source_default.cyan(" npx reend-ui add button") + "\n");
|
|
8962
|
-
}
|
|
8963
|
-
async function copyVariablesCss(cwd2, outputDir) {
|
|
8964
|
-
const stylesDir = (0, import_node_path2.join)(cwd2, "styles");
|
|
8965
|
-
if (!(0, import_node_fs2.existsSync)(stylesDir)) {
|
|
8966
|
-
(0, import_node_fs2.mkdirSync)(stylesDir, { recursive: true });
|
|
8967
|
-
}
|
|
8968
|
-
const destPath = (0, import_node_path2.join)(stylesDir, "reend-variables.css");
|
|
8969
|
-
try {
|
|
8970
|
-
const candidates = [
|
|
8971
|
-
(0, import_node_path2.join)(
|
|
8972
|
-
cwd2,
|
|
8973
|
-
"node_modules",
|
|
8974
|
-
"reend-components",
|
|
8975
|
-
"src",
|
|
8976
|
-
"styles",
|
|
8977
|
-
"variables.css"
|
|
8978
|
-
)
|
|
8979
|
-
];
|
|
8980
|
-
for (const src of candidates) {
|
|
8981
|
-
if ((0, import_node_fs2.existsSync)(src)) {
|
|
8982
|
-
const content = (0, import_node_fs2.readFileSync)(src, "utf-8");
|
|
8983
|
-
(0, import_node_fs2.writeFileSync)(destPath, content, "utf-8");
|
|
8984
|
-
log.success("Copied variables.css \u2192 styles/reend-variables.css");
|
|
8985
|
-
return;
|
|
8986
|
-
}
|
|
8987
|
-
}
|
|
8988
|
-
const url = "https://raw.githubusercontent.com/VBeatDead/ReEnd-Components/main/src/styles/variables.css";
|
|
8989
|
-
const res = await fetch(url);
|
|
8990
|
-
if (res.ok) {
|
|
8991
|
-
const content = await res.text();
|
|
8992
|
-
(0, import_node_fs2.writeFileSync)(destPath, content, "utf-8");
|
|
8993
|
-
log.success("Copied variables.css \u2192 styles/reend-variables.css");
|
|
8994
|
-
} else {
|
|
8995
|
-
log.warn(
|
|
8996
|
-
"Could not copy variables.css \u2014 add manually from reend-components/styles.css"
|
|
8997
|
-
);
|
|
8998
|
-
}
|
|
8999
|
-
} catch {
|
|
9000
|
-
log.warn(
|
|
9001
|
-
"Could not copy variables.css \u2014 add manually from reend-components/styles.css"
|
|
9002
|
-
);
|
|
9003
|
-
}
|
|
9004
|
-
}
|
|
9005
|
-
|
|
9006
|
-
// src/cli/commands/add.ts
|
|
9007
|
-
var import_node_fs3 = require("node:fs");
|
|
9008
|
-
var import_node_path3 = require("node:path");
|
|
9009
|
-
|
|
9010
8816
|
// src/cli/registry.ts
|
|
8817
|
+
var CLI_VERSION = "1.2.0";
|
|
8818
|
+
var GITHUB_RAW_ROOT = "https://raw.githubusercontent.com/VBeatDead/ReEnd-Components";
|
|
8819
|
+
var BASE_DEPS = ["clsx", "tailwind-merge", "class-variance-authority"];
|
|
9011
8820
|
var REGISTRY = {
|
|
9012
8821
|
// ── Core (Tier 1) ───────────────────────────────────────────────────────
|
|
9013
8822
|
button: {
|
|
@@ -9274,8 +9083,8 @@ var REGISTRY = {
|
|
|
9274
9083
|
name: "session-timeout-modal",
|
|
9275
9084
|
displayName: "SessionTimeoutModal",
|
|
9276
9085
|
type: "core",
|
|
9277
|
-
files: ["session-timeout-modal.tsx"],
|
|
9278
|
-
deps: [],
|
|
9086
|
+
files: ["session-timeout-modal.tsx", "dialog.tsx", "button.tsx"],
|
|
9087
|
+
deps: ["@radix-ui/react-dialog", "@radix-ui/react-slot"],
|
|
9279
9088
|
description: "Session expiry modal with CountdownTimer"
|
|
9280
9089
|
},
|
|
9281
9090
|
"file-upload": {
|
|
@@ -9430,7 +9239,7 @@ var REGISTRY = {
|
|
|
9430
9239
|
displayName: "TacticalPanel",
|
|
9431
9240
|
type: "signature",
|
|
9432
9241
|
files: ["signature/tactical-panel.tsx"],
|
|
9433
|
-
deps: [],
|
|
9242
|
+
deps: ["lucide-react"],
|
|
9434
9243
|
description: "HUD-style panel with status, headerAction, collapsible"
|
|
9435
9244
|
},
|
|
9436
9245
|
"holo-card": {
|
|
@@ -9446,7 +9255,7 @@ var REGISTRY = {
|
|
|
9446
9255
|
displayName: "DataStream",
|
|
9447
9256
|
type: "signature",
|
|
9448
9257
|
files: ["signature/data-stream.tsx"],
|
|
9449
|
-
deps: ["framer-motion"],
|
|
9258
|
+
deps: ["framer-motion", "lucide-react"],
|
|
9450
9259
|
description: "Scrolling data feed terminal with speed/messageType"
|
|
9451
9260
|
},
|
|
9452
9261
|
"tactical-badge": {
|
|
@@ -9462,7 +9271,7 @@ var REGISTRY = {
|
|
|
9462
9271
|
displayName: "WarningBanner",
|
|
9463
9272
|
type: "signature",
|
|
9464
9273
|
files: ["signature/warning-banner.tsx"],
|
|
9465
|
-
deps: [],
|
|
9274
|
+
deps: ["lucide-react"],
|
|
9466
9275
|
description: "Alert banner with caution/alert/critical severity"
|
|
9467
9276
|
},
|
|
9468
9277
|
"scan-divider": {
|
|
@@ -9607,13 +9416,252 @@ var REGISTRY = {
|
|
|
9607
9416
|
displayName: "ThemeSwitcher",
|
|
9608
9417
|
type: "core",
|
|
9609
9418
|
files: ["theme-switcher.tsx"],
|
|
9610
|
-
deps: [],
|
|
9419
|
+
deps: ["lucide-react"],
|
|
9611
9420
|
description: "Light/dark theme toggle with localStorage persistence"
|
|
9421
|
+
},
|
|
9422
|
+
toast: {
|
|
9423
|
+
name: "toast",
|
|
9424
|
+
displayName: "Toast",
|
|
9425
|
+
type: "core",
|
|
9426
|
+
files: ["toast.tsx", "toaster.tsx"],
|
|
9427
|
+
hooks: ["use-toast.ts"],
|
|
9428
|
+
deps: ["@radix-ui/react-toast", "lucide-react"],
|
|
9429
|
+
description: "Radix toast primitives + Toaster portal + useToast hook (imperative API)"
|
|
9612
9430
|
}
|
|
9613
9431
|
};
|
|
9432
|
+
function getFileUrl(filePath, ref = "main") {
|
|
9433
|
+
return `${GITHUB_RAW_ROOT}/${ref}/src/components/ui/${filePath}`;
|
|
9434
|
+
}
|
|
9435
|
+
function getHookUrl(filePath, ref = "main") {
|
|
9436
|
+
return `${GITHUB_RAW_ROOT}/${ref}/src/hooks/${filePath}`;
|
|
9437
|
+
}
|
|
9438
|
+
|
|
9439
|
+
// src/cli/commands/init.ts
|
|
9440
|
+
var import_node_fs2 = require("node:fs");
|
|
9441
|
+
var import_node_path2 = require("node:path");
|
|
9442
|
+
var import_prompts = __toESM(require_prompts3(), 1);
|
|
9443
|
+
|
|
9444
|
+
// src/cli/utils.ts
|
|
9445
|
+
var import_node_fs = require("node:fs");
|
|
9446
|
+
var import_node_path = require("node:path");
|
|
9447
|
+
var CONFIG_FILE = "reend-ui.config.json";
|
|
9448
|
+
function readConfig(cwd2) {
|
|
9449
|
+
const configPath = (0, import_node_path.join)(cwd2, CONFIG_FILE);
|
|
9450
|
+
if (!(0, import_node_fs.existsSync)(configPath)) return null;
|
|
9451
|
+
try {
|
|
9452
|
+
return JSON.parse((0, import_node_fs.readFileSync)(configPath, "utf-8"));
|
|
9453
|
+
} catch {
|
|
9454
|
+
return null;
|
|
9455
|
+
}
|
|
9456
|
+
}
|
|
9457
|
+
function writeConfig(cwd2, config) {
|
|
9458
|
+
const configPath = (0, import_node_path.join)(cwd2, CONFIG_FILE);
|
|
9459
|
+
(0, import_node_fs.writeFileSync)(configPath, JSON.stringify(config, null, 2) + "\n", "utf-8");
|
|
9460
|
+
}
|
|
9461
|
+
function detectFramework(cwd2) {
|
|
9462
|
+
const pkgPath = (0, import_node_path.join)(cwd2, "package.json");
|
|
9463
|
+
if (!(0, import_node_fs.existsSync)(pkgPath)) return "vite";
|
|
9464
|
+
try {
|
|
9465
|
+
const pkg = JSON.parse((0, import_node_fs.readFileSync)(pkgPath, "utf-8"));
|
|
9466
|
+
const allDeps = {
|
|
9467
|
+
...pkg.dependencies,
|
|
9468
|
+
...pkg.devDependencies
|
|
9469
|
+
};
|
|
9470
|
+
if (allDeps["next"]) return "next";
|
|
9471
|
+
if (allDeps["@remix-run/react"]) return "remix";
|
|
9472
|
+
if (allDeps["gatsby"]) return "gatsby";
|
|
9473
|
+
return "vite";
|
|
9474
|
+
} catch {
|
|
9475
|
+
return "vite";
|
|
9476
|
+
}
|
|
9477
|
+
}
|
|
9478
|
+
function detectTypeScript(cwd2) {
|
|
9479
|
+
return (0, import_node_fs.existsSync)((0, import_node_path.join)(cwd2, "tsconfig.json")) || (0, import_node_fs.existsSync)((0, import_node_path.join)(cwd2, "tsconfig.app.json"));
|
|
9480
|
+
}
|
|
9481
|
+
function detectTailwindConfig(cwd2) {
|
|
9482
|
+
const candidates = [
|
|
9483
|
+
"tailwind.config.ts",
|
|
9484
|
+
"tailwind.config.js",
|
|
9485
|
+
"tailwind.config.mjs"
|
|
9486
|
+
];
|
|
9487
|
+
for (const f of candidates) {
|
|
9488
|
+
if ((0, import_node_fs.existsSync)((0, import_node_path.join)(cwd2, f))) return f;
|
|
9489
|
+
}
|
|
9490
|
+
return void 0;
|
|
9491
|
+
}
|
|
9492
|
+
async function fetchText(url) {
|
|
9493
|
+
const res = await fetch(url);
|
|
9494
|
+
if (!res.ok) {
|
|
9495
|
+
throw new Error(`HTTP ${res.status} ${res.statusText} \u2014 ${url}`);
|
|
9496
|
+
}
|
|
9497
|
+
return res.text();
|
|
9498
|
+
}
|
|
9499
|
+
var log = {
|
|
9500
|
+
info: (msg) => console.log(` ${source_default.cyan("\u25C6")} ${msg}`),
|
|
9501
|
+
success: (msg) => console.log(` ${source_default.green("\u25C6")} ${source_default.green(msg)}`),
|
|
9502
|
+
warn: (msg) => console.log(` ${source_default.yellow("\u25C7")} ${source_default.yellow(msg)}`),
|
|
9503
|
+
error: (msg) => console.error(` ${source_default.red("\u2715")} ${source_default.red(msg)}`),
|
|
9504
|
+
step: (msg) => console.log(` ${source_default.dim("\u203A")} ${msg}`),
|
|
9505
|
+
blank: () => console.log(),
|
|
9506
|
+
header: (msg) => console.log(
|
|
9507
|
+
`
|
|
9508
|
+
${source_default.bold.white("\u25C6")} ${source_default.bold.white(msg.toUpperCase())}
|
|
9509
|
+
`
|
|
9510
|
+
)
|
|
9511
|
+
};
|
|
9512
|
+
|
|
9513
|
+
// src/cli/commands/init.ts
|
|
9514
|
+
async function runInit(cwd2) {
|
|
9515
|
+
log.header("ReEnd UI \u2014 Initialize");
|
|
9516
|
+
if ((0, import_node_fs2.existsSync)((0, import_node_path2.join)(cwd2, "reend-ui.config.json"))) {
|
|
9517
|
+
log.warn("reend-ui.config.json already exists.");
|
|
9518
|
+
const { overwrite } = await (0, import_prompts.default)({
|
|
9519
|
+
type: "confirm",
|
|
9520
|
+
name: "overwrite",
|
|
9521
|
+
message: "Overwrite existing config?",
|
|
9522
|
+
initial: false
|
|
9523
|
+
});
|
|
9524
|
+
if (!overwrite) {
|
|
9525
|
+
log.info("Init cancelled.");
|
|
9526
|
+
return;
|
|
9527
|
+
}
|
|
9528
|
+
}
|
|
9529
|
+
const framework = detectFramework(cwd2);
|
|
9530
|
+
const isTypescript = detectTypeScript(cwd2);
|
|
9531
|
+
const tailwindCfg = detectTailwindConfig(cwd2);
|
|
9532
|
+
log.step(`Detected framework: ${source_default.cyan(framework)}`);
|
|
9533
|
+
log.step(
|
|
9534
|
+
`TypeScript: ${isTypescript ? source_default.green("yes") : source_default.yellow("no")}`
|
|
9535
|
+
);
|
|
9536
|
+
if (tailwindCfg) log.step(`Tailwind config: ${source_default.cyan(tailwindCfg)}`);
|
|
9537
|
+
log.blank();
|
|
9538
|
+
const response = await (0, import_prompts.default)([
|
|
9539
|
+
{
|
|
9540
|
+
type: "text",
|
|
9541
|
+
name: "outputDir",
|
|
9542
|
+
message: "Component output directory:",
|
|
9543
|
+
initial: "components/ui"
|
|
9544
|
+
},
|
|
9545
|
+
{
|
|
9546
|
+
type: "confirm",
|
|
9547
|
+
name: "cssVariables",
|
|
9548
|
+
message: "Copy CSS design tokens (variables.css)?",
|
|
9549
|
+
initial: true
|
|
9550
|
+
}
|
|
9551
|
+
]);
|
|
9552
|
+
if (!response.outputDir) {
|
|
9553
|
+
log.error("Init cancelled.");
|
|
9554
|
+
return;
|
|
9555
|
+
}
|
|
9556
|
+
writeConfig(cwd2, {
|
|
9557
|
+
version: "1.0",
|
|
9558
|
+
framework,
|
|
9559
|
+
typescript: isTypescript,
|
|
9560
|
+
outputDir: response.outputDir,
|
|
9561
|
+
cssVariables: response.cssVariables,
|
|
9562
|
+
tailwindConfig: tailwindCfg
|
|
9563
|
+
});
|
|
9564
|
+
log.success("Created reend-ui.config.json");
|
|
9565
|
+
const outDir = (0, import_node_path2.join)(cwd2, response.outputDir);
|
|
9566
|
+
if (!(0, import_node_fs2.existsSync)(outDir)) {
|
|
9567
|
+
(0, import_node_fs2.mkdirSync)(outDir, { recursive: true });
|
|
9568
|
+
log.success(`Created directory: ${response.outputDir}`);
|
|
9569
|
+
}
|
|
9570
|
+
const projectBase = (0, import_node_path2.join)(outDir, "..", "..");
|
|
9571
|
+
createCnUtility(projectBase);
|
|
9572
|
+
if (response.cssVariables) {
|
|
9573
|
+
await copyVariablesCss(cwd2, projectBase);
|
|
9574
|
+
}
|
|
9575
|
+
log.blank();
|
|
9576
|
+
console.log(source_default.bold.white(" \u25C6 NEXT STEPS\n"));
|
|
9577
|
+
console.log(source_default.dim(" Install the base dependencies used by every component:\n"));
|
|
9578
|
+
console.log(
|
|
9579
|
+
source_default.cyan(" npm install clsx tailwind-merge class-variance-authority") + "\n"
|
|
9580
|
+
);
|
|
9581
|
+
console.log(
|
|
9582
|
+
source_default.dim(" Add the ReEnd Tailwind preset to your tailwind config:\n")
|
|
9583
|
+
);
|
|
9584
|
+
console.log(
|
|
9585
|
+
source_default.cyan(` // ${tailwindCfg ?? "tailwind.config.ts"}`) + "\n" + source_default.white(" import reendPreset from 'reend-components/tailwind'\n") + source_default.white(" export default {\n") + source_default.white(" presets: [reendPreset],\n") + source_default.white(" // ...your config\n") + source_default.white(" }") + "\n"
|
|
9586
|
+
);
|
|
9587
|
+
console.log(source_default.dim(" Import CSS variables in your global CSS:\n"));
|
|
9588
|
+
console.log(source_default.white(` @import 'reend-components/styles.css';`) + "\n");
|
|
9589
|
+
console.log(source_default.dim(" Add components:\n"));
|
|
9590
|
+
console.log(source_default.cyan(" npx reend-ui add button") + "\n");
|
|
9591
|
+
}
|
|
9592
|
+
var CN_UTILITY = `import { clsx, type ClassValue } from "clsx";
|
|
9593
|
+
import { twMerge } from "tailwind-merge";
|
|
9594
|
+
|
|
9595
|
+
export function cn(...inputs: ClassValue[]) {
|
|
9596
|
+
return twMerge(clsx(inputs));
|
|
9597
|
+
}
|
|
9598
|
+
`;
|
|
9599
|
+
function createCnUtility(projectBase) {
|
|
9600
|
+
const libDir = (0, import_node_path2.join)(projectBase, "lib");
|
|
9601
|
+
const destPath = (0, import_node_path2.join)(libDir, "utils.ts");
|
|
9602
|
+
if ((0, import_node_fs2.existsSync)(destPath)) {
|
|
9603
|
+
log.step("lib/utils.ts already exists \u2014 keeping yours");
|
|
9604
|
+
return;
|
|
9605
|
+
}
|
|
9606
|
+
if (!(0, import_node_fs2.existsSync)(libDir)) {
|
|
9607
|
+
(0, import_node_fs2.mkdirSync)(libDir, { recursive: true });
|
|
9608
|
+
}
|
|
9609
|
+
(0, import_node_fs2.writeFileSync)(destPath, CN_UTILITY, "utf-8");
|
|
9610
|
+
log.success("Created lib/utils.ts (cn helper)");
|
|
9611
|
+
}
|
|
9612
|
+
async function copyVariablesCss(cwd2, projectBase) {
|
|
9613
|
+
const stylesDir = (0, import_node_path2.join)(projectBase, "styles");
|
|
9614
|
+
if (!(0, import_node_fs2.existsSync)(stylesDir)) {
|
|
9615
|
+
(0, import_node_fs2.mkdirSync)(stylesDir, { recursive: true });
|
|
9616
|
+
}
|
|
9617
|
+
const destPath = (0, import_node_path2.join)(stylesDir, "reend-variables.css");
|
|
9618
|
+
try {
|
|
9619
|
+
const candidates = [
|
|
9620
|
+
(0, import_node_path2.join)(
|
|
9621
|
+
cwd2,
|
|
9622
|
+
"node_modules",
|
|
9623
|
+
"reend-components",
|
|
9624
|
+
"src",
|
|
9625
|
+
"styles",
|
|
9626
|
+
"variables.css"
|
|
9627
|
+
)
|
|
9628
|
+
];
|
|
9629
|
+
for (const src of candidates) {
|
|
9630
|
+
if ((0, import_node_fs2.existsSync)(src)) {
|
|
9631
|
+
const content = (0, import_node_fs2.readFileSync)(src, "utf-8");
|
|
9632
|
+
(0, import_node_fs2.writeFileSync)(destPath, content, "utf-8");
|
|
9633
|
+
log.success("Copied variables.css \u2192 styles/reend-variables.css");
|
|
9634
|
+
return;
|
|
9635
|
+
}
|
|
9636
|
+
}
|
|
9637
|
+
const url = "https://raw.githubusercontent.com/VBeatDead/ReEnd-Components/main/src/styles/variables.css";
|
|
9638
|
+
const res = await fetch(url);
|
|
9639
|
+
if (res.ok) {
|
|
9640
|
+
const content = await res.text();
|
|
9641
|
+
(0, import_node_fs2.writeFileSync)(destPath, content, "utf-8");
|
|
9642
|
+
log.success("Copied variables.css \u2192 styles/reend-variables.css");
|
|
9643
|
+
} else {
|
|
9644
|
+
log.warn(
|
|
9645
|
+
"Could not copy variables.css \u2014 add manually from reend-components/styles.css"
|
|
9646
|
+
);
|
|
9647
|
+
}
|
|
9648
|
+
} catch {
|
|
9649
|
+
log.warn(
|
|
9650
|
+
"Could not copy variables.css \u2014 add manually from reend-components/styles.css"
|
|
9651
|
+
);
|
|
9652
|
+
}
|
|
9653
|
+
}
|
|
9614
9654
|
|
|
9615
9655
|
// src/cli/commands/add.ts
|
|
9616
|
-
var
|
|
9656
|
+
var import_node_fs3 = require("node:fs");
|
|
9657
|
+
var import_node_path3 = require("node:path");
|
|
9658
|
+
async function fetchRegistryFile(urlFor) {
|
|
9659
|
+
try {
|
|
9660
|
+
return await fetchText(urlFor(`v${CLI_VERSION}`));
|
|
9661
|
+
} catch {
|
|
9662
|
+
return fetchText(urlFor("main"));
|
|
9663
|
+
}
|
|
9664
|
+
}
|
|
9617
9665
|
async function runAdd(components, cwd2, opts) {
|
|
9618
9666
|
log.header("ReEnd UI \u2014 Add Components");
|
|
9619
9667
|
const config = readConfig(cwd2);
|
|
@@ -9622,6 +9670,8 @@ async function runAdd(components, cwd2, opts) {
|
|
|
9622
9670
|
process.exit(1);
|
|
9623
9671
|
}
|
|
9624
9672
|
const outputDir = (0, import_node_path3.join)(cwd2, config.outputDir);
|
|
9673
|
+
const projectBase = (0, import_node_path3.join)(outputDir, "..", "..");
|
|
9674
|
+
const hooksDir = (0, import_node_path3.join)(projectBase, "hooks");
|
|
9625
9675
|
const depsToInstall = /* @__PURE__ */ new Set();
|
|
9626
9676
|
const added = [];
|
|
9627
9677
|
const skipped = [];
|
|
@@ -9634,28 +9684,41 @@ async function runAdd(components, cwd2, opts) {
|
|
|
9634
9684
|
continue;
|
|
9635
9685
|
}
|
|
9636
9686
|
log.info(`Adding ${source_default.cyan(entry.displayName)}...`);
|
|
9687
|
+
const targets = [
|
|
9688
|
+
...entry.files.map((file) => ({
|
|
9689
|
+
file,
|
|
9690
|
+
dest: (0, import_node_path3.join)(outputDir, file),
|
|
9691
|
+
hook: false
|
|
9692
|
+
})),
|
|
9693
|
+
...(entry.hooks ?? []).map((file) => ({
|
|
9694
|
+
file,
|
|
9695
|
+
dest: (0, import_node_path3.join)(hooksDir, file),
|
|
9696
|
+
hook: true
|
|
9697
|
+
}))
|
|
9698
|
+
];
|
|
9637
9699
|
let componentSuccess = true;
|
|
9638
|
-
for (const file of
|
|
9639
|
-
const
|
|
9640
|
-
const
|
|
9641
|
-
if ((0, import_node_fs3.existsSync)(
|
|
9642
|
-
log.warn(` ${
|
|
9700
|
+
for (const { file, dest, hook } of targets) {
|
|
9701
|
+
const destDir = (0, import_node_path3.dirname)(dest);
|
|
9702
|
+
const label = hook ? `hooks/${file}` : file;
|
|
9703
|
+
if ((0, import_node_fs3.existsSync)(dest) && !opts.overwrite) {
|
|
9704
|
+
log.warn(` ${label} already exists \u2014 use --overwrite to replace`);
|
|
9643
9705
|
skipped.push(entry.displayName);
|
|
9644
9706
|
componentSuccess = false;
|
|
9645
9707
|
continue;
|
|
9646
9708
|
}
|
|
9647
9709
|
try {
|
|
9648
|
-
|
|
9649
|
-
|
|
9650
|
-
|
|
9710
|
+
log.step(`Fetching ${label}...`);
|
|
9711
|
+
const content = await fetchRegistryFile(
|
|
9712
|
+
(ref) => hook ? getHookUrl(file, ref) : getFileUrl(file, ref)
|
|
9713
|
+
);
|
|
9651
9714
|
if (!(0, import_node_fs3.existsSync)(destDir)) {
|
|
9652
9715
|
(0, import_node_fs3.mkdirSync)(destDir, { recursive: true });
|
|
9653
9716
|
}
|
|
9654
|
-
(0, import_node_fs3.writeFileSync)(
|
|
9655
|
-
log.success(` Added \u2192 ${
|
|
9717
|
+
(0, import_node_fs3.writeFileSync)(dest, content, "utf-8");
|
|
9718
|
+
log.success(` Added \u2192 ${label}`);
|
|
9656
9719
|
} catch (err) {
|
|
9657
9720
|
const message = err instanceof Error ? err.message : String(err);
|
|
9658
|
-
log.error(` Failed to fetch ${
|
|
9721
|
+
log.error(` Failed to fetch ${label}: ${message}`);
|
|
9659
9722
|
componentSuccess = false;
|
|
9660
9723
|
failed.push(entry.displayName);
|
|
9661
9724
|
}
|
|
@@ -9677,22 +9740,21 @@ async function runAdd(components, cwd2, opts) {
|
|
|
9677
9740
|
if (failed.length > 0) {
|
|
9678
9741
|
log.error(`Failed: ${failed.join(", ")}`);
|
|
9679
9742
|
}
|
|
9743
|
+
if (added.length > 0) {
|
|
9744
|
+
for (const dep of BASE_DEPS) {
|
|
9745
|
+
depsToInstall.add(dep);
|
|
9746
|
+
}
|
|
9747
|
+
}
|
|
9680
9748
|
if (depsToInstall.size > 0) {
|
|
9681
9749
|
const deps = Array.from(depsToInstall).join(" ");
|
|
9682
9750
|
log.blank();
|
|
9683
|
-
console.log(source_default.bold.yellow(" \u26A1 Install
|
|
9751
|
+
console.log(source_default.bold.yellow(" \u26A1 Install dependencies:\n"));
|
|
9684
9752
|
console.log(source_default.cyan(` npm install ${deps}`) + "\n");
|
|
9685
9753
|
}
|
|
9686
|
-
if (added.length > 0) {
|
|
9754
|
+
if (added.length > 0 && !(0, import_node_fs3.existsSync)((0, import_node_path3.join)(projectBase, "lib", "utils.ts"))) {
|
|
9687
9755
|
log.blank();
|
|
9688
|
-
|
|
9689
|
-
|
|
9690
|
-
" Components require the cn() utility. Add to your project:\n"
|
|
9691
|
-
)
|
|
9692
|
-
);
|
|
9693
|
-
console.log(source_default.white(" import { cn } from 'reend-components'") + "\n");
|
|
9694
|
-
console.log(
|
|
9695
|
-
source_default.dim(" Or copy the cn utility from: lib/utils.ts") + "\n"
|
|
9756
|
+
log.warn(
|
|
9757
|
+
"lib/utils.ts (cn helper) not found \u2014 run `npx reend-ui init` to create it."
|
|
9696
9758
|
);
|
|
9697
9759
|
}
|
|
9698
9760
|
}
|
|
@@ -9746,10 +9808,9 @@ async function runUpdate(components, cwd2) {
|
|
|
9746
9808
|
const outputDir = (0, import_node_path4.join)(cwd2, config.outputDir);
|
|
9747
9809
|
let targets = components;
|
|
9748
9810
|
if (targets.length === 0) {
|
|
9749
|
-
targets = Object.keys(REGISTRY).filter(
|
|
9750
|
-
|
|
9751
|
-
|
|
9752
|
-
});
|
|
9811
|
+
targets = Object.keys(REGISTRY).filter(
|
|
9812
|
+
(name) => (0, import_node_fs4.existsSync)((0, import_node_path4.join)(outputDir, REGISTRY[name].files[0]))
|
|
9813
|
+
);
|
|
9753
9814
|
if (targets.length === 0) {
|
|
9754
9815
|
log.warn("No installed components found. Use: npx reend-ui add <name>");
|
|
9755
9816
|
return;
|
|
@@ -9766,7 +9827,7 @@ async function runUpdate(components, cwd2) {
|
|
|
9766
9827
|
log.error(`Unknown component: "${name}"`);
|
|
9767
9828
|
continue;
|
|
9768
9829
|
}
|
|
9769
|
-
const isInstalled =
|
|
9830
|
+
const isInstalled = (0, import_node_fs4.existsSync)((0, import_node_path4.join)(outputDir, entry.files[0]));
|
|
9770
9831
|
if (isInstalled) {
|
|
9771
9832
|
existing.push(name);
|
|
9772
9833
|
} else {
|
|
@@ -9790,7 +9851,7 @@ program2.name("reend-ui").description(
|
|
|
9790
9851
|
source_default.bold.white(
|
|
9791
9852
|
"\u25C6 ReEnd UI \u2014 Arknights: Endfield React Component Library\n"
|
|
9792
9853
|
) + source_default.dim(" Shadcn-style copy-paste workflow for ReEnd components.\n")
|
|
9793
|
-
).version(
|
|
9854
|
+
).version(CLI_VERSION);
|
|
9794
9855
|
program2.command("init").description("Initialize ReEnd UI in your project").action(async () => {
|
|
9795
9856
|
await runInit(cwd);
|
|
9796
9857
|
});
|