praxys-ui 1.3.1 → 1.3.4

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,216 @@
1
+ <div align="center">
2
+
3
+ # praxys-ui
4
+
5
+ **CLI for scaffolding [Praxys UI](https://ui.praxys.xyz) components into your React project.**
6
+
7
+ [![npm version](https://img.shields.io/npm/v/praxys-ui?style=flat-square&color=E84E2D&logo=npm)](https://www.npmjs.com/package/praxys-ui)
8
+ [![npm downloads](https://img.shields.io/npm/dm/praxys-ui?style=flat-square&color=C9958A)](https://www.npmjs.com/package/praxys-ui)
9
+ [![License](https://img.shields.io/badge/License-MIT-E84E2D?style=flat-square)](LICENSE)
10
+
11
+ </div>
12
+
13
+ ---
14
+
15
+ ## Install
16
+
17
+ No global install needed — use `npx`:
18
+
19
+ ```bash
20
+ npx praxys-ui init
21
+ ```
22
+
23
+ Or install globally:
24
+
25
+ ```bash
26
+ npm i -g praxys-ui
27
+ ```
28
+
29
+ ## Setup
30
+
31
+ ```bash
32
+ npx praxys-ui init
33
+ ```
34
+
35
+ This will:
36
+
37
+ 1. Detect your package manager (npm, pnpm, yarn, bun)
38
+ 2. Install core dependencies (`clsx`, `tailwind-merge`, `framer-motion`)
39
+ 3. Create `lib/utils.ts` with the `cn()` helper
40
+ 4. Write `praxys.config.json` for directory defaults
41
+
42
+ ## Adding Components
43
+
44
+ ```bash
45
+ # Interactive picker — browse and select from categories
46
+ npx praxys-ui add
47
+
48
+ # Add by name
49
+ npx praxys-ui add animated-button
50
+
51
+ # Add multiple at once
52
+ npx praxys-ui add accordion alert badge tooltip
53
+
54
+ # Add all 100 components
55
+ npx praxys-ui add all
56
+
57
+ # Add and install dependencies
58
+ npx praxys-ui add floating-menu --install-deps
59
+ ```
60
+
61
+ ## Browsing Components
62
+
63
+ ```bash
64
+ # List all components (grouped by category)
65
+ npx praxys-ui list
66
+
67
+ # Filter by category
68
+ npx praxys-ui list --category buttons
69
+
70
+ # Show only new components
71
+ npx praxys-ui list --new
72
+
73
+ # Search by name or description
74
+ npx praxys-ui list --search modal
75
+
76
+ # Show only installed components
77
+ npx praxys-ui list --installed
78
+
79
+ # Component details
80
+ npx praxys-ui info animated-button
81
+ ```
82
+
83
+ **Output:**
84
+
85
+ ```
86
+ Animated Button
87
+ Category: buttons
88
+ Dependencies: framer-motion, clsx, tailwind-merge
89
+ A button with a shiny border sweep and text reveal effect.
90
+ Docs: https://praxysui.vercel.app/components/animated-button
91
+ ```
92
+
93
+ ## Inspecting & Comparing
94
+
95
+ ```bash
96
+ # View source with syntax highlighting
97
+ npx praxys-ui view switch
98
+
99
+ # Compare local file with latest version
100
+ npx praxys-ui diff accordion
101
+ ```
102
+
103
+ ## Managing Components
104
+
105
+ ```bash
106
+ # Remove a component
107
+ npx praxys-ui remove alert
108
+ npx praxys-ui rm alert --yes # skip confirmation
109
+
110
+ # Update all installed components
111
+ npx praxys-ui update
112
+
113
+ # Update a specific component
114
+ npx praxys-ui update accordion
115
+
116
+ # Check for updates without writing
117
+ npx praxys-ui update --check
118
+ ```
119
+
120
+ ## Diagnostics
121
+
122
+ ```bash
123
+ # Check project setup
124
+ npx praxys-ui doctor
125
+ ```
126
+
127
+ ```
128
+ ✓ praxys.config.json found
129
+ ✓ Components directory exists (components/ui)
130
+ ✓ Utils file exists (lib/utils.ts)
131
+ ✓ Package manager: pnpm
132
+ ✓ clsx installed (^2.1.1)
133
+ ✓ tailwind-merge installed (^2.6.0)
134
+ ✓ framer-motion installed (^12.0.0)
135
+ ✓ 12/100 components installed
136
+
137
+ All checks passed!
138
+ ```
139
+
140
+ ```bash
141
+ # Installed vs available breakdown
142
+ npx praxys-ui stats
143
+ ```
144
+
145
+ ```
146
+ Category Installed Available
147
+ ────────────────────────────────────────
148
+ buttons 5/17 █████░░░░░░░░░░░░
149
+ cards 3/10 ███░░░░░░░
150
+ text 2/8 ██░░░░░░
151
+ navigation 2/18 ██░░░░░░░░░░░░░░░░
152
+ visual 0/12 ░░░░░░░░░░░░
153
+ media 0/6 ░░░░░░
154
+ ────────────────────────────────────────
155
+ Total 12/100
156
+
157
+ Coverage: 17% of components installed
158
+ ```
159
+
160
+ ## Commands Reference
161
+
162
+ | Command | Alias | Description |
163
+ |---------|-------|-------------|
164
+ | `init` | `i` | Initialize project — deps, utils, config |
165
+ | `add [components...]` | | Add components (interactive picker if no args) |
166
+ | `list` | `ls` | List components with filters |
167
+ | `info <component>` | | Show component metadata |
168
+ | `view <component>` | | View source with syntax highlighting |
169
+ | `diff <component>` | | Compare local vs remote |
170
+ | `remove <component>` | `rm` | Remove a component file |
171
+ | `update [component]` | | Update installed components |
172
+ | `doctor` | | Check project health |
173
+ | `stats` | | Installed vs available dashboard |
174
+
175
+ ### Global Options
176
+
177
+ | Flag | Commands | Description |
178
+ |------|----------|-------------|
179
+ | `-d, --dir <path>` | add, list, diff, remove, update, stats | Override component directory |
180
+ | `-y, --yes` | add, remove | Skip confirmation prompts |
181
+ | `--install-deps` | add | Install component dependencies |
182
+ | `-c, --category <cat>` | list | Filter by category |
183
+ | `-n, --new` | list | Show only new components |
184
+ | `-s, --search <query>` | list | Search by name/description |
185
+ | `--installed` | list | Show only installed components |
186
+ | `--check` | update | Dry-run — report changes only |
187
+
188
+ ## Config File
189
+
190
+ After `init`, a `praxys.config.json` is created:
191
+
192
+ ```json
193
+ {
194
+ "componentsDir": "components/ui",
195
+ "utilsDir": "lib"
196
+ }
197
+ ```
198
+
199
+ All commands read this file for directory defaults. You can override per-command with `--dir`.
200
+
201
+ ## Components
202
+
203
+ 100 components across 6 categories:
204
+
205
+ - **Buttons** (17) — Animated Button, Checkbox, Color Picker, Date Picker, File Upload, OTP Input, Rating, Slider, Switch, and more
206
+ - **Cards** (10) — Data Table, Glow Border Card, Spotlight Card, Stats Card, Timeline, and more
207
+ - **Text** (8) — Flip Text, Morphing Text, Typewriter Text, 3D Displacement Text, and more
208
+ - **Navigation** (18) — Accordion, Command Menu, Glass Dock, Combobox, Autocomplete, Floating Menu, and more
209
+ - **Visual** (12) — Liquid Ocean, Gradient Mesh, Parallax Scroll, Toast Notification, and more
210
+ - **Media** (6) — Animated Hero, Interactive Book, Image Comparison, and more
211
+
212
+ Browse all components at [ui.praxys.xyz/docs/components-overview](https://ui.praxys.xyz/docs/components-overview).
213
+
214
+ ## License
215
+
216
+ MIT
package/dist/index.js CHANGED
@@ -6,7 +6,7 @@ import prompts from "prompts";
6
6
  import { existsSync, mkdirSync, writeFileSync, readFileSync, unlinkSync } from "fs";
7
7
  import { join } from "path";
8
8
  import { execSync } from "child_process";
9
- const VERSION = "1.3.1";
9
+ const VERSION = "1.3.4";
10
10
  // ─── Utility file contents ──────────────────────────────
11
11
  const UTILS_CONTENT = `import { clsx, type ClassValue } from "clsx";
12
12
  import { twMerge } from "tailwind-merge";
@@ -89,6 +89,35 @@ const COMPONENT_REGISTRY = {
89
89
  "toast-notification": { title: "Toast Notification", description: "Stackable animated toast notifications with variants (success, error, warning, info), auto-dismiss, and manual dismiss.", category: "visual", dependencies: ["framer-motion", "clsx", "tailwind-merge"] },
90
90
  "tooltip": { title: "Tooltip", description: "A tooltip with 4 positions, configurable delay, direction-aware motion animation, and arrow pointer.", category: "navigation", dependencies: ["framer-motion", "clsx", "tailwind-merge"] },
91
91
  "typewriter-text": { title: "Typewriter Text", description: "An animated typing effect that cycles through strings, typing and deleting characters with a blinking cursor.", category: "text", dependencies: ["framer-motion", "clsx", "tailwind-merge"] },
92
+ "toggle-group": { title: "Toggle Group", description: "Segmented control with layoutId spring animation on the selection indicator, three sizes.", category: "buttons", dependencies: ["framer-motion", "clsx", "tailwind-merge"], isNew: true },
93
+ "number-input": { title: "Number Input", description: "Numeric stepper with animated increment/decrement buttons, min/max/step support, three sizes.", category: "buttons", dependencies: ["framer-motion", "clsx", "tailwind-merge"], isNew: true },
94
+ "search-input": { title: "Search Input", description: "Search bar with animated search icon, spinning loading indicator, and AnimatePresence clear button.", category: "buttons", dependencies: ["framer-motion", "clsx", "tailwind-merge"], isNew: true },
95
+ "password-input": { title: "Password Input", description: "Password input with animated show/hide toggle using SVG eye icons and AnimatePresence transitions.", category: "buttons", dependencies: ["framer-motion", "clsx", "tailwind-merge"], isNew: true },
96
+ "range-slider": { title: "Range Slider", description: "Dual-thumb range slider with framer-motion drag interaction, step snapping, and hover/tap animations.", category: "buttons", dependencies: ["framer-motion", "clsx", "tailwind-merge"], isNew: true },
97
+ "copy-button": { title: "Copy Button", description: "Click-to-copy button with animated transition between copy icon and checkmark feedback.", category: "buttons", dependencies: ["framer-motion", "clsx", "tailwind-merge"], isNew: true },
98
+ "mention-input": { title: "Mention Input", description: "Text input with @ mention detection, animated dropdown user list, and keyboard navigation.", category: "buttons", dependencies: ["framer-motion", "clsx", "tailwind-merge"], isNew: true },
99
+ "pricing-card": { title: "Pricing Card", description: "Animated pricing card with feature list, CTA button, popular badge, and hover scale effect.", category: "cards", dependencies: ["framer-motion", "clsx", "tailwind-merge"], isNew: true },
100
+ "profile-card": { title: "Profile Card", description: "Profile card with avatar, online indicator, social links, and staggered entrance animation.", category: "cards", dependencies: ["framer-motion", "clsx", "tailwind-merge"], isNew: true },
101
+ "feature-card": { title: "Feature Card", description: "Feature card with icon, title, description, and 3D tilt effect that follows the cursor.", category: "cards", dependencies: ["framer-motion", "clsx", "tailwind-merge"], isNew: true },
102
+ "comparison-table": { title: "Comparison Table", description: "Side-by-side comparison table with plan columns, check/cross icons, and staggered row animations.", category: "cards", dependencies: ["framer-motion", "clsx", "tailwind-merge"], isNew: true },
103
+ "stat-bar": { title: "Stat Bar", description: "Horizontal progress bar with label, percentage, and scroll-triggered spring fill animation.", category: "cards", dependencies: ["framer-motion", "clsx", "tailwind-merge"], isNew: true },
104
+ "gradient-text": { title: "Gradient Text", description: "Animated gradient text using background-clip with configurable colors and speed.", category: "text", dependencies: ["framer-motion", "clsx", "tailwind-merge"], isNew: true },
105
+ "scramble-text": { title: "Scramble Text", description: "Text decode effect that reveals characters one by one with random character scrambling.", category: "text", dependencies: ["framer-motion", "clsx", "tailwind-merge"], isNew: true },
106
+ "text-reveal": { title: "Text Reveal", description: "Splits text into words and animates each from below with staggered scroll-triggered entrance.", category: "text", dependencies: ["framer-motion", "clsx", "tailwind-merge"], isNew: true },
107
+ "glitch-text": { title: "Glitch Text", description: "RGB split glitch effect with clip-path slicing animation and configurable intensity levels.", category: "text", dependencies: ["framer-motion", "clsx", "tailwind-merge"], isNew: true },
108
+ "sidebar": { title: "Sidebar", description: "Collapsible sidebar navigation with animated width transition, staggered items, and expandable sub-items.", category: "navigation", dependencies: ["framer-motion", "clsx", "tailwind-merge"], isNew: true },
109
+ "bottom-sheet": { title: "Bottom Sheet", description: "Mobile bottom sheet drawer with drag-to-dismiss, snap points, spring animation, and backdrop blur.", category: "navigation", dependencies: ["framer-motion", "clsx", "tailwind-merge"], isNew: true },
110
+ "popover": { title: "Popover", description: "Floating popover with 4 sides, 3 alignments, arrow indicator, click-outside close, and directional animation.", category: "navigation", dependencies: ["framer-motion", "clsx", "tailwind-merge"], isNew: true },
111
+ "context-menu": { title: "Context Menu", description: "Right-click context menu with keyboard navigation, divider support, disabled items, and ARIA roles.", category: "navigation", dependencies: ["framer-motion", "clsx", "tailwind-merge"], isNew: true },
112
+ "mega-menu": { title: "Mega Menu", description: "Large dropdown navigation with hover trigger, multi-column grid sections, and delayed close.", category: "navigation", dependencies: ["framer-motion", "clsx", "tailwind-merge"], isNew: true },
113
+ "confetti": { title: "Confetti", description: "Celebration burst effect with randomized particles, colors, rotation, and physics-based falling animation.", category: "visual", dependencies: ["framer-motion", "clsx", "tailwind-merge"], isNew: true },
114
+ "particles": { title: "Particles", description: "Floating particle background with randomized drift paths, looping animations, and configurable density.", category: "visual", dependencies: ["framer-motion", "clsx", "tailwind-merge"], isNew: true },
115
+ "noise-texture": { title: "Noise Texture", description: "Animated grain overlay using SVG feTurbulence filter for a film-grain effect.", category: "visual", dependencies: ["clsx", "tailwind-merge"], isNew: true },
116
+ "aurora": { title: "Aurora", description: "Aurora borealis gradient background with blurred animated blobs in smooth keyframe paths.", category: "visual", dependencies: ["framer-motion", "clsx", "tailwind-merge"], isNew: true },
117
+ "blur-fade": { title: "Blur Fade", description: "Blur + fade entrance wrapper with configurable direction, delay, and duration.", category: "visual", dependencies: ["framer-motion", "clsx", "tailwind-merge"], isNew: true },
118
+ "carousel": { title: "Carousel", description: "Image carousel with directional slide animation, auto-play, arrow and dot navigation.", category: "media", dependencies: ["framer-motion", "clsx", "tailwind-merge"], isNew: true },
119
+ "avatar": { title: "Avatar", description: "Avatar component with four sizes, status indicators, fallback initials, and animated status dot.", category: "media", dependencies: ["framer-motion", "clsx", "tailwind-merge"], isNew: true },
120
+ "lightbox": { title: "Lightbox", description: "Fullscreen image viewer with zoom, arrow key navigation, thumbnail strip, and backdrop blur.", category: "media", dependencies: ["framer-motion", "clsx", "tailwind-merge"], isNew: true },
92
121
  };
93
122
  const COMPONENT_LIST = Object.keys(COMPONENT_REGISTRY);
94
123
  const CATEGORY_COLORS = {
@@ -163,7 +192,6 @@ function getComponentsDir(optDir) {
163
192
  function fuzzyMatch(query, text) {
164
193
  const lower = text.toLowerCase();
165
194
  const q = query.toLowerCase();
166
- // simple substring match on slug, title, or description
167
195
  return lower.includes(q);
168
196
  }
169
197
  function truncate(str, max) {
@@ -171,6 +199,65 @@ function truncate(str, max) {
171
199
  return str;
172
200
  return str.slice(0, max - 1) + "…";
173
201
  }
202
+ function levenshtein(a, b) {
203
+ const m = a.length, n = b.length;
204
+ const dp = Array.from({ length: m + 1 }, () => Array(n + 1).fill(0));
205
+ for (let i = 0; i <= m; i++)
206
+ dp[i][0] = i;
207
+ for (let j = 0; j <= n; j++)
208
+ dp[0][j] = j;
209
+ for (let i = 1; i <= m; i++) {
210
+ for (let j = 1; j <= n; j++) {
211
+ dp[i][j] = a[i - 1] === b[j - 1]
212
+ ? dp[i - 1][j - 1]
213
+ : 1 + Math.min(dp[i - 1][j], dp[i][j - 1], dp[i - 1][j - 1]);
214
+ }
215
+ }
216
+ return dp[m][n];
217
+ }
218
+ function didYouMean(input) {
219
+ let best = "";
220
+ let bestDist = Infinity;
221
+ for (const slug of COMPONENT_LIST) {
222
+ const dist = levenshtein(input.toLowerCase(), slug.toLowerCase());
223
+ if (dist < bestDist) {
224
+ bestDist = dist;
225
+ best = slug;
226
+ }
227
+ }
228
+ // Only suggest if distance is reasonable (less than ~40% of input length)
229
+ if (bestDist <= Math.max(2, Math.floor(input.length * 0.4))) {
230
+ return best;
231
+ }
232
+ return null;
233
+ }
234
+ function printNotFound(slug) {
235
+ const suggestion = didYouMean(slug);
236
+ if (suggestion) {
237
+ console.log(chalk.red(` Component "${slug}" not found.`) + chalk.dim(` Did you mean ${chalk.bold(suggestion)}?`));
238
+ }
239
+ else {
240
+ console.log(chalk.red(` Component "${slug}" not found.`));
241
+ }
242
+ }
243
+ async function checkForUpdates() {
244
+ try {
245
+ const res = await fetch("https://registry.npmjs.org/praxys-ui/latest", {
246
+ signal: AbortSignal.timeout(3000),
247
+ });
248
+ if (!res.ok)
249
+ return;
250
+ const data = await res.json();
251
+ const latest = data.version;
252
+ if (latest && latest !== VERSION) {
253
+ console.log(chalk.dim(` Update available: ${VERSION} → ${chalk.bold(latest)} Run ${chalk.cyan("npm i -g praxys-ui")} to update.`));
254
+ console.log("");
255
+ }
256
+ }
257
+ catch {
258
+ // Silently ignore — no network, timeout, etc.
259
+ }
260
+ }
174
261
  function colorizeSource(source) {
175
262
  const lines = source.split("\n");
176
263
  return lines
@@ -222,34 +309,22 @@ program
222
309
  // ── init ─────────────────────────────────────────────────
223
310
  program
224
311
  .command("init")
312
+ .alias("i")
225
313
  .description("Initialize Praxys UI in your project")
226
- .action(async () => {
314
+ .option("-d, --dir <directory>", "Component directory", "components/ui")
315
+ .option("--utils-dir <directory>", "Utils directory", "lib")
316
+ .action(async (opts) => {
317
+ const componentDir = opts.dir;
318
+ const utilsDir = opts.utilsDir;
319
+ const pm = detectPackageManager();
227
320
  console.log("");
228
321
  console.log(chalk.bold(` ${chalk.hex("#E84E2D")("Praxys UI")} — init`));
229
322
  console.log("");
230
- const pm = detectPackageManager();
231
- console.log(chalk.dim(` Package manager: ${pm}`));
232
- const { componentDir } = await prompts({
233
- type: "text",
234
- name: "componentDir",
235
- message: "Where should components be installed?",
236
- initial: "components/ui",
237
- });
238
- if (!componentDir) {
239
- console.log(chalk.yellow(" Cancelled."));
240
- return;
241
- }
242
- const { utilsDir } = await prompts({
243
- type: "text",
244
- name: "utilsDir",
245
- message: "Where should the utils file be created?",
246
- initial: "lib",
247
- });
248
- if (!utilsDir) {
249
- console.log(chalk.yellow(" Cancelled."));
250
- return;
251
- }
252
- // Install dependencies
323
+ console.log(chalk.dim(` Package manager ${pm}`));
324
+ console.log(chalk.dim(` Components ${componentDir}/`));
325
+ console.log(chalk.dim(` Utils ${utilsDir}/utils.ts`));
326
+ console.log("");
327
+ // 1. Install dependencies
253
328
  const spinner = ora("Installing dependencies...").start();
254
329
  try {
255
330
  const deps = ["clsx", "tailwind-merge", "framer-motion"];
@@ -261,27 +336,22 @@ program
261
336
  console.log(chalk.dim(" Run manually: " +
262
337
  installCmd(pm, ["clsx", "tailwind-merge", "framer-motion"])));
263
338
  }
264
- // Create utils file
265
- const utilsSpinner = ora("Creating utility files...").start();
266
- try {
267
- const utilsPath = join(process.cwd(), utilsDir);
268
- ensureDir(utilsPath);
269
- const utilsFile = join(utilsPath, "utils.ts");
270
- if (existsSync(utilsFile)) {
271
- utilsSpinner.warn("utils.ts already exists, skipping");
272
- }
273
- else {
274
- writeFileSync(utilsFile, UTILS_CONTENT, "utf-8");
275
- utilsSpinner.succeed(`Created ${utilsDir}/utils.ts`);
276
- }
339
+ // 2. Create utils file
340
+ const utilsPath = join(process.cwd(), utilsDir);
341
+ ensureDir(utilsPath);
342
+ const utilsFile = join(utilsPath, "utils.ts");
343
+ if (existsSync(utilsFile)) {
344
+ console.log(chalk.dim(" ○ utils.ts already exists, skipping"));
277
345
  }
278
- catch {
279
- utilsSpinner.fail("Failed to create utils file");
346
+ else {
347
+ writeFileSync(utilsFile, UTILS_CONTENT, "utf-8");
348
+ console.log(chalk.green(` ✓ Created ${utilsDir}/utils.ts`));
280
349
  }
281
- // Create component directory
350
+ // 3. Create component directory
282
351
  const compPath = join(process.cwd(), componentDir);
283
352
  ensureDir(compPath);
284
- // Write config file
353
+ console.log(chalk.green(` ✓ Created ${componentDir}/`));
354
+ // 4. Write config file
285
355
  const configPath = join(process.cwd(), "praxys.config.json");
286
356
  const config = {
287
357
  componentsDir: componentDir,
@@ -290,10 +360,11 @@ program
290
360
  writeFileSync(configPath, JSON.stringify(config, null, 2) + "\n", "utf-8");
291
361
  console.log(chalk.green(" ✓ Created praxys.config.json"));
292
362
  console.log("");
293
- console.log(chalk.green(" ✓ Praxys UI initialized!"));
363
+ console.log(chalk.green(" Done!"));
294
364
  console.log("");
295
- console.log(chalk.dim(` Add components with: ${chalk.bold("npx praxys-ui add <component>")}`));
296
- console.log(chalk.dim(` Browse components: ${chalk.bold("https://github.com/sushanttverma/Praxys-UI")}`));
365
+ console.log(chalk.dim(` npx praxys-ui add animated-button Add a component`));
366
+ console.log(chalk.dim(` npx praxys-ui add Browse & pick`));
367
+ console.log(chalk.dim(` npx praxys-ui list See all 100 components`));
297
368
  console.log("");
298
369
  });
299
370
  // ── add <component> ──────────────────────────────────────
@@ -358,15 +429,15 @@ async function installDepsForComponents(slugs) {
358
429
  }
359
430
  program
360
431
  .command("add")
361
- .description("Add a component (or all components) to your project")
362
- .argument("[component]", 'Component slug (e.g. animated-button) or "all". Omit for interactive picker.')
432
+ .description("Add one or more components to your project")
433
+ .argument("[components...]", 'Component slugs (e.g. animated-button alert) or "all". Omit for interactive picker.')
363
434
  .option("-d, --dir <directory>", "Component directory")
364
435
  .option("-y, --yes", "Skip overwrite prompts (skip existing files)", false)
365
436
  .option("--install-deps", "Install component dependencies after adding", false)
366
- .action(async (component, opts) => {
437
+ .action(async (components, opts) => {
367
438
  const dir = getComponentsDir(opts.dir);
368
- // ── interactive picker when no arg ───────────────────
369
- if (!component) {
439
+ // ── interactive picker when no args ──────────────────
440
+ if (!components || components.length === 0) {
370
441
  console.log("");
371
442
  console.log(chalk.bold(` ${chalk.hex("#E84E2D")("Praxys UI")} — add components`));
372
443
  console.log("");
@@ -432,11 +503,12 @@ program
432
503
  console.log("");
433
504
  return;
434
505
  }
506
+ const label = components.length === 1 ? chalk.cyan(components[0]) : chalk.cyan(`${components.length} components`);
435
507
  console.log("");
436
- console.log(chalk.bold(` ${chalk.hex("#E84E2D")("Praxys UI")} — add ${chalk.cyan(component)}`));
508
+ console.log(chalk.bold(` ${chalk.hex("#E84E2D")("Praxys UI")} — add ${label}`));
437
509
  console.log("");
438
510
  // ── add all ──────────────────────────────────────────
439
- if (component === "all") {
511
+ if (components.includes("all")) {
440
512
  const { confirm } = await prompts({
441
513
  type: "confirm",
442
514
  name: "confirm",
@@ -447,14 +519,19 @@ program
447
519
  console.log(chalk.yellow(" Cancelled."));
448
520
  return;
449
521
  }
522
+ // Parallel fetch in batches of 6
450
523
  let added = 0;
451
524
  let failed = 0;
452
- for (const slug of COMPONENT_LIST) {
453
- const ok = await addSingleComponent(slug, dir, opts.yes);
454
- if (ok)
455
- added++;
456
- else
457
- failed++;
525
+ const batchSize = 6;
526
+ for (let i = 0; i < COMPONENT_LIST.length; i += batchSize) {
527
+ const batch = COMPONENT_LIST.slice(i, i + batchSize);
528
+ const results = await Promise.allSettled(batch.map((slug) => addSingleComponent(slug, dir, opts.yes)));
529
+ for (const r of results) {
530
+ if (r.status === "fulfilled" && r.value)
531
+ added++;
532
+ else
533
+ failed++;
534
+ }
458
535
  }
459
536
  console.log("");
460
537
  console.log(chalk.green(` ✓ ${added} components added`) +
@@ -465,31 +542,67 @@ program
465
542
  console.log("");
466
543
  return;
467
544
  }
468
- // ── add single ───────────────────────────────────────
469
- if (!COMPONENT_LIST.includes(component)) {
470
- console.log(chalk.red(` Component "${component}" not found.`));
471
- console.log("");
472
- console.log(chalk.dim(" Available components:"));
473
- COMPONENT_LIST.forEach((c) => console.log(chalk.dim(` - ${c}`)));
474
- console.log(chalk.dim(` - ${chalk.bold("all")} (adds every component)`));
545
+ // ── validate all slugs first ─────────────────────────
546
+ const invalidSlugs = components.filter((c) => !COMPONENT_LIST.includes(c));
547
+ if (invalidSlugs.length > 0) {
548
+ for (const bad of invalidSlugs) {
549
+ const suggestion = didYouMean(bad);
550
+ if (suggestion) {
551
+ console.log(chalk.red(` Component "${bad}" not found.`) + chalk.dim(` Did you mean ${chalk.bold(suggestion)}?`));
552
+ }
553
+ else {
554
+ console.log(chalk.red(` Component "${bad}" not found.`));
555
+ }
556
+ }
557
+ console.log(chalk.dim(`\n Run ${chalk.bold("praxys-ui list")} to see available components.`));
475
558
  console.log("");
476
559
  return;
477
560
  }
478
- const ok = await addSingleComponent(component, dir, false);
479
- if (ok && opts.installDeps) {
480
- await installDepsForComponents([component]);
561
+ // ── add single or multiple ───────────────────────────
562
+ if (components.length === 1) {
563
+ const slug = components[0];
564
+ const ok = await addSingleComponent(slug, dir, false);
565
+ if (ok && opts.installDeps) {
566
+ await installDepsForComponents([slug]);
567
+ }
568
+ console.log("");
569
+ console.log(chalk.dim(` Import: ${chalk.bold(`import ${toPascalCase(slug)} from '@/${dir}/${slug}'`)}`));
570
+ console.log("");
571
+ }
572
+ else {
573
+ // Parallel fetch in batches of 6
574
+ let added = 0;
575
+ let failed = 0;
576
+ const batchSize = 6;
577
+ for (let i = 0; i < components.length; i += batchSize) {
578
+ const batch = components.slice(i, i + batchSize);
579
+ const results = await Promise.allSettled(batch.map((slug) => addSingleComponent(slug, dir, opts.yes)));
580
+ for (const r of results) {
581
+ if (r.status === "fulfilled" && r.value)
582
+ added++;
583
+ else
584
+ failed++;
585
+ }
586
+ }
587
+ console.log("");
588
+ console.log(chalk.green(` ✓ ${added} components added`) +
589
+ (failed > 0 ? chalk.red(`, ${failed} failed`) : ""));
590
+ if (opts.installDeps) {
591
+ await installDepsForComponents(components);
592
+ }
593
+ console.log("");
481
594
  }
482
- console.log("");
483
- console.log(chalk.dim(` Import: ${chalk.bold(`import ${toPascalCase(component)} from '@/${dir}/${component}'`)}`));
484
- console.log("");
485
595
  });
486
596
  // ── list ─────────────────────────────────────────────────
487
597
  program
488
598
  .command("list")
599
+ .alias("ls")
489
600
  .description("List all available components")
490
601
  .option("-c, --category <category>", "Filter by category (buttons, cards, text, navigation, visual, media)")
491
602
  .option("-n, --new", "Show only new components", false)
492
603
  .option("-s, --search <query>", "Search components by name or description")
604
+ .option("--installed", "Show only locally installed components", false)
605
+ .option("-d, --dir <directory>", "Component directory (used with --installed)")
493
606
  .action((opts) => {
494
607
  console.log("");
495
608
  console.log(chalk.bold(` ${chalk.hex("#E84E2D")("Praxys UI")} — components`));
@@ -506,6 +619,16 @@ program
506
619
  return;
507
620
  }
508
621
  }
622
+ // Filter by installed
623
+ if (opts.installed) {
624
+ const compPath = join(process.cwd(), getComponentsDir(opts.dir));
625
+ entries = entries.filter(([slug]) => existsSync(join(compPath, `${slug}.tsx`)));
626
+ if (entries.length === 0) {
627
+ console.log(chalk.yellow(` No installed components found.`));
628
+ console.log("");
629
+ return;
630
+ }
631
+ }
509
632
  // Filter by new
510
633
  if (opts.new) {
511
634
  entries = entries.filter(([, meta]) => meta.isNew);
@@ -558,7 +681,7 @@ program
558
681
  const meta = COMPONENT_REGISTRY[component];
559
682
  if (!meta) {
560
683
  console.log("");
561
- console.log(chalk.red(` Component "${component}" not found.`));
684
+ printNotFound(component);
562
685
  console.log(chalk.dim(` Run ${chalk.bold("praxys-ui list")} to see available components.`));
563
686
  console.log("");
564
687
  return;
@@ -580,7 +703,7 @@ program
580
703
  .action(async (component) => {
581
704
  if (!COMPONENT_REGISTRY[component]) {
582
705
  console.log("");
583
- console.log(chalk.red(` Component "${component}" not found.`));
706
+ printNotFound(component);
584
707
  console.log(chalk.dim(` Run ${chalk.bold("praxys-ui list")} to see available components.`));
585
708
  console.log("");
586
709
  return;
@@ -611,7 +734,7 @@ program
611
734
  const dir = getComponentsDir(opts.dir);
612
735
  if (!COMPONENT_REGISTRY[component]) {
613
736
  console.log("");
614
- console.log(chalk.red(` Component "${component}" not found.`));
737
+ printNotFound(component);
615
738
  console.log("");
616
739
  return;
617
740
  }
@@ -666,6 +789,7 @@ program
666
789
  // ── remove <component> ───────────────────────────────────
667
790
  program
668
791
  .command("remove")
792
+ .alias("rm")
669
793
  .description("Remove a component from your project")
670
794
  .argument("<component>", "Component slug")
671
795
  .option("-d, --dir <directory>", "Component directory")
@@ -674,7 +798,7 @@ program
674
798
  const dir = getComponentsDir(opts.dir);
675
799
  if (!COMPONENT_REGISTRY[component]) {
676
800
  console.log("");
677
- console.log(chalk.red(` Component "${component}" not found.`));
801
+ printNotFound(component);
678
802
  console.log("");
679
803
  return;
680
804
  }
@@ -727,7 +851,7 @@ program
727
851
  let slugsToCheck;
728
852
  if (component) {
729
853
  if (!COMPONENT_REGISTRY[component]) {
730
- console.log(chalk.red(` Component "${component}" not found.`));
854
+ printNotFound(component);
731
855
  console.log("");
732
856
  return;
733
857
  }
@@ -946,4 +1070,4 @@ program
946
1070
  console.log("");
947
1071
  });
948
1072
  // ── run ──────────────────────────────────────────────────
949
- program.parse();
1073
+ program.parseAsync().then(() => checkForUpdates());
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "praxys-ui",
3
- "version": "1.3.1",
3
+ "version": "1.3.4",
4
4
  "type": "module",
5
5
  "description": "CLI for scaffolding Praxys UI components into your project",
6
6
  "bin": {
@@ -8,7 +8,7 @@
8
8
  },
9
9
  "files": [
10
10
  "dist",
11
- "CHANGELOG.md"
11
+ "README.md"
12
12
  ],
13
13
  "scripts": {
14
14
  "build": "tsc",
package/CHANGELOG.md DELETED
@@ -1,319 +0,0 @@
1
- # Changelog
2
-
3
- All notable changes to Praxys UI are documented here.
4
-
5
- ## [1.2.6] — Feb 15, 2026
6
-
7
- **Color Customization & Enhanced Studio**
8
-
9
- Added comprehensive color customization to Animation Studio and Theme Customizer with random palette generation and per-color editing.
10
-
11
- ### Added
12
-
13
- - Color Scheme Customization — 10 pre-made color schemes (Ocean, Forest, Sunset, Purple, Rose Gold, Mint, Fire, Cyberpunk, Monochrome)
14
- - Theme Customizer Panel — "Make it yours" section with individual color editing (Primary, Secondary, Accent, Background, Text)
15
- - Random Palette Generator — 🎲 Generate harmonious color palettes with one click in both Studio and /customize
16
- - Per-Color Randomization — Random button (🎲) for each individual color property
17
- - Color Pickers — Visual color selection with hex/HSL text input support
18
-
19
- ### Fixed
20
-
21
- - React Style Warning — Changed background to backgroundImage to avoid conflicts with backgroundClip
22
- - HSL to Hex Conversion — All colors properly converted for CSS compatibility
23
-
24
- ### Improved
25
-
26
- - Random Color Algorithm — Uses color theory (analogous + complementary hues) for harmonious palettes
27
- - Color Contrast — Fixed lightness/saturation values ensure readable, professional themes
28
- - Live Preview Updates — All component previews dynamically use selected color scheme
29
-
30
- ## [1.2.5] — Feb 15, 2026
31
-
32
- **Animation Studio — Visual Animation Builder**
33
-
34
- Introducing the Animation Studio, a killer feature that sets PraxysUI apart. Visually design animations for any component with live preview, presets, and instant code generation.
35
-
36
- ### Added
37
-
38
- - Animation Studio (/studio) — Interactive visual playground for designing component animations
39
- - Live Preview Canvas — See animations play in real-time as you adjust parameters
40
- - Animation Controls — Fine-tune initial state, animate state, and transitions with intuitive sliders
41
- - 30+ Animation Presets — Pre-built entrance, attention, exit, and loop animations (fade, slide, bounce, scale, flip, rotate, etc.)
42
- - Component Selector — Search and filter through all 69 components with category filters
43
- - Code Generator — Instantly copy Framer Motion or CSS @keyframes code for your custom animations
44
- - Auto-Play Mode — Automatically replay animations when changing parameters or components
45
- - Category-Specific Previews — Realistic mockups for buttons, cards, text, navigation, and visual components
46
-
47
- ### Improved
48
-
49
- - Mobile Responsive — Compact dropdown component selector on mobile, full experience preserved
50
- - Navbar — Added "Studio" link for easy access
51
-
52
- ## [1.2.2] — Feb 15, 2026
53
-
54
- **Autocomplete API Fix**
55
-
56
- Fixed Autocomplete component API to use onSelect callback instead of onChange for better clarity and type safety.
57
-
58
- ### Fixed
59
-
60
- - Autocomplete — changed API from onChange to onSelect, now passes full option object instead of just value string
61
- - Autocomplete demo and documentation updated to reflect new API
62
- - TypeScript errors resolved in Autocomplete component
63
-
64
- ## [1.2.1] — Feb 15, 2026
65
-
66
- **6 New Components — Essential UI Elements**
67
-
68
- Essential interactive components: Switch, Slider, File Upload, OTP Input, Rating, and Autocomplete with async search — bringing the total to 69 components.
69
-
70
- ### Added
71
-
72
- - Switch — simple on/off toggle with spring animation, 3 sizes, optional label, keyboard accessible
73
- - Slider — range input with draggable thumb, animated track fill, value tooltip, min/max labels, step support, keyboard navigation
74
- - File Upload — drag-and-drop zone with animated borders, file list with remove buttons, progress bars, file type and size validation, multiple file support
75
- - OTP Input — PIN/verification code input with auto-focus next/prev, paste support, animated focus rings, configurable length (4-6)
76
- - Rating — interactive star rating with half-star support, hover preview, animated fill, read-only mode, 3 sizes, custom icon support
77
- - Autocomplete — async search input with debouncing, loading state, keyboard navigation, highlighted matching text, empty state
78
-
79
- ### Improved
80
-
81
- - CLI updated to v1.2.1 with all 69 components
82
- - Component count updated from 63 to 69 across site
83
-
84
- ## [1.2.0] — Feb 15, 2026
85
-
86
- **3 New Form Components — Complete Your Forms**
87
-
88
- Essential form components to complete your UI toolkit: Date Picker with range selection, Combobox with search, and Color Picker with HSL controls — bringing the total to 63 components.
89
-
90
- ### Added
91
-
92
- - Date Picker — animated calendar popup with month/year navigation, single/range selection, keyboard navigation, disabled dates support
93
- - Combobox — searchable select with filtering, single/multi-select modes, keyboard navigation, search highlighting, loading state
94
- - Color Picker — HSL sliders, hex input, preset swatches, alpha channel, format toggle (HEX/RGB/HSL), copy to clipboard
95
-
96
- ### Fixed
97
-
98
- - Skip-to-content accessibility link — now only appears on real keyboard Tab, never on route navigation
99
- - AnimatedInput and AnimatedTextarea — support both controlled and uncontrolled usage for Playground compatibility
100
-
101
- ### Improved
102
-
103
- - CLI updated to v1.2.0 with all 63 components
104
- - Component count updated from 60 to 63 across site
105
-
106
- ## [1.1.0] — Feb 14, 2026
107
-
108
- **11 New Components — Forms, Layout & Data**
109
-
110
- 11 new components covering forms (Input, Select, Textarea, Checkbox, Radio), feedback (Alert, Sheet), data display (Pagination, Timeline, Stats Card), and layout (Divider) — bringing the total to 60. CLI updated to v1.1.0.
111
-
112
- ### Added
113
-
114
- - Animated Input — floating label, animated focus ring, left/right icons, error state, 3 sizes
115
- - Animated Select — custom dropdown with keyboard navigation, spring animations, click-outside close
116
- - Animated Textarea — floating label, auto-resize, character counter, animated focus ring
117
- - Checkbox — animated SVG checkmark with pathLength draw, spring scale, error state, ARIA checkbox role
118
- - Radio Group — animated dot selection, horizontal/vertical layout, keyboard navigation, ARIA radiogroup
119
- - Alert — 4 variants (info/success/warning/error) with auto-icons, dismissible with animated exit
120
- - Pagination — sliding active indicator with layoutId, ellipsis, prev/next, 2 sizes
121
- - Sheet — slide-in drawer from 4 sides, backdrop blur, Escape close, scroll lock
122
- - Divider — horizontal/vertical with optional label, gradient mode, animated entrance
123
- - Timeline — alternating two-column layout, staggered scroll animations, active/completed states
124
- - Stats Card — animated counter with useSpring, trend indicator, icon slot
125
-
126
- ### Fixed
127
-
128
- - Navbar — replaced useEffect setState with React-idiomatic derived state pattern for route change detection
129
- - Sidebar — same derived state fix to comply with react-hooks/set-state-in-effect rule
130
- - Header inconsistency — docs pages now use the shared Navbar instead of a separate custom header
131
-
132
- ### Improved
133
-
134
- - CLI updated to v1.1.0 with all 60 components published to npm
135
- - Component count updated from 50 to 60 across landing page and registry
136
- - Navbar — active link highlighting, skip-to-content accessibility link
137
- - Docs — breadcrumbs on all pages, slim footer, back-to-top button
138
- - Changelog — extracted data to single source of truth, auto-generates CHANGELOG.md
139
- - ComponentPreview — proper ARIA tab roles (tablist, tab, tabpanel)
140
- - 404 page — now has Navbar/Footer, fixed stale template count
141
- - Loading skeletons added to changelog, templates, examples, and customize pages
142
-
143
- ## [0.9.0] — Feb 10, 2026
144
-
145
- **10 New Components & CLI v0.3.0**
146
-
147
- 10 new interactive components spanning modals, tooltips, dropdowns, progress indicators, and more — bringing the total to 50. CLI updated to v0.3.0.
148
-
149
- ### Added
150
-
151
- - Modal Dialog — animated modal with backdrop blur, spring scale, Escape key, scroll lock, and ARIA attributes
152
- - Tooltip — 4-position tooltip with configurable delay, direction-aware animation, and arrow pointer
153
- - Dropdown Menu — full keyboard navigation, click-outside close, divider and disabled item support
154
- - Progress Bar — animated bar with sm/md/lg sizes, candy-stripe overlay, custom colors, and label/value display
155
- - Stepper — horizontal/vertical multi-step indicator with animated check icons and connector fill
156
- - Image Comparison — before/after slider with pointer-capture drag, clip-based reveal, and animated handle
157
- - Animated Counter — spring-physics number counter triggered on scroll into view with prefix/suffix/decimals
158
- - Infinite Scroll — Intersection Observer-based with configurable threshold and animated loader
159
- - Command Menu — search-filtered palette with grouped items, keyboard nav, match highlighting, and shortcut badges
160
- - Animated Toggle — switch with spring-animated knob, 3 sizes, ARIA role="switch", and disabled state
161
-
162
- ### Improved
163
-
164
- - CLI updated to v0.3.0 with all 50 components published to npm
165
- - Component count updated from 34 to 50 across landing page and registry
166
-
167
- ## [0.8.0] — Feb 2, 2026
168
-
169
- **New Components, Theme Customizer & Open Source**
170
-
171
- 10 new components, interactive theme customizer with export, Props Playground for all components, and full open-source community setup.
172
-
173
- ### Added
174
-
175
- - Typewriter Text — animated typing effect with cursor and configurable speed
176
- - Toast Notification — stackable toast system with multiple variants
177
- - Accordion — smooth expand/collapse with icon rotation
178
- - Animated Tabs — tab switcher with sliding indicator and content transitions
179
- - Magnetic Cursor — element that pulls toward the mouse pointer
180
- - Parallax Scroll — depth-based scroll animations for layered content
181
- - Gradient Mesh — animated multi-point gradient background
182
- - Skeleton Loader — pulsing placeholder for loading states
183
- - Morphing Text — smooth text transitions between words
184
- - Spotlight Card — card with mouse-following light effect
185
- - Theme Customizer page (/customize) with color pickers, 6 presets, live preview, and CSS export
186
- - Interactive Props Playground with live controls for all 34 components
187
- - Live interactive demos on component showcase (landing page)
188
- - 6 interactive template pages with preview toolbar and responsive viewport switcher
189
- - CONTRIBUTING.md, CODE_OF_CONDUCT.md, issue templates, and PR template for open source
190
-
191
- ### Fixed
192
-
193
- - Nested <a> tags in ComponentShowcase — replaced Link with div + useRouter
194
- - ToastContainer crash when toasts/onDismiss are undefined in playground
195
- - LogoSlider animation shorthand/longhand conflict in React 19
196
- - Missing playground defaults for glass-dock and logo-slider
197
- - CopyButton invisible on touch devices — now always visible on mobile
198
-
199
- ### Improved
200
-
201
- - CLI updated to v0.2.0 with all 34 components
202
- - Component showcase redesigned with live demos instead of placeholder cards
203
- - Dark mode text contrast improved (--color-text-faint bumped to #6b6560)
204
- - Comprehensive responsive design fixes across all components and pages
205
-
206
- ## [0.7.0] — Jan 11, 2026
207
-
208
- **SEO, Accessibility & Polish**
209
-
210
- Comprehensive SEO metadata, accessibility audit fixes, and public assets.
211
-
212
- ### Added
213
-
214
- - Open Graph and Twitter Card metadata across all pages
215
- - Dynamic generateMetadata for all /docs/[slug] pages
216
- - SVG favicon, robots.txt, and sitemap.xml
217
-
218
- ### Fixed
219
-
220
- - suppressHydrationWarning on body to handle browser extension attributes
221
-
222
- ### Improved
223
-
224
- - ARIA labels, roles, and keyboard navigation on Navbar, CommandPalette, Sidebar
225
- - Focus trap in command palette dialog
226
- - aria-current="page" on active sidebar links
227
-
228
- ## [0.6.0] — Jan 8, 2026
229
-
230
- **Bug Fix Pass**
231
-
232
- Major audit fixing 10 issues across the docs — broken links, duplicate pages, layout problems, and error handling.
233
-
234
- ### Fixed
235
-
236
- - Broken /docs/components links across 5 files — now points to /docs/components-overview
237
- - Mobile menu not closing on link click in Navbar
238
- - Duplicate IntroductionPage — single source of truth now
239
- - ComponentPageClient dynamic import error handling with .catch() and error state
240
- - Sidebar slug extraction for trailing slashes
241
- - ComponentsOverviewPage uses sidebar order, removed dead code
242
- - Component count corrected to 24, added missing Logo Slider
243
- - GitHub links in Footer now point to actual repository
244
-
245
- ### Improved
246
-
247
- - Docs layout.tsx extracted to server component + DocsShell client component
248
-
249
- ## [0.5.0] — Jan 7, 2026
250
-
251
- **CLI Tool & Templates**
252
-
253
- Added a CLI for scaffolding components and a templates gallery page.
254
-
255
- ### Added
256
-
257
- - npx praxys-ui CLI with init, add, and list commands
258
- - Templates gallery page with 6 template previews
259
- - CLI docs page at /docs/cli
260
-
261
- ## [0.4.0] — Jan 4, 2026
262
-
263
- **Command Palette**
264
-
265
- Ctrl+K fuzzy search across all components and documentation pages.
266
-
267
- ### Added
268
-
269
- - Ctrl+K / Cmd+K keyboard shortcut to open search
270
- - Fuzzy matching with scoring (exact > starts with > contains > fuzzy)
271
- - Arrow key navigation and Enter to select
272
-
273
- ## [0.3.0] — Jan 2, 2026
274
-
275
- **Complete Component Library**
276
-
277
- All 24 components implemented with live previews, code examples, and props tables.
278
-
279
- ### Added
280
-
281
- - Interactive Book — 3D page-flip book component
282
- - Logo Slider — infinite marquee logo carousel
283
- - Animated Hero — cinematic hero section with parallax
284
- - Masked Avatars — overlapping avatar stack with hover reveal
285
- - Folder Preview — macOS-style folder with hover preview
286
- - Liquid Ocean, Liquid Metal, Reveal Loader — visual effects
287
- - Spotlight Navbar, Glass Dock — navigation components
288
- - Flip Fade Text, 3D Displacement Text — text effects
289
- - Testimonials Card, Staggered Grid, Expandable Bento Grid, Perspective Grid — cards & layout
290
- - Creepy Button, Social Flip Button — button variants
291
-
292
- ## [0.2.0] — Dec 22, 2025
293
-
294
- **Theme System & First Components**
295
-
296
- Light/dark mode with CSS custom properties and the first 6 animated components.
297
-
298
- ### Added
299
-
300
- - Light/dark theme toggle with localStorage persistence and FOUC prevention
301
- - Animated Button, Flip Text, Glow Border Card, Animated Number, Line Hover Link, Light Lines
302
- - Shiki dual-theme code blocks (vitesse-dark + vitesse-light)
303
- - Component preview with Preview/Code tab switcher
304
-
305
- ## [0.1.0] — Dec 15, 2025
306
-
307
- **Initial Release**
308
-
309
- Project scaffolding, design system, landing page, and docs infrastructure.
310
-
311
- ### Added
312
-
313
- - Next.js 16 project with React 19, Tailwind CSS 4, Framer Motion 12
314
- - Praxys brand palette — Void, Obsidian, Ignite, Blush, Chalk
315
- - Font stack — Geist Pixel Square, Satoshi, JetBrains Mono
316
- - Landing page with 7 sections (Navbar, Hero, Showcase, Features, Grid, CTA, Footer)
317
- - Docs with sidebar navigation and dynamic [slug] routing
318
- - Getting Started pages (Installation, Tailwind, Utilities)
319
- - Component registry architecture with lazy-loaded demos