jixoai-ui 0.0.0 → 0.1.2

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 ADDED
@@ -0,0 +1,24 @@
1
+ # jixoai-ui CLI
2
+
3
+ The official jixoai design-language CLI. It **shares shadcn's
4
+ `components.json`** and extends it with a non-conflicting `jixoai` block:
5
+
6
+ ```jsonc
7
+ {
8
+ // ...shadcn fields stay untouched (style, aliases, registries, ...)...
9
+ "registries": { "@jixoai": "https://ui.jixoai.com/r/{name}.json" },
10
+ "jixoai": { "brandHue": 160 }
11
+ }
12
+ ```
13
+
14
+ ## Usage
15
+
16
+ ```bash
17
+ npx jixoai-ui init --hue 160 # namespace + config + theme + hue, one shot
18
+ npx jixoai-ui add toc # = shadcn add @jixoai/toc, hue re-applied
19
+ npx jixoai-ui hue 165 # retheme by changing one number
20
+ npx jixoai-ui config # print the resolved jixoai config
21
+ ```
22
+
23
+ Requires `components.json` (run `npx shadcn init` first in fresh projects —
24
+ this CLI extends shadcn's config, it never replaces it).
@@ -0,0 +1,172 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * jixoai-ui — the official jixoai design-language CLI (bin/jixoai-ui.mjs).
4
+ *
5
+ * Orthogonal intents (2026-08-20): components.json extension management;
6
+ * brand-hue application; registry add delegation.
7
+ *
8
+ * Config contract (Owner decision, 2026-08-20): the CLI SHARES shadcn's
9
+ * components.json and extends it with a non-conflicting `jixoai` object:
10
+ *
11
+ * {
12
+ * ...shadcn fields (style, aliases, registries, ...) untouched...,
13
+ * "registries": { "@jixoai": "https://ui.jixoai.com/r/{name}.json" },
14
+ * "jixoai": { "brandHue": 160 }
15
+ * }
16
+ *
17
+ * The registry URL points at the official Pages-hosted registry; hue lives
18
+ * in ONE config field and is written into the installed jixoai.css
19
+ * (--brand-hue) on every init/add/hue run.
20
+ */
21
+
22
+ import { spawnSync } from "node:child_process";
23
+ import { existsSync, readFileSync, writeFileSync } from "node:fs";
24
+ import { join, resolve } from "node:path";
25
+ import process from "node:process";
26
+
27
+ const REGISTRY_URL = "https://ui.jixoai.com/r/{name}.json";
28
+ const NAMESPACE = "@jixoai";
29
+ const THEME_ITEM = "jixoai-theme";
30
+ const DEFAULT_HUE = 0;
31
+
32
+ const USAGE = `jixoai-ui — the jixoai design language CLI
33
+
34
+ Commands:
35
+ jixoai-ui init [--hue <degrees>] register the @jixoai namespace, add the
36
+ jixoai config block, install the theme,
37
+ and apply the brand hue
38
+ jixoai-ui hue <degrees> set the project brand hue (config + css)
39
+ jixoai-ui add <item...> install registry items (delegates to
40
+ \`shadcn add ${NAMESPACE}/<item>\`), then
41
+ re-applies the brand hue
42
+ jixoai-ui config print the resolved jixoai config
43
+
44
+ The CLI extends shadcn's components.json — run \`npx shadcn init\` first in
45
+ projects that don't have one yet.`;
46
+
47
+ function fail(message) {
48
+ console.error(`jixoai-ui: ${message}`);
49
+ process.exit(1);
50
+ }
51
+
52
+ function readConfig(cwd) {
53
+ const path = join(cwd, "components.json");
54
+ if (!existsSync(path)) {
55
+ fail(
56
+ "components.json not found. Run `npx shadcn init` first — this CLI extends shadcn's config, it does not replace it.",
57
+ );
58
+ }
59
+ return { path, config: JSON.parse(readFileSync(path, "utf8")) };
60
+ }
61
+
62
+ function writeConfig(path, config) {
63
+ writeFileSync(path, JSON.stringify(config, null, 2) + "\n");
64
+ }
65
+
66
+ function ensureNamespace(config) {
67
+ config.registries ??= {};
68
+ config.registries[NAMESPACE] ??= REGISTRY_URL;
69
+ if (config.registries[NAMESPACE] !== REGISTRY_URL) {
70
+ console.warn(
71
+ `jixoai-ui: keeping existing ${NAMESPACE} registry url (${config.registries[NAMESPACE]})`,
72
+ );
73
+ }
74
+ }
75
+
76
+ function themeCssPath(config, cwd) {
77
+ const lib = config.aliases?.lib;
78
+ if (typeof lib !== "string") return null;
79
+ const candidates = [resolve(cwd, lib, "jixoai.css"), resolve(cwd, `${lib}.css`)];
80
+ for (const candidate of candidates) {
81
+ if (existsSync(candidate)) return candidate;
82
+ }
83
+ return null;
84
+ }
85
+
86
+ function applyHue(cssPath, hue) {
87
+ if (!cssPath) {
88
+ console.warn(
89
+ "jixoai-ui: jixoai.css not found yet — the hue will be applied on the next init/add.",
90
+ );
91
+ return;
92
+ }
93
+ const css = readFileSync(cssPath, "utf8");
94
+ const next = css.replace(/--brand-hue:\s*[\d.]+/, `--brand-hue: ${hue}`);
95
+ if (next !== css) {
96
+ writeFileSync(cssPath, next);
97
+ console.log(`jixoai-ui: --brand-hue: ${hue} → ${cssPath}`);
98
+ }
99
+ }
100
+
101
+ function shadcn(args, cwd, configPath, config) {
102
+ // shadcn 4.18 rejects unknown top-level keys (our jixoai block), so the
103
+ // extension fields are stripped for the call and restored afterwards.
104
+ const { jixoai, ...rest } = config;
105
+ writeConfig(configPath, rest);
106
+ const result = spawnSync(
107
+ "npx",
108
+ ["--yes", "shadcn", ...args, "--yes"],
109
+ { stdio: "inherit", cwd, env: { ...process.env, npm_config_yes: "true" } },
110
+ );
111
+ if (result.status !== 0) {
112
+ writeConfig(configPath, config); // restore even on failure
113
+ fail(`\`shadcn ${args.join(" ")}\` exited with ${result.status}`);
114
+ }
115
+ const after = readConfig(cwd);
116
+ after.config.jixoai = jixoai;
117
+ writeConfig(after.path, after.config);
118
+ }
119
+
120
+ function hueFromArgs(args, fallback = DEFAULT_HUE) {
121
+ // accepts --hue <n> OR a bare positional degree value
122
+ const positional = args.find((a, i) => i > 0 && Number.isFinite(Number(a)));
123
+ const index = args.indexOf("--hue");
124
+ const value = index !== -1 ? Number(args[index + 1]) : (positional !== undefined ? Number(positional) : fallback);
125
+ if (!Number.isFinite(value) || value < 0 || value >= 360) {
126
+ fail("hue must be a number in [0, 360)");
127
+ }
128
+ return Math.round(value);
129
+ }
130
+
131
+ const [command, ...rest] = process.argv.slice(2);
132
+ const cwd = process.cwd();
133
+
134
+ switch (command) {
135
+ case "init": {
136
+ const { path, config } = readConfig(cwd);
137
+ const hue = hueFromArgs(rest, config.jixoai?.brandHue ?? DEFAULT_HUE);
138
+ ensureNamespace(config);
139
+ config.jixoai = { ...(config.jixoai ?? {}), brandHue: hue };
140
+ writeConfig(path, config);
141
+ console.log(`jixoai-ui: ${NAMESPACE} namespace + jixoai config written → ${path}`);
142
+ shadcn(["add", `${NAMESPACE}/${THEME_ITEM}`], cwd, path, config);
143
+ applyHue(themeCssPath(config, cwd), hue);
144
+ break;
145
+ }
146
+ case "hue": {
147
+ const hue = hueFromArgs(["--hue", rest[0]]);
148
+ const { path, config } = readConfig(cwd);
149
+ config.jixoai = { ...(config.jixoai ?? {}), brandHue: hue };
150
+ writeConfig(path, config);
151
+ applyHue(themeCssPath(config, cwd), hue);
152
+ break;
153
+ }
154
+ case "add": {
155
+ if (rest.length === 0) fail("add needs at least one item name (e.g. `toc`)");
156
+ const { path, config } = readConfig(cwd);
157
+ const hue = config.jixoai?.brandHue ?? DEFAULT_HUE;
158
+ for (const item of rest) {
159
+ shadcn(["add", `${NAMESPACE}/${item}`], cwd, path, readConfig(cwd).config);
160
+ }
161
+ applyHue(themeCssPath(config, cwd), hue);
162
+ break;
163
+ }
164
+ case "config": {
165
+ const { config } = readConfig(cwd);
166
+ console.log(JSON.stringify({ registry: REGISTRY_URL, ...config.jixoai }, null, 2));
167
+ break;
168
+ }
169
+ default:
170
+ console.log(USAGE);
171
+ process.exit(command && command !== "help" && command !== "--help" ? 1 : 0);
172
+ }
package/package.json CHANGED
@@ -1,9 +1,32 @@
1
1
  {
2
2
  "name": "jixoai-ui",
3
- "version": "0.0.0",
4
- "description": "Generated placeholder package reserved by pnpm-pub.",
5
- "main": "index.js",
3
+ "version": "0.1.2",
4
+ "description": "Official jixoai design-language CLI: initializes the @jixoai shadcn registry namespace, manages the jixoai extension fields in components.json, and applies the per-project brand hue.",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "bin": {
8
+ "jixoai-ui": "./bin/jixoai-ui.mjs"
9
+ },
6
10
  "files": [
7
- "index.js"
8
- ]
11
+ "bin/",
12
+ "README.md"
13
+ ],
14
+ "engines": {
15
+ "node": ">=20"
16
+ },
17
+ "keywords": [
18
+ "jixoai",
19
+ "shadcn",
20
+ "registry",
21
+ "cli",
22
+ "design-system"
23
+ ],
24
+ "publishConfig": {
25
+ "access": "public"
26
+ },
27
+ "repository": {
28
+ "type": "git",
29
+ "url": "https://github.com/jixoai/ui",
30
+ "directory": "cli"
31
+ }
9
32
  }
package/index.js DELETED
@@ -1 +0,0 @@
1
- module.exports = {};