plankui 0.1.2 → 0.1.3
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 +6 -3
- package/index.mjs +39 -4
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -37,7 +37,7 @@ npx plankui@latest init
|
|
|
37
37
|
npx plankui@latest add button select dialog
|
|
38
38
|
```
|
|
39
39
|
|
|
40
|
-
That's it. `init` sets up the design tokens once, and `add` drops each component into `components/ui`, together with every PlankUI file it builds on and the npm packages it needs.
|
|
40
|
+
That's it. `init` asks whether to build on **Radix UI or Base UI** and sets up the design tokens once, and `add` drops each component into `components/ui`, together with every PlankUI file it builds on and the npm packages it needs.
|
|
41
41
|
|
|
42
42
|
```tsx
|
|
43
43
|
import { Button } from "@/components/ui/button";
|
|
@@ -51,6 +51,7 @@ export function Save() {
|
|
|
51
51
|
|
|
52
52
|
- **You own the code.** Components land in your repo as plain TypeScript. Read them, change any line, never wait on a package upgrade.
|
|
53
53
|
- **Beautiful by default.** Six themes and five component styles (Soft, Flat, Liquid glass, Keycap, Brutal), in light and dark, from one tokens file.
|
|
54
|
+
- **Radix UI or Base UI.** Every component built on primitives comes in both, with the same props. Choose once at `init`.
|
|
54
55
|
- **Accessible.** Keyboard support, focus rings, ARIA roles and reduced motion handled for you.
|
|
55
56
|
- **Agent ready.** The [PlankUI MCP server](https://www.npmjs.com/package/@plankui/mcp) gives Cursor, Claude Code, VS Code and other agents the real source of every component.
|
|
56
57
|
|
|
@@ -58,7 +59,7 @@ export function Save() {
|
|
|
58
59
|
|
|
59
60
|
| Command | What it does |
|
|
60
61
|
| --- | --- |
|
|
61
|
-
| `plankui init` |
|
|
62
|
+
| `plankui init` | Asks Radix UI or Base UI (saved in `plankui.json`), writes `tokens.css`, `styles.css` and the `cn` helper, and installs `clsx` and `tailwind-merge` |
|
|
62
63
|
| `plankui add <names…>` | Copies components and the PlankUI files they build on, then installs their npm packages |
|
|
63
64
|
| `plankui list` | Lists every component you can add |
|
|
64
65
|
|
|
@@ -69,6 +70,7 @@ export function Save() {
|
|
|
69
70
|
| `--yes`, `-y` | Answer every prompt with its default and keep files that already exist. Use it in CI and for coding agents |
|
|
70
71
|
| `--overwrite` | Replace files that already exist |
|
|
71
72
|
| `--no-install` | Write the files but skip installing npm packages |
|
|
73
|
+
| `--base`, `--radix` | Use Base UI or Radix UI primitives for this run, whatever `plankui.json` says |
|
|
72
74
|
| `--cwd <dir>` | Run in another folder |
|
|
73
75
|
| `--registry <url>` | Read components from another registry |
|
|
74
76
|
|
|
@@ -76,7 +78,7 @@ The CLI picks your package manager (npm, pnpm, yarn or bun) from your lockfile,
|
|
|
76
78
|
|
|
77
79
|
## Components
|
|
78
80
|
|
|
79
|
-
|
|
81
|
+
43 components today, with more every week.
|
|
80
82
|
|
|
81
83
|
| | |
|
|
82
84
|
| --- | --- |
|
|
@@ -86,6 +88,7 @@ The CLI picks your package manager (npm, pnpm, yarn or bun) from your lockfile,
|
|
|
86
88
|
| **Feedback** | [Toast](https://plankui.com/docs/components/toast), [Alert](https://plankui.com/docs/components/alert), [Progress](https://plankui.com/docs/components/progress), [Skeleton](https://plankui.com/docs/components/skeleton), [Spinner](https://plankui.com/docs/components/spinner) |
|
|
87
89
|
| **Display** | [Card](https://plankui.com/docs/components/card), [Avatar](https://plankui.com/docs/components/avatar), [Badge](https://plankui.com/docs/components/badge), [Kbd](https://plankui.com/docs/components/kbd), [Separator](https://plankui.com/docs/components/separator), [Table](https://plankui.com/docs/components/table) |
|
|
88
90
|
| **Navigation** | [Tabs](https://plankui.com/docs/components/tabs), [Accordion](https://plankui.com/docs/components/accordion), [Breadcrumb](https://plankui.com/docs/components/breadcrumb), [Pagination](https://plankui.com/docs/components/pagination) |
|
|
91
|
+
| **Charts** | [Bar chart](https://plankui.com/docs/components/bar-chart), [Line chart](https://plankui.com/docs/components/line-chart), [Sparkline](https://plankui.com/docs/components/sparkline), [Bar list](https://plankui.com/docs/components/bar-list), [Stage bars](https://plankui.com/docs/components/stage-bars), [Chart card](https://plankui.com/docs/components/chart-card), [Steps card](https://plankui.com/docs/components/steps-card), [Most active days](https://plankui.com/docs/components/active-days-card) |
|
|
89
92
|
|
|
90
93
|
## Themes and styles
|
|
91
94
|
|
package/index.mjs
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
//
|
|
5
5
|
// npx plankui@latest init
|
|
6
6
|
// npx plankui@latest add button select dialog
|
|
7
|
+
// npx plankui@latest add select --base (the Base UI version)
|
|
7
8
|
// npx plankui@latest list
|
|
8
9
|
// npx plankui@latest login YOUR_LICENSE_KEY
|
|
9
10
|
import { existsSync, lstatSync, mkdirSync, readFileSync, realpathSync, rmSync, writeFileSync } from "node:fs";
|
|
@@ -12,7 +13,7 @@ import { dirname, isAbsolute, join, relative, resolve, sep } from "node:path";
|
|
|
12
13
|
import { spawnSync } from "node:child_process";
|
|
13
14
|
import { createInterface } from "node:readline/promises";
|
|
14
15
|
|
|
15
|
-
const VERSION = "0.1.
|
|
16
|
+
const VERSION = "0.1.3";
|
|
16
17
|
const DEFAULT_REGISTRY = "https://plankui.com/r";
|
|
17
18
|
|
|
18
19
|
/* ── Arguments ── */
|
|
@@ -31,6 +32,8 @@ const yes = flags.has("--yes") || flags.has("-y");
|
|
|
31
32
|
const overwrite = flags.has("--overwrite");
|
|
32
33
|
const skipInstall = flags.has("--no-install");
|
|
33
34
|
const cwd = opt("cwd", process.cwd());
|
|
35
|
+
/** Primitives asked for on this run: --base or --radix. Otherwise plankui.json decides. */
|
|
36
|
+
const libFlag = flags.has("--base") ? "base" : flags.has("--radix") ? "radix" : null;
|
|
34
37
|
const registry = (opt("registry", process.env.PLANKUI_REGISTRY) ?? DEFAULT_REGISTRY).replace(/\/$/, "");
|
|
35
38
|
|
|
36
39
|
/* ── Output ── */
|
|
@@ -53,6 +56,29 @@ async function confirm(question, fallback) {
|
|
|
53
56
|
return answer ? answer.startsWith("y") : fallback;
|
|
54
57
|
}
|
|
55
58
|
|
|
59
|
+
/** Pick one of two answers. With --yes or no terminal, takes the first. */
|
|
60
|
+
async function choose(question, options) {
|
|
61
|
+
if (yes || !process.stdin.isTTY) return options[0].value;
|
|
62
|
+
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
63
|
+
say(question);
|
|
64
|
+
options.forEach((o, i) => say(` ${i + 1}. ${o.label}${i === 0 ? dim(" (default)") : ""}`));
|
|
65
|
+
const answer = (await rl.question(dim("Choose 1 or 2: "))).trim();
|
|
66
|
+
rl.close();
|
|
67
|
+
return options[Number(answer) - 1]?.value ?? options[0].value;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/* ── Project settings: plankui.json ── */
|
|
71
|
+
const settingsFile = () => join(cwd, "plankui.json");
|
|
72
|
+
function settings() {
|
|
73
|
+
try {
|
|
74
|
+
return JSON.parse(readFileSync(settingsFile(), "utf8"));
|
|
75
|
+
} catch {
|
|
76
|
+
return {};
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
/** "radix" or "base": the flag, then plankui.json, then Radix. */
|
|
80
|
+
const primitives = () => libFlag ?? (settings().primitives === "base" ? "base" : "radix");
|
|
81
|
+
|
|
56
82
|
/* ── Project ── */
|
|
57
83
|
function project() {
|
|
58
84
|
const pkgPath = join(cwd, "package.json");
|
|
@@ -207,6 +233,12 @@ async function init() {
|
|
|
207
233
|
say(bold("PlankUI") + dim(` init, into ${relative(cwd, base) || "."}`));
|
|
208
234
|
if (!deps.tailwindcss) say(`${yellow("note")} Tailwind CSS v4 is not in package.json. PlankUI needs it: see the framework guides.`);
|
|
209
235
|
if (!deps.react) fail("React is not in package.json. PlankUI is for React 19 projects.");
|
|
236
|
+
const lib = libFlag ?? (await choose("Which primitives should the components use?", [
|
|
237
|
+
{ value: "radix", label: "Radix UI" },
|
|
238
|
+
{ value: "base", label: "Base UI" },
|
|
239
|
+
]));
|
|
240
|
+
writeFileSync(settingsFile(), JSON.stringify({ ...settings(), primitives: lib }, null, 2) + "\n");
|
|
241
|
+
say(`${green("saved")} plankui.json ${dim(`(components use ${lib === "base" ? "Base UI" : "Radix UI"})`)}`);
|
|
210
242
|
const spec = await fetchJson("init");
|
|
211
243
|
if (!spec) fail("The registry has no init file.");
|
|
212
244
|
for (const [state, file] of await writeFiles(base, spec.files)) say(`${state} ${file}`);
|
|
@@ -228,12 +260,14 @@ async function add() {
|
|
|
228
260
|
if (!(await confirm("Add components anyway?", true))) process.exit(1);
|
|
229
261
|
}
|
|
230
262
|
// Resolve every PlankUI file the requested components build on.
|
|
263
|
+
// With Base UI, each component comes from base/ when it has a Base UI version, otherwise the shared file.
|
|
264
|
+
const lib = primitives();
|
|
231
265
|
const queue = [...names.map((n) => n.toLowerCase())];
|
|
232
266
|
const seen = new Map();
|
|
233
267
|
while (queue.length) {
|
|
234
268
|
const name = queue.shift();
|
|
235
269
|
if (seen.has(name)) continue;
|
|
236
|
-
let item = await fetchJson(name);
|
|
270
|
+
let item = (lib === "base" ? await fetchJson(`base/${name}`) : null) ?? (await fetchJson(name));
|
|
237
271
|
if (!item) fail(`No component called "${name}". Run ${green("npx plankui@latest list")} to see them all.`);
|
|
238
272
|
const key = item.pro ? licenceKey() : null;
|
|
239
273
|
if (key) item = (await fetchPro(name, key)) ?? item;
|
|
@@ -250,7 +284,7 @@ async function add() {
|
|
|
250
284
|
}
|
|
251
285
|
if (!free.length) process.exit(locked.length ? 1 : 0);
|
|
252
286
|
const extra = free.filter((i) => !names.includes(i.name)).map((i) => i.name);
|
|
253
|
-
say(bold("PlankUI") + dim(` add ${free.map((i) => i.name).join(", ")}`) + (extra.length ? dim(` (needed by your picks: ${extra.join(", ")})`) : ""));
|
|
287
|
+
say(bold("PlankUI") + dim(` add ${free.map((i) => i.name).join(", ")}`) + (extra.length ? dim(` (needed by your picks: ${extra.join(", ")})`) : "") + (lib === "base" ? dim(", Base UI") : ""));
|
|
254
288
|
for (const [state, file] of await writeFiles(base, free.flatMap((i) => i.files))) say(`${state} ${file}`);
|
|
255
289
|
install(pm, free.flatMap((i) => i.dependencies), deps);
|
|
256
290
|
say();
|
|
@@ -280,7 +314,7 @@ const help = () => {
|
|
|
280
314
|
say(`${bold("plankui")} ${VERSION}: add PlankUI components to your React project.
|
|
281
315
|
|
|
282
316
|
${bold("Commands")}
|
|
283
|
-
init
|
|
317
|
+
init Choose Radix UI or Base UI, write tokens.css, styles.css and the cn helper
|
|
284
318
|
add <names...> Copy components and every PlankUI file they build on, install their packages
|
|
285
319
|
list Show every component
|
|
286
320
|
login <key> Save your PlankUI Pro licence key (once per machine)
|
|
@@ -290,6 +324,7 @@ ${bold("Options")}
|
|
|
290
324
|
--yes, -y Answer every prompt with its default (keeps files that already exist)
|
|
291
325
|
--overwrite Replace files that already exist
|
|
292
326
|
--no-install Write files but skip installing npm packages
|
|
327
|
+
--base, --radix Use Base UI or Radix UI primitives (init saves the choice in plankui.json)
|
|
293
328
|
--cwd <dir> Run in another folder
|
|
294
329
|
--registry <url> Read components from another registry`);
|
|
295
330
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "plankui",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"description": "Add accessible React components for Tailwind CSS v4 to your project. Six themes, five styles, and you own the code.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -28,7 +28,8 @@
|
|
|
28
28
|
"dark-mode",
|
|
29
29
|
"themes",
|
|
30
30
|
"copy-paste",
|
|
31
|
-
"plankui"
|
|
31
|
+
"plankui",
|
|
32
|
+
"base-ui"
|
|
32
33
|
],
|
|
33
34
|
"homepage": "https://plankui.com/docs/installation",
|
|
34
35
|
"license": "MIT",
|