@nikala-ui/cli 0.9.9 → 0.9.10

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 CHANGED
@@ -13,9 +13,19 @@ Official Documentation & Interactive Demos: [nikala.magradze.dev](https://nikala
13
13
  Execute directly using your preferred package manager:
14
14
 
15
15
  ```bash
16
+ # Add components
17
+ bunx @nikala-ui/cli add button dialog
18
+
19
+ # Upgrade / update installed components & hooks to latest registry versions
20
+ bunx @nikala-ui/cli upgrade
21
+ bunx @nikala-ui/cli update button --all
22
+
23
+ # Remove / uninstall installed components or hooks
24
+ bunx @nikala-ui/cli remove button
25
+ bunx @nikala-ui/cli uninstall -h create-clipboard
26
+
27
+ # Initialize project
16
28
  bunx @nikala-ui/cli init
17
- # or
18
- npx @nikala-ui/cli init
19
29
  ```
20
30
 
21
31
  ---
@@ -0,0 +1,9 @@
1
+ interface RemoveOptions {
2
+ all?: boolean;
3
+ hook?: boolean;
4
+ }
5
+ /**
6
+ * Command handler to safely uninstall/remove local Nikala UI components or reactive hooks.
7
+ */
8
+ export declare function removeCommand(components?: string[], options?: RemoveOptions): Promise<void>;
9
+ export {};
@@ -0,0 +1,93 @@
1
+ import fs from "fs-extra";
2
+ import path from "node:path";
3
+ import prompts from "prompts";
4
+ import pc from "picocolors";
5
+ import { readConfig } from "../utils/file.js";
6
+ /**
7
+ * Command handler to safely uninstall/remove local Nikala UI components or reactive hooks.
8
+ */
9
+ export async function removeCommand(components = [], options = {}) {
10
+ const cwd = process.cwd();
11
+ const config = await readConfig(cwd);
12
+ if (!config) {
13
+ console.log(pc.red("❌ nikala.config.json not found! Run `nikala init` first."));
14
+ process.exit(1);
15
+ }
16
+ const isHookMode = Boolean(options.hook);
17
+ const targetDir = isHookMode
18
+ ? config.alias.hooks
19
+ ? path.resolve(cwd, config.alias.hooks)
20
+ : path.join(cwd, "src/hooks")
21
+ : path.resolve(cwd, config.alias.components);
22
+ if (!(await fs.pathExists(targetDir))) {
23
+ console.log(pc.yellow(`⚠️ Directory ${targetDir} does not exist.`));
24
+ return;
25
+ }
26
+ // Find installed files in target directory
27
+ const files = await fs.readdir(targetDir);
28
+ const installedItems = [];
29
+ for (const file of files) {
30
+ if (file.endsWith(".tsx") || file.endsWith(".ts")) {
31
+ const name = path.basename(file, path.extname(file));
32
+ if (name !== "index" && name !== "cn") {
33
+ installedItems.push(name);
34
+ }
35
+ }
36
+ }
37
+ if (installedItems.length === 0) {
38
+ console.log(pc.yellow(`\n⚠️ No installed ${isHookMode ? "hooks" : "components"} found to remove.`));
39
+ return;
40
+ }
41
+ let itemsToRemove = [];
42
+ if (options.all || components.includes("all")) {
43
+ itemsToRemove = installedItems;
44
+ }
45
+ else if (components.length > 0) {
46
+ itemsToRemove = components.filter((c) => installedItems.includes(c));
47
+ if (itemsToRemove.length === 0) {
48
+ console.log(pc.red(`❌ None of the specified items (${components.join(", ")}) exist in ${targetDir}`));
49
+ return;
50
+ }
51
+ }
52
+ else {
53
+ const response = await prompts({
54
+ type: "autocompleteMultiselect",
55
+ name: "selectedItems",
56
+ message: `Select ${isHookMode ? "hooks" : "components"} to remove (Space to select, Enter to confirm)`,
57
+ choices: installedItems.map((item) => ({
58
+ title: item,
59
+ value: item,
60
+ })),
61
+ hint: "- Space to select. Return to submit.",
62
+ });
63
+ if (!response.selectedItems || response.selectedItems.length === 0) {
64
+ console.log(pc.yellow(`\n❌ Removal cancelled. No items selected.`));
65
+ return;
66
+ }
67
+ itemsToRemove = response.selectedItems;
68
+ }
69
+ const confirmPrompt = await prompts({
70
+ type: "confirm",
71
+ name: "confirmed",
72
+ message: `Are you sure you want to delete ${itemsToRemove.length} item(s) (${itemsToRemove.join(", ")})?`,
73
+ initial: false,
74
+ });
75
+ if (!confirmPrompt.confirmed) {
76
+ console.log(pc.yellow("\n❌ Removal cancelled."));
77
+ return;
78
+ }
79
+ console.log(pc.cyan(`\n🗑️ Removing items...\n`));
80
+ for (const name of itemsToRemove) {
81
+ const tsxPath = path.join(targetDir, `${name}.tsx`);
82
+ const tsPath = path.join(targetDir, `${name}.ts`);
83
+ if (await fs.pathExists(tsxPath)) {
84
+ await fs.remove(tsxPath);
85
+ console.log(pc.green(` ✓ Removed ${name}.tsx`));
86
+ }
87
+ else if (await fs.pathExists(tsPath)) {
88
+ await fs.remove(tsPath);
89
+ console.log(pc.green(` ✓ Removed ${name}.ts`));
90
+ }
91
+ }
92
+ console.log(pc.green(`\n✅ Successfully removed ${itemsToRemove.length} ${isHookMode ? "hook(s)" : "component(s)"}!`));
93
+ }
@@ -0,0 +1,10 @@
1
+ interface UpgradeOptions {
2
+ all?: boolean;
3
+ overwrite?: boolean;
4
+ }
5
+ /**
6
+ * Command handler to inspect local components/hooks against the latest registry
7
+ * and update them to the latest versions.
8
+ */
9
+ export declare function upgradeCommand(targets?: string[], options?: UpgradeOptions): Promise<void>;
10
+ export {};
@@ -0,0 +1,116 @@
1
+ import fs from "fs-extra";
2
+ import path from "node:path";
3
+ import prompts from "prompts";
4
+ import pc from "picocolors";
5
+ import { readConfig } from "../utils/file.js";
6
+ import { installDependencies } from "../utils/pkg.js";
7
+ import { getRegistryIndex, getRegistryItem } from "../utils/registry.js";
8
+ import { writeComponentFiles } from "../utils/add/write-component-files.js";
9
+ /**
10
+ * Command handler to inspect local components/hooks against the latest registry
11
+ * and update them to the latest versions.
12
+ */
13
+ export async function upgradeCommand(targets = [], options = {}) {
14
+ const cwd = process.cwd();
15
+ const config = await readConfig(cwd);
16
+ if (!config) {
17
+ console.log(pc.red("❌ nikala.config.json not found! Run `nikala init` first."));
18
+ process.exit(1);
19
+ }
20
+ const registryIndex = await getRegistryIndex();
21
+ if (!registryIndex) {
22
+ console.log(pc.red("❌ Failed to fetch registry index. Ensure network connection."));
23
+ process.exit(1);
24
+ }
25
+ const componentsDir = path.resolve(cwd, config.alias.components);
26
+ const hooksDir = config.alias.hooks ? path.resolve(cwd, config.alias.hooks) : path.join(cwd, "src/hooks");
27
+ // Inspect locally installed components and hooks
28
+ const installedItems = [];
29
+ for (const item of registryIndex) {
30
+ const isHook = item.type === "registry:hook";
31
+ const targetDir = isHook ? hooksDir : componentsDir;
32
+ const itemPath = path.join(targetDir, `${item.name}.tsx`);
33
+ const hookItemPath = path.join(targetDir, `${item.name}.ts`);
34
+ if ((await fs.pathExists(itemPath)) || (await fs.pathExists(hookItemPath))) {
35
+ installedItems.push({
36
+ name: item.name,
37
+ type: item.type,
38
+ title: item.title,
39
+ });
40
+ }
41
+ }
42
+ if (installedItems.length === 0) {
43
+ console.log(pc.yellow("\n⚠️ No Nikala UI components or hooks found in your project to upgrade."));
44
+ return;
45
+ }
46
+ let itemsToUpgrade = [];
47
+ if (options.all || targets.includes("all")) {
48
+ itemsToUpgrade = installedItems.map((i) => i.name);
49
+ }
50
+ else if (targets.length > 0) {
51
+ itemsToUpgrade = targets.filter((t) => installedItems.some((i) => i.name === t));
52
+ if (itemsToUpgrade.length === 0) {
53
+ console.log(pc.red(`❌ None of the requested items (${targets.join(", ")}) are installed locally.`));
54
+ return;
55
+ }
56
+ }
57
+ else {
58
+ const response = await prompts({
59
+ type: "autocompleteMultiselect",
60
+ name: "selected",
61
+ message: "Select installed components/hooks to upgrade to latest version",
62
+ choices: installedItems.map((item) => ({
63
+ title: `${item.title} (${item.type === "registry:hook" ? "Hook" : "Component"})`,
64
+ value: item.name,
65
+ selected: true,
66
+ })),
67
+ hint: "- Space to toggle selection. Return to confirm.",
68
+ });
69
+ if (!response.selected || response.selected.length === 0) {
70
+ console.log(pc.yellow("\n❌ Upgrade cancelled. No items selected."));
71
+ return;
72
+ }
73
+ itemsToUpgrade = response.selected;
74
+ }
75
+ // 2. Resolve internal registry component dependencies automatically
76
+ const { resolveRegistryDependencies } = await import("../utils/registry.js");
77
+ const resolvedUpgradeTargets = await resolveRegistryDependencies(itemsToUpgrade);
78
+ console.log(pc.cyan(`\n🔄 Upgrading ${resolvedUpgradeTargets.length} item(s) to latest registry version...\n`));
79
+ const requiredNpmDeps = new Set();
80
+ for (const name of resolvedUpgradeTargets) {
81
+ const item = await getRegistryItem(name);
82
+ if (!item)
83
+ continue;
84
+ const isHook = item.type === "registry:hook";
85
+ const targetDir = isHook ? hooksDir : componentsDir;
86
+ if (item.dependencies) {
87
+ for (const dep of item.dependencies) {
88
+ requiredNpmDeps.add(dep);
89
+ }
90
+ }
91
+ await writeComponentFiles(cwd, item, targetDir, true);
92
+ console.log(pc.green(` ✓ Updated ${name} (${isHook ? "Hook" : "Component"})`));
93
+ }
94
+ // Check npm packages upgrade
95
+ const missingNpmDeps = [];
96
+ const userPkgPath = path.join(cwd, "package.json");
97
+ if (await fs.pathExists(userPkgPath)) {
98
+ try {
99
+ const userPkg = await fs.readJson(userPkgPath);
100
+ const installed = { ...userPkg.dependencies, ...userPkg.devDependencies };
101
+ for (const dep of requiredNpmDeps) {
102
+ if (!installed[dep]) {
103
+ missingNpmDeps.push(dep);
104
+ }
105
+ }
106
+ }
107
+ catch {
108
+ missingNpmDeps.push(...Array.from(requiredNpmDeps));
109
+ }
110
+ }
111
+ if (missingNpmDeps.length > 0) {
112
+ console.log(pc.yellow("\n📦 Installing newly required dependencies..."));
113
+ await installDependencies(missingNpmDeps, cwd);
114
+ }
115
+ console.log(pc.green(`\n✅ Successfully upgraded ${itemsToUpgrade.length} item(s) to latest version!`));
116
+ }
package/dist/index.js CHANGED
@@ -6,14 +6,16 @@ import { add } from "./commands/add.js";
6
6
  import { themeCommand } from "./commands/theme.js";
7
7
  import { validateCommand } from "./commands/validate.js";
8
8
  import { diffCommand } from "./commands/diff.js";
9
- console.log(`\n🎨 ${pc.bold(pc.red("Nikala UI"))} ${pc.dim("v0.9.9")} — SolidJS + Tailwind v4 components`);
9
+ import { upgradeCommand } from "./commands/upgrade.js";
10
+ import { removeCommand } from "./commands/remove.js";
11
+ console.log(`\n🎨 ${pc.bold(pc.red("Nikala UI"))} ${pc.dim("v0.9.10")} — SolidJS + Tailwind v4 components`);
10
12
  console.log(` ${pc.italic(pc.dim("Honoring Niko Pirosmani (Nikala)"))}\n`);
11
13
  console.log(` ${pc.dim("Docs:")} ${pc.underline(pc.cyan("https://nikala.magradze.dev"))}\n`);
12
14
  const program = new Command();
13
15
  program
14
16
  .name("nikala")
15
17
  .description("Nikala UI — SolidJS + Tailwind v4 components")
16
- .version("0.9.9");
18
+ .version("0.9.10");
17
19
  program
18
20
  .command("init")
19
21
  .description("Initialize Nikala UI in your project")
@@ -26,6 +28,22 @@ program
26
28
  .option("--all", "Add all available items")
27
29
  .option("-h, --hook", "Add reactive hook primitive(s) instead of UI components")
28
30
  .action(add);
31
+ // Upgrade / Update command
32
+ program
33
+ .command("upgrade [components...]")
34
+ .alias("update")
35
+ .description("Upgrade locally installed components and hooks to the latest registry version")
36
+ .option("--all", "Upgrade all installed items")
37
+ .action((components, options) => upgradeCommand(components, options));
38
+ // Remove / Uninstall command
39
+ program
40
+ .command("remove [components...]")
41
+ .alias("uninstall")
42
+ .alias("clean")
43
+ .description("Remove or uninstall installed components or reactive hooks from your project")
44
+ .option("-h, --hook", "Remove reactive hook primitive(s) instead of UI components")
45
+ .option("--all", "Remove all installed components or hooks")
46
+ .action((components, options) => removeCommand(components, options));
29
47
  // Parent theme command
30
48
  const themeProg = program
31
49
  .command("theme")
@@ -3,24 +3,43 @@ export interface BasePalette {
3
3
  lightFg: string;
4
4
  darkBg: string;
5
5
  darkFg: string;
6
+ lightCard: string;
7
+ darkCard: string;
8
+ lightPopover: string;
9
+ darkPopover: string;
6
10
  lightMuted: string;
7
11
  lightMutedFg: string;
8
12
  darkMuted: string;
9
13
  darkMutedFg: string;
14
+ lightAccent: string;
15
+ darkAccent: string;
10
16
  lightBorder: string;
11
17
  darkBorder: string;
18
+ lightInput: string;
19
+ darkInput: string;
12
20
  lightRing: string;
13
21
  darkRing: string;
22
+ lightSidebar: string;
23
+ darkSidebar: string;
24
+ lightSidebarBorder: string;
25
+ darkSidebarBorder: string;
14
26
  }
15
27
  export interface PrimaryColor {
16
28
  light: string;
17
29
  dark: string;
18
30
  lightFg: string;
19
31
  darkFg: string;
32
+ charts: {
33
+ chart1: string;
34
+ chart2: string;
35
+ chart3: string;
36
+ chart4: string;
37
+ chart5: string;
38
+ };
20
39
  }
21
40
  export declare const BASE_PALETTES: Record<string, BasePalette>;
22
41
  export declare const PRIMARY_COLORS: Record<string, PrimaryColor>;
23
42
  /**
24
- * Generates Tailwind CSS v4 theme variables based on base palette and primary accent color.
43
+ * Generates Tailwind CSS v4 theme variables matching tweakcn specification.
25
44
  */
26
45
  export declare function generateThemeCss(baseColor?: string, primaryColor?: string): string;
@@ -1,124 +1,244 @@
1
1
  export const BASE_PALETTES = {
2
2
  zinc: {
3
- lightBg: "#ffffff",
4
- lightFg: "#09090b",
5
- darkBg: "#09090b",
6
- darkFg: "#fafafa",
7
- lightMuted: "#f4f4f5",
8
- lightMutedFg: "#71717a",
9
- darkMuted: "#27272a",
10
- darkMutedFg: "#a1a1aa",
11
- lightBorder: "#e4e4e7",
12
- darkBorder: "#27272a",
13
- lightRing: "#18181b",
14
- darkRing: "#d4d4d8",
3
+ lightBg: "oklch(1 0 0)",
4
+ lightFg: "oklch(0.1450 0 0)",
5
+ darkBg: "oklch(0.1450 0 0)",
6
+ darkFg: "oklch(0.9850 0 0)",
7
+ lightCard: "oklch(1 0 0)",
8
+ darkCard: "oklch(0.2050 0 0)",
9
+ lightPopover: "oklch(1 0 0)",
10
+ darkPopover: "oklch(0.2690 0 0)",
11
+ lightMuted: "oklch(0.9700 0 0)",
12
+ lightMutedFg: "oklch(0.5560 0 0)",
13
+ darkMuted: "oklch(0.2690 0 0)",
14
+ darkMutedFg: "oklch(0.7080 0 0)",
15
+ lightAccent: "oklch(0.9700 0 0)",
16
+ darkAccent: "oklch(0.3710 0 0)",
17
+ lightBorder: "oklch(0.9220 0 0)",
18
+ darkBorder: "oklch(0.2750 0 0)",
19
+ lightInput: "oklch(0.9220 0 0)",
20
+ darkInput: "oklch(0.3250 0 0)",
21
+ lightRing: "oklch(0.7080 0 0)",
22
+ darkRing: "oklch(0.5560 0 0)",
23
+ lightSidebar: "oklch(0.9850 0 0)",
24
+ darkSidebar: "oklch(0.2050 0 0)",
25
+ lightSidebarBorder: "oklch(0.9220 0 0)",
26
+ darkSidebarBorder: "oklch(0.2750 0 0)",
15
27
  },
16
28
  slate: {
17
- lightBg: "#ffffff",
18
- lightFg: "#020617",
19
- darkBg: "#020617",
20
- darkFg: "#f8fafc",
21
- lightMuted: "#f1f5f9",
22
- lightMutedFg: "#64748b",
23
- darkMuted: "#1e293b",
24
- darkMutedFg: "#94a3b8",
25
- lightBorder: "#e2e8f0",
26
- darkBorder: "#1e293b",
27
- lightRing: "#0f172a",
28
- darkRing: "#cbd5e1",
29
+ lightBg: "oklch(1 0 0)",
30
+ lightFg: "oklch(0.13 0.028 261.692)",
31
+ darkBg: "oklch(0.13 0.028 261.692)",
32
+ darkFg: "oklch(0.985 0.002 247.839)",
33
+ lightCard: "oklch(1 0 0)",
34
+ darkCard: "oklch(0.18 0.025 261.692)",
35
+ lightPopover: "oklch(1 0 0)",
36
+ darkPopover: "oklch(0.24 0.025 261.692)",
37
+ lightMuted: "oklch(0.965 0.007 247.896)",
38
+ lightMutedFg: "oklch(0.552 0.016 285.938)",
39
+ darkMuted: "oklch(0.24 0.025 261.692)",
40
+ darkMutedFg: "oklch(0.704 0.015 286.067)",
41
+ lightAccent: "oklch(0.965 0.007 247.896)",
42
+ darkAccent: "oklch(0.34 0.025 261.692)",
43
+ lightBorder: "oklch(0.92 0.008 286.32)",
44
+ darkBorder: "oklch(0.27 0.02 261.692)",
45
+ lightInput: "oklch(0.92 0.008 286.32)",
46
+ darkInput: "oklch(0.32 0.02 261.692)",
47
+ lightRing: "oklch(0.7 0.015 286.067)",
48
+ darkRing: "oklch(0.55 0.016 285.938)",
49
+ lightSidebar: "oklch(0.985 0.002 247.839)",
50
+ darkSidebar: "oklch(0.18 0.025 261.692)",
51
+ lightSidebarBorder: "oklch(0.92 0.008 286.32)",
52
+ darkSidebarBorder: "oklch(0.27 0.02 261.692)",
29
53
  },
30
54
  gray: {
31
- lightBg: "#ffffff",
32
- lightFg: "#030712",
33
- darkBg: "#030712",
34
- darkFg: "#f9fafb",
35
- lightMuted: "#f3f4f6",
36
- lightMutedFg: "#6b7280",
37
- darkMuted: "#1f2937",
38
- darkMutedFg: "#9ca3af",
39
- lightBorder: "#e5e7eb",
40
- darkBorder: "#1f2937",
41
- lightRing: "#111827",
42
- darkRing: "#d1d5db",
55
+ lightBg: "oklch(1 0 0)",
56
+ lightFg: "oklch(0.141 0.005 285.823)",
57
+ darkBg: "oklch(0.141 0.005 285.823)",
58
+ darkFg: "oklch(0.985 0 0)",
59
+ lightCard: "oklch(1 0 0)",
60
+ darkCard: "oklch(0.205 0.005 285.823)",
61
+ lightPopover: "oklch(1 0 0)",
62
+ darkPopover: "oklch(0.269 0.005 285.823)",
63
+ lightMuted: "oklch(0.967 0.001 286.375)",
64
+ lightMutedFg: "oklch(0.552 0.016 285.938)",
65
+ darkMuted: "oklch(0.269 0.005 285.823)",
66
+ darkMutedFg: "oklch(0.707 0.004 286.32)",
67
+ lightAccent: "oklch(0.967 0.001 286.375)",
68
+ darkAccent: "oklch(0.371 0.005 285.823)",
69
+ lightBorder: "oklch(0.92 0.004 286.32)",
70
+ darkBorder: "oklch(0.275 0.005 285.823)",
71
+ lightInput: "oklch(0.92 0.004 286.32)",
72
+ darkInput: "oklch(0.325 0.005 285.823)",
73
+ lightRing: "oklch(0.707 0.004 286.32)",
74
+ darkRing: "oklch(0.552 0.016 285.938)",
75
+ lightSidebar: "oklch(0.985 0 0)",
76
+ darkSidebar: "oklch(0.205 0.005 285.823)",
77
+ lightSidebarBorder: "oklch(0.92 0.004 286.32)",
78
+ darkSidebarBorder: "oklch(0.275 0.005 285.823)",
43
79
  },
44
80
  neutral: {
45
- lightBg: "#ffffff",
46
- lightFg: "#0a0a0a",
47
- darkBg: "#0a0a0a",
48
- darkFg: "#fafafa",
49
- lightMuted: "#f5f5f5",
50
- lightMutedFg: "#737373",
51
- darkMuted: "#262626",
52
- darkMutedFg: "#a3a3a3",
53
- lightBorder: "#e5e5e5",
54
- darkBorder: "#262626",
55
- lightRing: "#171717",
56
- darkRing: "#d4d4d4",
81
+ lightBg: "oklch(1 0 0)",
82
+ lightFg: "oklch(0.145 0 0)",
83
+ darkBg: "oklch(0.145 0 0)",
84
+ darkFg: "oklch(0.985 0 0)",
85
+ lightCard: "oklch(1 0 0)",
86
+ darkCard: "oklch(0.205 0 0)",
87
+ lightPopover: "oklch(1 0 0)",
88
+ darkPopover: "oklch(0.269 0 0)",
89
+ lightMuted: "oklch(0.970 0 0)",
90
+ lightMutedFg: "oklch(0.556 0 0)",
91
+ darkMuted: "oklch(0.269 0 0)",
92
+ darkMutedFg: "oklch(0.708 0 0)",
93
+ lightAccent: "oklch(0.970 0 0)",
94
+ darkAccent: "oklch(0.371 0 0)",
95
+ lightBorder: "oklch(0.922 0 0)",
96
+ darkBorder: "oklch(0.275 0 0)",
97
+ lightInput: "oklch(0.922 0 0)",
98
+ darkInput: "oklch(0.325 0 0)",
99
+ lightRing: "oklch(0.708 0 0)",
100
+ darkRing: "oklch(0.556 0 0)",
101
+ lightSidebar: "oklch(0.985 0 0)",
102
+ darkSidebar: "oklch(0.205 0 0)",
103
+ lightSidebarBorder: "oklch(0.922 0 0)",
104
+ darkSidebarBorder: "oklch(0.275 0 0)",
57
105
  },
58
106
  stone: {
59
- lightBg: "#ffffff",
60
- lightFg: "#0c0a09",
61
- darkBg: "#0c0a09",
62
- darkFg: "#fafaf9",
63
- lightMuted: "#f5f5f4",
64
- lightMutedFg: "#78716c",
65
- darkMuted: "#292524",
66
- darkMutedFg: "#a8a29e",
67
- lightBorder: "#e7e5e4",
68
- darkBorder: "#292524",
69
- lightRing: "#1c1917",
70
- darkRing: "#d6d3d1",
107
+ lightBg: "oklch(1 0 0)",
108
+ lightFg: "oklch(0.147 0.004 49.25)",
109
+ darkBg: "oklch(0.147 0.004 49.25)",
110
+ darkFg: "oklch(0.985 0.001 106.423)",
111
+ lightCard: "oklch(1 0 0)",
112
+ darkCard: "oklch(0.216 0.006 56.043)",
113
+ lightPopover: "oklch(1 0 0)",
114
+ darkPopover: "oklch(0.274 0.006 56.043)",
115
+ lightMuted: "oklch(0.967 0.003 91.685)",
116
+ lightMutedFg: "oklch(0.553 0.013 58.071)",
117
+ darkMuted: "oklch(0.274 0.006 56.043)",
118
+ darkMutedFg: "oklch(0.709 0.01 56.259)",
119
+ lightAccent: "oklch(0.967 0.003 91.685)",
120
+ darkAccent: "oklch(0.374 0.007 56.043)",
121
+ lightBorder: "oklch(0.923 0.003 48.717)",
122
+ darkBorder: "oklch(0.279 0.006 56.043)",
123
+ lightInput: "oklch(0.923 0.003 48.717)",
124
+ darkInput: "oklch(0.329 0.006 56.043)",
125
+ lightRing: "oklch(0.709 0.01 56.259)",
126
+ darkRing: "oklch(0.553 0.013 58.071)",
127
+ lightSidebar: "oklch(0.985 0.001 106.423)",
128
+ darkSidebar: "oklch(0.216 0.006 56.043)",
129
+ lightSidebarBorder: "oklch(0.923 0.003 48.717)",
130
+ darkSidebarBorder: "oklch(0.279 0.006 56.043)",
71
131
  },
72
132
  };
73
133
  export const PRIMARY_COLORS = {
74
- wine: { light: "#722f37", dark: "#9e3b47", lightFg: "#ffffff", darkFg: "#ffffff" },
75
- violet: { light: "#7c3aed", dark: "#8b5cf6", lightFg: "#ffffff", darkFg: "#ffffff" },
76
- sky: { light: "#0284c7", dark: "#38bdf8", lightFg: "#ffffff", darkFg: "#0f172a" },
77
- emerald: { light: "#059669", dark: "#34d399", lightFg: "#ffffff", darkFg: "#052e16" },
78
- rose: { light: "#e11d48", dark: "#fb7185", lightFg: "#ffffff", darkFg: "#ffffff" },
79
- amber: { light: "#d97706", dark: "#fbbf24", lightFg: "#ffffff", darkFg: "#111827" },
80
- zinc: { light: "#18181b", dark: "#fafafa", lightFg: "#fafafa", darkFg: "#18181b" },
134
+ wine: {
135
+ light: "oklch(0.4 0.09 15.0)",
136
+ dark: "oklch(0.4 0.09 15.0)",
137
+ lightFg: "oklch(0.9850 0 0)",
138
+ darkFg: "oklch(0.9850 0 0)",
139
+ charts: {
140
+ chart1: "oklch(0.55 0.18 15)",
141
+ chart2: "oklch(0.65 0.15 25)",
142
+ chart3: "oklch(0.45 0.12 350)",
143
+ chart4: "oklch(0.75 0.10 35)",
144
+ chart5: "oklch(0.35 0.08 10)",
145
+ },
146
+ },
147
+ violet: {
148
+ light: "oklch(0.55 0.22 285)",
149
+ dark: "oklch(0.65 0.2 285)",
150
+ lightFg: "oklch(0.9850 0 0)",
151
+ darkFg: "oklch(0.9850 0 0)",
152
+ charts: {
153
+ chart1: "oklch(0.65 0.22 285)",
154
+ chart2: "oklch(0.55 0.19 260)",
155
+ chart3: "oklch(0.75 0.15 310)",
156
+ chart4: "oklch(0.45 0.16 270)",
157
+ chart5: "oklch(0.85 0.10 290)",
158
+ },
159
+ },
160
+ sky: {
161
+ light: "oklch(0.6 0.16 230)",
162
+ dark: "oklch(0.7 0.14 230)",
163
+ lightFg: "oklch(0.9850 0 0)",
164
+ darkFg: "oklch(0.1450 0 0)",
165
+ charts: {
166
+ chart1: "oklch(0.7 0.16 230)",
167
+ chart2: "oklch(0.6 0.14 210)",
168
+ chart3: "oklch(0.5 0.15 250)",
169
+ chart4: "oklch(0.8 0.10 220)",
170
+ chart5: "oklch(0.4 0.12 240)",
171
+ },
172
+ },
173
+ emerald: {
174
+ light: "oklch(0.55 0.18 160)",
175
+ dark: "oklch(0.65 0.16 160)",
176
+ lightFg: "oklch(0.9850 0 0)",
177
+ darkFg: "oklch(0.1450 0 0)",
178
+ charts: {
179
+ chart1: "oklch(0.65 0.18 160)",
180
+ chart2: "oklch(0.55 0.15 140)",
181
+ chart3: "oklch(0.45 0.16 175)",
182
+ chart4: "oklch(0.75 0.12 150)",
183
+ chart5: "oklch(0.35 0.10 165)",
184
+ },
185
+ },
186
+ rose: {
187
+ light: "oklch(0.55 0.22 15)",
188
+ dark: "oklch(0.65 0.2 15)",
189
+ lightFg: "oklch(0.9850 0 0)",
190
+ darkFg: "oklch(0.9850 0 0)",
191
+ charts: {
192
+ chart1: "oklch(0.65 0.22 15)",
193
+ chart2: "oklch(0.55 0.18 350)",
194
+ chart3: "oklch(0.75 0.16 25)",
195
+ chart4: "oklch(0.45 0.15 5)",
196
+ chart5: "oklch(0.85 0.10 30)",
197
+ },
198
+ },
199
+ amber: {
200
+ light: "oklch(0.65 0.18 70)",
201
+ dark: "oklch(0.75 0.16 70)",
202
+ lightFg: "oklch(0.9850 0 0)",
203
+ darkFg: "oklch(0.1450 0 0)",
204
+ charts: {
205
+ chart1: "oklch(0.75 0.18 70)",
206
+ chart2: "oklch(0.65 0.16 50)",
207
+ chart3: "oklch(0.55 0.15 85)",
208
+ chart4: "oklch(0.85 0.12 60)",
209
+ chart5: "oklch(0.45 0.14 75)",
210
+ },
211
+ },
212
+ zinc: {
213
+ light: "oklch(0.2050 0 0)",
214
+ dark: "oklch(0.9850 0 0)",
215
+ lightFg: "oklch(0.9850 0 0)",
216
+ darkFg: "oklch(0.1450 0 0)",
217
+ charts: {
218
+ chart1: "oklch(0.8100 0.1000 252)",
219
+ chart2: "oklch(0.6200 0.1900 260)",
220
+ chart3: "oklch(0.5500 0.2200 263)",
221
+ chart4: "oklch(0.4900 0.2200 264)",
222
+ chart5: "oklch(0.4200 0.1800 266)",
223
+ },
224
+ },
81
225
  };
82
226
  /**
83
- * Generates Tailwind CSS v4 theme variables based on base palette and primary accent color.
227
+ * Generates Tailwind CSS v4 theme variables matching tweakcn specification.
84
228
  */
85
229
  export function generateThemeCss(baseColor = "zinc", primaryColor = "wine") {
86
230
  const base = BASE_PALETTES[baseColor] || BASE_PALETTES.zinc;
87
231
  const primary = PRIMARY_COLORS[primaryColor] || PRIMARY_COLORS.wine;
88
232
  return `@import "tailwindcss";
89
233
 
90
- @theme inline {
91
- --color-background: var(--background);
92
- --color-foreground: var(--foreground);
93
- --color-card: var(--card);
94
- --color-card-foreground: var(--card-foreground);
95
- --color-popover: var(--popover);
96
- --color-popover-foreground: var(--popover-foreground);
97
- --color-primary: var(--primary);
98
- --color-primary-foreground: var(--primary-foreground);
99
- --color-secondary: var(--secondary);
100
- --color-secondary-foreground: var(--secondary-foreground);
101
- --color-muted: var(--muted);
102
- --color-muted-foreground: var(--muted-foreground);
103
- --color-accent: var(--accent);
104
- --color-accent-foreground: var(--accent-foreground);
105
- --color-destructive: var(--destructive);
106
- --color-destructive-foreground: var(--destructive-foreground);
107
- --color-border: var(--border);
108
- --color-input: var(--input);
109
- --color-ring: var(--ring);
110
- --radius-lg: var(--radius);
111
- --radius-md: calc(var(--radius) - 2px);
112
- --radius-sm: calc(var(--radius) - 4px);
113
- }
234
+ @custom-variant dark (&:is(.dark *));
114
235
 
115
236
  :root {
116
- color-scheme: light;
117
237
  --background: ${base.lightBg};
118
238
  --foreground: ${base.lightFg};
119
- --card: ${base.lightBg};
239
+ --card: ${base.lightCard};
120
240
  --card-foreground: ${base.lightFg};
121
- --popover: ${base.lightBg};
241
+ --popover: ${base.lightPopover};
122
242
  --popover-foreground: ${base.lightFg};
123
243
  --primary: ${primary.light};
124
244
  --primary-foreground: ${primary.lightFg};
@@ -126,23 +246,54 @@ export function generateThemeCss(baseColor = "zinc", primaryColor = "wine") {
126
246
  --secondary-foreground: ${base.lightFg};
127
247
  --muted: ${base.lightMuted};
128
248
  --muted-foreground: ${base.lightMutedFg};
129
- --accent: ${base.lightMuted};
249
+ --accent: ${base.lightAccent};
130
250
  --accent-foreground: ${base.lightFg};
131
- --destructive: #ef4444;
132
- --destructive-foreground: #ffffff;
251
+ --destructive: oklch(0.5770 0.2450 27.3250);
252
+ --destructive-foreground: oklch(1 0 0);
133
253
  --border: ${base.lightBorder};
134
- --input: ${base.lightBorder};
254
+ --input: ${base.lightInput};
135
255
  --ring: ${base.lightRing};
136
- --radius: 0.5rem;
256
+ --chart-1: ${primary.charts.chart1};
257
+ --chart-2: ${primary.charts.chart2};
258
+ --chart-3: ${primary.charts.chart3};
259
+ --chart-4: ${primary.charts.chart4};
260
+ --chart-5: ${primary.charts.chart5};
261
+ --sidebar: ${base.lightSidebar};
262
+ --sidebar-foreground: ${base.lightFg};
263
+ --sidebar-primary: ${primary.light};
264
+ --sidebar-primary-foreground: ${primary.lightFg};
265
+ --sidebar-accent: ${base.lightMuted};
266
+ --sidebar-accent-foreground: ${base.lightFg};
267
+ --sidebar-border: ${base.lightSidebarBorder};
268
+ --sidebar-ring: ${base.lightRing};
269
+ --font-sans: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji';
270
+ --font-serif: ui-serif, Georgia, Cambria, "Times New Roman", Times, serif;
271
+ --font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
272
+ --radius: 0.625rem;
273
+ --shadow-x: 0;
274
+ --shadow-y: 1px;
275
+ --shadow-blur: 3px;
276
+ --shadow-spread: 0px;
277
+ --shadow-opacity: 0.1;
278
+ --shadow-color: oklch(0 0 0);
279
+ --shadow-2xs: 0 1px 3px 0px hsl(0 0% 0% / 0.05);
280
+ --shadow-xs: 0 1px 3px 0px hsl(0 0% 0% / 0.05);
281
+ --shadow-sm: 0 1px 3px 0px hsl(0 0% 0% / 0.10), 0 1px 2px -1px hsl(0 0% 0% / 0.10);
282
+ --shadow: 0 1px 3px 0px hsl(0 0% 0% / 0.10), 0 1px 2px -1px hsl(0 0% 0% / 0.10);
283
+ --shadow-md: 0 1px 3px 0px hsl(0 0% 0% / 0.10), 0 2px 4px -1px hsl(0 0% 0% / 0.10);
284
+ --shadow-lg: 0 1px 3px 0px hsl(0 0% 0% / 0.10), 0 4px 6px -1px hsl(0 0% 0% / 0.10);
285
+ --shadow-xl: 0 1px 3px 0px hsl(0 0% 0% / 0.10), 0 8px 10px -1px hsl(0 0% 0% / 0.10);
286
+ --shadow-2xl: 0 1px 3px 0px hsl(0 0% 0% / 0.25);
287
+ --tracking-normal: 0em;
288
+ --spacing: 0.25rem;
137
289
  }
138
290
 
139
291
  .dark {
140
- color-scheme: dark;
141
292
  --background: ${base.darkBg};
142
293
  --foreground: ${base.darkFg};
143
- --card: ${base.darkBg};
294
+ --card: ${base.darkCard};
144
295
  --card-foreground: ${base.darkFg};
145
- --popover: ${base.darkBg};
296
+ --popover: ${base.darkPopover};
146
297
  --popover-foreground: ${base.darkFg};
147
298
  --primary: ${primary.dark};
148
299
  --primary-foreground: ${primary.darkFg};
@@ -150,14 +301,97 @@ export function generateThemeCss(baseColor = "zinc", primaryColor = "wine") {
150
301
  --secondary-foreground: ${base.darkFg};
151
302
  --muted: ${base.darkMuted};
152
303
  --muted-foreground: ${base.darkMutedFg};
153
- --accent: ${base.darkMuted};
304
+ --accent: ${base.darkAccent};
154
305
  --accent-foreground: ${base.darkFg};
155
- --destructive: #7f1d1d;
156
- --destructive-foreground: #ffffff;
306
+ --destructive: oklch(0.7040 0.1910 22.2160);
307
+ --destructive-foreground: ${base.darkFg};
157
308
  --border: ${base.darkBorder};
158
- --input: ${base.darkBorder};
309
+ --input: ${base.darkInput};
159
310
  --ring: ${base.darkRing};
160
- --radius: 0.5rem;
311
+ --chart-1: ${primary.charts.chart1};
312
+ --chart-2: ${primary.charts.chart2};
313
+ --chart-3: ${primary.charts.chart3};
314
+ --chart-4: ${primary.charts.chart4};
315
+ --chart-5: ${primary.charts.chart5};
316
+ --sidebar: ${base.darkSidebar};
317
+ --sidebar-foreground: ${base.darkFg};
318
+ --sidebar-primary: ${primary.dark};
319
+ --sidebar-primary-foreground: ${primary.darkFg};
320
+ --sidebar-accent: ${base.darkMuted};
321
+ --sidebar-accent-foreground: ${base.darkFg};
322
+ --sidebar-border: ${base.darkSidebarBorder};
323
+ --sidebar-ring: ${base.darkRing};
324
+ --font-sans: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji';
325
+ --font-serif: ui-serif, Georgia, Cambria, "Times New Roman", Times, serif;
326
+ --font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
327
+ --radius: 0.625rem;
328
+ --shadow-x: 0;
329
+ --shadow-y: 1px;
330
+ --shadow-blur: 3px;
331
+ --shadow-spread: 0px;
332
+ --shadow-opacity: 0.1;
333
+ --shadow-color: oklch(0 0 0);
334
+ --shadow-2xs: 0 1px 3px 0px hsl(0 0% 0% / 0.05);
335
+ --shadow-xs: 0 1px 3px 0px hsl(0 0% 0% / 0.05);
336
+ --shadow-sm: 0 1px 3px 0px hsl(0 0% 0% / 0.10), 0 1px 2px -1px hsl(0 0% 0% / 0.10);
337
+ --shadow: 0 1px 3px 0px hsl(0 0% 0% / 0.10), 0 1px 2px -1px hsl(0 0% 0% / 0.10);
338
+ --shadow-md: 0 1px 3px 0px hsl(0 0% 0% / 0.10), 0 2px 4px -1px hsl(0 0% 0% / 0.10);
339
+ --shadow-lg: 0 1px 3px 0px hsl(0 0% 0% / 0.10), 0 4px 6px -1px hsl(0 0% 0% / 0.10);
340
+ --shadow-xl: 0 1px 3px 0px hsl(0 0% 0% / 0.10), 0 8px 10px -1px hsl(0 0% 0% / 0.10);
341
+ --shadow-2xl: 0 1px 3px 0px hsl(0 0% 0% / 0.25);
342
+ }
343
+
344
+ @theme inline {
345
+ --color-background: var(--background);
346
+ --color-foreground: var(--foreground);
347
+ --color-card: var(--card);
348
+ --color-card-foreground: var(--card-foreground);
349
+ --color-popover: var(--popover);
350
+ --color-popover-foreground: var(--popover-foreground);
351
+ --color-primary: var(--primary);
352
+ --color-primary-foreground: var(--primary-foreground);
353
+ --color-secondary: var(--secondary);
354
+ --color-secondary-foreground: var(--secondary-foreground);
355
+ --color-muted: var(--muted);
356
+ --color-muted-foreground: var(--muted-foreground);
357
+ --color-accent: var(--accent);
358
+ --color-accent-foreground: var(--accent-foreground);
359
+ --color-destructive: var(--destructive);
360
+ --color-destructive-foreground: var(--destructive-foreground);
361
+ --color-border: var(--border);
362
+ --color-input: var(--input);
363
+ --color-ring: var(--ring);
364
+ --color-chart-1: var(--chart-1);
365
+ --color-chart-2: var(--chart-2);
366
+ --color-chart-3: var(--chart-3);
367
+ --color-chart-4: var(--chart-4);
368
+ --color-chart-5: var(--chart-5);
369
+ --color-sidebar: var(--sidebar);
370
+ --color-sidebar-foreground: var(--sidebar-foreground);
371
+ --color-sidebar-primary: var(--sidebar-primary);
372
+ --color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
373
+ --color-sidebar-accent: var(--sidebar-accent);
374
+ --color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
375
+ --color-sidebar-border: var(--sidebar-border);
376
+ --color-sidebar-ring: var(--sidebar-ring);
377
+
378
+ --font-sans: var(--font-sans);
379
+ --font-mono: var(--font-mono);
380
+ --font-serif: var(--font-serif);
381
+
382
+ --radius-sm: calc(var(--radius) - 4px);
383
+ --radius-md: calc(var(--radius) - 2px);
384
+ --radius-lg: var(--radius);
385
+ --radius-xl: calc(var(--radius) + 4px);
386
+
387
+ --shadow-2xs: var(--shadow-2xs);
388
+ --shadow-xs: var(--shadow-xs);
389
+ --shadow-sm: var(--shadow-sm);
390
+ --shadow: var(--shadow);
391
+ --shadow-md: var(--shadow-md);
392
+ --shadow-lg: var(--shadow-lg);
393
+ --shadow-xl: var(--shadow-xl);
394
+ --shadow-2xl: var(--shadow-2xl);
161
395
  }
162
396
 
163
397
  @layer base {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nikala-ui/cli",
3
- "version": "0.9.9",
3
+ "version": "0.9.10",
4
4
  "description": "Command line interface for Nikala UI",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",