uix-ui 0.1.1 → 0.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 +8 -0
- package/bin/uix-ui.mjs +55 -7
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -19,4 +19,12 @@ import { Button } from "@/components/ui/button";
|
|
|
19
19
|
Dark mode: `<html data-theme="dark">`. Options: `--overwrite` (add), `--no-install` (print the install command
|
|
20
20
|
instead of running it), `--registry <url|folder>` (init).
|
|
21
21
|
|
|
22
|
+
UIX Pro (marketing blocks, nine visual styles, 210 more themes): set your key, then add them by name.
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
export UIX_LICENSE=<your key>
|
|
26
|
+
npx uix-ui@latest add hero pricing-card skins
|
|
27
|
+
npx uix-ui@latest theme acid-prompt
|
|
28
|
+
```
|
|
29
|
+
|
|
22
30
|
Docs, live components and all 42 themes: https://uixdesign.pagestro.com/ui · Source: https://github.com/mdrakibshekh/uix-ui · MIT
|
package/bin/uix-ui.mjs
CHANGED
|
@@ -15,7 +15,8 @@ const HELP = `uix-ui: UIX components and themes for React + Tailwind v4
|
|
|
15
15
|
|
|
16
16
|
--overwrite replace files that already exist (add)
|
|
17
17
|
--no-install don't run the package manager, just print the command
|
|
18
|
-
Pro
|
|
18
|
+
UIX Pro: set UIX_LICENSE=<your key>, then add Pro items by name (hero, pricing-card, skins…) or switch to a
|
|
19
|
+
Pro theme (npx uix-ui theme acid-prompt). \`list\` shows them all.`;
|
|
19
20
|
|
|
20
21
|
const cwd = process.cwd();
|
|
21
22
|
const argv = process.argv.slice(2);
|
|
@@ -54,28 +55,56 @@ function source(cfg, name) {
|
|
|
54
55
|
return { ns, item, url: url.replace('{name}', item), headers: Object.fromEntries(Object.entries(headers).map(([k, v]) => [k, env(v)])) };
|
|
55
56
|
}
|
|
56
57
|
|
|
58
|
+
const PRICING = 'https://uixdesign.pagestro.com/pricing';
|
|
59
|
+
const missing = (src) => Object.assign(new Error(`"${src.item}" is not in the registry (${src.url}).`), { missing: true });
|
|
60
|
+
|
|
57
61
|
async function load(src) {
|
|
58
62
|
if (!/^https?:/.test(src.url)) {
|
|
59
|
-
if (!existsSync(src.url))
|
|
63
|
+
if (!existsSync(src.url)) throw missing(src);
|
|
60
64
|
return JSON.parse(readFileSync(src.url, 'utf8'));
|
|
61
65
|
}
|
|
62
66
|
const res = await fetch(src.url, { headers: src.headers });
|
|
63
|
-
if (res.status === 401
|
|
67
|
+
if (res.status === 401) die(process.env.UIX_LICENSE ? `UIX_LICENSE is set, but that key wasn't found. Check it in your UIX account (${PRICING}).` : `${src.item.startsWith('theme-') ? `The "${src.item.slice(6)}" theme` : `"${src.item}"`} is part of UIX Pro. Set UIX_LICENSE to your key (${PRICING}).`);
|
|
68
|
+
if (res.status === 403) die(`"${src.item}" needs an active UIX Pro licence; this key's plan has ended (${PRICING}).`);
|
|
69
|
+
if (res.status === 404) throw missing(src);
|
|
64
70
|
if (!res.ok) die(`"${src.item}" could not be loaded (${res.status} from ${src.url}).`);
|
|
65
71
|
return res.json();
|
|
66
72
|
}
|
|
67
73
|
|
|
74
|
+
/** The Pro index (names only, no key needed), or null when there is no Pro registry. */
|
|
75
|
+
let proIndex;
|
|
76
|
+
async function loadProIndex(cfg) {
|
|
77
|
+
if (proIndex !== undefined) return proIndex;
|
|
78
|
+
if (!cfg.registries?.['@uix-pro']) return (proIndex = null);
|
|
79
|
+
const ps = source(cfg, '@uix-pro/x');
|
|
80
|
+
return (proIndex = await load({ ...ps, item: 'registry.json', url: ps.url.replace(/\/x\.json$/, '/registry.json'), headers: {} }).catch(() => null));
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/** A bare name that the free registry doesn't have is looked up in Pro (`hero` → `@uix-pro/hero`). */
|
|
84
|
+
async function loadAny(cfg, src) {
|
|
85
|
+
try { return { src, it: await load(src) }; } catch (e) {
|
|
86
|
+
if (!e.missing || src.ns !== '@uix') throw e;
|
|
87
|
+
const index = await loadProIndex(cfg);
|
|
88
|
+
if (!index?.items.some(i => i.name === src.item)) throw Object.assign(new Error(`"${src.item.replace(/^theme-/, '')}" is not a uix-ui component or theme. See the list: npx uix-ui list`), { missing: true });
|
|
89
|
+
const pro = source(cfg, `@uix-pro/${src.item}`);
|
|
90
|
+
return { src: pro, it: await load(pro) };
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
68
94
|
/** Loads the items and everything they depend on, dependencies first. */
|
|
69
95
|
async function resolveAll(cfg, list) {
|
|
70
96
|
const seen = new Map();
|
|
71
97
|
const visit = async (name) => {
|
|
72
|
-
|
|
98
|
+
let src = source(cfg, name);
|
|
73
99
|
const key = `${src.ns}/${src.item}`;
|
|
74
100
|
if (seen.has(key)) return;
|
|
75
101
|
seen.set(key, null);
|
|
76
|
-
const
|
|
102
|
+
const bare = !name.startsWith('@');
|
|
103
|
+
const got = bare ? await loadAny(cfg, src) : { src, it: await load(src) };
|
|
104
|
+
const it = got.it;
|
|
105
|
+
if (got.src !== src) { seen.delete(key); src = got.src; seen.set(`${src.ns}/${src.item}`, null); }
|
|
77
106
|
for (const d of it.registryDependencies ?? []) await visit(d.startsWith('@') ? d : `${src.ns}/${d}`);
|
|
78
|
-
seen.delete(
|
|
107
|
+
seen.delete(`${src.ns}/${src.item}`); seen.set(`${src.ns}/${src.item}`, it);
|
|
79
108
|
};
|
|
80
109
|
for (const n of list) await visit(n);
|
|
81
110
|
return [...seen.values()];
|
|
@@ -102,6 +131,20 @@ function place(cfg, items, overwrite) {
|
|
|
102
131
|
write(file, code);
|
|
103
132
|
say(` wrote ${shown}`);
|
|
104
133
|
}
|
|
134
|
+
for (const it of items) for (const f of it.files) if (/\.css$/.test(f.path) && !/(^|\/)uix\.css$/.test(f.path)) importCss(cfg, target(cfg, f));
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/** Adds `@import "<file>";` to the app's main CSS, after the theme import (visual styles, backdrops). */
|
|
138
|
+
function importCss(cfg, file) {
|
|
139
|
+
const cssFile = join(cwd, cfg.tailwind?.css ?? 'src/index.css');
|
|
140
|
+
if (!existsSync(cssFile)) return;
|
|
141
|
+
let src = readFileSync(cssFile, 'utf8');
|
|
142
|
+
const imp = `@import "${rel(cssFile, file)}";`;
|
|
143
|
+
if (src.includes(imp)) return;
|
|
144
|
+
const last = [...src.matchAll(/@import [^;\n]+;?/g)].pop(); // after the theme and any earlier style sheets
|
|
145
|
+
src = last ? src.slice(0, last.index + last[0].length) + `\n${imp}` + src.slice(last.index + last[0].length) : `${imp}\n${src}`;
|
|
146
|
+
write(cssFile, src);
|
|
147
|
+
say(` updated ${relative(cwd, cssFile)}`);
|
|
105
148
|
}
|
|
106
149
|
|
|
107
150
|
function install(items) {
|
|
@@ -192,7 +235,12 @@ async function main() {
|
|
|
192
235
|
const index = await load({ ...src, item: 'registry.json', url: src.url.replace(/\/r\/x\.json$/, '/registry.json') });
|
|
193
236
|
const comps = index.items.filter(i => i.type === 'registry:ui' && i.name !== 'icons').map(i => i.name);
|
|
194
237
|
const themes = index.items.filter(i => i.name.startsWith('theme')).map(i => i.name === 'theme' ? 'uix' : i.name.slice(6));
|
|
195
|
-
|
|
238
|
+
say(`Components (${comps.length}): ${comps.join(', ')}\n\nThemes (${themes.length}): ${themes.join(', ')}`);
|
|
239
|
+
const pro = await loadProIndex(cfg);
|
|
240
|
+
if (!pro) return;
|
|
241
|
+
const blocks = pro.items.filter(i => !i.name.startsWith('theme-')).map(i => i.name);
|
|
242
|
+
const proThemes = pro.items.filter(i => i.name.startsWith('theme-')).map(i => i.name.slice(6));
|
|
243
|
+
return say(`\nUIX Pro, with UIX_LICENSE (${PRICING}):\n Blocks and styles (${blocks.length}): ${blocks.join(', ')}\n Themes (${proThemes.length}): ${proThemes.join(', ')}`);
|
|
196
244
|
}
|
|
197
245
|
die(`unknown command "${cmd}".\n\n${HELP}`);
|
|
198
246
|
}
|