@dinachi/cli 0.5.1 → 0.6.1
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 +390 -13
- package/package.json +12 -5
- package/templates/accordion/accordion.tsx +8 -3
- package/templates/alert-dialog/alert-dialog.tsx +24 -25
- package/templates/alert-dialog/index.ts +1 -1
- package/templates/autocomplete/autocomplete.tsx +0 -1
- package/templates/avatar/avatar.tsx +1 -3
- package/templates/badge/badge.tsx +167 -0
- package/templates/badge/index.ts +2 -0
- package/templates/button/button.tsx +6 -6
- package/templates/button/index.ts +2 -2
- package/templates/card/card.tsx +78 -0
- package/templates/card/index.ts +1 -0
- package/templates/checkbox/checkbox.tsx +2 -3
- package/templates/checkbox-group/checkbox-group.tsx +1 -3
- package/templates/collapsible/collapsible.tsx +1 -2
- package/templates/combobox/combobox.tsx +0 -1
- package/templates/context-menu/context-menu.tsx +0 -1
- package/templates/dialog/dialog.tsx +1 -1
- package/templates/drawer/drawer.tsx +0 -1
- package/templates/field/field.tsx +69 -85
- package/templates/fieldset/fieldset.tsx +0 -1
- package/templates/form/form.tsx +36 -28
- package/templates/input/index.ts +1 -2
- package/templates/input/input.tsx +0 -1
- package/templates/menu/menu.tsx +0 -1
- package/templates/menubar/menubar.tsx +21 -22
- package/templates/meter/meter.tsx +0 -1
- package/templates/navigation-menu/index.ts +1 -13
- package/templates/navigation-menu/navigation-menu.tsx +1 -3
- package/templates/number-field/number-field.tsx +0 -1
- package/templates/popover/popover.tsx +0 -1
- package/templates/preview-card/preview-card.tsx +0 -1
- package/templates/progress/progress.tsx +0 -1
- package/templates/radio/radio.tsx +0 -1
- package/templates/scroll-area/scroll-area.tsx +0 -1
- package/templates/select/select.tsx +1 -4
- package/templates/separator/separator.tsx +0 -1
- package/templates/slider/index.ts +10 -0
- package/templates/slider/slider.tsx +1 -3
- package/templates/switch/switch.tsx +0 -1
- package/templates/tabs/index.ts +8 -0
- package/templates/tabs/tabs.tsx +8 -3
- package/templates/textarea/index.ts +2 -0
- package/templates/textarea/textarea.tsx +23 -0
- package/templates/toast/toast.tsx +3 -2
- package/templates/toggle/toggle.tsx +0 -1
- package/templates/toggle-group/toggle-group.tsx +0 -1
- package/templates/toolbar/toolbar.tsx +0 -1
- package/templates/tooltip/tooltip.tsx +0 -1
- package/templates/tsconfig.json +20 -0
- package/templates/utils/utils.ts +0 -1
- package/templates/utils/variants.ts +0 -1
package/dist/index.js
CHANGED
|
@@ -102,6 +102,13 @@ function getComponentRegistry() {
|
|
|
102
102
|
dependencies: ["@base-ui/react", "class-variance-authority"],
|
|
103
103
|
utilityDependencies: ["cn"]
|
|
104
104
|
},
|
|
105
|
+
badge: {
|
|
106
|
+
name: "badge",
|
|
107
|
+
description: "A small status indicator for highlighting information.",
|
|
108
|
+
files: [{ name: "badge.tsx" }, { name: "index.ts" }],
|
|
109
|
+
dependencies: ["@base-ui/react", "class-variance-authority"],
|
|
110
|
+
utilityDependencies: ["cn"]
|
|
111
|
+
},
|
|
105
112
|
button: {
|
|
106
113
|
name: "button",
|
|
107
114
|
description: "A customizable button component with multiple variants.",
|
|
@@ -109,6 +116,13 @@ function getComponentRegistry() {
|
|
|
109
116
|
dependencies: ["@base-ui/react", "class-variance-authority"],
|
|
110
117
|
utilityDependencies: ["cn", "variants"]
|
|
111
118
|
},
|
|
119
|
+
card: {
|
|
120
|
+
name: "card",
|
|
121
|
+
description: "A container for grouping related content with header, body, and footer sections.",
|
|
122
|
+
files: [{ name: "card.tsx" }, { name: "index.ts" }],
|
|
123
|
+
dependencies: [],
|
|
124
|
+
utilityDependencies: ["cn"]
|
|
125
|
+
},
|
|
112
126
|
checkbox: {
|
|
113
127
|
name: "checkbox",
|
|
114
128
|
description: "A control that allows the user to select one or more options from a set.",
|
|
@@ -292,6 +306,13 @@ function getComponentRegistry() {
|
|
|
292
306
|
dependencies: ["@base-ui/react"],
|
|
293
307
|
utilityDependencies: ["cn"]
|
|
294
308
|
},
|
|
309
|
+
textarea: {
|
|
310
|
+
name: "textarea",
|
|
311
|
+
description: "A multi-line text input for longer form content.",
|
|
312
|
+
files: [{ name: "textarea.tsx" }, { name: "index.ts" }],
|
|
313
|
+
dependencies: [],
|
|
314
|
+
utilityDependencies: ["cn"]
|
|
315
|
+
},
|
|
295
316
|
toast: {
|
|
296
317
|
name: "toast",
|
|
297
318
|
description: "Generates toast notifications with support for different types, promises, actions, and global management.",
|
|
@@ -647,6 +668,45 @@ ${withTrailingComma}
|
|
|
647
668
|
`;
|
|
648
669
|
return next;
|
|
649
670
|
}
|
|
671
|
+
function detectTailwindMajorVersion(projectRoot) {
|
|
672
|
+
const packageJsonPath = path3.join(projectRoot, "package.json");
|
|
673
|
+
if (!fs3.existsSync(packageJsonPath)) return 4;
|
|
674
|
+
try {
|
|
675
|
+
const raw = fs3.readFileSync(packageJsonPath, "utf-8");
|
|
676
|
+
const packageJson = JSON.parse(raw);
|
|
677
|
+
const deps = { ...packageJson.dependencies ?? {}, ...packageJson.devDependencies ?? {} };
|
|
678
|
+
const twVersion = deps.tailwindcss;
|
|
679
|
+
if (!twVersion) return 4;
|
|
680
|
+
const match = twVersion.match(/(\d+)/);
|
|
681
|
+
return match ? parseInt(match[1], 10) : 4;
|
|
682
|
+
} catch {
|
|
683
|
+
return 4;
|
|
684
|
+
}
|
|
685
|
+
}
|
|
686
|
+
async function ensureTW4Plugin(deps, cssFilePath) {
|
|
687
|
+
if (!deps.includes("tailwindcss-animate")) {
|
|
688
|
+
return null;
|
|
689
|
+
}
|
|
690
|
+
if (!fs3.existsSync(cssFilePath)) {
|
|
691
|
+
return { skipped: true, path: cssFilePath };
|
|
692
|
+
}
|
|
693
|
+
const content = await fs3.readFile(cssFilePath, "utf-8");
|
|
694
|
+
if (content.includes("tailwindcss-animate")) {
|
|
695
|
+
return { exists: true, path: cssFilePath };
|
|
696
|
+
}
|
|
697
|
+
const pluginLine = '@plugin "tailwindcss-animate";';
|
|
698
|
+
const importMatch = content.match(/^@import\s+["']tailwindcss["'];?\s*$/m);
|
|
699
|
+
let updated;
|
|
700
|
+
if (importMatch) {
|
|
701
|
+
updated = content.replace(importMatch[0], `${importMatch[0].trimEnd()}
|
|
702
|
+
${pluginLine}`);
|
|
703
|
+
} else {
|
|
704
|
+
updated = `${pluginLine}
|
|
705
|
+
${content}`;
|
|
706
|
+
}
|
|
707
|
+
await fs3.writeFile(cssFilePath, updated);
|
|
708
|
+
return { updated: true, path: cssFilePath };
|
|
709
|
+
}
|
|
650
710
|
async function ensureTailwindConfig(deps, projectRoot, configuredFileName) {
|
|
651
711
|
if (!deps.includes("tailwindcss-animate")) {
|
|
652
712
|
return null;
|
|
@@ -740,8 +800,8 @@ ${linesToAppend.join("\n")}
|
|
|
740
800
|
await fs3.writeFile(targetPath, updatedContent);
|
|
741
801
|
allFilesAdded.push({ name: "index.ts", path: path3.join(targetDir, "index.ts") });
|
|
742
802
|
}
|
|
743
|
-
var addCommand = new Command("add").description("Add a component to your project").argument("[
|
|
744
|
-
async (
|
|
803
|
+
var addCommand = new Command("add").description("Add a component to your project").argument("[components...]", "Names of the components to add (optional when using --all)").option("-y, --yes", "Skip confirmation prompts").option("-o, --overwrite", "Overwrite existing files").option("-a, --all", "Install all available components").option("--skip-install", "Skip package installation").action(
|
|
804
|
+
async (componentNames, options) => {
|
|
745
805
|
const spinner = ora("Adding component...").start();
|
|
746
806
|
try {
|
|
747
807
|
const config = await getConfig();
|
|
@@ -764,7 +824,7 @@ var addCommand = new Command("add").description("Add a component to your project
|
|
|
764
824
|
}
|
|
765
825
|
componentsToInstall = Array.from(allComponentsWithDeps);
|
|
766
826
|
} else {
|
|
767
|
-
if (
|
|
827
|
+
if (componentNames.length === 0) {
|
|
768
828
|
spinner.fail("\u274C Component name is required when not using --all flag.");
|
|
769
829
|
console.log("Available components:");
|
|
770
830
|
Object.keys(registry).forEach((name) => {
|
|
@@ -772,16 +832,23 @@ var addCommand = new Command("add").description("Add a component to your project
|
|
|
772
832
|
});
|
|
773
833
|
process.exit(1);
|
|
774
834
|
}
|
|
775
|
-
const
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
835
|
+
for (const name of componentNames) {
|
|
836
|
+
if (!registry[name]) {
|
|
837
|
+
spinner.fail(`\u274C Component "${name}" not found.`);
|
|
838
|
+
console.log("Available components:");
|
|
839
|
+
Object.keys(registry).forEach((n) => {
|
|
840
|
+
console.log(` ${chalk.cyan(n)}`);
|
|
841
|
+
});
|
|
842
|
+
process.exit(1);
|
|
843
|
+
}
|
|
783
844
|
}
|
|
784
|
-
|
|
845
|
+
const allWithDeps = /* @__PURE__ */ new Set();
|
|
846
|
+
for (const name of componentNames) {
|
|
847
|
+
allWithDeps.add(name);
|
|
848
|
+
const deps = getComponentDependencies(name);
|
|
849
|
+
deps.forEach((dep) => allWithDeps.add(dep));
|
|
850
|
+
}
|
|
851
|
+
componentsToInstall = Array.from(allWithDeps);
|
|
785
852
|
}
|
|
786
853
|
if (!options.all) {
|
|
787
854
|
spinner.text = `Installing ${componentsToInstall.join(", ")}...`;
|
|
@@ -847,7 +914,11 @@ var addCommand = new Command("add").description("Add a component to your project
|
|
|
847
914
|
}
|
|
848
915
|
}
|
|
849
916
|
spinner.text = "Updating Tailwind configuration...";
|
|
850
|
-
const
|
|
917
|
+
const tailwindMajor = detectTailwindMajorVersion(projectRoot);
|
|
918
|
+
const tailwindConfigInfo = tailwindMajor >= 4 ? await ensureTW4Plugin(
|
|
919
|
+
allDepsInstalled,
|
|
920
|
+
path3.resolve(projectRoot, config.tailwind?.css || "src/index.css")
|
|
921
|
+
) : await ensureTailwindConfig(
|
|
851
922
|
allDepsInstalled,
|
|
852
923
|
projectRoot,
|
|
853
924
|
config.tailwind?.config || "tailwind.config.js"
|
|
@@ -946,6 +1017,287 @@ export function cn(...inputs: ClassValue[]) {
|
|
|
946
1017
|
}
|
|
947
1018
|
`;
|
|
948
1019
|
}
|
|
1020
|
+
function detectTailwindMajorVersion2(projectRoot) {
|
|
1021
|
+
const packageJsonPath = path4.join(projectRoot, "package.json");
|
|
1022
|
+
if (!fs4.existsSync(packageJsonPath)) return 4;
|
|
1023
|
+
try {
|
|
1024
|
+
const raw = fs4.readFileSync(packageJsonPath, "utf-8");
|
|
1025
|
+
const packageJson = JSON.parse(raw);
|
|
1026
|
+
const deps = { ...packageJson.dependencies ?? {}, ...packageJson.devDependencies ?? {} };
|
|
1027
|
+
const twVersion = deps.tailwindcss;
|
|
1028
|
+
if (!twVersion) return 4;
|
|
1029
|
+
const match = twVersion.match(/(\d+)/);
|
|
1030
|
+
return match ? parseInt(match[1], 10) : 4;
|
|
1031
|
+
} catch {
|
|
1032
|
+
return 4;
|
|
1033
|
+
}
|
|
1034
|
+
}
|
|
1035
|
+
function getThemeCSS(tailwindMajor, mode) {
|
|
1036
|
+
const lightVars = `:root {
|
|
1037
|
+
--background: oklch(0.986 0.0034 145.5499);
|
|
1038
|
+
--foreground: oklch(0.1459 0.0497 142.4953);
|
|
1039
|
+
--card: oklch(0.9781 0.0017 145.5621);
|
|
1040
|
+
--card-foreground: oklch(0.1459 0.0497 142.4953);
|
|
1041
|
+
--popover: oklch(1 0 0);
|
|
1042
|
+
--popover-foreground: oklch(0.1324 0.0033 145.3864);
|
|
1043
|
+
--primary: oklch(0.1324 0.0033 145.3864);
|
|
1044
|
+
--primary-foreground: oklch(0.9729 0.0101 145.4971);
|
|
1045
|
+
--secondary: oklch(0.9248 0.0051 145.5339);
|
|
1046
|
+
--secondary-foreground: oklch(0.1324 0.0033 145.3864);
|
|
1047
|
+
--muted: oklch(0.9631 0.0017 145.5619);
|
|
1048
|
+
--muted-foreground: oklch(0.1849 0.0629 142.4953);
|
|
1049
|
+
--accent: oklch(0.9248 0.0051 145.5339);
|
|
1050
|
+
--accent-foreground: oklch(0.1459 0.0497 142.4953);
|
|
1051
|
+
--destructive: oklch(0.5248 0.1368 20.8317);
|
|
1052
|
+
--destructive-foreground: oklch(1 0 0);
|
|
1053
|
+
--border: oklch(0.9239 0.0017 145.5613);
|
|
1054
|
+
--input: oklch(0.8481 0.0105 145.4823);
|
|
1055
|
+
--ring: oklch(0.1459 0.0497 142.4953);
|
|
1056
|
+
--radius: 0.625rem;
|
|
1057
|
+
}`;
|
|
1058
|
+
const darkVars = `.dark {
|
|
1059
|
+
--background: oklch(0.1149 0 0);
|
|
1060
|
+
--foreground: oklch(0.7999 0.0218 134.1191);
|
|
1061
|
+
--card: oklch(0.133 0.0021 196.9098);
|
|
1062
|
+
--card-foreground: oklch(0.7996 0.023 132.5769);
|
|
1063
|
+
--popover: oklch(0.1663 0.0138 135.2766);
|
|
1064
|
+
--popover-foreground: oklch(0.9742 0.0101 131.3574);
|
|
1065
|
+
--primary: oklch(0.9729 0.0101 145.4971);
|
|
1066
|
+
--primary-foreground: oklch(0.1324 0.0033 145.3864);
|
|
1067
|
+
--secondary: oklch(0.1844 0.0062 122.0354);
|
|
1068
|
+
--secondary-foreground: oklch(0.8009 0.0399 133.2927);
|
|
1069
|
+
--muted: oklch(0.1579 0.0017 196.9874);
|
|
1070
|
+
--muted-foreground: oklch(0.7897 0.0171 133.8518);
|
|
1071
|
+
--accent: oklch(0.1391 0.0113 136.9894);
|
|
1072
|
+
--accent-foreground: oklch(0.9742 0.0101 131.3574);
|
|
1073
|
+
--destructive: oklch(0.2258 0.0524 12.6119);
|
|
1074
|
+
--destructive-foreground: oklch(1 0 0);
|
|
1075
|
+
--border: oklch(0.1811 0.0128 129.2819);
|
|
1076
|
+
--input: oklch(0.2213 0.0193 135.2915);
|
|
1077
|
+
--ring: oklch(0.9248 0.0051 145.5339);
|
|
1078
|
+
}`;
|
|
1079
|
+
const parts = [];
|
|
1080
|
+
if (tailwindMajor >= 4) {
|
|
1081
|
+
if (mode === "full") {
|
|
1082
|
+
parts.push('@import "tailwindcss";');
|
|
1083
|
+
}
|
|
1084
|
+
parts.push(lightVars, darkVars);
|
|
1085
|
+
parts.push(`@theme inline {
|
|
1086
|
+
--color-background: var(--background);
|
|
1087
|
+
--color-foreground: var(--foreground);
|
|
1088
|
+
--color-card: var(--card);
|
|
1089
|
+
--color-card-foreground: var(--card-foreground);
|
|
1090
|
+
--color-popover: var(--popover);
|
|
1091
|
+
--color-popover-foreground: var(--popover-foreground);
|
|
1092
|
+
--color-primary: var(--primary);
|
|
1093
|
+
--color-primary-foreground: var(--primary-foreground);
|
|
1094
|
+
--color-secondary: var(--secondary);
|
|
1095
|
+
--color-secondary-foreground: var(--secondary-foreground);
|
|
1096
|
+
--color-muted: var(--muted);
|
|
1097
|
+
--color-muted-foreground: var(--muted-foreground);
|
|
1098
|
+
--color-accent: var(--accent);
|
|
1099
|
+
--color-accent-foreground: var(--accent-foreground);
|
|
1100
|
+
--color-destructive: var(--destructive);
|
|
1101
|
+
--color-destructive-foreground: var(--destructive-foreground);
|
|
1102
|
+
--color-border: var(--border);
|
|
1103
|
+
--color-input: var(--input);
|
|
1104
|
+
--color-ring: var(--ring);
|
|
1105
|
+
--radius-sm: calc(var(--radius) - 4px);
|
|
1106
|
+
--radius-md: calc(var(--radius) - 2px);
|
|
1107
|
+
--radius-lg: var(--radius);
|
|
1108
|
+
--radius-xl: calc(var(--radius) + 4px);
|
|
1109
|
+
}`);
|
|
1110
|
+
parts.push(`@layer base {
|
|
1111
|
+
* {
|
|
1112
|
+
@apply border-border outline-ring/50;
|
|
1113
|
+
}
|
|
1114
|
+
body {
|
|
1115
|
+
@apply bg-background text-foreground;
|
|
1116
|
+
}
|
|
1117
|
+
}`);
|
|
1118
|
+
} else {
|
|
1119
|
+
if (mode === "full") {
|
|
1120
|
+
parts.push("@tailwind base;\n@tailwind components;\n@tailwind utilities;");
|
|
1121
|
+
}
|
|
1122
|
+
parts.push(lightVars, darkVars);
|
|
1123
|
+
parts.push(`@layer base {
|
|
1124
|
+
* {
|
|
1125
|
+
@apply border-border;
|
|
1126
|
+
}
|
|
1127
|
+
body {
|
|
1128
|
+
@apply bg-background text-foreground;
|
|
1129
|
+
}
|
|
1130
|
+
}`);
|
|
1131
|
+
}
|
|
1132
|
+
return parts.join("\n\n") + "\n";
|
|
1133
|
+
}
|
|
1134
|
+
function stripConflictingCSS(css) {
|
|
1135
|
+
let result = css;
|
|
1136
|
+
result = result.replace(/@media\s*\(\s*prefers-color-scheme\s*:\s*dark\s*\)\s*\{[\s\S]*?\n\}/g, "");
|
|
1137
|
+
result = result.replace(/:root\s*\{[^}]*\}/g, "");
|
|
1138
|
+
result = result.replace(/\.dark\s*\{[^}]*\}/g, "");
|
|
1139
|
+
result = result.replace(/@theme\s+inline\s*\{[^}]*\}/g, "");
|
|
1140
|
+
result = result.replace(/(?:^|\n)body\s*\{[^}]*\}/g, "");
|
|
1141
|
+
result = result.replace(/\n{3,}/g, "\n\n");
|
|
1142
|
+
return result.trim();
|
|
1143
|
+
}
|
|
1144
|
+
async function injectThemeCSS(cssFilePath, tailwindMajor) {
|
|
1145
|
+
await fs4.ensureDir(path4.dirname(cssFilePath));
|
|
1146
|
+
if (fs4.existsSync(cssFilePath)) {
|
|
1147
|
+
const existing = await fs4.readFile(cssFilePath, "utf-8");
|
|
1148
|
+
if (existing.includes("--primary:")) {
|
|
1149
|
+
return { path: cssFilePath, skipped: true };
|
|
1150
|
+
}
|
|
1151
|
+
const cleaned = stripConflictingCSS(existing);
|
|
1152
|
+
const theme2 = getThemeCSS(tailwindMajor, "append");
|
|
1153
|
+
const result = cleaned.length > 0 ? cleaned + "\n\n" + theme2 : getThemeCSS(tailwindMajor, "full");
|
|
1154
|
+
await fs4.writeFile(cssFilePath, result);
|
|
1155
|
+
return { path: cssFilePath, updated: true };
|
|
1156
|
+
}
|
|
1157
|
+
const theme = getThemeCSS(tailwindMajor, "full");
|
|
1158
|
+
await fs4.writeFile(cssFilePath, theme);
|
|
1159
|
+
return { path: cssFilePath, created: true };
|
|
1160
|
+
}
|
|
1161
|
+
function getTW3ColorExtend() {
|
|
1162
|
+
return `colors: {
|
|
1163
|
+
border: "var(--border)",
|
|
1164
|
+
input: "var(--input)",
|
|
1165
|
+
ring: "var(--ring)",
|
|
1166
|
+
background: "var(--background)",
|
|
1167
|
+
foreground: "var(--foreground)",
|
|
1168
|
+
primary: {
|
|
1169
|
+
DEFAULT: "var(--primary)",
|
|
1170
|
+
foreground: "var(--primary-foreground)",
|
|
1171
|
+
},
|
|
1172
|
+
secondary: {
|
|
1173
|
+
DEFAULT: "var(--secondary)",
|
|
1174
|
+
foreground: "var(--secondary-foreground)",
|
|
1175
|
+
},
|
|
1176
|
+
destructive: {
|
|
1177
|
+
DEFAULT: "var(--destructive)",
|
|
1178
|
+
foreground: "var(--destructive-foreground)",
|
|
1179
|
+
},
|
|
1180
|
+
muted: {
|
|
1181
|
+
DEFAULT: "var(--muted)",
|
|
1182
|
+
foreground: "var(--muted-foreground)",
|
|
1183
|
+
},
|
|
1184
|
+
accent: {
|
|
1185
|
+
DEFAULT: "var(--accent)",
|
|
1186
|
+
foreground: "var(--accent-foreground)",
|
|
1187
|
+
},
|
|
1188
|
+
popover: {
|
|
1189
|
+
DEFAULT: "var(--popover)",
|
|
1190
|
+
foreground: "var(--popover-foreground)",
|
|
1191
|
+
},
|
|
1192
|
+
card: {
|
|
1193
|
+
DEFAULT: "var(--card)",
|
|
1194
|
+
foreground: "var(--card-foreground)",
|
|
1195
|
+
},
|
|
1196
|
+
},
|
|
1197
|
+
borderRadius: {
|
|
1198
|
+
lg: "var(--radius)",
|
|
1199
|
+
md: "calc(var(--radius) - 2px)",
|
|
1200
|
+
sm: "calc(var(--radius) - 4px)",
|
|
1201
|
+
},`;
|
|
1202
|
+
}
|
|
1203
|
+
function createTW3Config(isCjs) {
|
|
1204
|
+
const colorExtend = getTW3ColorExtend();
|
|
1205
|
+
if (isCjs) {
|
|
1206
|
+
return `/** @type {import('tailwindcss').Config} */
|
|
1207
|
+
module.exports = {
|
|
1208
|
+
content: [
|
|
1209
|
+
"./src/**/*.{js,ts,jsx,tsx}",
|
|
1210
|
+
"./app/**/*.{js,ts,jsx,tsx}",
|
|
1211
|
+
"./components/**/*.{js,ts,jsx,tsx}",
|
|
1212
|
+
],
|
|
1213
|
+
theme: {
|
|
1214
|
+
extend: {
|
|
1215
|
+
${colorExtend}
|
|
1216
|
+
},
|
|
1217
|
+
},
|
|
1218
|
+
plugins: [],
|
|
1219
|
+
}
|
|
1220
|
+
`;
|
|
1221
|
+
}
|
|
1222
|
+
return `/** @type {import('tailwindcss').Config} */
|
|
1223
|
+
export default {
|
|
1224
|
+
content: [
|
|
1225
|
+
"./src/**/*.{js,ts,jsx,tsx}",
|
|
1226
|
+
"./app/**/*.{js,ts,jsx,tsx}",
|
|
1227
|
+
"./components/**/*.{js,ts,jsx,tsx}",
|
|
1228
|
+
],
|
|
1229
|
+
theme: {
|
|
1230
|
+
extend: {
|
|
1231
|
+
${colorExtend}
|
|
1232
|
+
},
|
|
1233
|
+
},
|
|
1234
|
+
plugins: [],
|
|
1235
|
+
}
|
|
1236
|
+
`;
|
|
1237
|
+
}
|
|
1238
|
+
async function ensureTW3ColorConfig(projectRoot, configFileName) {
|
|
1239
|
+
const candidates = [
|
|
1240
|
+
configFileName,
|
|
1241
|
+
"tailwind.config.ts",
|
|
1242
|
+
"tailwind.config.js",
|
|
1243
|
+
"tailwind.config.mjs",
|
|
1244
|
+
"tailwind.config.cjs"
|
|
1245
|
+
];
|
|
1246
|
+
let configPath = null;
|
|
1247
|
+
for (const candidate of candidates) {
|
|
1248
|
+
const candidatePath = path4.join(projectRoot, candidate);
|
|
1249
|
+
if (fs4.existsSync(candidatePath)) {
|
|
1250
|
+
configPath = candidatePath;
|
|
1251
|
+
break;
|
|
1252
|
+
}
|
|
1253
|
+
}
|
|
1254
|
+
if (!configPath) {
|
|
1255
|
+
configPath = path4.join(projectRoot, configFileName);
|
|
1256
|
+
const ext = path4.extname(configPath);
|
|
1257
|
+
const isCjs = ext === ".cjs";
|
|
1258
|
+
await fs4.writeFile(configPath, createTW3Config(isCjs));
|
|
1259
|
+
return { path: configPath, created: true };
|
|
1260
|
+
}
|
|
1261
|
+
const content = await fs4.readFile(configPath, "utf-8");
|
|
1262
|
+
if (content.includes('"var(--primary)"') || content.includes("'var(--primary)'")) {
|
|
1263
|
+
return { path: configPath, skipped: true };
|
|
1264
|
+
}
|
|
1265
|
+
const colorExtend = getTW3ColorExtend();
|
|
1266
|
+
const extendMatch = content.match(/extend\s*:\s*\{/);
|
|
1267
|
+
if (extendMatch && extendMatch.index !== void 0) {
|
|
1268
|
+
const insertPos = extendMatch.index + extendMatch[0].length;
|
|
1269
|
+
const updated = content.slice(0, insertPos) + "\n " + colorExtend + content.slice(insertPos);
|
|
1270
|
+
await fs4.writeFile(configPath, updated);
|
|
1271
|
+
return { path: configPath, updated: true };
|
|
1272
|
+
}
|
|
1273
|
+
const themeMatch = content.match(/theme\s*:\s*\{/);
|
|
1274
|
+
if (themeMatch && themeMatch.index !== void 0) {
|
|
1275
|
+
const insertPos = themeMatch.index + themeMatch[0].length;
|
|
1276
|
+
const extendBlock = `
|
|
1277
|
+
extend: {
|
|
1278
|
+
${colorExtend}
|
|
1279
|
+
},`;
|
|
1280
|
+
const updated = content.slice(0, insertPos) + extendBlock + content.slice(insertPos);
|
|
1281
|
+
await fs4.writeFile(configPath, updated);
|
|
1282
|
+
return { path: configPath, updated: true };
|
|
1283
|
+
}
|
|
1284
|
+
const closingBrace = content.lastIndexOf("}");
|
|
1285
|
+
if (closingBrace !== -1) {
|
|
1286
|
+
const before = content.slice(0, closingBrace).trimEnd();
|
|
1287
|
+
const needsComma = !before.endsWith(",") && !before.endsWith("{");
|
|
1288
|
+
const themeBlock = `${needsComma ? "," : ""}
|
|
1289
|
+
theme: {
|
|
1290
|
+
extend: {
|
|
1291
|
+
${colorExtend}
|
|
1292
|
+
},
|
|
1293
|
+
},
|
|
1294
|
+
`;
|
|
1295
|
+
const updated = before + themeBlock + content.slice(closingBrace);
|
|
1296
|
+
await fs4.writeFile(configPath, updated);
|
|
1297
|
+
return { path: configPath, updated: true };
|
|
1298
|
+
}
|
|
1299
|
+
return { path: configPath, skipped: true };
|
|
1300
|
+
}
|
|
949
1301
|
function readJsonConfig(filePath) {
|
|
950
1302
|
try {
|
|
951
1303
|
const content = fs4.readFileSync(filePath, "utf-8");
|
|
@@ -1041,6 +1393,15 @@ var initCommand = new Command2("init").description("Initialize Dinachi UI in you
|
|
|
1041
1393
|
await fs4.ensureDir(utilsDirPath);
|
|
1042
1394
|
const utilsContent = createUtilsFileContent();
|
|
1043
1395
|
await fs4.writeFile(utilsFilePath, utilsContent);
|
|
1396
|
+
spinner.text = "Setting up color theme...";
|
|
1397
|
+
const tailwindMajor = detectTailwindMajorVersion2(projectRoot);
|
|
1398
|
+
const cssFilePath = path4.resolve(projectRoot, projectConfig.cssPath);
|
|
1399
|
+
const themeCSSResult = await injectThemeCSS(cssFilePath, tailwindMajor);
|
|
1400
|
+
let twColorConfigResult = null;
|
|
1401
|
+
if (tailwindMajor < 4) {
|
|
1402
|
+
spinner.text = "Configuring Tailwind color mappings...";
|
|
1403
|
+
twColorConfigResult = await ensureTW3ColorConfig(projectRoot, projectConfig.tailwindConfig);
|
|
1404
|
+
}
|
|
1044
1405
|
spinner.text = "Installing dependencies...";
|
|
1045
1406
|
const deps = ["class-variance-authority", "clsx", "tailwind-merge"];
|
|
1046
1407
|
if (!options.skipInstall) {
|
|
@@ -1091,6 +1452,22 @@ var initCommand = new Command2("init").description("Initialize Dinachi UI in you
|
|
|
1091
1452
|
` ${chalk2.yellow("!")} Could not update ${aliasConfigUpdate.path}. Configure @/* manually if you use alias imports.`
|
|
1092
1453
|
);
|
|
1093
1454
|
}
|
|
1455
|
+
if (themeCSSResult.created) {
|
|
1456
|
+
console.log(` ${chalk2.green("+")} Created ${projectConfig.cssPath} with color theme (light + dark)`);
|
|
1457
|
+
} else if (themeCSSResult.updated) {
|
|
1458
|
+
console.log(` ${chalk2.blue("~")} Updated ${projectConfig.cssPath} with color theme (light + dark)`);
|
|
1459
|
+
} else if (themeCSSResult.skipped) {
|
|
1460
|
+
console.log(` ${chalk2.gray("-")} Color theme already configured in ${projectConfig.cssPath}`);
|
|
1461
|
+
}
|
|
1462
|
+
if (twColorConfigResult) {
|
|
1463
|
+
if (twColorConfigResult.created) {
|
|
1464
|
+
console.log(` ${chalk2.green("+")} Created ${projectConfig.tailwindConfig} with color mappings`);
|
|
1465
|
+
} else if (twColorConfigResult.updated) {
|
|
1466
|
+
console.log(` ${chalk2.blue("~")} Updated ${projectConfig.tailwindConfig} with color mappings`);
|
|
1467
|
+
} else if (twColorConfigResult.skipped) {
|
|
1468
|
+
console.log(` ${chalk2.gray("-")} Color mappings already in ${projectConfig.tailwindConfig}`);
|
|
1469
|
+
}
|
|
1470
|
+
}
|
|
1094
1471
|
if (!projectConfig.isTypeScript) {
|
|
1095
1472
|
console.log();
|
|
1096
1473
|
console.log(
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dinachi/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.1",
|
|
4
4
|
"description": "CLI for adding Dinachi UI components to your project",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"keywords": [
|
|
@@ -27,18 +27,25 @@
|
|
|
27
27
|
"templates"
|
|
28
28
|
],
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"commander": "^14.0.2",
|
|
31
30
|
"chalk": "^5.3.0",
|
|
32
|
-
"
|
|
33
|
-
"
|
|
31
|
+
"commander": "^14.0.2",
|
|
32
|
+
"execa": "^9.6.1",
|
|
34
33
|
"fs-extra": "^11.2.0",
|
|
35
34
|
"node-fetch": "^3.3.2",
|
|
36
|
-
"
|
|
35
|
+
"ora": "^9.0.0",
|
|
36
|
+
"prompts": "^2.4.2",
|
|
37
37
|
"ts-morph": "^27.0.2"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
|
+
"@base-ui/react": "1.2.0",
|
|
40
41
|
"@types/fs-extra": "^11.0.4",
|
|
41
42
|
"@types/prompts": "^2.4.9",
|
|
43
|
+
"@types/react": "^19.2.14",
|
|
44
|
+
"class-variance-authority": "^0.7.1",
|
|
45
|
+
"clsx": "^2.1.1",
|
|
46
|
+
"lucide-react": "0.552.0",
|
|
47
|
+
"react": "19.2.4",
|
|
48
|
+
"tailwind-merge": "^3.5.0",
|
|
42
49
|
"tsup": "^8.0.1",
|
|
43
50
|
"typescript": "^5.5.3"
|
|
44
51
|
},
|
|
@@ -1,10 +1,15 @@
|
|
|
1
|
-
// @ts-nocheck
|
|
2
1
|
import * as React from "react";
|
|
3
2
|
import { Accordion as BaseAccordion } from "@base-ui/react/accordion";
|
|
4
|
-
import { cn } from "@/lib/utils"
|
|
3
|
+
import { cn } from "@/lib/utils";
|
|
5
4
|
import { ChevronDown } from "lucide-react";
|
|
6
5
|
|
|
7
|
-
const Accordion =
|
|
6
|
+
const Accordion = React.forwardRef<
|
|
7
|
+
React.ComponentRef<typeof BaseAccordion.Root>,
|
|
8
|
+
React.ComponentProps<typeof BaseAccordion.Root>
|
|
9
|
+
>(({ className, ...props }, ref) => (
|
|
10
|
+
<BaseAccordion.Root ref={ref} className={cn(className)} {...props} />
|
|
11
|
+
));
|
|
12
|
+
Accordion.displayName = "Accordion";
|
|
8
13
|
|
|
9
14
|
const AccordionItem = React.forwardRef<
|
|
10
15
|
HTMLDivElement,
|
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
import
|
|
3
|
-
import {
|
|
4
|
-
import { cn } from "@/lib/utils"
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { AlertDialog as BaseAlertDialog } from "@base-ui/react";
|
|
3
|
+
import { cn } from "@/lib/utils";
|
|
5
4
|
|
|
6
|
-
const AlertDialog = BaseAlertDialog.Root
|
|
5
|
+
const AlertDialog = BaseAlertDialog.Root;
|
|
7
6
|
|
|
8
7
|
const AlertDialogTrigger = React.forwardRef<
|
|
9
8
|
HTMLButtonElement,
|
|
@@ -21,10 +20,10 @@ const AlertDialogTrigger = React.forwardRef<
|
|
|
21
20
|
)}
|
|
22
21
|
{...props}
|
|
23
22
|
/>
|
|
24
|
-
))
|
|
25
|
-
AlertDialogTrigger.displayName = "AlertDialogTrigger"
|
|
23
|
+
));
|
|
24
|
+
AlertDialogTrigger.displayName = "AlertDialogTrigger";
|
|
26
25
|
|
|
27
|
-
const AlertDialogPortal = BaseAlertDialog.Portal
|
|
26
|
+
const AlertDialogPortal = BaseAlertDialog.Portal;
|
|
28
27
|
|
|
29
28
|
const AlertDialogBackdrop = React.forwardRef<
|
|
30
29
|
HTMLDivElement,
|
|
@@ -40,8 +39,8 @@ const AlertDialogBackdrop = React.forwardRef<
|
|
|
40
39
|
)}
|
|
41
40
|
{...props}
|
|
42
41
|
/>
|
|
43
|
-
))
|
|
44
|
-
AlertDialogBackdrop.displayName = "AlertDialogBackdrop"
|
|
42
|
+
));
|
|
43
|
+
AlertDialogBackdrop.displayName = "AlertDialogBackdrop";
|
|
45
44
|
|
|
46
45
|
const AlertDialogPopup = React.forwardRef<
|
|
47
46
|
HTMLDivElement,
|
|
@@ -58,8 +57,8 @@ const AlertDialogPopup = React.forwardRef<
|
|
|
58
57
|
)}
|
|
59
58
|
{...props}
|
|
60
59
|
/>
|
|
61
|
-
))
|
|
62
|
-
AlertDialogPopup.displayName = "AlertDialogPopup"
|
|
60
|
+
));
|
|
61
|
+
AlertDialogPopup.displayName = "AlertDialogPopup";
|
|
63
62
|
|
|
64
63
|
const AlertDialogTitle = React.forwardRef<
|
|
65
64
|
HTMLHeadingElement,
|
|
@@ -70,8 +69,8 @@ const AlertDialogTitle = React.forwardRef<
|
|
|
70
69
|
className={cn("text-lg font-semibold", className)}
|
|
71
70
|
{...props}
|
|
72
71
|
/>
|
|
73
|
-
))
|
|
74
|
-
AlertDialogTitle.displayName = "AlertDialogTitle"
|
|
72
|
+
));
|
|
73
|
+
AlertDialogTitle.displayName = "AlertDialogTitle";
|
|
75
74
|
|
|
76
75
|
const AlertDialogDescription = React.forwardRef<
|
|
77
76
|
HTMLParagraphElement,
|
|
@@ -82,8 +81,8 @@ const AlertDialogDescription = React.forwardRef<
|
|
|
82
81
|
className={cn("text-sm text-muted-foreground", className)}
|
|
83
82
|
{...props}
|
|
84
83
|
/>
|
|
85
|
-
))
|
|
86
|
-
AlertDialogDescription.displayName = "AlertDialogDescription"
|
|
84
|
+
));
|
|
85
|
+
AlertDialogDescription.displayName = "AlertDialogDescription";
|
|
87
86
|
|
|
88
87
|
const AlertDialogAction = React.forwardRef<
|
|
89
88
|
HTMLButtonElement,
|
|
@@ -99,8 +98,8 @@ const AlertDialogAction = React.forwardRef<
|
|
|
99
98
|
)}
|
|
100
99
|
{...props}
|
|
101
100
|
/>
|
|
102
|
-
))
|
|
103
|
-
AlertDialogAction.displayName = "AlertDialogAction"
|
|
101
|
+
));
|
|
102
|
+
AlertDialogAction.displayName = "AlertDialogAction";
|
|
104
103
|
|
|
105
104
|
const AlertDialogCancel = React.forwardRef<
|
|
106
105
|
HTMLButtonElement,
|
|
@@ -116,8 +115,8 @@ const AlertDialogCancel = React.forwardRef<
|
|
|
116
115
|
)}
|
|
117
116
|
{...props}
|
|
118
117
|
/>
|
|
119
|
-
))
|
|
120
|
-
AlertDialogCancel.displayName = "AlertDialogCancel"
|
|
118
|
+
));
|
|
119
|
+
AlertDialogCancel.displayName = "AlertDialogCancel";
|
|
121
120
|
|
|
122
121
|
const AlertDialogHeader = ({
|
|
123
122
|
className,
|
|
@@ -130,8 +129,8 @@ const AlertDialogHeader = ({
|
|
|
130
129
|
)}
|
|
131
130
|
{...props}
|
|
132
131
|
/>
|
|
133
|
-
)
|
|
134
|
-
AlertDialogHeader.displayName = "AlertDialogHeader"
|
|
132
|
+
);
|
|
133
|
+
AlertDialogHeader.displayName = "AlertDialogHeader";
|
|
135
134
|
|
|
136
135
|
const AlertDialogFooter = ({
|
|
137
136
|
className,
|
|
@@ -144,8 +143,8 @@ const AlertDialogFooter = ({
|
|
|
144
143
|
)}
|
|
145
144
|
{...props}
|
|
146
145
|
/>
|
|
147
|
-
)
|
|
148
|
-
AlertDialogFooter.displayName = "AlertDialogFooter"
|
|
146
|
+
);
|
|
147
|
+
AlertDialogFooter.displayName = "AlertDialogFooter";
|
|
149
148
|
|
|
150
149
|
export {
|
|
151
150
|
AlertDialog,
|
|
@@ -159,4 +158,4 @@ export {
|
|
|
159
158
|
AlertDialogCancel,
|
|
160
159
|
AlertDialogHeader,
|
|
161
160
|
AlertDialogFooter,
|
|
162
|
-
}
|
|
161
|
+
};
|
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
// @ts-nocheck
|
|
2
1
|
import * as React from "react";
|
|
3
2
|
import { Avatar as BaseAvatar } from "@base-ui/react";
|
|
4
3
|
import { cva, type VariantProps } from "class-variance-authority";
|
|
5
|
-
import { cn } from "@/lib/utils"
|
|
6
|
-
|
|
4
|
+
import { cn } from "@/lib/utils";
|
|
7
5
|
|
|
8
6
|
const avatarVariants = cva(
|
|
9
7
|
"relative flex h-10 w-10 shrink-0 overflow-hidden rounded-full",
|