smoothui-cli 1.0.4 → 1.0.5

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.github.md CHANGED
@@ -1,413 +1,71 @@
1
- # SmoothUI
1
+ # smoothui-cli
2
2
 
3
- ![Screenshot of SmoothUI](/apps/docs/public/readme.png)
3
+ CLI to install [SmoothUI](https://smoothui.dev) components - beautifully designed React components with smooth animations.
4
4
 
5
- <div align="center">
6
-
7
- ![Next.js Badge](https://img.shields.io/badge/Next.js-000?logo=nextdotjs&logoColor=fff&style=flat)
8
- ![Tailwind CSS Badge](https://img.shields.io/badge/Tailwind%20CSS-06B6D4?logo=tailwindcss&logoColor=fff&style=flat)
9
- ![Motion Badge](https://img.shields.io/badge/Motion-ECD53F?style=flat)
10
-
11
- [![Build Status](https://img.shields.io/endpoint.svg?url=https%3A%2F%2Factions-badge.atrox.dev%2Fpheralb%2Fsvgl%2Fbadge%3Fref%3Dmain&style=flat)](https://actions-badge.atrox.dev/educlopez/smoothui/goto?ref=main)
12
- ![GitHub stars](https://img.shields.io/github/stars/educlopez/smoothui)
13
- ![GitHub issues](https://img.shields.io/github/issues/educlopez/smoothui)
14
- ![GitHub forks](https://img.shields.io/github/forks/educlopez/smoothui)
15
- ![GitHub PRs](https://img.shields.io/github/issues-pr/educlopez/smoothui)
16
- [![Website](https://img.shields.io/badge/website-smoothui.dev-blue)](https://smoothui.dev)
17
-
18
- </div>
19
-
20
- SmoothUI is a collection of beautifully designed components with smooth animations built with React, Tailwind CSS, and Motion. This project aims to provide developers with a set of reusable UI components that enhance user experience through delightful animations and modern design patterns.
21
-
22
- ## Table of Contents
23
-
24
- - [SmoothUI](#smoothui)
25
- - [Table of Contents](#table-of-contents)
26
- - [Features](#features)
27
- - [Quick Start](#quick-start)
28
- - [Installation](#installation)
29
- - [Using SmoothUI CLI](#using-smoothui-cli)
30
- - [Using shadcn CLI](#using-shadcn-cli)
31
- - [Manual Installation](#manual-installation)
32
- - [Usage](#usage)
33
- - [Basic Usage](#basic-usage)
34
- - [Advanced Usage](#advanced-usage)
35
- - [Available Components](#available-components)
36
- - [UI Components](#ui-components)
37
- - [Interactive Components](#interactive-components)
38
- - [Layout Components](#layout-components)
39
- - [Utility Components](#utility-components)
40
- - [MCP Support](#mcp-support)
41
- - [🤖 AI Assistant Integration](#-ai-assistant-integration)
42
- - [Quick MCP Setup](#quick-mcp-setup)
43
- - [Registry System](#registry-system)
44
- - [Automatic Dependencies](#automatic-dependencies)
45
- - [Component Structure](#component-structure)
46
- - [Registry Features](#registry-features)
47
- - [Troubleshooting](#troubleshooting)
48
- - [Common Issues](#common-issues)
49
- - [1. Authentication Error (401)](#1-authentication-error-401)
50
- - [2. Registry Not Found](#2-registry-not-found)
51
- - [3. Import Path Issues](#3-import-path-issues)
52
- - [4. Missing Dependencies](#4-missing-dependencies)
53
- - [Getting Help](#getting-help)
54
- - [Contributing](#contributing)
55
- - [Development Setup](#development-setup)
56
- - [License](#license)
57
-
58
- ## Features
59
-
60
- - **Modern Design System**: A cohesive and contemporary design language with a new mascot called Smoothy
61
- - **Smooth Animations**: Built-in animations powered by Motion for delightful user experiences
62
- - **Responsive Design**: Fully responsive components designed with Tailwind CSS
63
- - **Dark Mode Support**: Components support both light and dark themes out of the box
64
- - **Color Customization**: Dynamic color switcher for easy theme customization
65
- - **Documentation**: Comprehensive documentation with props, examples, and usage guidelines
66
- - **Accessibility**: Enhanced accessibility features across all components
67
- - **TypeScript Support**: Full TypeScript support with type definitions
68
- - **Easy Integration**: Simple API for integrating components into your projects
69
- - **CLI Tools**: Dedicated SmoothUI CLI and shadcn registry support for easy component installation
70
-
71
- ## Quick Start
72
-
73
- Get started with SmoothUI in just one command:
5
+ ## Installation
74
6
 
75
7
  ```bash
76
- # Using SmoothUI CLI (recommended)
77
8
  npx smoothui-cli add siri-orb
78
-
79
- # Or using shadcn CLI
80
- npx shadcn@latest add @smoothui/siri-orb
81
- ```
82
-
83
- Then use the component:
84
-
85
- ```tsx
86
- import { SiriOrb } from "@/components/smoothui/ui/SiriOrb";
87
-
88
- export default function App() {
89
- return <SiriOrb size="200px" />;
90
- }
91
9
  ```
92
10
 
93
- ## Installation
94
-
95
- ### Using SmoothUI CLI
11
+ ## Usage
96
12
 
97
- The SmoothUI CLI provides an interactive way to browse and install components with automatic dependency resolution.
13
+ ### Add components
98
14
 
99
15
  ```bash
100
16
  # Add a single component
101
17
  npx smoothui-cli add siri-orb
102
18
 
103
19
  # Add multiple components
104
- npx smoothui-cli add siri-orb rich-popover animated-input
20
+ npx smoothui-cli add siri-orb grid-loader animated-tabs
105
21
 
106
- # Interactive mode - browse and select components
22
+ # Interactive mode - browse and select
107
23
  npx smoothui-cli add
108
-
109
- # List all available components
110
- npx smoothui-cli list
111
- ```
112
-
113
- **Features:**
114
-
115
- - Interactive component picker with search and categories
116
- - Auto-detects package manager (npm, pnpm, yarn, bun)
117
- - Auto-detects component paths and tsconfig aliases
118
- - Shows dependency tree before installation
119
- - Handles file conflicts with overwrite prompts
120
- - Auto-installs npm dependencies
121
-
122
- ### Using shadcn CLI
123
-
124
- SmoothUI is an official shadcn registry, so you can install components directly using the `@smoothui` namespace:
125
-
126
- ```bash
127
- # Install a single component
128
- npx shadcn@latest add @smoothui/siri-orb
129
-
130
- # Install multiple components
131
- npx shadcn@latest add @smoothui/rich-popover @smoothui/animated-input
132
24
  ```
133
25
 
134
- ### Manual Installation
135
-
136
- If you prefer to install components manually, you can copy the component files directly:
137
-
138
- 1. **Install dependencies**:
26
+ ### List components
139
27
 
140
28
  ```bash
141
- pnpm add motion tailwindcss lucide-react clsx tailwind-merge
142
- ```
143
-
144
- 2. **Copy component files** from the [components directory](src/components/smoothui/ui/)
145
-
146
- 3. **Set up utilities**:
147
-
148
- ```bash
149
- # Create lib/utils/cn.ts
150
- mkdir -p lib/utils
151
- ```
152
-
153
- ```tsx
154
- // lib/utils/cn.ts
155
- import { clsx, type ClassValue } from "clsx";
156
- import { twMerge } from "tailwind-merge";
157
-
158
- export function cn(...inputs: ClassValue[]) {
159
- return twMerge(clsx(inputs));
160
- }
161
- ```
162
-
163
- ## Usage
164
-
165
- ### Basic Usage
166
-
167
- ```tsx
168
- import { SiriOrb } from "@/components/smoothui/ui/SiriOrb";
169
-
170
- export default function App() {
171
- return (
172
- <div className="flex min-h-screen items-center justify-center">
173
- <SiriOrb
174
- size="200px"
175
- colors={{
176
- bg: "oklch(95% 0.02 264.695)",
177
- c1: "oklch(75% 0.15 350)",
178
- c2: "oklch(80% 0.12 200)",
179
- c3: "oklch(78% 0.14 280)",
180
- }}
181
- animationDuration={20}
182
- />
183
- </div>
184
- );
185
- }
186
- ```
187
-
188
- ### Advanced Usage
189
-
190
- ```tsx
191
- import { RichPopover } from "@/components/smoothui/ui/RichPopover";
192
- import { ScrollableCardStack } from "@/components/smoothui/ui/ScrollableCardStack";
193
-
194
- export default function Dashboard() {
195
- const cards = [
196
- {
197
- id: "1",
198
- name: "John Doe",
199
- handle: "@johndoe",
200
- avatar: "/avatars/john.jpg",
201
- video: "/videos/john.mp4",
202
- href: "https://twitter.com/johndoe",
203
- },
204
- // ... more cards
205
- ];
206
-
207
- return (
208
- <div className="space-y-8">
209
- <RichPopover />
210
- <ScrollableCardStack items={cards} />
211
- </div>
212
- );
213
- }
214
- ```
215
-
216
- ## Available Components
217
-
218
- SmoothUI includes a wide variety of components:
219
-
220
- ### UI Components
221
-
222
- - **SiriOrb** - Animated orb with smooth color transitions
223
- - **RichPopover** - Advanced popover with rich content
224
- - **ScrollableCardStack** - Interactive card stack with smooth scrolling
225
- - **AnimatedInput** - Input field with smooth animations
226
- - **DynamicIsland** - iOS-style dynamic island component
227
- - **FluidMorph** - Fluid morphing animations
228
- - **MatrixCard** - Matrix-style card with particle effects
229
-
230
- ### Interactive Components
231
-
232
- - **CursorFollow** - Custom cursor following component
233
- - **ScrambleHover** - Text scramble effect on hover
234
- - **WaveText** - Animated wave text effect
235
- - **TypewriterText** - Typewriter text animation
236
-
237
- ### Layout Components
238
-
239
- - **ExpandableCards** - Expandable card layout
240
- - **ScrollableCardStack** - Stack of scrollable cards
241
- - **AppDownloadStack** - App download showcase
242
-
243
- ### Utility Components
244
-
245
- - **ButtonCopy** - Copy button with feedback
246
- - **ClipCornersButton** - Button with clipped corners
247
- - **DotMorphButton** - Button with morphing dot animation
248
-
249
- [View all components →](https://smoothui.dev)
250
-
251
- ## MCP Support
252
-
253
- SmoothUI is fully compatible with the **shadcn MCP server**, enabling AI assistants to discover and install components automatically.
254
-
255
- ### 🤖 AI Assistant Integration
256
-
257
- With MCP support, AI assistants like **Claude**, **Cursor**, and **GitHub Copilot** can:
258
-
259
- - **Discover Components**: Browse all available SmoothUI components
260
- - **Install Components**: Automatically install components with dependencies
261
- - **Provide Usage Examples**: Get code examples and integration help
262
- - **Smart Suggestions**: Receive intelligent component recommendations
263
-
264
- ### Quick MCP Setup
265
-
266
- 1. **Configure your registry** in `components.json`:
29
+ # Show all available components
30
+ npx smoothui-cli list
267
31
 
268
- ```json
269
- {
270
- "registries": {
271
- "@smoothui": "https://smoothui.dev/r/{name}.json"
272
- }
273
- }
32
+ # JSON output
33
+ npx smoothui-cli list --json
274
34
  ```
275
35
 
276
- 2. **Install MCP server**:
36
+ ### Options
277
37
 
278
38
  ```bash
279
- npx shadcn@latest mcp init --client claude
280
- # or for Cursor: npx shadcn@latest mcp init --client cursor
281
- # or for VS Code: npx shadcn@latest mcp init --client vscode
282
- ```
283
-
284
- 3. **Try these prompts**:
285
-
286
- - "Show me the components in the smoothui registry"
287
- - "Install the SiriOrb component from smoothui"
288
- - "Create a landing page using smoothui components"
289
-
290
- [Learn more about MCP support →](https://smoothui.dev/doc/mcp)
291
-
292
- ## Registry System
293
-
294
- SmoothUI uses a custom registry system compatible with shadcn CLI v3. Each component includes:
39
+ # Custom install path
40
+ npx smoothui-cli add siri-orb --path src/components/ui
295
41
 
296
- ### Automatic Dependencies
297
-
298
- - **Package Dependencies**: Required npm packages are automatically included
299
- - **Utility Files**: Shared utilities like `cn` are automatically bundled
300
- - **Import Paths**: All import paths are automatically resolved
301
-
302
- ### Component Structure
303
-
304
- When you install a component, you get:
305
-
306
- ```
307
- components/smoothui/ui/
308
- ├── ComponentName.tsx # Main component file
309
- lib/utils/
310
- └── cn.ts # Utility functions (if needed)
42
+ # Force overwrite existing files
43
+ npx smoothui-cli add siri-orb --force
311
44
  ```
312
45
 
313
- ### Registry Features
314
-
315
- - **Self-contained**: Each component includes all necessary dependencies
316
- - **Type-safe**: Full TypeScript support with proper types
317
- - **Optimized**: Components are optimized for performance
318
- - **Accessible**: Built-in accessibility features
319
-
320
- ## Troubleshooting
321
-
322
- ### Common Issues
323
-
324
- #### 1. Authentication Error (401)
325
-
326
- **Error**: `You are not authorized to access the item`
327
-
328
- **Solution**: This usually happens with Vercel preview deployments. Use the production URL:
329
-
330
- ```json
331
- {
332
- "registries": {
333
- "@smoothui": "https://smoothui.dev/r/{name}.json"
334
- }
335
- }
336
- ```
46
+ ## Features
337
47
 
338
- #### 2. Registry Not Found
48
+ - Interactive component picker with search and categories
49
+ - Auto-detects package manager (npm, pnpm, yarn, bun)
50
+ - Auto-detects component paths and tsconfig aliases
51
+ - Shows dependency tree before installation
52
+ - Handles file conflicts with overwrite prompts
53
+ - Auto-installs npm dependencies
339
54
 
340
- **Error**: `The item at https://smoothui.dev/r/registry.json was not found`
55
+ ## Alternative: shadcn CLI
341
56
 
342
- **Solution**: The search command might not work as expected. Install components directly:
57
+ You can also use the shadcn CLI with the `@smoothui` registry:
343
58
 
344
59
  ```bash
345
60
  npx shadcn@latest add @smoothui/siri-orb
346
61
  ```
347
62
 
348
- #### 3. Import Path Issues
349
-
350
- **Error**: `Cannot find module '@/lib/utils/cn'`
351
-
352
- **Solution**: Make sure your `tsconfig.json` includes the path alias:
353
-
354
- ```json
355
- {
356
- "compilerOptions": {
357
- "paths": {
358
- "@/*": ["./src/*"]
359
- }
360
- }
361
- }
362
- ```
363
-
364
- #### 4. Missing Dependencies
365
-
366
- **Error**: `Cannot find module 'clsx'`
367
-
368
- **Solution**: Install missing dependencies:
369
-
370
- ```bash
371
- pnpm add clsx tailwind-merge motion
372
- ```
373
-
374
- ### Getting Help
375
-
376
- - **Documentation**: Visit [smoothui.dev](https://smoothui.dev) for detailed documentation
377
- - **Issues**: Report bugs on [GitHub Issues](https://github.com/educlopez/smoothui/issues)
378
- - **Discussions**: Join discussions on [GitHub Discussions](https://github.com/educlopez/smoothui/discussions)
379
-
380
- ## Contributing
381
-
382
- We welcome contributions! Please see our [Contributing Guide](CONTRIBUTING.md) for details.
63
+ ## Links
383
64
 
384
- ### Development Setup
385
-
386
- 1. **Clone the repository**:
387
-
388
- ```bash
389
- git clone https://github.com/educlopez/smoothui.git
390
- cd smoothui
391
- ```
392
-
393
- 2. **Install dependencies**:
394
-
395
- ```bash
396
- pnpm install
397
- ```
398
-
399
- 3. **Start development server**:
400
-
401
- ```bash
402
- pnpm dev
403
- ```
404
-
405
- 4. **Build registry**:
406
-
407
- ```bash
408
- pnpm run build:registry
409
- ```
65
+ - [Documentation](https://smoothui.dev)
66
+ - [Components](https://smoothui.dev/docs/components)
67
+ - [GitHub](https://github.com/educlopez/smoothui)
410
68
 
411
69
  ## License
412
70
 
413
- This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
71
+ MIT
package/dist/index.js CHANGED
@@ -1,2 +1,2 @@
1
1
  #!/usr/bin/env node
2
- import{confirm as Le,isCancel as ne,select as Ne,spinner as De}from"@clack/prompts";var _="https://smoothui.dev",k={"Basic UI":["accordion","animated-input","animated-progress-bar","animated-tabs","animated-toggle","basic-dropdown","basic-modal","basic-toast","notification-badge","searchable-dropdown","skeleton-loader","tweet-card"],Buttons:["button-copy","clip-corners-button","dot-morph-button","magnetic-button"],"Text Effects":["wave-text","reveal-text","typewriter-text","scramble-hover","scroll-reveal-paragraph"],AI:["ai-branch","ai-input"],"Cards & Layouts":["expandable-cards","glow-hover-card","scrollable-card-stack","switchboard-card","phototab","job-listing-component"],"Loaders & Effects":["grid-loader","siri-orb","cursor-follow","github-stars-animation"],Interactive:["animated-o-t-p-input","animated-tags","app-download-stack","apple-invites","contribution-graph","dynamic-island","figma-comment","image-metadata-preview","infinite-slider","interactive-image-selector","number-flow","power-off-slide","price-flow","rich-popover","reviews-carousel","social-selector","user-account-avatar"]},K=["src/components/ui","components/ui","src/components","components","app/components/ui"],Y=[{file:"bun.lockb",cmd:"bun"},{file:"pnpm-lock.yaml",cmd:"pnpm"},{file:"yarn.lock",cmd:"yarn"},{file:"package-lock.json",cmd:"npm"}],d={active:"\u25C6",done:"\u25C7",selected:"\u25CF",unselected:"\u25CB",cursor:"\u276F",success:"\u2713",error:"\u2717",bar:"\u2502"};import{createInterface as le,emitKeypressEvents as pe}from"readline";import p from"picocolors";var me=e=>{let t=new Map;for(let o of e){let n=o.category||"Other";t.has(n)||t.set(n,[]),t.get(n)?.push(o)}return t},de=(e,t)=>{console.log(`${p.cyan(d.active)} ${e}`),console.log(`${p.dim(d.bar)}`),console.log(`${p.dim(d.bar)} Search: ${t}${p.dim("\u258C")}`),console.log(`${p.dim(d.bar)}`)},fe=(e,t,o)=>{let n=t?p.green(d.selected):p.dim(d.unselected),s=o?p.cyan(d.cursor):" ",r=o?p.cyan(e.label):e.label;console.log(`${p.dim(d.bar)} ${s} ${n} ${r}`)},ge=e=>{console.log(`${p.dim(d.bar)}`),console.log(`${p.dim(d.bar)} ${p.dim(`${e} selected \u2502 \u2191\u2193 navigate \u2502 space select \u2502 enter confirm \u2502 esc cancel`)}`)},ue=(e,t,o)=>{let n=0,s=t.scrollOffset,r=t.scrollOffset+o;for(let[c,a]of e){if(n>=r)break;n>=s&&console.log(`${p.dim(d.bar)} ${p.bold(p.dim(c))}`),n++;for(let i of a){if(n>=r)break;if(n>=s){let m=t.selected.has(i.value),l=n-1===t.cursorIndex;fe(i,m,l)}n++}}},he=(e,t,o,n)=>()=>{let s=B(t,o.searchQuery);process.stdout.write("\x1B[2J\x1B[H"),de(e,o.searchQuery);let r=me(s);ue(r,o,n),ge(o.selected.size)},B=(e,t)=>{if(!t)return e;let o=t.toLowerCase();return e.filter(n=>n.label.toLowerCase().includes(o)||n.category?.toLowerCase().includes(o))},ye=(e,t,o,n)=>{e.name==="up"?(t.cursorIndex=Math.max(0,t.cursorIndex-1),t.cursorIndex<t.scrollOffset&&(t.scrollOffset=t.cursorIndex)):e.name==="down"&&(t.cursorIndex=Math.min(o-1,t.cursorIndex+1),t.cursorIndex>=t.scrollOffset+n&&(t.scrollOffset=t.cursorIndex-n+1))},be=(e,t)=>{let o=t[e.cursorIndex];o&&(e.selected.has(o.value)?e.selected.delete(o.value):e.selected.add(o.value))},xe=(e,t,o)=>{t.name==="backspace"?(o.searchQuery=o.searchQuery.slice(0,-1),o.cursorIndex=0,o.scrollOffset=0):e&&e.length===1&&!t.ctrl&&!t.meta&&(o.searchQuery+=e,o.cursorIndex=0,o.scrollOffset=0)},Q=e=>{process.stdin.isTTY&&process.stdin.setRawMode(!1),e.close()},H=e=>{let{message:t,items:o,maxVisible:n=10}=e;return new Promise(s=>{let r={selected:new Set,searchQuery:"",cursorIndex:0,scrollOffset:0},c=le({input:process.stdin,output:process.stdout});process.stdin.isTTY&&process.stdin.setRawMode(!0),pe(process.stdin,c);let a=he(t,o,r,n),i=(m,l)=>{let b=B(o,r.searchQuery),R=b.length;if(l.name==="escape"||l.ctrl&&l.name==="c"){Q(c),s(null);return}if(l.name==="return"){Q(c),s([...r.selected]);return}l.name==="up"||l.name==="down"?ye(l,r,R,n):l.name==="space"?be(r,b):xe(m,l,r),a()};process.stdin.on("keypress",i),a()})};import v from"picocolors";var O=d,C=v.dim,ve=v.cyan,we=v.green,Se=v.red,He=v.yellow,L=v.bold,N=v.gray;function T(e,t){console.log(`${e} ${t}`)}function j(e){T(ve(O.active),e)}function y(e){T(C(O.done),e)}function J(e){T(we(O.success),e)}function P(e){T(Se(O.error),e)}function g(e=""){console.log(`${C(O.bar)} ${e}`)}function I(){console.log(),j(L("SmoothUI")),console.log()}import{existsSync as M,readFileSync as W}from"fs";import{join as E}from"path";var Ie=/^(npm|pnpm|yarn|bun)@/,$e=()=>{let e=process.cwd();for(let{file:o,cmd:n}of Y)if(M(E(e,o)))return n;let t=E(e,"package.json");if(M(t))try{let o=JSON.parse(W(t,"utf-8"));if(o.packageManager){let n=o.packageManager.match(Ie);if(n)return n[1]}}catch{}return"npm"},Oe=()=>{let e=process.cwd();for(let t of K)if(M(E(e,t)))return t;return null},Ce=()=>{let e=process.cwd(),t=["tsconfig.json","jsconfig.json"];for(let o of t){let n=E(e,o);if(M(n))try{let r=W(n,"utf-8").replace(/\/\*[\s\S]*?\*\/|\/\/.*/g,""),a=JSON.parse(r).compilerOptions?.paths;if(a){for(let[i,m]of Object.entries(a))if(i.endsWith("/*")&&Array.isArray(m))return i.slice(0,-2)}}catch{}}return"@"},q=()=>({componentPath:Oe()||"components/ui",alias:Ce(),packageManager:$e()});import{spawnSync as je}from"child_process";import{existsSync as z,mkdirSync as Pe,readFileSync as et,writeFileSync as Re}from"fs";import{dirname as ke,join as Te}from"path";var Me=(e,t)=>t==="@"?e:e.replace(/@\/components\//g,`${t}/components/`);var V=async(e,t,o,n)=>{let s=[],r=[],c=o;for(let a of e.files){let i=Te(process.cwd(),t.componentPath,a.path),m=ke(i);if(z(m)||Pe(m,{recursive:!0}),z(i)&&!c){let b=await n(a.path);if(b==="skip"){r.push(a.path);continue}b==="all"&&(c=!0)}let l=Me(a.content,t.alias);Re(i,l,"utf-8"),s.push(a.path)}return{written:s,skipped:r}},X=(e,t)=>{if(e.length===0)return!0;let o={npm:["npm","install",...e],pnpm:["pnpm","add",...e],yarn:["yarn","add",...e],bun:["bun","add",...e]},[n,...s]=o[t];return je(n,s,{stdio:"pipe",shell:!0}).status===0};var Z=process.env.SMOOTHUI_REGISTRY_URL||_,Ee=/\/r\/([^/]+)\.json$/;async function Ae(){let e=`${Z}/r/registry.json`,t=await fetch(e);if(!t.ok)throw new Error(`Failed to fetch registry: ${t.status}`);return t.json()}async function ee(e){let t=`${Z}/r/${e}.json`,o=await fetch(t);if(!o.ok)throw new Error(`Component "${e}" not found`);return o.json()}function te(e){let t=e.match(Ee);return t?t[1]:e}async function A(){return(await Ae()).items.map(t=>t.name)}async function D(e,t=new Set){let o=await ee(e);t.add(e);let n=[];if(o.registryDependencies)for(let s of o.registryDependencies){let r=te(s);if(t.has(r)||!s.includes("smoothui.dev"))continue;let c=await D(r,t);n.push(c)}return{component:o,children:n}}function F(e){let t=[e.component];for(let o of e.children)t.push(...F(o));return t}function oe(e){let t=new Set,o=new Set,n=new Set(["react","react-dom","next","tailwindcss","@types/react","@types/react-dom","@types/node","typescript"]);for(let s of e){for(let r of s.dependencies||[])n.has(r)||t.add(r);for(let r of s.devDependencies||[])n.has(r)||o.add(r)}return{dependencies:[...t],devDependencies:[...o]}}function U(e,t="",o=!0){g(`${t}${o?"\u2514\u2500":"\u251C\u2500"} ${e.component.name}`);let s=t+(o?" ":"\u2502 "),r=[...e.component.dependencies||[]].filter(c=>!["react","react-dom","next"].includes(c));r.length>0&&e.children.length===0&&g(`${s}\u2514\u2500 ${N(`npm: ${r.join(", ")}`)}`);for(let c=0;c<e.children.length;c++){let a=e.children[c],i=c===e.children.length-1&&r.length===0;U(a,s,i)}r.length>0&&e.children.length>0&&g(`${s}\u2514\u2500 ${N(`npm: ${r.join(", ")}`)}`)}async function re(e,t){I();let o=q();t.path&&(o.componentPath=t.path),y(`Detected: ${o.componentPath}/ (${o.packageManager})`),console.log();let n=e;if(n.length===0){let h=(await A()).map(f=>{let S="Other";for(let[ie,ae]of Object.entries(k))if(ae.includes(f)){S=ie;break}return{value:f,label:f,category:S}}),x=await H({message:"Select components to install:",items:h});if(!x||x.length===0){console.log(),y("No components selected.");return}n=x,y(`Selected: ${n.join(", ")}`),console.log()}j("Resolving dependencies..."),g();let s=[],r=new Set;for(let u of n)try{let h=await D(u,r),x=F(h);for(let f of x)r.has(f.name)||(r.add(f.name),s.push(f));U(h)}catch(h){P(`Failed to resolve ${u}: ${h.message}`);return}g();let{dependencies:c,devDependencies:a}=oe(s),i=[...c,...a],m=s.length,l=i.length,b=l>0?`Install ${m} component${m>1?"s":""} + ${l} npm package${l>1?"s":""}?`:`Install ${m} component${m>1?"s":""}?`,R=await Le({message:b});if(ne(R)||!R){y("Installation cancelled.");return}console.log();let G=t.force??!1;for(let u of s){let{written:h,skipped:x}=await V(u,o,G,async f=>{let S=await Ne({message:`File exists: ${f}`,options:[{value:"overwrite",label:"Overwrite"},{value:"skip",label:"Skip"},{value:"all",label:"Overwrite all"}]});return ne(S)?"skip":(S==="all"&&(G=!0),S)});for(let f of h)y(`Written: ${o.componentPath}/${f}`);for(let f of x)y(`Skipped: ${f}`)}if(i.length>0){let u=De();u.start(`Installing ${i.join(", ")}`),X(i,o.packageManager)?u.stop(`Installed: ${i.join(", ")}`):(u.stop("Failed to install dependencies"),g(`Run manually: ${o.packageManager} add ${i.join(" ")}`))}console.log(),J(`Done! ${m} component${m>1?"s":""} installed.`)}async function se(e){let t=await A();if(e.json){console.log(JSON.stringify(t,null,2));return}I(),j(`Available components (${t.length})`),g();let o=new Map;for(let n of t){let s="Other";for(let[c,a]of Object.entries(k))if(a.includes(n)){s=c;break}let r=o.get(s);r?r.push(n):o.set(s,[n])}for(let[n,s]of o){g(L(C(n)));for(let r of s.sort())g(` ${r}`);g()}y(`Use ${C("npx smoothui add <component>")} to install`)}var $=process.argv.slice(2),w=$[0];function ce(){I(),console.log("Usage: npx smoothui <command> [options]"),console.log(),console.log("Commands:"),console.log(" add [components...] Add components to your project"),console.log(" list List available components"),console.log(),console.log("Options:"),console.log(" --path <path> Custom component install path"),console.log(" --force Overwrite existing files without asking"),console.log(" --json Output as JSON (list command)"),console.log(" --help Show this help message"),console.log(),console.log("Examples:"),console.log(" npx smoothui add siri-orb"),console.log(" npx smoothui add siri-orb grid-loader"),console.log(" npx smoothui add # Interactive mode"),console.log(" npx smoothui list")}async function Fe(){try{if(!w||w==="--help"||w==="-h"){ce();return}if(w==="add"){let e=[],t,o=!1;for(let n=1;n<$.length;n++){let s=$[n];s==="--path"&&$[n+1]?(t=$[n+1],n++):s==="--force"||s==="-f"?o=!0:s.startsWith("-")||e.push(s)}await re(e,{path:t,force:o});return}if(w==="list"||w==="ls"){let e=$.includes("--json");await se({json:e});return}P(`Unknown command: ${w}`),ce(),process.exit(1)}catch(e){P(e.message),process.exit(1)}}Fe();
2
+ import{confirm as De,isCancel as se,select as Fe,spinner as Ue}from"@clack/prompts";var _="https://smoothui.dev",M={"Basic UI":["accordion","animated-input","animated-progress-bar","animated-tabs","animated-toggle","basic-dropdown","basic-modal","basic-toast","notification-badge","searchable-dropdown","skeleton-loader","tweet-card"],Buttons:["button-copy","clip-corners-button","dot-morph-button","magnetic-button"],"Text Effects":["wave-text","reveal-text","typewriter-text","scramble-hover","scroll-reveal-paragraph"],AI:["ai-branch","ai-input"],"Cards & Layouts":["expandable-cards","glow-hover-card","scrollable-card-stack","switchboard-card","phototab","job-listing-component"],"Loaders & Effects":["grid-loader","siri-orb","cursor-follow","github-stars-animation"],Interactive:["animated-o-t-p-input","animated-tags","app-download-stack","apple-invites","contribution-graph","dynamic-island","figma-comment","image-metadata-preview","infinite-slider","interactive-image-selector","number-flow","power-off-slide","price-flow","rich-popover","reviews-carousel","social-selector","user-account-avatar"]},K=["src/components/ui","components/ui","src/components","components","app/components/ui"],Y=[{file:"bun.lockb",cmd:"bun"},{file:"pnpm-lock.yaml",cmd:"pnpm"},{file:"yarn.lock",cmd:"yarn"},{file:"package-lock.json",cmd:"npm"}],m={active:"\u25C6",done:"\u25C7",selected:"\u25CF",unselected:"\u25CB",cursor:"\u276F",success:"\u2713",error:"\u2717",bar:"\u2502"};import{createInterface as de,emitKeypressEvents as me}from"readline";import d from"picocolors";var fe=t=>{let e=new Map;for(let o of t){let n=o.category||"Other";e.has(n)||e.set(n,[]),e.get(n)?.push(o)}return e},ge=(t,e)=>{console.log(`${d.cyan(m.active)} ${t}`),console.log(`${d.dim(m.bar)}`),console.log(`${d.dim(m.bar)} Search: ${e}${d.dim("\u258C")}`),console.log(`${d.dim(m.bar)}`)},ue=(t,e,o)=>{let n=e?d.green(m.selected):d.dim(m.unselected),s=o?d.cyan(m.cursor):" ",r=o?d.cyan(t.label):t.label;console.log(`${d.dim(m.bar)} ${s} ${n} ${r}`)},he=t=>{console.log(`${d.dim(m.bar)}`),console.log(`${d.dim(m.bar)} ${d.dim(`${t} selected \u2502 \u2191\u2193 navigate \u2502 space select \u2502 enter confirm \u2502 esc cancel`)}`)},ye=(t,e,o)=>{let n=0,s=e.scrollOffset,r=e.scrollOffset+o;for(let[i,c]of t){if(n>=r)break;n>=s&&console.log(`${d.dim(m.bar)} ${d.bold(d.dim(i))}`),n++;for(let a of c){if(n>=r)break;if(n>=s){let p=e.selected.has(a.value),l=n-1===e.cursorIndex;ue(a,p,l)}n++}}},be=(t,e,o,n)=>()=>{let s=B(e,o.searchQuery);process.stdout.write("\x1B[2J\x1B[H"),ge(t,o.searchQuery);let r=fe(s);ye(r,o,n),he(o.selected.size)},B=(t,e)=>{if(!e)return t;let o=e.toLowerCase();return t.filter(n=>n.label.toLowerCase().includes(o)||n.category?.toLowerCase().includes(o))},xe=(t,e,o,n)=>{if(o<=0){e.cursorIndex=0,e.scrollOffset=0;return}t.name==="up"?(e.cursorIndex=Math.max(0,e.cursorIndex-1),e.cursorIndex<e.scrollOffset&&(e.scrollOffset=e.cursorIndex)):t.name==="down"&&(e.cursorIndex=Math.min(o-1,e.cursorIndex+1),e.cursorIndex>=e.scrollOffset+n&&(e.scrollOffset=e.cursorIndex-n+1))},ve=(t,e)=>{let o=e[t.cursorIndex];o&&(t.selected.has(o.value)?t.selected.delete(o.value):t.selected.add(o.value))},we=(t,e,o)=>{e.name==="backspace"?(o.searchQuery=o.searchQuery.slice(0,-1),o.cursorIndex=0,o.scrollOffset=0):t&&t.length===1&&!e.ctrl&&!e.meta&&(o.searchQuery+=t,o.cursorIndex=0,o.scrollOffset=0)},Q=(t,e)=>{e&&process.stdin.removeListener("keypress",e),process.stdin.isTTY&&process.stdin.setRawMode(!1),t.close()},H=t=>{let{message:e,items:o,maxVisible:n=10}=t;return new Promise(s=>{let r={selected:new Set,searchQuery:"",cursorIndex:0,scrollOffset:0},i=de({input:process.stdin,output:process.stdout});process.stdin.isTTY&&process.stdin.setRawMode(!0),me(process.stdin,i);let c=be(e,o,r,n),a=(p,l)=>{let x=B(o,r.searchQuery),S=x.length;if(l.name==="escape"||l.ctrl&&l.name==="c"){Q(i,a),s(null);return}if(l.name==="return"){Q(i,a),s([...r.selected]);return}l.name==="up"||l.name==="down"?xe(l,r,S,n):l.name==="space"?ve(r,x):we(p,l,r),c()};process.stdin.on("keypress",a),c()})};import v from"picocolors";var R=m,P=v.dim,Se=v.cyan,$e=v.green,Ie=v.red,We=v.yellow,N=v.bold,D=v.gray;function T(t,e){console.log(`${t} ${e}`)}function j(t){T(Se(R.active),t)}function b(t){T(P(R.done),t)}function J(t){T($e(R.success),t)}function k(t){T(Ie(R.error),t)}function f(t=""){console.log(`${P(R.bar)} ${t}`)}function I(){console.log(),j(N("SmoothUI")),console.log()}import{existsSync as E,readFileSync as W}from"fs";import{join as A}from"path";var Oe=/^(npm|pnpm|yarn|bun)@/,Ce=()=>{let t=process.cwd();for(let{file:o,cmd:n}of Y)if(E(A(t,o)))return n;let e=A(t,"package.json");if(E(e))try{let o=JSON.parse(W(e,"utf-8"));if(o.packageManager){let n=o.packageManager.match(Oe);if(n)return n[1]}}catch{}return"npm"},Re=()=>{let t=process.cwd();for(let e of K)if(E(A(t,e)))return e;return null},Pe=()=>{let t=process.cwd(),e=["tsconfig.json","jsconfig.json"];for(let o of e){let n=A(t,o);if(E(n))try{let r=W(n,"utf-8").replace(/\/\*[\s\S]*?\*\/|\/\/.*/g,""),c=JSON.parse(r).compilerOptions?.paths;if(c){for(let[a,p]of Object.entries(c))if(a.endsWith("/*")&&Array.isArray(p))return a.slice(0,-2)}}catch{}}return"@"},q=()=>({componentPath:Re()||"components/ui",alias:Pe(),packageManager:Ce()});import{spawnSync as z}from"child_process";import{existsSync as V,mkdirSync as je,readFileSync as ot,writeFileSync as ke}from"fs";import{dirname as Me,isAbsolute as Te,relative as Ee,resolve as X}from"path";var Ae=(t,e)=>e==="@"?t:t.replace(/@\/components\//g,`${e}/components/`);var Z=async(t,e,o,n)=>{let s=[],r=[],i=o,c=X(process.cwd(),e.componentPath);for(let a of t.files){let p=X(c,a.path),l=Ee(c,p);if(l.startsWith("..")||Te(l))throw new Error(`Invalid registry file path: ${a.path}`);let x=Me(p);if(V(x)||je(x,{recursive:!0}),V(p)&&!i){let C=await n(a.path);if(C==="skip"){r.push(a.path);continue}C==="all"&&(i=!0)}let S=Ae(a.content,e.alias);ke(p,S,"utf-8"),s.push(a.path)}return{written:s,skipped:r}},ee=(t,e,o)=>{let n=!0;if(t.length>0){let s={npm:["npm","install",...t],pnpm:["pnpm","add",...t],yarn:["yarn","add",...t],bun:["bun","add",...t]},[r,...i]=s[o];z(r,i,{stdio:"pipe"}).status!==0&&(n=!1)}if(e.length>0){let s={npm:["npm","install","-D",...e],pnpm:["pnpm","add","-D",...e],yarn:["yarn","add","-D",...e],bun:["bun","add","-d",...e]},[r,...i]=s[o];z(r,i,{stdio:"pipe"}).status!==0&&(n=!1)}return n};var te=process.env.SMOOTHUI_REGISTRY_URL||_,Le=/\/r\/([^/]+)\.json$/;async function Ne(){let t=`${te}/r/registry.json`,e=await fetch(t);if(!e.ok)throw new Error(`Failed to fetch registry: ${e.status}`);return e.json()}async function oe(t){let e=`${te}/r/${t}.json`,o=await fetch(e);if(!o.ok)throw new Error(`Component "${t}" not found`);return o.json()}function ne(t){let e=t.match(Le);return e?e[1]:t}async function L(){return(await Ne()).items.map(e=>e.name)}async function F(t,e=new Set){let o=await oe(t);e.add(t);let n=[];if(o.registryDependencies)for(let s of o.registryDependencies){let r=ne(s);if(e.has(r)||!s.includes("smoothui.dev"))continue;let i=await F(r,e);n.push(i)}return{component:o,children:n}}function U(t){let e=[t.component];for(let o of t.children)e.push(...U(o));return e}function re(t){let e=new Set,o=new Set,n=new Set(["react","react-dom","next","tailwindcss","@types/react","@types/react-dom","@types/node","typescript"]);for(let s of t){for(let r of s.dependencies||[])n.has(r)||e.add(r);for(let r of s.devDependencies||[])n.has(r)||o.add(r)}return{dependencies:[...e],devDependencies:[...o]}}function G(t,e="",o=!0){f(`${e}${o?"\u2514\u2500":"\u251C\u2500"} ${t.component.name}`);let s=e+(o?" ":"\u2502 "),r=[...t.component.dependencies||[]].filter(i=>!["react","react-dom","next"].includes(i));r.length>0&&t.children.length===0&&f(`${s}\u2514\u2500 ${D(`npm: ${r.join(", ")}`)}`);for(let i=0;i<t.children.length;i++){let c=t.children[i],a=i===t.children.length-1&&r.length===0;G(c,s,a)}r.length>0&&t.children.length>0&&f(`${s}\u2514\u2500 ${D(`npm: ${r.join(", ")}`)}`)}async function ie(t,e){I();let o=q();e.path&&(o.componentPath=e.path),b(`Detected: ${o.componentPath}/ (${o.packageManager})`),console.log();let n=t;if(n.length===0){let h=(await L()).map(g=>{let $="Other";for(let[le,pe]of Object.entries(M))if(pe.includes(g)){$=le;break}return{value:g,label:g,category:$}}),y=await H({message:"Select components to install:",items:h});if(!y||y.length===0){console.log(),b("No components selected.");return}n=y,b(`Selected: ${n.join(", ")}`),console.log()}j("Resolving dependencies..."),f();let s=[],r=new Set;for(let u of n)if(!r.has(u))try{let h=await F(u),y=U(h);for(let g of y)r.has(g.name)||(r.add(g.name),s.push(g));G(h)}catch(h){k(`Failed to resolve ${u}: ${h.message}`);return}f();let{dependencies:i,devDependencies:c}=re(s),a=[...i,...c],p=s.length,l=i.length+c.length,x=l>0?`Install ${p} component${p>1?"s":""} + ${l} npm package${l>1?"s":""}?`:`Install ${p} component${p>1?"s":""}?`,S=await De({message:x});if(se(S)||!S){b("Installation cancelled.");return}console.log();let C=e.force??!1;for(let u of s){let{written:h,skipped:y}=await Z(u,o,C,async g=>{let $=await Fe({message:`File exists: ${g}`,options:[{value:"overwrite",label:"Overwrite"},{value:"skip",label:"Skip"},{value:"all",label:"Overwrite all"}]});return se($)?"skip":($==="all"&&(C=!0),$)});for(let g of h)b(`Written: ${o.componentPath}/${g}`);for(let g of y)b(`Skipped: ${g}`)}if(i.length>0||c.length>0){let u=Ue();if(u.start(`Installing ${a.join(", ")}`),ee(i,c,o.packageManager))u.stop(`Installed: ${a.join(", ")}`);else if(u.stop("Failed to install dependencies"),i.length>0&&f(`Run manually: ${o.packageManager} add ${i.join(" ")}`),c.length>0){let y=o.packageManager==="bun"?"-d":"-D";f(`Run manually: ${o.packageManager} add ${y} ${c.join(" ")}`)}}console.log(),J(`Done! ${p} component${p>1?"s":""} installed.`)}async function ce(t){let e=await L();if(t.json){console.log(JSON.stringify(e,null,2));return}I(),j(`Available components (${e.length})`),f();let o=new Map;for(let n of e){let s="Other";for(let[i,c]of Object.entries(M))if(c.includes(n)){s=i;break}let r=o.get(s);r?r.push(n):o.set(s,[n])}for(let[n,s]of o){f(N(P(n)));for(let r of s.sort())f(` ${r}`);f()}b(`Use ${P("npx smoothui add <component>")} to install`)}var O=process.argv.slice(2),w=O[0];function ae(){I(),console.log("Usage: npx smoothui <command> [options]"),console.log(),console.log("Commands:"),console.log(" add [components...] Add components to your project"),console.log(" list List available components"),console.log(),console.log("Options:"),console.log(" --path <path> Custom component install path"),console.log(" --force Overwrite existing files without asking"),console.log(" --json Output as JSON (list command)"),console.log(" --help Show this help message"),console.log(),console.log("Examples:"),console.log(" npx smoothui add siri-orb"),console.log(" npx smoothui add siri-orb grid-loader"),console.log(" npx smoothui add # Interactive mode"),console.log(" npx smoothui list")}async function Ge(){try{if(!w||w==="--help"||w==="-h"){ae();return}if(w==="add"){let t=[],e,o=!1;for(let n=1;n<O.length;n++){let s=O[n];s==="--path"&&O[n+1]?(e=O[n+1],n++):s==="--force"||s==="-f"?o=!0:s.startsWith("-")||t.push(s)}await ie(t,{path:e,force:o});return}if(w==="list"||w==="ls"){let t=O.includes("--json");await ce({json:t});return}k(`Unknown command: ${w}`),ae(),process.exit(1)}catch(t){let e=t instanceof Error?t.message:String(t);k(e||"An unknown error occurred"),process.exit(1)}}Ge();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "smoothui-cli",
3
- "version": "1.0.4",
3
+ "version": "1.0.5",
4
4
  "author": "educalvolpz",
5
5
  "description": "CLI to install SmoothUI components - beautifully designed React components with smooth animations",
6
6
  "private": false,