vibe-ui-suite 4.0.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 ADDED
@@ -0,0 +1,151 @@
1
+ # vibe-ui-suite
2
+
3
+ <p align="center">
4
+ <strong>Deterministic design contracts, component recipes, and WCAG evaluation gates for AI coding agents.</strong>
5
+ </p>
6
+
7
+ <p align="center">
8
+ <a href="https://www.npmjs.com/package/vibe-ui-suite"><img src="https://img.shields.io/npm/v/vibe-ui-suite?color=blue&style=flat-square" alt="NPM Version" /></a>
9
+ <a href="https://marketplace.visualstudio.com/items?itemName=omid-io.vibe-ui-vscode"><img src="https://img.shields.io/visual-studio-marketplace/v/omid-io.vibe-ui-vscode?color=blue&style=flat-square&logo=visual-studio-code" alt="VS Code Marketplace" /></a>
10
+ <a href="https://open-vsx.org/extension/omid-io/vibe-ui-vscode"><img src="https://img.shields.io/open-vsx/v/omid-io/vibe-ui-vscode?color=blue&style=flat-square" alt="Open-VSX Version" /></a>
11
+ <a href="https://github.com/omid-io/vibe-ui-suite/blob/main/LICENSE"><img src="https://img.shields.io/badge/license-MIT-green?style=flat-square" alt="License" /></a>
12
+ </p>
13
+
14
+ ---
15
+
16
+ ## ⚡ What is Vibe UI Suite?
17
+
18
+ Modern AI coding agents (Cursor, Claude Code, Windsurf, v0) are fast, but they often produce **"AI Slop"**:
19
+ - Clichéd, low-contrast purple/indigo gradients that fail basic accessibility (WCAG AA).
20
+ - Uncalibrated spacing, broken mobile layouts, and excessive blur overlays.
21
+ - Broken bidirectional text (RTL/BiDi) and inverted business formulas.
22
+
23
+ **`vibe-ui-suite`** acts as a **machine-verifiable design linter and contrast gatekeeper**. It equips your project with typed OKLCH color spaces, physics animation curves, accessible component recipes, and automated editor rule contracts (`.cursorrules`, `CLAUDE.md`, `.windsurfrules`).
24
+
25
+ ---
26
+
27
+ ## 🚀 Quick Start (3 Seconds)
28
+
29
+ ### 1. Initialize Workspace Contracts (`init`)
30
+
31
+ Scaffold AI editor contracts and OKLCH CSS variables in your project with zero manual configuration:
32
+
33
+ ```bash
34
+ npx vibe-ui-suite init
35
+ ```
36
+
37
+ This interactive command sets up:
38
+ - `.cursorrules` / `CLAUDE.md` / `.windsurfrules` with strict anti-slop invariants.
39
+ - 5 distinct visual chemistry themes (Minimalist SaaS, Swiss Editorial, Neobrutalism, Luxury Glass 2.0, Stripe Crisp Light).
40
+ - Native Tailwind CSS v4 variables or Tailwind v3 configuration.
41
+
42
+ ---
43
+
44
+ ### 2. Add Accessible Component Primitives (`add`)
45
+
46
+ Add verified, zero-emoji, accessible React 19 component templates directly into your codebase (`components/vibe-ui/`):
47
+
48
+ ```bash
49
+ # Add an expandable reasoning / thinking trace drawer
50
+ npx vibe-ui-suite add thinking-drawer
51
+
52
+ # Add a dense telemetry HUD with live metric formatting
53
+ npx vibe-ui-suite add telemetry-hud
54
+
55
+ # Add a real-time WCAG AAA contrast indicator badge
56
+ npx vibe-ui-suite add contrast-badge
57
+ ```
58
+
59
+ ### 3. List Registry Components (`list`)
60
+
61
+ ```bash
62
+ npx vibe-ui-suite list
63
+ ```
64
+
65
+ ---
66
+
67
+ ## 🎨 Programmatic Usage
68
+
69
+ ### 1. Native Tailwind CSS v4 (`@theme`) — Recommended
70
+
71
+ In your global stylesheet (e.g. `app/globals.css` or `src/index.css`):
72
+
73
+ ```css
74
+ @import "tailwindcss";
75
+ @import "vibe-ui-suite/v4.css";
76
+ ```
77
+
78
+ Zero JavaScript configuration files required. Instantly unlocks:
79
+ - **Semantic Color Utilities:** `bg-vibe-canvas`, `bg-vibe-surface`, `text-vibe-primary`, `border-vibe-border`
80
+ - **Physics Springs:** `transition-vibe-spring`, `transition-vibe-snap`, `transition-vibe-glide`
81
+ - **Surface Elevation:** `shadow-vibe-brutal`, `shadow-vibe-glass`
82
+
83
+ ---
84
+
85
+ ### 2. Direct Token Imports (TypeScript / JavaScript)
86
+
87
+ Access typed OKLCH color spaces and mathematical contrast verification utilities:
88
+
89
+ ```typescript
90
+ import { VISUAL_CHEMISTRIES, MOTION_CURVES, getContrastRatio } from 'vibe-ui-suite';
91
+
92
+ // Access typed OKLCH color tokens
93
+ const saasColors = VISUAL_CHEMISTRIES.MINIMALIST_SAAS.colors;
94
+ console.log(saasColors.primaryAccent); // 'oklch(0.65 0.22 260)'
95
+
96
+ // Verify real-time WCAG contrast mathematics
97
+ const contrast = getContrastRatio('#0F172A', '#F8FAFC');
98
+ console.log(`Contrast ratio: ${contrast.toFixed(2)}:1`); // e.g. 15.8:1 (AAA Certified)
99
+ ```
100
+
101
+ ---
102
+
103
+ ### 3. Tailwind CSS v3 Legacy Plugin (Backward Compatible)
104
+
105
+ In your `tailwind.config.js` or `tailwind.config.ts`:
106
+
107
+ ```javascript
108
+ import vibeUiPlugin from 'vibe-ui-suite/tailwind';
109
+
110
+ export default {
111
+ content: ['./app/**/*.{js,ts,jsx,tsx}', './components/**/*.{js,ts,jsx,tsx}'],
112
+ plugins: [vibeUiPlugin],
113
+ };
114
+ ```
115
+
116
+ ---
117
+
118
+ ## 🛠️ CLI Command Reference
119
+
120
+ | Command | Description |
121
+ | :--- | :--- |
122
+ | `npx vibe-ui-suite init` | Interactively scaffold AI editor contracts & OKLCH variables |
123
+ | `npx vibe-ui-suite init --dry-run` | Preview file operations without modifying disk |
124
+ | `npx vibe-ui-suite add <name>` | Copy an accessible component primitive into `components/vibe-ui/` |
125
+ | `npx vibe-ui-suite add <name> -f` | Overwrite existing component with automated `.bak` backup |
126
+ | `npx vibe-ui-suite list` | List all available component primitives in the registry |
127
+ | `npx vibe-ui-suite -v` | Display installed version |
128
+ | `npx vibe-ui-suite -h` | Display full help menu |
129
+
130
+ ---
131
+
132
+ ## 🧩 Companion IDE Extensions
133
+
134
+ Install the companion extension for real-time contrast auditing, instant color inspection, and 1-click component templates right inside your editor:
135
+
136
+ - **VS Code Marketplace:** [`omid-io.vibe-ui-vscode`](https://marketplace.visualstudio.com/items?itemName=omid-io.vibe-ui-vscode)
137
+ - **Open-VSX Registry:** [`omid-io.vibe-ui-vscode`](https://open-vsx.org/extension/omid-io/vibe-ui-vscode) (for Cursor, Windsurf, VSCodium)
138
+
139
+ ---
140
+
141
+ ## 🌐 Community & Ecosystem
142
+
143
+ - **Documentation & Live Showcase:** [https://omid-io.github.io/vibe-ui-suite/](https://omid-io.github.io/vibe-ui-suite/)
144
+ - **GitHub Repository:** [https://github.com/omid-io/vibe-ui-suite](https://github.com/omid-io/vibe-ui-suite)
145
+ - **Issue Tracker:** [https://github.com/omid-io/vibe-ui-suite/issues](https://github.com/omid-io/vibe-ui-suite/issues)
146
+
147
+ ---
148
+
149
+ ## 📄 License
150
+
151
+ MIT © [Omid Zaferi](https://github.com/omid-io)
package/build.js ADDED
@@ -0,0 +1,23 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+
4
+ const srcDistDir = path.resolve(__dirname, '../tokens/dist');
5
+ const targetDistDir = path.resolve(__dirname, 'dist');
6
+
7
+ if (!fs.existsSync(srcDistDir)) {
8
+ console.error('Error: ../tokens/dist does not exist. Please build @omid-io/tokens first.');
9
+ process.exit(1);
10
+ }
11
+
12
+ // Copy recursively from tokens/dist to vibe-ui-suite/dist
13
+ fs.cpSync(srcDistDir, targetDistDir, { recursive: true });
14
+
15
+ // Ensure executable permission on dist/cli.js
16
+ const cliPath = path.join(targetDistDir, 'cli.js');
17
+ if (fs.existsSync(cliPath)) {
18
+ try {
19
+ fs.chmodSync(cliPath, 0o755);
20
+ } catch (e) {}
21
+ }
22
+
23
+ console.log('✅ vibe-ui-suite build complete: synchronized dist/ from tokens package.');
package/dist/cli.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/cli.js ADDED
@@ -0,0 +1,278 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
4
+ if (k2 === undefined) k2 = k;
5
+ var desc = Object.getOwnPropertyDescriptor(m, k);
6
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
7
+ desc = { enumerable: true, get: function() { return m[k]; } };
8
+ }
9
+ Object.defineProperty(o, k2, desc);
10
+ }) : (function(o, m, k, k2) {
11
+ if (k2 === undefined) k2 = k;
12
+ o[k2] = m[k];
13
+ }));
14
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
15
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
16
+ }) : function(o, v) {
17
+ o["default"] = v;
18
+ });
19
+ var __importStar = (this && this.__importStar) || (function () {
20
+ var ownKeys = function(o) {
21
+ ownKeys = Object.getOwnPropertyNames || function (o) {
22
+ var ar = [];
23
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
24
+ return ar;
25
+ };
26
+ return ownKeys(o);
27
+ };
28
+ return function (mod) {
29
+ if (mod && mod.__esModule) return mod;
30
+ var result = {};
31
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
32
+ __setModuleDefault(result, mod);
33
+ return result;
34
+ };
35
+ })();
36
+ Object.defineProperty(exports, "__esModule", { value: true });
37
+ const fs = __importStar(require("fs"));
38
+ const path = __importStar(require("path"));
39
+ const readline = __importStar(require("readline"));
40
+ const components_1 = require("./registry/components");
41
+ const index_1 = require("./index");
42
+ const VERSION = '4.0.0';
43
+ function printBanner() {
44
+ console.log(`
45
+ \x1b[35m ▲ VIBE UI CLI v${VERSION}\x1b[0m
46
+ \x1b[90mDeterministic UI contracts & component primitives for AI coding assistants\x1b[0m
47
+ `);
48
+ }
49
+ function printHelp() {
50
+ printBanner();
51
+ console.log(`\x1b[1mUSAGE:\x1b[0m
52
+ npx vibe-ui-suite <command> [options]
53
+ npx @omid-io/tokens <command> [options]
54
+ vibe-ui <command> [options]
55
+
56
+ \x1b[1mCOMMANDS:\x1b[0m
57
+ \x1b[32minit\x1b[0m Initialize Vibe UI contracts, OKLCH tokens & AI rules in current project
58
+ \x1b[32madd <component>\x1b[0m Add an accessible, AI-native component template to your project
59
+ \x1b[32mlist\x1b[0m List all available component primitives in the registry
60
+
61
+ \x1b[1mOPTIONS:\x1b[0m
62
+ -f, --force Overwrite existing files (creates automated .bak backups)
63
+ --dry-run Preview file operations without making actual modifications
64
+ -v, --version Show CLI version
65
+ -h, --help Show help menu
66
+
67
+ \x1b[1mEXAMPLES:\x1b[0m
68
+ npx vibe-ui-suite init
69
+ npx vibe-ui-suite init --dry-run
70
+ npx vibe-ui-suite add thinking-drawer
71
+ npx vibe-ui-suite add thinking-drawer --force
72
+ `);
73
+ }
74
+ function prompt(rl, query) {
75
+ return new Promise((resolve) => rl.question(query, resolve));
76
+ }
77
+ function safeWriteFile(filePath, content, options) {
78
+ const relPath = path.relative(process.cwd(), filePath);
79
+ if (options.dryRun) {
80
+ console.log(` \x1b[34m[dry-run]\x1b[0m Would write: ${relPath}`);
81
+ return { written: false, skipped: false };
82
+ }
83
+ if (fs.existsSync(filePath) && !options.force) {
84
+ console.log(` \x1b[33m[skip]\x1b[0m ${relPath} already exists. (Use --force to overwrite)`);
85
+ return { written: false, skipped: true };
86
+ }
87
+ if (fs.existsSync(filePath) && options.force) {
88
+ const backupPath = `${filePath}.bak`;
89
+ fs.copyFileSync(filePath, backupPath);
90
+ fs.writeFileSync(filePath, content, 'utf-8');
91
+ console.log(` \x1b[35m[backup]\x1b[0m Backed up existing file to ${path.relative(process.cwd(), backupPath)}`);
92
+ return { written: true, skipped: false, backup: backupPath };
93
+ }
94
+ fs.writeFileSync(filePath, content, 'utf-8');
95
+ return { written: true, skipped: false };
96
+ }
97
+ const CONTRACT_RULES = `# Vibe UI Design & Code Quality Contract
98
+ # Generated via npx vibe-ui-suite init
99
+
100
+ Follow strict anti-slop guidelines:
101
+ - Zero raw unicode emojis (use inline SVGs only)
102
+ - Strict WCAG 2.2 AA contrast (>= 4.5:1 body, >= 3.0:1 headings)
103
+ - Use typed OKLCH color spaces for perceptual accuracy
104
+ - Strict maximum of 3 backdrop-filter / glass layers
105
+ - Semantic RTL: preserve physical macro coordinate stability
106
+ `;
107
+ async function handleInit(options) {
108
+ printBanner();
109
+ if (options.dryRun) {
110
+ console.log('\x1b[34m[DRY-RUN MODE ACTIVATED: No files will be modified on disk]\x1b[0m\n');
111
+ }
112
+ const rl = readline.createInterface({
113
+ input: process.stdin,
114
+ output: process.stdout,
115
+ });
116
+ try {
117
+ console.log('\x1b[1mInitialize Vibe UI in current workspace:\x1b[0m\n');
118
+ // 1. Select Visual Chemistry
119
+ console.log('\x1b[36m1. Select Visual Chemistry:\x1b[0m');
120
+ console.log(' [1] Minimalist SaaS (Monochrome restraint, high signal - Recommended)');
121
+ console.log(' [2] Luxury Glass 2.0 (Specular Fresnel, deep dark, gold accents)');
122
+ console.log(' [3] Neobrutalism (Hard 3px black offset shadows, bold high saturation)');
123
+ console.log(' [4] Swiss Editorial (Asymmetric grid, typography-first, high contrast)');
124
+ console.log(' [5] Stripe Crisp Light (Developer docs, precision micro-borders)');
125
+ const chemChoice = (await prompt(rl, 'Choice [1-5] (default: 1): ')).trim() || '1';
126
+ const chemMap = {
127
+ '1': 'MINIMALIST_SAAS',
128
+ '2': 'LUXURY_GLASS_2',
129
+ '3': 'NEOBRUTALISM',
130
+ '4': 'SWISS_EDITORIAL',
131
+ '5': 'STRIPE_CRISP_LIGHT',
132
+ };
133
+ const selectedChemKey = chemMap[chemChoice] || 'MINIMALIST_SAAS';
134
+ const selectedChem = index_1.VISUAL_CHEMISTRIES[selectedChemKey];
135
+ // 2. Select AI Editor
136
+ console.log('\n\x1b[36m2. Select AI Coding Environment:\x1b[0m');
137
+ console.log(' [1] Cursor (.cursorrules - Recommended)');
138
+ console.log(' [2] Claude Code (CLAUDE.md)');
139
+ console.log(' [3] Windsurf (.windsurfrules)');
140
+ console.log(' [4] All of the above');
141
+ const editorChoice = (await prompt(rl, 'Choice [1-4] (default: 1): ')).trim() || '1';
142
+ // 3. Write contract rules safely
143
+ const cwd = process.cwd();
144
+ const createdFiles = [];
145
+ if (editorChoice === '1' || editorChoice === '4') {
146
+ const res = safeWriteFile(path.join(cwd, '.cursorrules'), CONTRACT_RULES, options);
147
+ if (res.written)
148
+ createdFiles.push('.cursorrules');
149
+ }
150
+ if (editorChoice === '2' || editorChoice === '4') {
151
+ const claudePath = path.join(cwd, 'CLAUDE.md');
152
+ if (options.dryRun) {
153
+ console.log(' \x1b[34m[dry-run]\x1b[0m Would update CLAUDE.md');
154
+ }
155
+ else if (fs.existsSync(claudePath)) {
156
+ fs.appendFileSync(claudePath, `\n\n${CONTRACT_RULES}`, 'utf-8');
157
+ createdFiles.push('CLAUDE.md (appended)');
158
+ }
159
+ else {
160
+ const res = safeWriteFile(claudePath, CONTRACT_RULES, options);
161
+ if (res.written)
162
+ createdFiles.push('CLAUDE.md');
163
+ }
164
+ }
165
+ if (editorChoice === '3' || editorChoice === '4') {
166
+ const res = safeWriteFile(path.join(cwd, '.windsurfrules'), CONTRACT_RULES, options);
167
+ if (res.written)
168
+ createdFiles.push('.windsurfrules');
169
+ }
170
+ // 4. Generate CSS Tokens file safely
171
+ const cssContent = `:root {
172
+ /* Vibe UI Chemistry: ${selectedChem.name} (${selectedChem.id}) */
173
+ --vibe-canvas: ${selectedChem.colors.canvas};
174
+ --vibe-surface: ${selectedChem.colors.surface};
175
+ --vibe-border: ${selectedChem.colors.border};
176
+ --vibe-primary-accent: ${selectedChem.colors.primaryAccent};
177
+ --vibe-text-primary: ${selectedChem.colors.textPrimary};
178
+ --vibe-text-muted: ${selectedChem.colors.textMuted};
179
+ --vibe-ring: ${selectedChem.colors.ring};
180
+ }
181
+ `;
182
+ const cssPath = path.join(cwd, 'vibe-tokens.css');
183
+ const cssRes = safeWriteFile(cssPath, cssContent, options);
184
+ if (cssRes.written)
185
+ createdFiles.push('vibe-tokens.css');
186
+ console.log('\n\x1b[32m✔ Initialized successfully!\x1b[0m');
187
+ if (createdFiles.length > 0) {
188
+ console.log('\x1b[90mGenerated/Updated files:\x1b[0m');
189
+ createdFiles.forEach((f) => console.log(` + ${f}`));
190
+ }
191
+ console.log(`
192
+ \x1b[1mNext Steps:\x1b[0m
193
+ 1. Import \x1b[35mvibe-tokens.css\x1b[0m into your layout or globals.css
194
+ 2. Run \x1b[32mnpx @omid-io/tokens add thinking-drawer\x1b[0m to add your first AI component
195
+ `);
196
+ }
197
+ finally {
198
+ rl.close();
199
+ }
200
+ }
201
+ function handleAdd(componentName, options = { force: false, dryRun: false }) {
202
+ if (!componentName) {
203
+ console.log('\x1b[33mError: Please specify a component to add.\x1b[0m\n');
204
+ handleList();
205
+ console.log('\nUsage: npx @omid-io/tokens add <component> [--force]');
206
+ process.exit(1);
207
+ return;
208
+ }
209
+ const comp = components_1.COMPONENT_REGISTRY[componentName.toLowerCase()];
210
+ if (!comp) {
211
+ console.log(`\x1b[31mError: Unknown component "${componentName}".\x1b[0m\n`);
212
+ handleList();
213
+ process.exit(1);
214
+ return;
215
+ }
216
+ const cwd = process.cwd();
217
+ const targetDir = path.join(cwd, 'components', 'vibe-ui');
218
+ if (!options.dryRun) {
219
+ fs.mkdirSync(targetDir, { recursive: true });
220
+ }
221
+ const targetFile = path.join(targetDir, comp.filename);
222
+ const writeRes = safeWriteFile(targetFile, comp.code, options);
223
+ if (writeRes.skipped) {
224
+ console.log(`\n\x1b[33mWarning: Component already exists at components/vibe-ui/${comp.filename}\x1b[0m`);
225
+ console.log(`To overwrite with automated .bak backup, re-run with:`);
226
+ console.log(` \x1b[32mnpx @omid-io/tokens add ${componentName} --force\x1b[0m\n`);
227
+ return;
228
+ }
229
+ if (writeRes.written) {
230
+ console.log(`\x1b[32m✔ Added component "${comp.name}"!\x1b[0m`);
231
+ console.log(` \x1b[90mLocation:\x1b[0m components/vibe-ui/${comp.filename}`);
232
+ console.log(` \x1b[90mDescription:\x1b[0m ${comp.description}\n`);
233
+ console.log(`\x1b[1mUsage in your page or view:\x1b[0m`);
234
+ console.log(` import { ${comp.filename.replace('.tsx', '')} } from '@/components/vibe-ui/${comp.filename.replace('.tsx', '')}';\n`);
235
+ }
236
+ }
237
+ function handleList() {
238
+ console.log('\x1b[1mAvailable Vibe UI Components:\x1b[0m');
239
+ Object.values(components_1.COMPONENT_REGISTRY).forEach((comp) => {
240
+ console.log(` \x1b[32m${comp.name.padEnd(18)}\x1b[0m \x1b[90m${comp.description}\x1b[0m`);
241
+ });
242
+ }
243
+ async function main() {
244
+ const rawArgs = process.argv.slice(2);
245
+ const force = rawArgs.includes('--force') || rawArgs.includes('-f');
246
+ const dryRun = rawArgs.includes('--dry-run');
247
+ const filteredArgs = rawArgs.filter((a) => !['--force', '-f', '--dry-run'].includes(a));
248
+ const cmd = filteredArgs[0]?.toLowerCase();
249
+ const options = { force, dryRun };
250
+ if (!cmd || cmd === '--help' || cmd === '-h') {
251
+ printHelp();
252
+ return;
253
+ }
254
+ if (cmd === '--version' || cmd === '-v') {
255
+ console.log(`v${VERSION}`);
256
+ return;
257
+ }
258
+ switch (cmd) {
259
+ case 'init':
260
+ await handleInit(options);
261
+ break;
262
+ case 'add':
263
+ handleAdd(filteredArgs[1], options);
264
+ break;
265
+ case 'list':
266
+ printBanner();
267
+ handleList();
268
+ break;
269
+ default:
270
+ console.log(`\x1b[31mUnknown command "${cmd}".\x1b[0m`);
271
+ printHelp();
272
+ process.exit(1);
273
+ }
274
+ }
275
+ main().catch((err) => {
276
+ console.error('\x1b[31mFatal CLI error:\x1b[0m', err);
277
+ process.exit(1);
278
+ });