popcn 0.0.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/dist/index.js ADDED
@@ -0,0 +1,1503 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/index.ts
4
+ import { Command } from "commander";
5
+
6
+ // src/commands/init.ts
7
+ import * as fs3 from "fs";
8
+ import * as path3 from "path";
9
+ import chalk from "chalk";
10
+ import prompts from "prompts";
11
+ import ora from "ora";
12
+
13
+ // src/utils/get-config.ts
14
+ import * as fs from "fs";
15
+ import * as path from "path";
16
+
17
+ // src/schemas/config.ts
18
+ import { z } from "zod";
19
+ var componentsConfigSchema = z.object({
20
+ $schema: z.string().optional(),
21
+ style: z.string().default("aurorapop"),
22
+ skin: z.enum(["aurora", "neumopop", "glasspop"]).default("aurora"),
23
+ theme: z.string().default("cosmic"),
24
+ tailwind: z.object({
25
+ config: z.string(),
26
+ css: z.string()
27
+ }),
28
+ aliases: z.object({
29
+ components: z.string(),
30
+ utils: z.string(),
31
+ lib: z.string()
32
+ }),
33
+ registryUrl: z.string().url().optional()
34
+ });
35
+ function validateConfig(data) {
36
+ const result = componentsConfigSchema.safeParse(data);
37
+ if (result.success) {
38
+ return result.data;
39
+ }
40
+ return null;
41
+ }
42
+
43
+ // src/utils/get-config.ts
44
+ var CONFIG_FILE = "components.json";
45
+ function getConfigPath(cwd = process.cwd()) {
46
+ return path.join(cwd, CONFIG_FILE);
47
+ }
48
+ function configExists(cwd = process.cwd()) {
49
+ return fs.existsSync(getConfigPath(cwd));
50
+ }
51
+ function getConfig(cwd = process.cwd()) {
52
+ const configPath = getConfigPath(cwd);
53
+ if (!fs.existsSync(configPath)) {
54
+ return null;
55
+ }
56
+ try {
57
+ const content = fs.readFileSync(configPath, "utf-8");
58
+ const data = JSON.parse(content);
59
+ return validateConfig(data);
60
+ } catch {
61
+ return null;
62
+ }
63
+ }
64
+ function writeConfig(config, cwd = process.cwd()) {
65
+ const configPath = getConfigPath(cwd);
66
+ fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
67
+ }
68
+ function resolveAlias(alias, cwd = process.cwd()) {
69
+ if (alias.startsWith("@/")) {
70
+ return path.join(cwd, alias.slice(2));
71
+ }
72
+ return path.join(cwd, alias);
73
+ }
74
+
75
+ // src/utils/get-package-manager.ts
76
+ import * as fs2 from "fs";
77
+ import * as path2 from "path";
78
+ function getPackageManager(cwd = process.cwd()) {
79
+ if (fs2.existsSync(path2.join(cwd, "bun.lockb"))) {
80
+ return "bun";
81
+ }
82
+ if (fs2.existsSync(path2.join(cwd, "pnpm-lock.yaml"))) {
83
+ return "pnpm";
84
+ }
85
+ if (fs2.existsSync(path2.join(cwd, "yarn.lock"))) {
86
+ return "yarn";
87
+ }
88
+ if (fs2.existsSync(path2.join(cwd, "package-lock.json"))) {
89
+ return "npm";
90
+ }
91
+ const packageJsonPath = path2.join(cwd, "package.json");
92
+ if (fs2.existsSync(packageJsonPath)) {
93
+ try {
94
+ const packageJson = JSON.parse(fs2.readFileSync(packageJsonPath, "utf-8"));
95
+ if (packageJson.packageManager) {
96
+ if (packageJson.packageManager.startsWith("pnpm")) return "pnpm";
97
+ if (packageJson.packageManager.startsWith("yarn")) return "yarn";
98
+ if (packageJson.packageManager.startsWith("bun")) return "bun";
99
+ }
100
+ } catch {
101
+ }
102
+ }
103
+ return "npm";
104
+ }
105
+ function getInstallCommand(pm) {
106
+ switch (pm) {
107
+ case "pnpm":
108
+ return "pnpm add";
109
+ case "yarn":
110
+ return "yarn add";
111
+ case "bun":
112
+ return "bun add";
113
+ default:
114
+ return "npm install";
115
+ }
116
+ }
117
+
118
+ // src/utils/templates.ts
119
+ var AURORAPOP_CSS = `@tailwind base;
120
+ @tailwind components;
121
+ @tailwind utilities;
122
+
123
+ /* =====================================================
124
+ AuroraPop Design System - CSS Tokens
125
+ ===================================================== */
126
+
127
+ :root {
128
+ /* Base colors (r g b format for Tailwind alpha) */
129
+ --ap-background: 10 10 20;
130
+ --ap-foreground: 255 255 255;
131
+
132
+ /* Primary/Secondary - Cosmic theme default */
133
+ --ap-primary: 99 102 241;
134
+ --ap-primary-foreground: 255 255 255;
135
+ --ap-secondary: 168 85 247;
136
+ --ap-secondary-foreground: 255 255 255;
137
+
138
+ /* Aurora gradient tokens - Cosmic */
139
+ --ap-aurora-1: 99 102 241;
140
+ --ap-aurora-2: 139 92 246;
141
+ --ap-aurora-3: 56 189 248;
142
+
143
+ /* Glow */
144
+ --ap-glow-strength: 1;
145
+
146
+ /* Gradient control */
147
+ --ap-grad: 1;
148
+
149
+ /* =====================================================
150
+ Gradient Direction Tokens
151
+ ===================================================== */
152
+
153
+ /* Gradient angle (0=top, 90=right, 180=bottom, 270=left) */
154
+ --ap-grad-angle: 135deg; /* Default: top-left to bottom-right */
155
+
156
+ /* Shine/shimmer angle */
157
+ --ap-shine-angle: 105deg; /* Shimmer sweep angle */
158
+
159
+ /* Shine thickness (percentage for gradient spread) */
160
+ --ap-shine-width: 10%; /* Width of the shine band (5%=thin, 10%=normal, 20%=wide) */
161
+
162
+ /* =====================================================
163
+ Animation Tokens
164
+ ===================================================== */
165
+
166
+ /* Duration tokens */
167
+ --ap-dur-1: 100ms; /* Micro: button press */
168
+ --ap-dur-2: 200ms; /* Quick: pop, snap */
169
+ --ap-dur-3: 300ms; /* Standard: most transitions */
170
+ --ap-dur-4: 500ms; /* Emphasis: entrance animations, morph */
171
+ --ap-dur-5: 800ms; /* Dramatic: confetti, complex sequences */
172
+
173
+ /* Easing tokens */
174
+ --ap-ease-pop: cubic-bezier(0.34, 1.56, 0.64, 1); /* Bouncy */
175
+ --ap-ease-soft: cubic-bezier(0.4, 0, 0.2, 1); /* Soft */
176
+ --ap-ease-snap: cubic-bezier(0.2, 0, 0, 1); /* Sharp */
177
+ --ap-ease-spring: cubic-bezier(0.175, 0.885, 0.32, 1.275); /* Elastic */
178
+
179
+ /* Motion control tokens */
180
+ --ap-motion: 1; /* 1=enabled, 0=disabled (follows --ap-grad pattern) */
181
+ --ap-motion-scale: 1; /* Intensity scale (0.5=subtle, 1=normal, 1.5=dramatic) */
182
+
183
+ /* Borders/Muted */
184
+ --ap-border: 63 63 70;
185
+ --ap-muted: 39 39 42;
186
+ --ap-muted-foreground: 161 161 170;
187
+
188
+ /* Ring */
189
+ --ap-ring: 99 102 241;
190
+
191
+ /* Radius */
192
+ --ap-radius: 0.5rem;
193
+ }
194
+
195
+ /* Dark theme (default) */
196
+ .dark,
197
+ [data-theme="dark"] {
198
+ --ap-background: 10 10 20;
199
+ --ap-foreground: 255 255 255;
200
+ --ap-border: 63 63 70;
201
+ --ap-muted: 39 39 42;
202
+ --ap-muted-foreground: 161 161 170;
203
+ }
204
+
205
+ /* Light theme */
206
+ .light,
207
+ [data-theme="light"] {
208
+ --ap-background: 250 250 252;
209
+ --ap-foreground: 15 15 20;
210
+ --ap-primary-foreground: 255 255 255;
211
+ --ap-secondary-foreground: 255 255 255;
212
+ --ap-border: 228 228 231;
213
+ --ap-muted: 244 244 245;
214
+ --ap-muted-foreground: 113 113 122;
215
+ }
216
+
217
+ /* Theme Preset: Sunset (Pink/Orange/Yellow) */
218
+ .theme-sunset,
219
+ [data-theme="sunset"] {
220
+ --ap-primary: 236 72 153;
221
+ --ap-secondary: 251 146 60;
222
+ --ap-aurora-1: 236 72 153;
223
+ --ap-aurora-2: 251 146 60;
224
+ --ap-aurora-3: 250 204 21;
225
+ --ap-ring: 236 72 153;
226
+ }
227
+
228
+ /* Theme Preset: Neon (Cyan/Magenta/Lime) */
229
+ .theme-neon,
230
+ [data-theme="neon"] {
231
+ --ap-primary: 6 182 212;
232
+ --ap-secondary: 217 70 239;
233
+ --ap-aurora-1: 6 182 212;
234
+ --ap-aurora-2: 217 70 239;
235
+ --ap-aurora-3: 163 230 53;
236
+ --ap-ring: 6 182 212;
237
+ }
238
+
239
+ /* Theme Preset: Mono (Grayscale) */
240
+ .theme-mono,
241
+ [data-theme="mono"] {
242
+ --ap-primary: 161 161 170;
243
+ --ap-primary-foreground: 10 10 20;
244
+ --ap-secondary: 113 113 122;
245
+ --ap-secondary-foreground: 255 255 255;
246
+ --ap-aurora-1: 161 161 170;
247
+ --ap-aurora-2: 113 113 122;
248
+ --ap-aurora-3: 82 82 91;
249
+ --ap-ring: 161 161 170;
250
+ --ap-glow-strength: 0.5;
251
+ }
252
+
253
+ /* Gradient disable */
254
+ .ap-no-gradient {
255
+ --ap-grad: 0;
256
+ }
257
+
258
+ /* Motion disable */
259
+ .ap-no-motion {
260
+ --ap-motion: 0;
261
+ }
262
+
263
+ /* Respect system reduced-motion preference */
264
+ @media (prefers-reduced-motion: reduce) {
265
+ :root {
266
+ --ap-motion: 0;
267
+ --ap-motion-scale: 0;
268
+ }
269
+ }
270
+
271
+ /* =====================================================
272
+ Base Styles
273
+ ===================================================== */
274
+
275
+ @layer base {
276
+ * {
277
+ @apply border-border;
278
+ }
279
+
280
+ body {
281
+ @apply bg-background text-foreground antialiased;
282
+ }
283
+ }
284
+
285
+ /* =====================================================
286
+ Aurora Background Component
287
+ ===================================================== */
288
+
289
+ .aurora-bg {
290
+ position: fixed;
291
+ inset: 0;
292
+ z-index: -1;
293
+ overflow: hidden;
294
+ background: rgb(var(--ap-background));
295
+ }
296
+
297
+ .aurora-bg::before {
298
+ content: "";
299
+ position: absolute;
300
+ top: -50%;
301
+ left: -50%;
302
+ width: 200%;
303
+ height: 200%;
304
+ background: radial-gradient(
305
+ ellipse 80% 50% at 20% 40%,
306
+ rgba(var(--ap-aurora-1), 0.15),
307
+ transparent 50%
308
+ ),
309
+ radial-gradient(
310
+ ellipse 60% 40% at 80% 60%,
311
+ rgba(var(--ap-aurora-2), 0.12),
312
+ transparent 50%
313
+ ),
314
+ radial-gradient(
315
+ ellipse 50% 60% at 40% 80%,
316
+ rgba(var(--ap-aurora-3), 0.1),
317
+ transparent 50%
318
+ );
319
+ animation: aurora-shift 15s ease infinite;
320
+ background-size: 200% 200%;
321
+ }
322
+
323
+ @keyframes aurora-shift {
324
+ 0% {
325
+ background-position: 0% 50%;
326
+ }
327
+ 50% {
328
+ background-position: 100% 50%;
329
+ }
330
+ 100% {
331
+ background-position: 0% 50%;
332
+ }
333
+ }
334
+
335
+ /* =====================================================
336
+ Utility Classes
337
+ ===================================================== */
338
+
339
+ /* Aurora gradient text */
340
+ .text-aurora {
341
+ background: linear-gradient(
342
+ var(--ap-grad-angle, 135deg),
343
+ rgb(var(--ap-aurora-1)),
344
+ rgb(var(--ap-aurora-2)),
345
+ rgb(var(--ap-aurora-3))
346
+ );
347
+ -webkit-background-clip: text;
348
+ background-clip: text;
349
+ color: transparent;
350
+ }
351
+
352
+ /* Aurora gradient background */
353
+ .bg-aurora {
354
+ background: linear-gradient(
355
+ var(--ap-grad-angle, 135deg),
356
+ rgb(var(--ap-aurora-1)),
357
+ rgb(var(--ap-aurora-2)),
358
+ rgb(var(--ap-aurora-3))
359
+ );
360
+ }
361
+
362
+ /* Shine effect overlay (use on ::before pseudo-element) */
363
+ .shine-effect::before {
364
+ background: linear-gradient(
365
+ var(--ap-shine-angle, 105deg),
366
+ transparent calc(50% - var(--ap-shine-width, 10%)),
367
+ rgba(255, 255, 255, 0.35) 50%,
368
+ transparent calc(50% + var(--ap-shine-width, 10%))
369
+ );
370
+ }
371
+
372
+ /* Switch aurora variant */
373
+ .switch-aurora[data-state="checked"] {
374
+ background: linear-gradient(
375
+ var(--ap-grad-angle, 135deg),
376
+ rgb(var(--ap-aurora-1)),
377
+ rgb(var(--ap-aurora-2)),
378
+ rgb(var(--ap-aurora-3))
379
+ );
380
+ }
381
+
382
+ /* ===== Gradient Direction Utilities ===== */
383
+ .ap-grad-t { --ap-grad-angle: 0deg; }
384
+ .ap-grad-tr { --ap-grad-angle: 45deg; }
385
+ .ap-grad-r { --ap-grad-angle: 90deg; }
386
+ .ap-grad-br { --ap-grad-angle: 135deg; }
387
+ .ap-grad-b { --ap-grad-angle: 180deg; }
388
+ .ap-grad-bl { --ap-grad-angle: 225deg; }
389
+ .ap-grad-l { --ap-grad-angle: 270deg; }
390
+ .ap-grad-tl { --ap-grad-angle: 315deg; }
391
+
392
+ /* Shine direction utilities */
393
+ .ap-shine-t { --ap-shine-angle: 0deg; }
394
+ .ap-shine-tr { --ap-shine-angle: 45deg; }
395
+ .ap-shine-r { --ap-shine-angle: 90deg; }
396
+ .ap-shine-br { --ap-shine-angle: 135deg; }
397
+ .ap-shine-b { --ap-shine-angle: 180deg; }
398
+ .ap-shine-bl { --ap-shine-angle: 225deg; }
399
+ .ap-shine-l { --ap-shine-angle: 270deg; }
400
+ .ap-shine-tl { --ap-shine-angle: 315deg; }
401
+
402
+ /* Shine width utilities */
403
+ .ap-shine-thin { --ap-shine-width: 5%; }
404
+ .ap-shine-normal { --ap-shine-width: 10%; }
405
+ .ap-shine-wide { --ap-shine-width: 20%; }
406
+ .ap-shine-ultra { --ap-shine-width: 30%; }
407
+
408
+ /* Glass effect */
409
+ .glass {
410
+ background: rgba(var(--ap-background), 0.6);
411
+ backdrop-filter: blur(12px);
412
+ border: 1px solid rgba(var(--ap-border), 0.3);
413
+ }
414
+
415
+ /* Glow effect on hover */
416
+ .glow-hover {
417
+ transition: box-shadow 0.3s ease;
418
+ }
419
+
420
+ .glow-hover:hover {
421
+ box-shadow:
422
+ 0 0 20px rgba(var(--ap-primary), calc(0.3 * var(--ap-glow-strength))),
423
+ 0 0 40px rgba(var(--ap-secondary), calc(0.2 * var(--ap-glow-strength)));
424
+ }
425
+
426
+ /* =====================================================
427
+ Animation Utility Classes
428
+ ===================================================== */
429
+
430
+ @layer utilities {
431
+ /* ===== Transition Presets ===== */
432
+ .ap-trans-pop {
433
+ transition-property: transform, opacity, box-shadow;
434
+ transition-duration: var(--ap-dur-2);
435
+ transition-timing-function: var(--ap-ease-pop);
436
+ }
437
+
438
+ .ap-trans-snap {
439
+ transition-property: transform, opacity, box-shadow;
440
+ transition-duration: var(--ap-dur-1);
441
+ transition-timing-function: var(--ap-ease-snap);
442
+ }
443
+
444
+ .ap-trans-soft {
445
+ transition-property: transform, opacity, box-shadow;
446
+ transition-duration: var(--ap-dur-3);
447
+ transition-timing-function: var(--ap-ease-soft);
448
+ }
449
+
450
+ .ap-trans-spring {
451
+ transition-property: transform, opacity, box-shadow;
452
+ transition-duration: var(--ap-dur-3);
453
+ transition-timing-function: var(--ap-ease-spring);
454
+ }
455
+
456
+ /* ===== Hover States ===== */
457
+ .ap-hover-float {
458
+ transition: transform var(--ap-dur-3) var(--ap-ease-soft);
459
+ }
460
+ .ap-hover-float:hover {
461
+ transform: translateY(calc(-4px * var(--ap-motion-scale, 1)));
462
+ }
463
+
464
+ .ap-hover-glow {
465
+ transition: box-shadow var(--ap-dur-3) var(--ap-ease-soft);
466
+ }
467
+ .ap-hover-glow:hover {
468
+ box-shadow: 0 0 calc(20px * var(--ap-motion-scale, 1)) rgba(var(--ap-primary), 0.4);
469
+ }
470
+
471
+ .ap-hover-scale {
472
+ transition: transform var(--ap-dur-2) var(--ap-ease-pop);
473
+ }
474
+ .ap-hover-scale:hover {
475
+ transform: scale(calc(1 + 0.05 * var(--ap-motion-scale, 1)));
476
+ }
477
+
478
+ .ap-hover-tilt {
479
+ transition: transform var(--ap-dur-2) var(--ap-ease-pop);
480
+ }
481
+ .ap-hover-tilt:hover {
482
+ transform: rotate(calc(3deg * var(--ap-motion-scale, 1)));
483
+ }
484
+
485
+ /* ===== Active States ===== */
486
+ .ap-active-squish {
487
+ transition: transform var(--ap-dur-1) var(--ap-ease-snap);
488
+ }
489
+ .ap-active-squish:active {
490
+ transform: scale(0.95, 0.97);
491
+ }
492
+
493
+ .ap-active-press {
494
+ transition: transform var(--ap-dur-1) var(--ap-ease-snap);
495
+ }
496
+ .ap-active-press:active {
497
+ transform: scale(0.97);
498
+ }
499
+
500
+ /* ===== Enter Animations ===== */
501
+ .ap-enter-pop {
502
+ animation: ap-scale-in var(--ap-dur-2) var(--ap-ease-pop) forwards;
503
+ }
504
+
505
+ .ap-enter-slide {
506
+ animation: ap-slide-up var(--ap-dur-3) var(--ap-ease-spring) forwards;
507
+ }
508
+
509
+ .ap-enter-bounce {
510
+ animation: ap-bounce var(--ap-dur-3) var(--ap-ease-pop) forwards;
511
+ }
512
+
513
+ .ap-enter-jelly {
514
+ animation: ap-jelly var(--ap-dur-3) var(--ap-ease-spring) forwards;
515
+ }
516
+
517
+ /* ===== Exit Animations ===== */
518
+ .ap-exit-fade {
519
+ animation: ap-scale-out var(--ap-dur-2) var(--ap-ease-soft) forwards;
520
+ }
521
+
522
+ .ap-exit-slide {
523
+ animation: ap-slide-down var(--ap-dur-2) var(--ap-ease-soft) forwards;
524
+ }
525
+
526
+ /* ===== Special Effects ===== */
527
+ .ap-wiggle {
528
+ animation: ap-wiggle var(--ap-dur-4) var(--ap-ease-snap);
529
+ }
530
+
531
+ .ap-pulse-ring {
532
+ animation: ap-pulse-ring var(--ap-dur-4) var(--ap-ease-soft) forwards;
533
+ }
534
+
535
+ .ap-confetti {
536
+ animation: ap-confetti var(--ap-dur-5) var(--ap-ease-soft) forwards;
537
+ }
538
+
539
+ /* ===== Motion Reduce ===== */
540
+ .ap-motion-reduce,
541
+ .ap-motion-reduce * {
542
+ --ap-motion: 0 !important;
543
+ --ap-motion-scale: 0 !important;
544
+ animation: none !important;
545
+ transition-duration: 0.01ms !important;
546
+ }
547
+ }
548
+
549
+ /* Global reduced motion override */
550
+ @media (prefers-reduced-motion: reduce) {
551
+ .ap-hover-float:hover,
552
+ .ap-hover-scale:hover,
553
+ .ap-hover-tilt:hover,
554
+ .ap-active-squish:active,
555
+ .ap-active-press:active {
556
+ transform: none;
557
+ }
558
+
559
+ .ap-enter-pop,
560
+ .ap-enter-slide,
561
+ .ap-enter-bounce,
562
+ .ap-enter-jelly,
563
+ .ap-exit-fade,
564
+ .ap-exit-slide,
565
+ .ap-wiggle,
566
+ .ap-pulse-ring,
567
+ .ap-confetti {
568
+ animation: none;
569
+ opacity: 1;
570
+ }
571
+ }
572
+ `;
573
+ var NEUMOPOP_CSS = `
574
+ /* =====================================================
575
+ NeumoPop Skin - Neumorphism + Pop Design
576
+ ===================================================== */
577
+
578
+ [data-skin="neumopop"] {
579
+ --ap-shadow-light: rgba(255, 255, 255, 0.05);
580
+ --ap-shadow-dark: rgba(0, 0, 0, 0.4);
581
+ --ap-elev-1: 4px 4px 8px var(--ap-shadow-dark),
582
+ -4px -4px 8px var(--ap-shadow-light);
583
+ --ap-elev-2: 6px 6px 12px var(--ap-shadow-dark),
584
+ -6px -6px 12px var(--ap-shadow-light);
585
+ --ap-elev-3: 10px 10px 20px var(--ap-shadow-dark),
586
+ -10px -10px 20px var(--ap-shadow-light);
587
+ --ap-inset-1: inset 2px 2px 5px var(--ap-shadow-dark),
588
+ inset -2px -2px 5px var(--ap-shadow-light);
589
+ --ap-inset-2: inset 4px 4px 8px var(--ap-shadow-dark),
590
+ inset -4px -4px 8px var(--ap-shadow-light);
591
+ --ap-glow-strength: 0.3;
592
+ }
593
+
594
+ [data-skin="neumopop"].light,
595
+ .light[data-skin="neumopop"],
596
+ .light [data-skin="neumopop"] {
597
+ --ap-shadow-light: rgba(255, 255, 255, 0.7);
598
+ --ap-shadow-dark: rgba(0, 0, 0, 0.12);
599
+ }
600
+
601
+ [data-skin="neumopop"] .bg-aurora {
602
+ background: rgb(var(--ap-primary));
603
+ box-shadow: var(--ap-elev-2);
604
+ }
605
+
606
+ [data-skin="neumopop"] .text-aurora {
607
+ background: none;
608
+ -webkit-background-clip: unset;
609
+ background-clip: unset;
610
+ color: rgb(var(--ap-primary));
611
+ }
612
+
613
+ [data-skin="neumopop"] .glass {
614
+ background: rgb(var(--ap-muted));
615
+ backdrop-filter: none;
616
+ border: 1px solid rgba(var(--ap-border), 0.2);
617
+ box-shadow: var(--ap-elev-1);
618
+ }
619
+
620
+ [data-skin="neumopop"] .shine-effect::before {
621
+ background: linear-gradient(
622
+ 135deg,
623
+ rgba(255, 255, 255, 0.1) 0%,
624
+ transparent 50%
625
+ );
626
+ }
627
+
628
+ [data-skin="neumopop"] .glow-hover:hover {
629
+ box-shadow: var(--ap-elev-3);
630
+ }
631
+
632
+ [data-skin="neumopop"] .switch-aurora[data-state="checked"] {
633
+ background: rgb(var(--ap-primary));
634
+ box-shadow: var(--ap-inset-2);
635
+ }
636
+
637
+ [data-skin="neumopop"] .aurora-bg::before {
638
+ background: none;
639
+ animation: none;
640
+ }
641
+
642
+ [data-skin="neumopop"] button.bg-aurora:active,
643
+ [data-skin="neumopop"] [role="button"].bg-aurora:active {
644
+ box-shadow: var(--ap-inset-1);
645
+ }
646
+
647
+ [data-skin="neumopop"] input,
648
+ [data-skin="neumopop"] textarea,
649
+ [data-skin="neumopop"] select {
650
+ box-shadow: var(--ap-inset-1);
651
+ }
652
+ `;
653
+ var GLASSPOP_CSS = `
654
+ /* =====================================================
655
+ GlassPop Skin - Apple Liquid Glass Design
656
+ ===================================================== */
657
+
658
+ [data-skin="glasspop"] {
659
+ --ap-glass-bg: var(--ap-background);
660
+ --ap-glass-alpha: 0.22;
661
+ --ap-glass-blur: 32px;
662
+ --ap-glass-saturation: 1.7;
663
+ --ap-glass-brightness: 1.08;
664
+ --ap-glass-contrast: 1.05;
665
+ --ap-glass-border-alpha: 0.22;
666
+ --ap-glass-edge: inset 0 1px 0 rgba(255, 255, 255, 0.18),
667
+ inset 0 -1px 0 rgba(0, 0, 0, 0.18);
668
+ --ap-glass-highlight-alpha: 0.18;
669
+ --ap-glass-shadow-alpha: 0.22;
670
+ --ap-liquid-shine-alpha: 0.22;
671
+ --ap-liquid-shine-speed: 4s;
672
+ --ap-liquid-noise-alpha: 0.015;
673
+ --ap-liquid-refract-alpha: 0.12;
674
+ --ap-glass: 1;
675
+ --ap-liquid: 1;
676
+ --ap-glow-strength: 0.5;
677
+ --ap-surface: rgba(var(--ap-glass-bg), var(--ap-glass-alpha));
678
+ --ap-surface-border: rgba(var(--ap-border), var(--ap-glass-border-alpha));
679
+ --ap-surface-shadow: 0 10px 40px rgba(0, 0, 0, var(--ap-glass-shadow-alpha)),
680
+ 0 2px 8px rgba(0, 0, 0, calc(var(--ap-glass-shadow-alpha) * 0.6));
681
+ }
682
+
683
+ [data-skin="glasspop"].light,
684
+ .light[data-skin="glasspop"],
685
+ .light [data-skin="glasspop"] {
686
+ --ap-glass-alpha: 0.38;
687
+ --ap-glass-blur: 34px;
688
+ --ap-glass-saturation: 1.5;
689
+ --ap-glass-brightness: 1.02;
690
+ --ap-glass-contrast: 1.02;
691
+ --ap-glass-border-alpha: 0.35;
692
+ --ap-glass-edge: inset 0 1px 0 rgba(255, 255, 255, 0.65),
693
+ inset 0 -1px 0 rgba(0, 0, 0, 0.06);
694
+ --ap-glass-highlight-alpha: 0.22;
695
+ --ap-glass-shadow-alpha: 0.08;
696
+ --ap-liquid-shine-alpha: 0.24;
697
+ --ap-liquid-refract-alpha: 0.14;
698
+ }
699
+
700
+ .ap-no-glass { --ap-glass: 0; }
701
+ .ap-no-liquid { --ap-liquid: 0; }
702
+
703
+ [data-skin="glasspop"] .glass {
704
+ position: relative;
705
+ background:
706
+ linear-gradient(
707
+ 135deg,
708
+ rgba(255, 255, 255, var(--ap-glass-highlight-alpha)) 0%,
709
+ rgba(255, 255, 255, 0) 45%
710
+ ),
711
+ linear-gradient(
712
+ 315deg,
713
+ rgba(0, 0, 0, 0.22) 0%,
714
+ rgba(0, 0, 0, 0) 50%
715
+ ),
716
+ var(--ap-surface);
717
+ backdrop-filter: blur(var(--ap-glass-blur)) saturate(var(--ap-glass-saturation))
718
+ brightness(var(--ap-glass-brightness)) contrast(var(--ap-glass-contrast));
719
+ -webkit-backdrop-filter: blur(var(--ap-glass-blur)) saturate(var(--ap-glass-saturation))
720
+ brightness(var(--ap-glass-brightness)) contrast(var(--ap-glass-contrast));
721
+ border: 1px solid var(--ap-surface-border);
722
+ box-shadow: var(--ap-glass-edge), var(--ap-surface-shadow);
723
+ }
724
+
725
+ [data-skin="glasspop"] .glass::before {
726
+ content: "";
727
+ position: absolute;
728
+ inset: 0;
729
+ border-radius: inherit;
730
+ background:
731
+ radial-gradient(
732
+ 120% 140% at 0% 0%,
733
+ rgba(255, 255, 255, var(--ap-glass-highlight-alpha)) 0%,
734
+ transparent 55%
735
+ ),
736
+ radial-gradient(
737
+ 120% 120% at 100% 0%,
738
+ rgba(255, 255, 255, calc(var(--ap-glass-highlight-alpha) * 0.7)) 0%,
739
+ transparent 60%
740
+ ),
741
+ radial-gradient(
742
+ 160% 120% at 50% 120%,
743
+ rgba(0, 0, 0, calc(var(--ap-liquid-refract-alpha) * 0.7)) 0%,
744
+ transparent 60%
745
+ );
746
+ pointer-events: none;
747
+ }
748
+
749
+ [data-skin="glasspop"] .bg-aurora {
750
+ position: relative;
751
+ background: rgba(var(--ap-primary), 0.7);
752
+ backdrop-filter: blur(var(--ap-glass-blur)) saturate(var(--ap-glass-saturation))
753
+ brightness(var(--ap-glass-brightness)) contrast(var(--ap-glass-contrast));
754
+ -webkit-backdrop-filter: blur(var(--ap-glass-blur)) saturate(var(--ap-glass-saturation))
755
+ brightness(var(--ap-glass-brightness)) contrast(var(--ap-glass-contrast));
756
+ border: 1px solid rgba(255, 255, 255, calc(var(--ap-glass-border-alpha) + 0.08));
757
+ box-shadow: var(--ap-glass-edge), var(--ap-surface-shadow);
758
+ }
759
+
760
+ [data-skin="glasspop"] .aurora-bg {
761
+ background-color: rgb(var(--ap-background));
762
+ background-image: linear-gradient(
763
+ var(--ap-grad-angle, 135deg),
764
+ rgb(var(--ap-aurora-1)),
765
+ rgb(var(--ap-aurora-2)),
766
+ rgb(var(--ap-aurora-3))
767
+ );
768
+ }
769
+
770
+ [data-skin="glasspop"] .ap-dialog-overlay {
771
+ background: rgba(0, 0, 0, 0.35);
772
+ }
773
+
774
+ [data-skin="glasspop"].light .ap-dialog-overlay,
775
+ .light [data-skin="glasspop"] .ap-dialog-overlay {
776
+ background: rgba(15, 23, 42, 0.18);
777
+ }
778
+
779
+ [data-skin="glasspop"] .ap-dialog-content {
780
+ position: fixed;
781
+ z-index: 60;
782
+ background:
783
+ linear-gradient(
784
+ 135deg,
785
+ rgba(255, 255, 255, calc(var(--ap-glass-highlight-alpha) * 0.8)) 0%,
786
+ rgba(255, 255, 255, 0) 45%
787
+ ),
788
+ var(--ap-surface);
789
+ backdrop-filter: blur(calc(var(--ap-glass-blur) * 0.9))
790
+ saturate(var(--ap-glass-saturation))
791
+ brightness(var(--ap-glass-brightness))
792
+ contrast(var(--ap-glass-contrast));
793
+ -webkit-backdrop-filter: blur(calc(var(--ap-glass-blur) * 0.9))
794
+ saturate(var(--ap-glass-saturation))
795
+ brightness(var(--ap-glass-brightness))
796
+ contrast(var(--ap-glass-contrast));
797
+ border-color: rgba(255, 255, 255, calc(var(--ap-glass-border-alpha) + 0.08));
798
+ box-shadow: var(--ap-glass-edge),
799
+ 0 24px 80px rgba(0, 0, 0, 0.35);
800
+ }
801
+
802
+ [data-skin="glasspop"] .bg-aurora::before {
803
+ content: "";
804
+ position: absolute;
805
+ inset: 0;
806
+ border-radius: inherit;
807
+ background: linear-gradient(
808
+ 135deg,
809
+ rgba(255, 255, 255, calc(var(--ap-glass-highlight-alpha) * 0.8)) 0%,
810
+ rgba(255, 255, 255, 0) 55%
811
+ );
812
+ pointer-events: none;
813
+ }
814
+
815
+ [data-skin="glasspop"] .glow-hover:hover {
816
+ box-shadow: var(--ap-glass-edge),
817
+ 0 8px 32px rgba(var(--ap-primary), calc(0.15 * var(--ap-glow-strength))),
818
+ 0 2px 8px rgba(0, 0, 0, var(--ap-glass-shadow-alpha));
819
+ }
820
+
821
+ [data-skin="glasspop"] .switch-aurora[data-state="checked"] {
822
+ background: rgba(var(--ap-primary), 0.75);
823
+ backdrop-filter: blur(10px) saturate(1.4) brightness(1.05);
824
+ -webkit-backdrop-filter: blur(10px) saturate(1.4) brightness(1.05);
825
+ box-shadow: var(--ap-glass-edge);
826
+ }
827
+
828
+ [data-skin="glasspop"] button.bg-aurora:active,
829
+ [data-skin="glasspop"] [role="button"].bg-aurora:active {
830
+ background: rgba(var(--ap-primary), 0.85);
831
+ box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.15),
832
+ 0 1px 2px rgba(0, 0, 0, var(--ap-glass-shadow-alpha));
833
+ transform: scale(0.98);
834
+ }
835
+
836
+ [data-skin="glasspop"] input,
837
+ [data-skin="glasspop"] textarea,
838
+ [data-skin="glasspop"] select {
839
+ background:
840
+ linear-gradient(
841
+ 135deg,
842
+ rgba(255, 255, 255, calc(var(--ap-glass-highlight-alpha) * 0.6)) 0%,
843
+ rgba(255, 255, 255, 0) 45%
844
+ ),
845
+ rgba(var(--ap-glass-bg), calc(var(--ap-glass-alpha) * 0.55));
846
+ backdrop-filter: blur(calc(var(--ap-glass-blur) * 0.55)) saturate(var(--ap-glass-saturation))
847
+ brightness(var(--ap-glass-brightness));
848
+ -webkit-backdrop-filter: blur(calc(var(--ap-glass-blur) * 0.55)) saturate(var(--ap-glass-saturation))
849
+ brightness(var(--ap-glass-brightness));
850
+ border-color: var(--ap-surface-border);
851
+ box-shadow: var(--ap-glass-edge),
852
+ inset 0 1px 3px rgba(0, 0, 0, calc(var(--ap-glass-shadow-alpha) * 0.4));
853
+ }
854
+
855
+ [data-skin="glasspop"] input:focus,
856
+ [data-skin="glasspop"] textarea:focus,
857
+ [data-skin="glasspop"] select:focus {
858
+ border-color: rgba(var(--ap-primary), 0.6);
859
+ box-shadow: var(--ap-glass-edge),
860
+ 0 0 0 3px rgba(var(--ap-primary), 0.15),
861
+ inset 0 1px 3px rgba(0, 0, 0, calc(var(--ap-glass-shadow-alpha) * 0.3));
862
+ }
863
+ `;
864
+ var UTILS_TS = `import { type ClassValue, clsx } from "clsx"
865
+ import { twMerge } from "tailwind-merge"
866
+
867
+ export function cn(...inputs: ClassValue[]) {
868
+ return twMerge(clsx(inputs))
869
+ }
870
+ `;
871
+
872
+ // src/commands/init.ts
873
+ function detectFramework(cwd) {
874
+ const packageJsonPath = path3.join(cwd, "package.json");
875
+ if (!fs3.existsSync(packageJsonPath)) {
876
+ return null;
877
+ }
878
+ try {
879
+ const packageJson = JSON.parse(fs3.readFileSync(packageJsonPath, "utf-8"));
880
+ const deps = {
881
+ ...packageJson.dependencies,
882
+ ...packageJson.devDependencies
883
+ };
884
+ if (deps.next) return "next";
885
+ if (deps.astro) return "astro";
886
+ if (deps.vite) return "vite";
887
+ } catch {
888
+ }
889
+ return null;
890
+ }
891
+ function detectTailwind(cwd) {
892
+ const possibleConfigs = [
893
+ "tailwind.config.js",
894
+ "tailwind.config.ts",
895
+ "tailwind.config.mjs",
896
+ "tailwind.config.cjs"
897
+ ];
898
+ for (const config of possibleConfigs) {
899
+ if (fs3.existsSync(path3.join(cwd, config))) {
900
+ return config;
901
+ }
902
+ }
903
+ return null;
904
+ }
905
+ function detectCssFile(cwd, framework) {
906
+ const possiblePaths = [
907
+ "app/globals.css",
908
+ "src/app/globals.css",
909
+ "styles/globals.css",
910
+ "src/styles/globals.css",
911
+ "src/index.css",
912
+ "src/styles.css",
913
+ "styles/index.css"
914
+ ];
915
+ for (const cssPath of possiblePaths) {
916
+ if (fs3.existsSync(path3.join(cwd, cssPath))) {
917
+ return cssPath;
918
+ }
919
+ }
920
+ if (framework === "next") return "app/globals.css";
921
+ if (framework === "vite") return "src/index.css";
922
+ if (framework === "astro") return "src/styles/globals.css";
923
+ return "styles/globals.css";
924
+ }
925
+ async function initCommand(options) {
926
+ const cwd = process.cwd();
927
+ console.log();
928
+ console.log(chalk.bold(" popcn/ui ") + chalk.dim("- AuroraPop Design System"));
929
+ console.log();
930
+ if (configExists(cwd) && !options.force) {
931
+ console.log(
932
+ chalk.yellow(" Project already initialized. Use --force to reinitialize.")
933
+ );
934
+ return;
935
+ }
936
+ const detectedFramework = detectFramework(cwd);
937
+ const detectedTailwind = detectTailwind(cwd);
938
+ const pm = getPackageManager(cwd);
939
+ let framework = detectedFramework || "next";
940
+ let tailwindConfig = detectedTailwind || "tailwind.config.ts";
941
+ let cssFile = detectCssFile(cwd, detectedFramework);
942
+ let componentsPath = "@/components";
943
+ let utilsPath = "@/lib/utils";
944
+ let skin = "aurora";
945
+ let theme = "cosmic";
946
+ if (!options.yes && !options.defaults) {
947
+ const response = await prompts([
948
+ {
949
+ type: "select",
950
+ name: "framework",
951
+ message: "Which framework are you using?",
952
+ choices: [
953
+ { title: "Next.js", value: "next" },
954
+ { title: "Vite + React", value: "vite" },
955
+ { title: "Astro + React", value: "astro" }
956
+ ],
957
+ initial: framework === "next" ? 0 : framework === "vite" ? 1 : 2
958
+ },
959
+ {
960
+ type: "text",
961
+ name: "tailwindConfig",
962
+ message: "Where is your Tailwind config?",
963
+ initial: tailwindConfig
964
+ },
965
+ {
966
+ type: "text",
967
+ name: "cssFile",
968
+ message: "Where is your global CSS file?",
969
+ initial: cssFile
970
+ },
971
+ {
972
+ type: "text",
973
+ name: "componentsPath",
974
+ message: "Where should components be installed?",
975
+ initial: componentsPath
976
+ },
977
+ {
978
+ type: "text",
979
+ name: "utilsPath",
980
+ message: "Where should utils be installed?",
981
+ initial: utilsPath
982
+ },
983
+ {
984
+ type: "select",
985
+ name: "skin",
986
+ message: "Which skin style?",
987
+ choices: [
988
+ { title: "Aurora (Gradient-driven)", value: "aurora" },
989
+ { title: "NeumoPop (Neumorphism)", value: "neumopop" },
990
+ { title: "GlassPop (Liquid Glass)", value: "glasspop" }
991
+ ],
992
+ initial: 0
993
+ },
994
+ {
995
+ type: "select",
996
+ name: "theme",
997
+ message: "Which theme preset?",
998
+ choices: [
999
+ { title: "Cosmic (Indigo/Purple/Sky)", value: "cosmic" },
1000
+ { title: "Sunset (Pink/Orange/Yellow)", value: "sunset" },
1001
+ { title: "Neon (Cyan/Magenta/Lime)", value: "neon" }
1002
+ ],
1003
+ initial: 0
1004
+ }
1005
+ ]);
1006
+ if (!response.framework) {
1007
+ console.log(chalk.red(" Cancelled."));
1008
+ return;
1009
+ }
1010
+ framework = response.framework;
1011
+ tailwindConfig = response.tailwindConfig;
1012
+ cssFile = response.cssFile;
1013
+ componentsPath = response.componentsPath;
1014
+ utilsPath = response.utilsPath;
1015
+ skin = response.skin;
1016
+ theme = response.theme;
1017
+ }
1018
+ const spinner = ora("Initializing popcn/ui...").start();
1019
+ try {
1020
+ const config = {
1021
+ $schema: "https://popcnui.com/schema.json",
1022
+ style: "aurorapop",
1023
+ skin,
1024
+ theme,
1025
+ tailwind: {
1026
+ config: tailwindConfig,
1027
+ css: cssFile
1028
+ },
1029
+ aliases: {
1030
+ components: componentsPath,
1031
+ utils: utilsPath,
1032
+ lib: utilsPath.replace("/utils", "")
1033
+ }
1034
+ };
1035
+ writeConfig(config, cwd);
1036
+ spinner.text = "Created components.json";
1037
+ const resolveAlias2 = (alias) => {
1038
+ if (alias.startsWith("@/")) {
1039
+ return path3.join(cwd, alias.slice(2));
1040
+ }
1041
+ return path3.join(cwd, alias);
1042
+ };
1043
+ const componentsDir = resolveAlias2(componentsPath);
1044
+ const libDir = resolveAlias2(config.aliases.lib);
1045
+ fs3.mkdirSync(path3.join(componentsDir, "ui"), { recursive: true });
1046
+ fs3.mkdirSync(libDir, { recursive: true });
1047
+ const utilsFilePath = path3.join(libDir, "utils.ts");
1048
+ if (!fs3.existsSync(utilsFilePath) || options.force) {
1049
+ fs3.writeFileSync(utilsFilePath, UTILS_TS);
1050
+ spinner.text = "Created lib/utils.ts";
1051
+ }
1052
+ const cssFilePath = path3.join(cwd, cssFile);
1053
+ const cssDir = path3.dirname(cssFilePath);
1054
+ fs3.mkdirSync(cssDir, { recursive: true });
1055
+ const skinCssMap = {
1056
+ aurora: AURORAPOP_CSS,
1057
+ neumopop: AURORAPOP_CSS + "\n" + NEUMOPOP_CSS,
1058
+ glasspop: AURORAPOP_CSS + "\n" + GLASSPOP_CSS
1059
+ };
1060
+ const cssTemplate = skinCssMap[skin] ?? AURORAPOP_CSS;
1061
+ if (!fs3.existsSync(cssFilePath)) {
1062
+ fs3.writeFileSync(cssFilePath, cssTemplate);
1063
+ spinner.text = `Created ${cssFile}`;
1064
+ } else {
1065
+ const existingCss = fs3.readFileSync(cssFilePath, "utf-8");
1066
+ if (!existingCss.includes("--ap-primary")) {
1067
+ const tailwindDirectives = `@tailwind base;
1068
+ @tailwind components;
1069
+ @tailwind utilities;
1070
+ `;
1071
+ const cssWithoutDirectives = existingCss.replace(/@tailwind base;?\n?/g, "").replace(/@tailwind components;?\n?/g, "").replace(/@tailwind utilities;?\n?/g, "").trim();
1072
+ fs3.writeFileSync(
1073
+ cssFilePath,
1074
+ AURORAPOP_CSS + "\n\n/* Your existing styles */\n" + cssWithoutDirectives
1075
+ );
1076
+ spinner.text = `Updated ${cssFile} with AuroraPop tokens`;
1077
+ }
1078
+ }
1079
+ spinner.succeed(chalk.green("Initialized popcn/ui"));
1080
+ console.log();
1081
+ console.log(chalk.dim(" Next steps:"));
1082
+ console.log();
1083
+ console.log(
1084
+ chalk.cyan(` ${getInstallCommand(pm)} class-variance-authority clsx tailwind-merge`)
1085
+ );
1086
+ console.log();
1087
+ console.log(chalk.dim(" Then add components:"));
1088
+ console.log(chalk.cyan(" npx popcn add button"));
1089
+ console.log();
1090
+ } catch (error) {
1091
+ spinner.fail(chalk.red("Failed to initialize"));
1092
+ console.error(error);
1093
+ process.exit(1);
1094
+ }
1095
+ }
1096
+
1097
+ // src/commands/add.ts
1098
+ import * as fs4 from "fs";
1099
+ import * as path4 from "path";
1100
+ import chalk2 from "chalk";
1101
+ import prompts2 from "prompts";
1102
+ import ora2 from "ora";
1103
+
1104
+ // src/schemas/registry.ts
1105
+ import { z as z2 } from "zod";
1106
+ var registryItemTypeSchema = z2.enum([
1107
+ "ui",
1108
+ "component",
1109
+ "util",
1110
+ "style",
1111
+ "theme",
1112
+ "hook",
1113
+ "lib"
1114
+ ]);
1115
+ var registryFileSchema = z2.object({
1116
+ path: z2.string(),
1117
+ type: z2.string(),
1118
+ content: z2.string()
1119
+ });
1120
+ var registryComponentSchema = z2.object({
1121
+ name: z2.string(),
1122
+ type: registryItemTypeSchema,
1123
+ description: z2.string().optional(),
1124
+ files: z2.array(registryFileSchema),
1125
+ dependencies: z2.array(z2.string()).optional(),
1126
+ devDependencies: z2.array(z2.string()).optional(),
1127
+ registryDependencies: z2.array(z2.string()).optional()
1128
+ });
1129
+ var registryStyleSchema = z2.object({
1130
+ name: z2.string(),
1131
+ type: z2.literal("style"),
1132
+ description: z2.string().optional(),
1133
+ cssVars: z2.object({
1134
+ dark: z2.record(z2.string()),
1135
+ light: z2.record(z2.string())
1136
+ }),
1137
+ tailwindConfig: z2.record(z2.unknown()).optional()
1138
+ });
1139
+ var registryThemeSchema = z2.object({
1140
+ name: z2.string(),
1141
+ type: z2.literal("theme"),
1142
+ label: z2.string().optional(),
1143
+ description: z2.string().optional(),
1144
+ cssVars: z2.record(z2.string())
1145
+ });
1146
+ var registryIndexSchema = z2.object({
1147
+ version: z2.string(),
1148
+ components: z2.array(
1149
+ z2.object({
1150
+ name: z2.string(),
1151
+ type: z2.string(),
1152
+ description: z2.string().optional(),
1153
+ dependencies: z2.array(z2.string()).optional(),
1154
+ registryDependencies: z2.array(z2.string()).optional()
1155
+ })
1156
+ ),
1157
+ styles: z2.array(
1158
+ z2.object({
1159
+ name: z2.string(),
1160
+ type: z2.string(),
1161
+ description: z2.string().optional()
1162
+ })
1163
+ ),
1164
+ themes: z2.array(
1165
+ z2.object({
1166
+ name: z2.string(),
1167
+ type: z2.string(),
1168
+ description: z2.string().optional()
1169
+ })
1170
+ )
1171
+ });
1172
+
1173
+ // src/utils/registry.ts
1174
+ var DEFAULT_REGISTRY_URL = "https://popcnui.com/api/registry";
1175
+ function getRegistryUrl() {
1176
+ return process.env.POPCN_REGISTRY_URL || DEFAULT_REGISTRY_URL;
1177
+ }
1178
+ var RegistryError = class extends Error {
1179
+ constructor(message, code) {
1180
+ super(message);
1181
+ this.code = code;
1182
+ this.name = "RegistryError";
1183
+ }
1184
+ };
1185
+ async function fetchRegistry() {
1186
+ const url = getRegistryUrl();
1187
+ try {
1188
+ const response = await fetch(url);
1189
+ if (!response.ok) {
1190
+ throw new RegistryError(
1191
+ `Failed to fetch registry: ${response.statusText}`,
1192
+ response.status === 404 ? "NOT_FOUND" : "NETWORK"
1193
+ );
1194
+ }
1195
+ const data = await response.json();
1196
+ const result = registryIndexSchema.safeParse(data);
1197
+ if (!result.success) {
1198
+ throw new RegistryError(
1199
+ `Invalid registry format: ${result.error.errors[0]?.message}`,
1200
+ "VALIDATION"
1201
+ );
1202
+ }
1203
+ return result.data;
1204
+ } catch (err) {
1205
+ if (err instanceof RegistryError) throw err;
1206
+ throw new RegistryError(
1207
+ `Network error: ${err instanceof Error ? err.message : "Unknown error"}`,
1208
+ "NETWORK"
1209
+ );
1210
+ }
1211
+ }
1212
+ async function fetchComponent(name) {
1213
+ const url = `${getRegistryUrl()}/ui/${name}`;
1214
+ try {
1215
+ const response = await fetch(url);
1216
+ if (!response.ok) {
1217
+ throw new RegistryError(
1218
+ `Component "${name}" not found`,
1219
+ response.status === 404 ? "NOT_FOUND" : "NETWORK"
1220
+ );
1221
+ }
1222
+ const data = await response.json();
1223
+ const result = registryComponentSchema.safeParse(data);
1224
+ if (!result.success) {
1225
+ throw new RegistryError(
1226
+ `Invalid component format for "${name}": ${result.error.errors[0]?.message}`,
1227
+ "VALIDATION"
1228
+ );
1229
+ }
1230
+ return result.data;
1231
+ } catch (err) {
1232
+ if (err instanceof RegistryError) throw err;
1233
+ throw new RegistryError(
1234
+ `Failed to fetch component "${name}": ${err instanceof Error ? err.message : "Unknown error"}`,
1235
+ "NETWORK"
1236
+ );
1237
+ }
1238
+ }
1239
+
1240
+ // src/commands/add.ts
1241
+ async function addCommand(components, options) {
1242
+ const cwd = process.cwd();
1243
+ console.log();
1244
+ if (!configExists(cwd)) {
1245
+ console.log(
1246
+ chalk2.red(" Project not initialized. Run ") + chalk2.cyan("popcn init") + chalk2.red(" first.")
1247
+ );
1248
+ return;
1249
+ }
1250
+ const config = getConfig(cwd);
1251
+ if (!config) {
1252
+ console.log(chalk2.red(" Failed to read components.json"));
1253
+ return;
1254
+ }
1255
+ if (!components || components.length === 0) {
1256
+ const spinner = ora2("Fetching available components...").start();
1257
+ try {
1258
+ const registry = await fetchRegistry();
1259
+ spinner.stop();
1260
+ console.log(chalk2.bold(" Available components:"));
1261
+ console.log();
1262
+ for (const component of registry.components) {
1263
+ console.log(
1264
+ chalk2.cyan(` ${component.name}`) + chalk2.dim(` - ${component.description || ""}`)
1265
+ );
1266
+ }
1267
+ console.log();
1268
+ console.log(chalk2.dim(" Usage: ") + chalk2.cyan("popcn add <component>"));
1269
+ console.log();
1270
+ if (!options.yes) {
1271
+ const response = await prompts2({
1272
+ type: "multiselect",
1273
+ name: "components",
1274
+ message: "Which components would you like to add?",
1275
+ choices: registry.components.map((c) => ({
1276
+ title: c.name,
1277
+ value: c.name,
1278
+ description: c.description
1279
+ }))
1280
+ });
1281
+ if (response.components && response.components.length > 0) {
1282
+ components = response.components;
1283
+ } else {
1284
+ return;
1285
+ }
1286
+ } else {
1287
+ return;
1288
+ }
1289
+ } catch (error) {
1290
+ spinner.fail(chalk2.red("Failed to fetch registry"));
1291
+ console.error(error);
1292
+ return;
1293
+ }
1294
+ }
1295
+ const pm = getPackageManager(cwd);
1296
+ const allDependencies = /* @__PURE__ */ new Set();
1297
+ const installedComponents = [];
1298
+ for (const componentName of components) {
1299
+ const spinner = ora2(`Adding ${componentName}...`).start();
1300
+ try {
1301
+ const component = await fetchComponent(componentName);
1302
+ if (component.dependencies) {
1303
+ component.dependencies.forEach((dep) => allDependencies.add(dep));
1304
+ }
1305
+ if (component.registryDependencies && component.registryDependencies.length > 0) {
1306
+ for (const depName of component.registryDependencies) {
1307
+ if (!installedComponents.includes(depName)) {
1308
+ spinner.text = `Adding dependency: ${depName}...`;
1309
+ const depComponent = await fetchComponent(depName);
1310
+ await writeComponentFiles(depComponent, config, cwd, options.overwrite);
1311
+ installedComponents.push(depName);
1312
+ if (depComponent.dependencies) {
1313
+ depComponent.dependencies.forEach((dep) => allDependencies.add(dep));
1314
+ }
1315
+ }
1316
+ }
1317
+ }
1318
+ await writeComponentFiles(component, config, cwd, options.overwrite);
1319
+ installedComponents.push(componentName);
1320
+ spinner.succeed(chalk2.green(`Added ${componentName}`));
1321
+ } catch (error) {
1322
+ spinner.fail(chalk2.red(`Failed to add ${componentName}`));
1323
+ if (error instanceof Error) {
1324
+ console.log(chalk2.dim(` ${error.message}`));
1325
+ }
1326
+ }
1327
+ }
1328
+ if (allDependencies.size > 0) {
1329
+ console.log();
1330
+ console.log(chalk2.dim(" Install dependencies:"));
1331
+ console.log();
1332
+ console.log(
1333
+ chalk2.cyan(` ${getInstallCommand(pm)} ${Array.from(allDependencies).join(" ")}`)
1334
+ );
1335
+ console.log();
1336
+ }
1337
+ }
1338
+ async function writeComponentFiles(component, config, cwd, overwrite) {
1339
+ if (!config) return;
1340
+ for (const file of component.files) {
1341
+ let outputPath;
1342
+ if (file.path.startsWith("components/ui/")) {
1343
+ const fileName = path4.basename(file.path);
1344
+ const componentsDir = resolveAlias(config.aliases.components, cwd);
1345
+ outputPath = path4.join(componentsDir, "ui", fileName);
1346
+ } else if (file.path.startsWith("lib/")) {
1347
+ const fileName = path4.basename(file.path);
1348
+ const libDir = resolveAlias(config.aliases.lib, cwd);
1349
+ outputPath = path4.join(libDir, fileName);
1350
+ } else {
1351
+ outputPath = path4.join(cwd, file.path);
1352
+ }
1353
+ if (fs4.existsSync(outputPath) && !overwrite) {
1354
+ console.log(chalk2.dim(` Skipping ${file.path} (already exists)`));
1355
+ continue;
1356
+ }
1357
+ fs4.mkdirSync(path4.dirname(outputPath), { recursive: true });
1358
+ let content = file.content;
1359
+ if (config.aliases.utils !== "@/lib/utils") {
1360
+ content = content.replace(
1361
+ /@\/lib\/utils/g,
1362
+ config.aliases.utils
1363
+ );
1364
+ }
1365
+ fs4.writeFileSync(outputPath, content);
1366
+ }
1367
+ }
1368
+
1369
+ // src/commands/list.ts
1370
+ import chalk3 from "chalk";
1371
+ import ora3 from "ora";
1372
+ function groupRegistry(registry) {
1373
+ return {
1374
+ components: registry.components || [],
1375
+ styles: registry.styles || [],
1376
+ themes: registry.themes || []
1377
+ };
1378
+ }
1379
+ function printGroupedItems(title, items) {
1380
+ if (items.length === 0) return;
1381
+ console.log();
1382
+ console.log(chalk3.bold.cyan(` ${title}`));
1383
+ console.log(chalk3.dim(" " + "\u2500".repeat(40)));
1384
+ for (const item of items) {
1385
+ const description = item.description ? chalk3.dim(` - ${item.description}`) : "";
1386
+ console.log(` ${chalk3.white(item.name)}${description}`);
1387
+ }
1388
+ }
1389
+ async function listCommand(options) {
1390
+ console.log();
1391
+ const spinner = ora3("Fetching registry...").start();
1392
+ try {
1393
+ const registry = await fetchRegistry();
1394
+ spinner.stop();
1395
+ if (options.json) {
1396
+ const grouped2 = groupRegistry(registry);
1397
+ console.log(JSON.stringify(grouped2, null, 2));
1398
+ return;
1399
+ }
1400
+ console.log(chalk3.bold(" popcn/ui Registry"));
1401
+ console.log();
1402
+ const grouped = groupRegistry(registry);
1403
+ printGroupedItems("Components", grouped.components);
1404
+ printGroupedItems("Styles", grouped.styles);
1405
+ printGroupedItems("Themes", grouped.themes);
1406
+ const totalCount = grouped.components.length + grouped.styles.length + grouped.themes.length;
1407
+ console.log();
1408
+ console.log(chalk3.dim(` ${totalCount} items available`));
1409
+ console.log();
1410
+ console.log(chalk3.dim(" Usage:"));
1411
+ console.log(chalk3.cyan(" popcn add <component>") + chalk3.dim(" - Add a component"));
1412
+ console.log(chalk3.cyan(" popcn list --json") + chalk3.dim(" - Output as JSON"));
1413
+ console.log();
1414
+ } catch (error) {
1415
+ spinner.fail(chalk3.red("Failed to fetch registry"));
1416
+ if (error instanceof Error) {
1417
+ console.log(chalk3.dim(` ${error.message}`));
1418
+ }
1419
+ process.exit(1);
1420
+ }
1421
+ }
1422
+
1423
+ // package.json
1424
+ var package_default = {
1425
+ name: "popcn",
1426
+ version: "0.0.1",
1427
+ description: "CLI for popcn/ui - AuroraPop design system",
1428
+ publishConfig: {
1429
+ access: "public"
1430
+ },
1431
+ type: "module",
1432
+ bin: "./dist/index.js",
1433
+ main: "./dist/index.js",
1434
+ types: "./dist/index.d.ts",
1435
+ exports: {
1436
+ ".": {
1437
+ types: "./dist/index.d.ts",
1438
+ default: "./dist/index.js"
1439
+ }
1440
+ },
1441
+ files: [
1442
+ "dist"
1443
+ ],
1444
+ engines: {
1445
+ node: ">=18.0.0"
1446
+ },
1447
+ scripts: {
1448
+ dev: "tsup --watch",
1449
+ build: "tsup",
1450
+ test: "vitest run",
1451
+ "test:watch": "vitest",
1452
+ clean: "rm -rf dist node_modules",
1453
+ "pub:beta": "pnpm build && pnpm publish --no-git-checks --access public --tag beta",
1454
+ "pub:next": "pnpm build && pnpm publish --no-git-checks --access public --tag next",
1455
+ "pub:release": "pnpm build && pnpm publish --access public"
1456
+ },
1457
+ dependencies: {
1458
+ chalk: "^5.3.0",
1459
+ commander: "^12.1.0",
1460
+ "fs-extra": "^11.2.0",
1461
+ ora: "^8.1.1",
1462
+ prompts: "^2.4.2",
1463
+ zod: "^3.24.1"
1464
+ },
1465
+ devDependencies: {
1466
+ "@types/fs-extra": "^11.0.4",
1467
+ "@types/node": "^22.10.0",
1468
+ "@types/prompts": "^2.4.9",
1469
+ tsup: "^8.3.5",
1470
+ typescript: "^5.7.2",
1471
+ vitest: "^2.1.8"
1472
+ },
1473
+ keywords: [
1474
+ "cli",
1475
+ "ui",
1476
+ "components",
1477
+ "aurora",
1478
+ "aurorapop",
1479
+ "tailwind",
1480
+ "radix-ui",
1481
+ "design-system",
1482
+ "gradient",
1483
+ "motion"
1484
+ ],
1485
+ author: {
1486
+ name: "popcn",
1487
+ url: "https://popcnui.com"
1488
+ },
1489
+ license: "MIT",
1490
+ repository: {
1491
+ type: "git",
1492
+ url: "https://github.com/popcn/ui.git",
1493
+ directory: "packages/popcn"
1494
+ }
1495
+ };
1496
+
1497
+ // src/index.ts
1498
+ var program = new Command();
1499
+ program.name("popcn").description("CLI for popcn/ui - AuroraPop design system").version(package_default.version);
1500
+ program.command("init").description("Initialize popcn/ui in your project").option("-y, --yes", "Skip confirmation prompts", false).option("-d, --defaults", "Use default configuration", false).option("-f, --force", "Force overwrite existing files", false).action(initCommand);
1501
+ program.command("add").description("Add a component to your project").argument("[components...]", "Components to add").option("-y, --yes", "Skip confirmation prompts", false).option("-o, --overwrite", "Overwrite existing files", false).option("-p, --path <path>", "Custom path for components").action(addCommand);
1502
+ program.command("list").description("List all available components, styles, and themes").option("--json", "Output as JSON", false).action(listCommand);
1503
+ program.parse();