uix-ui 0.2.0 → 0.3.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 +10 -0
- package/bin/uix-ui.mjs +45 -8
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -27,4 +27,14 @@ npx uix-ui@latest add hero pricing-card skins
|
|
|
27
27
|
npx uix-ui@latest theme acid-prompt
|
|
28
28
|
```
|
|
29
29
|
|
|
30
|
+
Your own design system, made at [uixdesign.pagestro.com/generate](https://uixdesign.pagestro.com/generate) and saved to
|
|
31
|
+
your account: pull its theme, tokens (DTCG, in `src/styles/tokens`) and any components, then sync when it changes.
|
|
32
|
+
The API key is on your account page. `uix.json` remembers the system and the version you have.
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
export UIX_API_KEY=uixm_…
|
|
36
|
+
npx uix-ui@latest pull <id> button card # the id is in your Studio link: /s/<id>
|
|
37
|
+
npx uix-ui@latest sync # pulls again only if you saved a newer version
|
|
38
|
+
```
|
|
39
|
+
|
|
30
40
|
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
|
@@ -5,16 +5,21 @@ import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
|
5
5
|
import { dirname, join, relative, resolve, sep } from 'node:path';
|
|
6
6
|
import { spawnSync } from 'node:child_process';
|
|
7
7
|
|
|
8
|
-
const
|
|
8
|
+
const SITE = 'https://uixdesign.pagestro.com';
|
|
9
|
+
const DEFAULT_REGISTRY = `${SITE}/ui/r`;
|
|
9
10
|
const HELP = `uix-ui: UIX components and themes for React + Tailwind v4
|
|
10
11
|
|
|
11
12
|
npx uix-ui init [--preset <id>] [--registry <url|folder>] set up the theme, utils and components.json
|
|
12
13
|
npx uix-ui add <component...> copy components into your app
|
|
13
14
|
npx uix-ui theme <preset> switch to another UIX preset (uix = default)
|
|
14
15
|
npx uix-ui list components and themes in the registry
|
|
16
|
+
npx uix-ui pull <id> [component...] your saved design system (uixdesign.pagestro.com/s/<id>):
|
|
17
|
+
its theme, tokens and components; remembered in uix.json
|
|
18
|
+
npx uix-ui sync pull again if the system changed since the last pull
|
|
15
19
|
|
|
16
20
|
--overwrite replace files that already exist (add)
|
|
17
21
|
--no-install don't run the package manager, just print the command
|
|
22
|
+
pull, sync: set UIX_API_KEY (or --key) to the API key from your account page (uixdesign.pagestro.com/account).
|
|
18
23
|
UIX Pro: set UIX_LICENSE=<your key>, then add Pro items by name (hero, pricing-card, skins…) or switch to a
|
|
19
24
|
Pro theme (npx uix-ui theme acid-prompt). \`list\` shows them all.`;
|
|
20
25
|
|
|
@@ -27,7 +32,7 @@ const flag = (n, bool = false) => {
|
|
|
27
32
|
argv.splice(i, takes ? 2 : 1);
|
|
28
33
|
return takes ? v : true;
|
|
29
34
|
};
|
|
30
|
-
const opts = { preset: flag('preset'), registry: flag('registry'), overwrite: flag('overwrite', true), noInstall: flag('no-install', true) };
|
|
35
|
+
const opts = { preset: flag('preset'), registry: flag('registry'), overwrite: flag('overwrite', true), noInstall: flag('no-install', true), key: flag('key'), site: flag('site') };
|
|
31
36
|
const [cmd, ...names] = argv;
|
|
32
37
|
|
|
33
38
|
const say = (s) => console.log(s);
|
|
@@ -56,6 +61,7 @@ function source(cfg, name) {
|
|
|
56
61
|
}
|
|
57
62
|
|
|
58
63
|
const PRICING = 'https://uixdesign.pagestro.com/pricing';
|
|
64
|
+
let pin = ''; // pull: `?v=<version>`, so the site answers with that version, not a copy cached a few seconds ago
|
|
59
65
|
const missing = (src) => Object.assign(new Error(`"${src.item}" is not in the registry (${src.url}).`), { missing: true });
|
|
60
66
|
|
|
61
67
|
async function load(src) {
|
|
@@ -63,7 +69,7 @@ async function load(src) {
|
|
|
63
69
|
if (!existsSync(src.url)) throw missing(src);
|
|
64
70
|
return JSON.parse(readFileSync(src.url, 'utf8'));
|
|
65
71
|
}
|
|
66
|
-
const res = await fetch(src.url, { headers: src.headers });
|
|
72
|
+
const res = await fetch(src.url + pin, { headers: src.headers });
|
|
67
73
|
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
74
|
if (res.status === 403) die(`"${src.item}" needs an active UIX Pro licence; this key's plan has ended (${PRICING}).`);
|
|
69
75
|
if (res.status === 404) throw missing(src);
|
|
@@ -103,7 +109,7 @@ async function resolveAll(cfg, list) {
|
|
|
103
109
|
const got = bare ? await loadAny(cfg, src) : { src, it: await load(src) };
|
|
104
110
|
const it = got.it;
|
|
105
111
|
if (got.src !== src) { seen.delete(key); src = got.src; seen.set(`${src.ns}/${src.item}`, null); }
|
|
106
|
-
for (const d of it.registryDependencies ?? []) await visit(d.startsWith('@') ? d : `${src.ns}/${d}`);
|
|
112
|
+
for (const d of it.registryDependencies ?? []) await visit(d.startsWith('@') ? d : `${src.ns}/${/^https?:/.test(d) ? d.split('/').pop().replace(/\.json$/, '') : d}`);
|
|
107
113
|
seen.delete(`${src.ns}/${src.item}`); seen.set(`${src.ns}/${src.item}`, it);
|
|
108
114
|
};
|
|
109
115
|
for (const n of list) await visit(n);
|
|
@@ -199,7 +205,8 @@ async function init() {
|
|
|
199
205
|
cfg.registries = {
|
|
200
206
|
...cfg.registries,
|
|
201
207
|
'@uix': `${registry}/{name}.json`,
|
|
202
|
-
|
|
208
|
+
// a saved system's registry (/r/<id>) already has the owner's Pro items
|
|
209
|
+
...(/\/r$/.test(registry) && { '@uix-pro': { url: `${registry.replace(/\/r$/, '/r/pro')}/{name}.json`, headers: { Authorization: 'Bearer ${UIX_LICENSE}' } } }),
|
|
203
210
|
};
|
|
204
211
|
write(join(cwd, 'components.json'), JSON.stringify(cfg, null, 2) + '\n');
|
|
205
212
|
say(' wrote components.json');
|
|
@@ -216,12 +223,42 @@ async function init() {
|
|
|
216
223
|
const items = await resolveAll(cfg, ['utils']);
|
|
217
224
|
place(cfg, items, false);
|
|
218
225
|
install(items);
|
|
219
|
-
|
|
226
|
+
return cfg;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/** Your saved system, through the account API (the key proves it's yours): { id, name, version, … }. */
|
|
230
|
+
async function system(site, id) {
|
|
231
|
+
const key = opts.key ?? process.env.UIX_API_KEY;
|
|
232
|
+
if (!key) die(`set UIX_API_KEY (or --key) to the API key from ${site}/account.`);
|
|
233
|
+
const res = await fetch(`${site}/api/me/systems/${id}`, { headers: { Authorization: `Bearer ${key}` } }).catch(e => die(`could not reach ${site} (${e.cause?.code ?? e.message}).`));
|
|
234
|
+
if (res.status === 401) die(`that API key wasn't accepted. Make a new one at ${site}/account.`);
|
|
235
|
+
if (res.status === 404) die(`there's no design system "${id}" in your account (${site}/account#systems).`);
|
|
236
|
+
if (!res.ok) die(`could not load "${id}" (${res.status} from ${site}).`);
|
|
237
|
+
return (await res.json()).system;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
/** pull: the system's theme, its DTCG tokens and any named components; sync: the same, only when the version moved. */
|
|
241
|
+
async function pull(id, names) {
|
|
242
|
+
const saved = existsSync(join(cwd, 'uix.json')) ? readJson('uix.json') : {};
|
|
243
|
+
id ??= saved.system;
|
|
244
|
+
if (!id) die(cmd === 'sync' ? 'nothing to sync yet. Run `npx uix-ui pull <id>` first (the id is in your Studio link, /s/<id>).' : 'name the design system, e.g. `npx uix-ui pull k3x9d0a2bq` (the id is in your Studio link, /s/<id>).');
|
|
245
|
+
const site = (opts.site ?? saved.site ?? SITE).replace(/\/$/, '');
|
|
246
|
+
const sys = await system(site, id);
|
|
247
|
+
if (cmd === 'sync' && sys.version === saved.version && id === saved.system) return say(`Up to date: "${sys.name}", version ${sys.version}.`);
|
|
248
|
+
pin = `?v=${sys.version}`;
|
|
249
|
+
opts.registry = `${site}/r/${id}`;
|
|
250
|
+
const cfg = await init();
|
|
251
|
+
const tokens = await load({ item: 'tokens', url: `${site}/s/${id}.json`, headers: {} });
|
|
252
|
+
for (const [name, t] of Object.entries(tokens)) { write(join(srcRoot, 'styles', name), JSON.stringify(t, null, 2) + '\n'); say(` wrote ${relative(cwd, join(srcRoot, 'styles', name))}`); }
|
|
253
|
+
if (names.length) { const items = await resolveAll(cfg, names); place(cfg, items, !!opts.overwrite); install(items); }
|
|
254
|
+
write(join(cwd, 'uix.json'), JSON.stringify({ system: id, name: sys.name, version: sys.version, site: site === SITE ? undefined : site }, null, 2) + '\n');
|
|
255
|
+
say(`\n"${sys.name}", version ${sys.version}${saved.version && saved.system === id ? ` (was ${saved.version})` : ''}. Later changes: npx uix-ui sync`);
|
|
220
256
|
}
|
|
221
257
|
|
|
222
258
|
async function main() {
|
|
223
259
|
if (!cmd || cmd === 'help' || cmd === '--help' || cmd === '-h') return say(HELP);
|
|
224
|
-
if (cmd === 'init') return init();
|
|
260
|
+
if (cmd === 'init') return init().then(() => say(`\nDone. Next: npx uix-ui add button card input\nDark mode: <html data-theme="dark">. Other presets: npx uix-ui theme <preset>.`));
|
|
261
|
+
if (cmd === 'pull' || cmd === 'sync') return pull(cmd === 'pull' ? names[0] : undefined, names.slice(1));
|
|
225
262
|
const cfg = config();
|
|
226
263
|
if (cmd === 'add') {
|
|
227
264
|
if (!names.length) die('name at least one component, e.g. `npx uix-ui add button`.');
|
|
@@ -232,7 +269,7 @@ async function main() {
|
|
|
232
269
|
if (cmd === 'theme') return applyTheme(cfg, names[0] ?? opts.preset);
|
|
233
270
|
if (cmd === 'list') {
|
|
234
271
|
const src = source(cfg, 'x');
|
|
235
|
-
const index = await load({ ...src, item: 'registry.json', url: src.url.replace(/\/r\/x\.json$/, '/registry.json') });
|
|
272
|
+
const index = await load({ ...src, item: 'registry.json', url: src.url.replace(/\/r\/x\.json$/, '/registry.json').replace(/\/x\.json$/, '/registry.json') });
|
|
236
273
|
const comps = index.items.filter(i => i.type === 'registry:ui' && i.name !== 'icons').map(i => i.name);
|
|
237
274
|
const themes = index.items.filter(i => i.name.startsWith('theme')).map(i => i.name === 'theme' ? 'uix' : i.name.slice(6));
|
|
238
275
|
say(`Components (${comps.length}): ${comps.join(', ')}\n\nThemes (${themes.length}): ${themes.join(', ')}`);
|