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 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 DEFAULT_REGISTRY = 'https://uixdesign.pagestro.com/ui/r';
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
- '@uix-pro': { url: `${registry.replace(/\/r$/, '/r/pro')}/{name}.json`, headers: { Authorization: 'Bearer ${UIX_LICENSE}' } },
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
- say(`\nDone. Next: npx uix-ui add button card input\nDark mode: <html data-theme="dark">. Other presets: npx uix-ui theme <preset>.`);
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(', ')}`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "uix-ui",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "Add UIX components and themes to your React + Tailwind app: npx uix-ui init.",
5
5
  "license": "MIT",
6
6
  "type": "module",