smoothui-cli 1.1.0 → 1.1.1
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 +31 -373
- package/dist/index.js +3 -1
- package/package.json +1 -1
package/README.github.md
CHANGED
|
@@ -1,413 +1,71 @@
|
|
|
1
|
-
#
|
|
1
|
+
# smoothui-cli
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
CLI to install [SmoothUI](https://smoothui.dev) components - beautifully designed React components with smooth animations.
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-

|
|
8
|
-

|
|
9
|
-

|
|
10
|
-
|
|
11
|
-
[](https://actions-badge.atrox.dev/educlopez/smoothui/goto?ref=main)
|
|
12
|
-

|
|
13
|
-

|
|
14
|
-

|
|
15
|
-

|
|
16
|
-
[](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
|
-
##
|
|
94
|
-
|
|
95
|
-
### Using SmoothUI CLI
|
|
11
|
+
## Usage
|
|
96
12
|
|
|
97
|
-
|
|
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
|
|
20
|
+
npx smoothui-cli add siri-orb grid-loader animated-tabs
|
|
105
21
|
|
|
106
|
-
# Interactive mode - browse and select
|
|
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
|
-
###
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
36
|
+
### Options
|
|
277
37
|
|
|
278
38
|
```bash
|
|
279
|
-
|
|
280
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
55
|
+
## Alternative: shadcn CLI
|
|
341
56
|
|
|
342
|
-
|
|
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
|
-
|
|
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
|
-
|
|
385
|
-
|
|
386
|
-
|
|
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
|
-
|
|
71
|
+
MIT
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,4 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{confirm as Le,isCancel as ae,select as Ne,spinner as De}from"@clack/prompts";var _="https://smoothui.dev",O={"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"]},Y=["src/components/ui","components/ui","src/components","components","app/components/ui"],H=[{file:"bun.lockb",cmd:"bun"},{file:"pnpm-lock.yaml",cmd:"pnpm"},{file:"yarn.lock",cmd:"yarn"},{file:"package-lock.json",cmd:"npm"}],J={active:"\u25C6",done:"\u25C7",selected:"\u25CF",unselected:"\u25CB",cursor:"\u276F",success:"\u2713",error:"\u2717",bar:"\u2502"};import{createInterface as ge,emitKeypressEvents as fe}from"readline";import a from"picocolors";var h={active:"\u25C6",done:"\u25C7",selected:"\u25CF",unselected:"\u25CB",pointer:"\u276F",bar:"\u2502"},Q=(e,t)=>{if(!t)return e;let o=t.toLowerCase();return e.filter(s=>s.label.toLowerCase().includes(o)||s.value.toLowerCase().includes(o)||s.category?.toLowerCase().includes(o))},ue=(e,t=3)=>{let o=[...e];return o.length===0?"":o.length<=t?o.join(", "):`${o.slice(0,t).join(", ")} +${o.length-t} more`},he=(e,t,o,s)=>{let r=Q(t,o.searchQuery),n=r.length;process.stdout.write("\x1B[2J\x1B[H"),console.log(`${a.green(h.active)} ${e} ${a.dim("(space to toggle)")}`),console.log(`${a.dim(h.bar)}`);let i=o.searchQuery||a.dim("Type to search...");console.log(`${a.dim(h.bar)} ${a.cyan("Search:")} ${i}${a.inverse(" ")}`),console.log(`${a.dim(h.bar)}`);let l=Math.floor(s/2),p=Math.max(0,o.cursorIndex-l),c=Math.min(n,p+s);c-p<s&&p>0&&(p=Math.max(0,c-s)),p>0&&console.log(`${a.dim(h.bar)} ${a.dim(`\u2191 ${p} more`)}`);for(let m=p;m<c;m++){let g=r[m],f=o.selected.has(g.value),b=m===o.cursorIndex,x=b?a.cyan(h.pointer):" ",u=f?a.green(h.selected):a.dim(h.unselected),v=b?a.cyan(g.label):g.label,N=g.category?a.dim(` (${g.category})`):"";console.log(`${a.dim(h.bar)} ${x} ${u} ${v}${N}`)}let d=n-c;d>0&&console.log(`${a.dim(h.bar)} ${a.dim(`\u2193 ${d} more`)}`),n===0&&console.log(`${a.dim(h.bar)} ${a.dim("No components found")}`),console.log(`${a.dim(h.bar)}`);let $=ue(o.selected);$&&(console.log(`${a.dim(h.bar)} ${a.green("Selected:")} ${$}`),console.log(`${a.dim(h.bar)}`)),console.log(`${a.dim(h.bar)} ${a.dim("\u2191\u2193 navigate \u2022 space select \u2022 enter confirm \u2022 esc cancel")}`)},K=(e,t)=>{t&&process.stdin.removeListener("keypress",t),process.stdin.isTTY&&process.stdin.setRawMode(!1),e.close(),process.stdout.write("\x1B[?25h")},W=e=>{let{message:t,items:o,maxVisible:s=8}=e;return new Promise(r=>{let n={selected:new Set,searchQuery:"",cursorIndex:0},i=ge({input:process.stdin,output:process.stdout});process.stdin.isTTY&&(process.stdin.setRawMode(!0),process.stdout.write("\x1B[?25l")),fe(process.stdin,i);let l=()=>he(t,o,n,s),p=(c,d)=>{let $=Q(o,n.searchQuery),m=$.length;if(d.name==="escape"||d.ctrl&&d.name==="c"){K(i,p),process.stdout.write("\x1B[2J\x1B[H"),r(null);return}if(d.name==="return"){K(i,p),process.stdout.write("\x1B[2J\x1B[H"),r([...n.selected]);return}if(d.name==="up")n.cursorIndex=Math.max(0,n.cursorIndex-1);else if(d.name==="down")n.cursorIndex=Math.min(m-1,n.cursorIndex+1);else if(d.name==="space"){let g=$[n.cursorIndex];g&&(n.selected.has(g.value)?n.selected.delete(g.value):n.selected.add(g.value))}else d.name==="backspace"?(n.searchQuery=n.searchQuery.slice(0,-1),n.cursorIndex=0):c&&c.length===1&&!d.ctrl&&!d.meta&&(n.searchQuery+=c,n.cursorIndex=0);m===0?n.cursorIndex=0:n.cursorIndex>=m&&(n.cursorIndex=m-1),l()};process.stdin.on("keypress",p),l()})};import S from"picocolors";var k=J,R=S.dim,ye=S.cyan,be=S.green,xe=S.red,Ke=S.yellow,q=S.bold,D=S.gray,$e=["\x1B[38;5;252m","\x1B[38;5;249m","\x1B[38;5;246m","\x1B[38;5;243m","\x1B[38;5;240m","\x1B[38;5;237m"],we="\x1B[0m",B=["\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2557 \u2588\u2588\u2557\u2588\u2588\u2557 \u2588\u2588\u2557\u2588\u2588\u2557","\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2554\u2550\u2550\u2550\u2588\u2588\u2557\u255A\u2550\u2550\u2588\u2588\u2554\u2550\u2550\u255D\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551","\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2554\u2588\u2588\u2588\u2588\u2554\u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551","\u255A\u2550\u2550\u2550\u2550\u2588\u2588\u2551\u2588\u2588\u2551\u255A\u2588\u2588\u2554\u255D\u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551","\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2551\u2588\u2588\u2551 \u255A\u2550\u255D \u2588\u2588\u2551\u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D \u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551\u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2551","\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u255D"],ve="1.1.0";function T(e,t){console.log(`${e} ${t}`)}function E(e){T(ye(k.active),e)}function w(e){T(R(k.done),e)}function V(e){T(be(k.success),e)}function P(e){T(xe(k.error),e)}function y(e=""){console.log(`${R(k.bar)} ${e}`)}function j(){console.log();for(let e=0;e<B.length;e++)console.log(`${$e[e]}${B[e]}${we}`);console.log(),console.log(` ${R(`v${ve}`)}`),console.log()}import{existsSync as M,readFileSync as X}from"fs";import{join as A}from"path";var Se=/^(npm|pnpm|yarn|bun)@/,Ie=()=>{let e=process.cwd();for(let{file:o,cmd:s}of H)if(M(A(e,o)))return s;let t=A(e,"package.json");if(M(t))try{let o=JSON.parse(X(t,"utf-8"));if(o.packageManager){let s=o.packageManager.match(Se);if(s)return s[1]}}catch{}return"npm"},Re=()=>{let e=process.cwd();for(let t of Y)if(M(A(e,t)))return t;return null},je=()=>{let e=process.cwd(),t=["tsconfig.json","jsconfig.json"];for(let o of t){let s=A(e,o);if(M(s))try{let n=X(s,"utf-8").replace(/\/\*[\s\S]*?\*\/|\/\/.*/g,""),l=JSON.parse(n).compilerOptions?.paths;if(l){for(let[p,c]of Object.entries(l))if(p.endsWith("/*")&&Array.isArray(c))return p.slice(0,-2)}}catch{}}return"@"},z=()=>({componentPath:Re()||"components/ui",alias:je(),packageManager:Ie()});import{spawnSync as Z}from"child_process";import{existsSync as ee,mkdirSync as Ce,readFileSync as Ze,writeFileSync as ke}from"fs";import{dirname as Pe,isAbsolute as Oe,relative as Te,resolve as te}from"path";var Ee=(e,t)=>t==="@"?e:e.replace(/@\/components\//g,`${t}/components/`);var oe=async(e,t,o,s)=>{let r=[],n=[],i=o,l=te(process.cwd(),t.componentPath);for(let p of e.files){let c=p.target||p.path;c.startsWith("components/")&&(c=c.slice(11));let d=te(l,c),$=Te(l,d);if($.startsWith("..")||Oe($))throw new Error(`Invalid registry file path: ${c}`);let m=Pe(d);if(ee(m)||Ce(m,{recursive:!0}),ee(d)&&!i){let f=await s(c);if(f==="skip"){n.push(c);continue}f==="all"&&(i=!0)}let g=Ee(p.content,t.alias);ke(d,g,"utf-8"),r.push(c)}return{written:r,skipped:n}},ne=(e,t,o)=>{let s=!0;if(e.length>0){let r={npm:["npm","install",...e],pnpm:["pnpm","add",...e],yarn:["yarn","add",...e],bun:["bun","add",...e]},[n,...i]=r[o];Z(n,i,{stdio:"pipe"}).status!==0&&(s=!1)}if(t.length>0){let r={npm:["npm","install","-D",...t],pnpm:["pnpm","add","-D",...t],yarn:["yarn","add","-D",...t],bun:["bun","add","-d",...t]},[n,...i]=r[o];Z(n,i,{stdio:"pipe"}).status!==0&&(s=!1)}return s};var se=process.env.SMOOTHUI_REGISTRY_URL||_,Me=/\/r\/([^/]+)\.json$/;async function Ae(){let e=`${se}/r/registry.json`,t=await fetch(e);if(!t.ok)throw new Error(`Failed to fetch registry: ${t.status}`);return t.json()}async function re(e){let t=`${se}/r/${e}.json`,o=await fetch(t);if(!o.ok)throw new Error(`Component "${e}" not found`);return o.json()}function ie(e){let t=e.match(Me);return t?t[1]:e}async function L(){return(await Ae()).items.map(t=>t.name)}async function F(e,t=new Set){let o=await re(e);t.add(e);let s=[];if(o.registryDependencies)for(let r of o.registryDependencies){let n=ie(r);if(t.has(n)||!r.includes("smoothui.dev"))continue;let i=await F(n,t);s.push(i)}return{component:o,children:s}}function U(e){let t=[e.component];for(let o of e.children)t.push(...U(o));return t}function ce(e){let t=new Set,o=new Set,s=new Set(["react","react-dom","next","tailwindcss","@types/react","@types/react-dom","@types/node","typescript"]);for(let r of e){for(let n of r.dependencies||[])s.has(n)||t.add(n);for(let n of r.devDependencies||[])s.has(n)||o.add(n)}return{dependencies:[...t],devDependencies:[...o]}}function G(e,t="",o=!0){y(`${t}${o?"\u2514\u2500":"\u251C\u2500"} ${e.component.name}`);let r=t+(o?" ":"\u2502 "),n=[...e.component.dependencies||[]].filter(i=>!["react","react-dom","next"].includes(i));n.length>0&&e.children.length===0&&y(`${r}\u2514\u2500 ${D(`npm: ${n.join(", ")}`)}`);for(let i=0;i<e.children.length;i++){let l=e.children[i],p=i===e.children.length-1&&n.length===0;G(l,r,p)}n.length>0&&e.children.length>0&&y(`${r}\u2514\u2500 ${D(`npm: ${n.join(", ")}`)}`)}async function le(e,t){j();let o=z();t.path&&(o.componentPath=t.path),w(`Detected: ${o.componentPath}/ (${o.packageManager})`),console.log();let s=e;if(s.length===0){let b=(await L()).map(u=>{let v="Other";for(let[N,me]of Object.entries(O))if(me.includes(u)){v=N;break}return{value:u,label:u,category:v}}),x=await W({message:"Select components to install:",items:b});if(!x||x.length===0){console.log(),w("No components selected.");return}s=x,w(`Selected: ${s.join(", ")}`),console.log()}E("Resolving dependencies..."),y();let r=[],n=new Set;for(let f of s)if(!n.has(f))try{let b=await F(f),x=U(b);for(let u of x)n.has(u.name)||(n.add(u.name),r.push(u));G(b)}catch(b){P(`Failed to resolve ${f}: ${b.message}`);return}y();let{dependencies:i,devDependencies:l}=ce(r),p=[...i,...l],c=r.length,d=i.length+l.length,$=d>0?`Install ${c} component${c>1?"s":""} + ${d} npm package${d>1?"s":""}?`:`Install ${c} component${c>1?"s":""}?`,m=await Le({message:$});if(ae(m)||!m){w("Installation cancelled.");return}console.log();let g=t.force??!1;for(let f of r){let{written:b,skipped:x}=await oe(f,o,g,async u=>{let v=await Ne({message:`File exists: ${u}`,options:[{value:"overwrite",label:"Overwrite"},{value:"skip",label:"Skip"},{value:"all",label:"Overwrite all"}]});return ae(v)?"skip":(v==="all"&&(g=!0),v)});for(let u of b)w(`Written: ${o.componentPath}/${u}`);for(let u of x)w(`Skipped: ${u}`)}if(i.length>0||l.length>0){let f=De();if(f.start(`Installing ${p.join(", ")}`),ne(i,l,o.packageManager))f.stop(`Installed: ${p.join(", ")}`);else if(f.stop("Failed to install dependencies"),i.length>0&&y(`Run manually: ${o.packageManager} add ${i.join(" ")}`),l.length>0){let x=o.packageManager==="bun"?"-d":"-D";y(`Run manually: ${o.packageManager} add ${x} ${l.join(" ")}`)}}console.log(),V(`Done! ${c} component${c>1?"s":""} installed.`)}async function pe(e){let t=await L();if(e.json){console.log(JSON.stringify(t,null,2));return}j(),E(`Available components (${t.length})`),y();let o=new Map;for(let s of t){let r="Other";for(let[i,l]of Object.entries(O))if(l.includes(s)){r=i;break}let n=o.get(r);n?n.push(s):o.set(r,[s])}for(let[s,r]of o){y(q(R(s)));for(let n of r.sort())y(` ${n}`);y()}w(`Use ${R("npx smoothui add <component>")} to install`)}var C=process.argv.slice(2),I=C[0];function de(){j(),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(!I||I==="--help"||I==="-h"){de();return}if(I==="add"){let e=[],t,o=!1;for(let s=1;s<C.length;s++){let r=C[s];r==="--path"&&C[s+1]?(t=C[s+1],s++):r==="--force"||r==="-f"?o=!0:r.startsWith("-")||e.push(r)}await le(e,{path:t,force:o});return}if(I==="list"||I==="ls"){let e=C.includes("--json");await pe({json:e});return}P(`Unknown command: ${I}`),de(),process.exit(1)}catch(e){let t=e instanceof Error?e.message:String(e);P(t||"An unknown error occurred"),process.exit(1)}}Fe();
|
|
2
|
+
import{confirm as et,isCancel as be,select as tt,spinner as nt}from"@clack/prompts";var X="https://smoothui.dev",D={"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"]},Z=["src/components/ui","components/ui","src/components","components","app/components/ui"],ee=[{file:"bun.lockb",cmd:"bun"},{file:"pnpm-lock.yaml",cmd:"pnpm"},{file:"yarn.lock",cmd:"yarn"},{file:"package-lock.json",cmd:"npm"}],te={active:"\u25C6",done:"\u25C7",selected:"\u25CF",unselected:"\u25CB",cursor:"\u276F",success:"\u2713",error:"\u2717",bar:"\u2502"};import{createInterface as je,emitKeypressEvents as Ee}from"readline";import{Writable as Te}from"stream";import m from"picocolors";var Ae=new Te({write(e,t,n){n()}}),Pe=m.green("\u25C6"),ke=m.red("\u25A0"),Oe=m.green("\u25C7"),Me=m.green("\u25CF"),Le=m.dim("\u25CB"),x=m.dim("\u2502"),ne=e=>{let{message:t,items:n,maxVisible:o=8}=e;return new Promise(s=>{let r=je({input:process.stdin,output:Ae,terminal:!1});process.stdin.isTTY&&process.stdin.setRawMode(!0),Ee(process.stdin,r);let c="",a=0,d=new Set,l=0,y=(p,i)=>{if(!i)return!0;let b=i.toLowerCase();return p.label.toLowerCase().includes(b)||p.value.toLowerCase().includes(b)},I=()=>n.filter(p=>y(p,c)),j=()=>{if(l>0){process.stdout.write(`\x1B[${l}A`);for(let p=0;p<l;p++)process.stdout.write("\x1B[2K\x1B[1B");process.stdout.write(`\x1B[${l}A`)}},h=(p="active")=>{j();let i=[],b=I(),A=p==="active"?Pe:p==="cancel"?ke:Oe;if(i.push(`${A} ${m.bold(t)}`),p==="active"){let K=`${x} ${m.dim("Search:")} ${c}${m.inverse(" ")}`;i.push(K),i.push(`${x} ${m.dim("\u2191\u2193 move, space select, enter confirm")}`),i.push(`${x}`);let R=Math.max(0,Math.min(a-Math.floor(o/2),b.length-o)),q=Math.min(b.length,R+o),z=b.slice(R,q);if(b.length===0)i.push(`${x} ${m.dim("No matches found")}`);else{for(let $=0;$<z.length;$++){let L=z[$],xe=R+$,ye=d.has(L.value),Q=xe===a,Se=ye?Me:Le,Re=Q?m.underline(L.label):L.label,Ce=L.hint?m.dim(` (${L.hint})`):"",Ie=Q?m.cyan("\u276F"):" ";i.push(`${x} ${Ie} ${Se} ${Re}${Ce}`)}let C=R,M=b.length-q;if(C>0||M>0){let $=[];C>0&&$.push(`\u2191 ${C} more`),M>0&&$.push(`\u2193 ${M} more`),i.push(`${x} ${m.dim($.join(" "))}`)}}if(i.push(`${x}`),d.size===0)i.push(`${x} ${m.dim("Selected: (none)")}`);else{let C=n.filter($=>d.has($.value)).map($=>$.label),M=C.length<=3?C.join(", "):`${C.slice(0,3).join(", ")} +${C.length-3} more`;i.push(`${x} ${m.green("Selected:")} ${M}`)}i.push(`${m.dim("\u2514")}`)}else if(p==="submit"){let K=n.filter(R=>d.has(R.value)).map(R=>R.label);i.push(`${x} ${m.dim(K.join(", "))}`)}else p==="cancel"&&i.push(`${x} ${m.strikethrough(m.dim("Cancelled"))}`);process.stdout.write(`${i.join(`
|
|
3
|
+
`)}
|
|
4
|
+
`),l=i.length},f=()=>{process.stdin.removeListener("keypress",g),process.stdin.isTTY&&process.stdin.setRawMode(!1),r.close()},v=()=>{h("submit"),f(),s([...d])},w=()=>{h("cancel"),f(),s(null)},g=(p,i)=>{if(!i)return;let b=I();if(i.name==="return"){v();return}if(i.name==="escape"||i.ctrl&&i.name==="c"){w();return}if(i.name==="up"){a=Math.max(0,a-1),h();return}if(i.name==="down"){a=Math.min(b.length-1,a+1),h();return}if(i.name==="space"){let A=b[a];A&&(d.has(A.value)?d.delete(A.value):d.add(A.value)),h();return}if(i.name==="backspace"){c=c.slice(0,-1),a=0,h();return}i.sequence&&!i.ctrl&&!i.meta&&i.sequence.length===1&&(c+=i.sequence,a=0,h())};process.stdin.on("keypress",g),h()})};import E from"picocolors";var N=te,P=E.dim,Ne=E.cyan,_e=E.green,De=E.red,mt=E.yellow,se=E.bold,H=E.gray,Fe=["\x1B[38;5;252m","\x1B[38;5;249m","\x1B[38;5;246m","\x1B[38;5;243m","\x1B[38;5;240m","\x1B[38;5;237m"],Ue="\x1B[0m",oe=["\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2557 \u2588\u2588\u2557\u2588\u2588\u2557 \u2588\u2588\u2557\u2588\u2588\u2557","\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2554\u2550\u2550\u2550\u2588\u2588\u2557\u255A\u2550\u2550\u2588\u2588\u2554\u2550\u2550\u255D\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551","\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2554\u2588\u2588\u2588\u2588\u2554\u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551","\u255A\u2550\u2550\u2550\u2550\u2588\u2588\u2551\u2588\u2588\u2551\u255A\u2588\u2588\u2554\u255D\u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551","\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2551\u2588\u2588\u2551 \u255A\u2550\u255D \u2588\u2588\u2551\u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D \u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551\u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2551","\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u255D"],Ge="1.1.1";function F(e,t){console.log(`${e} ${t}`)}function U(e){F(Ne(N.active),e)}function S(e){F(P(N.done),e)}function re(e){F(_e(N.success),e)}function _(e){F(De(N.error),e)}function u(e=""){console.log(`${P(N.bar)} ${e}`)}function k(){console.log();for(let e=0;e<oe.length;e++)console.log(`${Fe[e]}${oe[e]}${Ue}`);console.log(),console.log(` ${P(`v${Ge}`)}`),console.log()}import{existsSync as G,readFileSync as ie}from"fs";import{join as Y}from"path";var Ye=/^(npm|pnpm|yarn|bun)@/,Be=()=>{let e=process.cwd();for(let{file:n,cmd:o}of ee)if(G(Y(e,n)))return o;let t=Y(e,"package.json");if(G(t))try{let n=JSON.parse(ie(t,"utf-8"));if(n.packageManager){let o=n.packageManager.match(Ye);if(o)return o[1]}}catch{}return"npm"},Ke=()=>{let e=process.cwd();for(let t of Z)if(G(Y(e,t)))return t;return null},He=()=>{let e=process.cwd(),t=["tsconfig.json","jsconfig.json"];for(let n of t){let o=Y(e,n);if(G(o))try{let r=ie(o,"utf-8").replace(/\/\*[\s\S]*?\*\/|\/\/.*/g,""),a=JSON.parse(r).compilerOptions?.paths;if(a){for(let[d,l]of Object.entries(a))if(d.endsWith("/*")&&Array.isArray(l))return d.slice(0,-2)}}catch{}}return"@"},ce=()=>({componentPath:Ke()||"components/ui",alias:He(),packageManager:Be()});import{spawnSync as ae}from"child_process";import{existsSync as le,mkdirSync as Ve,readFileSync as vt,writeFileSync as We}from"fs";import{dirname as Je,isAbsolute as qe,relative as ze,resolve as pe}from"path";var Qe=(e,t)=>t==="@"?e:e.replace(/@\/components\//g,`${t}/components/`);var me=async(e,t,n,o)=>{let s=[],r=[],c=n,a=pe(process.cwd(),t.componentPath);for(let d of e.files){let l=d.target||d.path;l.startsWith("components/")&&(l=l.slice(11));let y=pe(a,l),I=ze(a,y);if(I.startsWith("..")||qe(I))throw new Error(`Invalid registry file path: ${l}`);let j=Je(y);if(le(j)||Ve(j,{recursive:!0}),le(y)&&!c){let f=await o(l);if(f==="skip"){r.push(l);continue}f==="all"&&(c=!0)}let h=Qe(d.content,t.alias);We(y,h,"utf-8"),s.push(l)}return{written:s,skipped:r}},de=(e,t,n)=>{let o=!0;if(e.length>0){let s={npm:["npm","install",...e],pnpm:["pnpm","add",...e],yarn:["yarn","add",...e],bun:["bun","add",...e]},[r,...c]=s[n];ae(r,c,{stdio:"pipe"}).status!==0&&(o=!1)}if(t.length>0){let s={npm:["npm","install","-D",...t],pnpm:["pnpm","add","-D",...t],yarn:["yarn","add","-D",...t],bun:["bun","add","-d",...t]},[r,...c]=s[n];ae(r,c,{stdio:"pipe"}).status!==0&&(o=!1)}return o};var fe=process.env.SMOOTHUI_REGISTRY_URL||X,Xe=/\/r\/([^/]+)\.json$/;async function Ze(){let e=`${fe}/r/registry.json`,t=await fetch(e);if(!t.ok)throw new Error(`Failed to fetch registry: ${t.status}`);return t.json()}async function ge(e){let t=`${fe}/r/${e}.json`,n=await fetch(t);if(!n.ok)throw new Error(`Component "${e}" not found`);return n.json()}function ue(e){let t=e.match(Xe);return t?t[1]:e}async function B(){return(await Ze()).items.map(t=>t.name)}async function V(e,t=new Set){let n=await ge(e);t.add(e);let o=[];if(n.registryDependencies)for(let s of n.registryDependencies){let r=ue(s);if(t.has(r)||!s.includes("smoothui.dev"))continue;let c=await V(r,t);o.push(c)}return{component:n,children:o}}function W(e){let t=[e.component];for(let n of e.children)t.push(...W(n));return t}function he(e){let t=new Set,n=new Set,o=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||[])o.has(r)||t.add(r);for(let r of s.devDependencies||[])o.has(r)||n.add(r)}return{dependencies:[...t],devDependencies:[...n]}}function J(e,t="",n=!0){u(`${t}${n?"\u2514\u2500":"\u251C\u2500"} ${e.component.name}`);let s=t+(n?" ":"\u2502 "),r=[...e.component.dependencies||[]].filter(c=>!["react","react-dom","next"].includes(c));r.length>0&&e.children.length===0&&u(`${s}\u2514\u2500 ${H(`npm: ${r.join(", ")}`)}`);for(let c=0;c<e.children.length;c++){let a=e.children[c],d=c===e.children.length-1&&r.length===0;J(a,s,d)}r.length>0&&e.children.length>0&&u(`${s}\u2514\u2500 ${H(`npm: ${r.join(", ")}`)}`)}async function $e(e,t){k();let n=ce();t.path&&(n.componentPath=t.path),S(`Detected: ${n.componentPath}/ (${n.packageManager})`),console.log();let o=e;if(o.length===0){let v=(await B()).map(g=>{let p="Other";for(let[i,b]of Object.entries(D))if(b.includes(g)){p=i;break}return{value:g,label:g,category:p}}),w=await ne({message:"Select components to install:",items:v});if(!w||w.length===0){console.log(),S("No components selected.");return}o=w,S(`Selected: ${o.join(", ")}`),console.log()}U("Resolving dependencies..."),u();let s=[],r=new Set;for(let f of o)if(!r.has(f))try{let v=await V(f),w=W(v);for(let g of w)r.has(g.name)||(r.add(g.name),s.push(g));J(v)}catch(v){_(`Failed to resolve ${f}: ${v.message}`);return}u();let{dependencies:c,devDependencies:a}=he(s),d=[...c,...a],l=s.length,y=c.length+a.length,I=y>0?`Install ${l} component${l>1?"s":""} + ${y} npm package${y>1?"s":""}?`:`Install ${l} component${l>1?"s":""}?`,j=await et({message:I});if(be(j)||!j){S("Installation cancelled.");return}console.log();let h=t.force??!1;for(let f of s){let{written:v,skipped:w}=await me(f,n,h,async g=>{let p=await tt({message:`File exists: ${g}`,options:[{value:"overwrite",label:"Overwrite"},{value:"skip",label:"Skip"},{value:"all",label:"Overwrite all"}]});return be(p)?"skip":(p==="all"&&(h=!0),p)});for(let g of v)S(`Written: ${n.componentPath}/${g}`);for(let g of w)S(`Skipped: ${g}`)}if(c.length>0||a.length>0){let f=nt();if(f.start(`Installing ${d.join(", ")}`),de(c,a,n.packageManager))f.stop(`Installed: ${d.join(", ")}`);else if(f.stop("Failed to install dependencies"),c.length>0&&u(`Run manually: ${n.packageManager} add ${c.join(" ")}`),a.length>0){let w=n.packageManager==="bun"?"-d":"-D";u(`Run manually: ${n.packageManager} add ${w} ${a.join(" ")}`)}}console.log(),re(`Done! ${l} component${l>1?"s":""} installed.`)}async function ve(e){let t=await B();if(e.json){console.log(JSON.stringify(t,null,2));return}k(),U(`Available components (${t.length})`),u();let n=new Map;for(let o of t){let s="Other";for(let[c,a]of Object.entries(D))if(a.includes(o)){s=c;break}let r=n.get(s);r?r.push(o):n.set(s,[o])}for(let[o,s]of n){u(se(P(o)));for(let r of s.sort())u(` ${r}`);u()}S(`Use ${P("npx smoothui add <component>")} to install`)}var O=process.argv.slice(2),T=O[0];function we(){k(),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 ot(){try{if(!T||T==="--help"||T==="-h"){we();return}if(T==="add"){let e=[],t,n=!1;for(let o=1;o<O.length;o++){let s=O[o];s==="--path"&&O[o+1]?(t=O[o+1],o++):s==="--force"||s==="-f"?n=!0:s.startsWith("-")||e.push(s)}await $e(e,{path:t,force:n});return}if(T==="list"||T==="ls"){let e=O.includes("--json");await ve({json:e});return}_(`Unknown command: ${T}`),we(),process.exit(1)}catch(e){let t=e instanceof Error?e.message:String(e);_(t||"An unknown error occurred"),process.exit(1)}}ot();
|