metabinaries 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,777 @@
1
+ export const uiTemplates = {
2
+ 'components/ui/alert.tsx': `import * as React from 'react';
3
+ import { cva, type VariantProps } from 'class-variance-authority';
4
+
5
+ import { cn } from '@/lib/utils';
6
+
7
+ const alertVariants = cva(
8
+ 'relative w-full rounded-lg border px-4 py-3 text-sm grid has-[>svg]:grid-cols-[calc(var(--spacing)*4)_1fr] grid-cols-[0_1fr] has-[>svg]:gap-x-3 gap-y-0.5 items-start [&>svg]:size-4 [&>svg]:translate-y-0.5 [&>svg]:text-current',
9
+ {
10
+ variants: {
11
+ variant: {
12
+ default: 'bg-card text-card-foreground',
13
+ destructive:
14
+ 'text-destructive bg-card [&>svg]:text-current *:data-[slot=alert-description]:text-destructive/90',
15
+ },
16
+ },
17
+ defaultVariants: {
18
+ variant: 'default',
19
+ },
20
+ }
21
+ );
22
+
23
+ function Alert({
24
+ className,
25
+ variant,
26
+ ...props
27
+ }: React.ComponentProps<'div'> & VariantProps<typeof alertVariants>) {
28
+ return (
29
+ <div
30
+ data-slot='alert'
31
+ role='alert'
32
+ className={cn(alertVariants({ variant }), className)}
33
+ {...props}
34
+ />
35
+ );
36
+ }
37
+
38
+ function AlertTitle({ className, ...props }: React.ComponentProps<'div'>) {
39
+ return (
40
+ <div
41
+ data-slot='alert-title'
42
+ className={cn(
43
+ 'col-start-2 line-clamp-1 min-h-4 font-medium tracking-tight',
44
+ className
45
+ )}
46
+ {...props}
47
+ />
48
+ );
49
+ }
50
+
51
+ function AlertDescription({
52
+ className,
53
+ ...props
54
+ }: React.ComponentProps<'div'>) {
55
+ return (
56
+ <div
57
+ data-slot='alert-description'
58
+ className={cn(
59
+ 'text-muted-foreground col-start-2 grid justify-items-start gap-1 text-sm [&_p]:leading-relaxed',
60
+ className
61
+ )}
62
+ {...props}
63
+ />
64
+ );
65
+ }
66
+
67
+ export { Alert, AlertTitle, AlertDescription };`,
68
+
69
+ 'components/ui/animated-group.tsx': `'use client';
70
+ import { ReactNode } from 'react';
71
+ import { motion, Variants } from 'framer-motion';
72
+ import React from 'react';
73
+
74
+ export type PresetType =
75
+ | 'fade'
76
+ | 'slide'
77
+ | 'scale'
78
+ | 'blur'
79
+ | 'blur-slide'
80
+ | 'zoom'
81
+ | 'flip'
82
+ | 'bounce'
83
+ | 'rotate'
84
+ | 'swing';
85
+
86
+ export type AnimatedGroupProps = {
87
+ children: ReactNode;
88
+ className?: string;
89
+ variants?: {
90
+ container?: Variants;
91
+ item?: Variants;
92
+ };
93
+ preset?: PresetType;
94
+ as?: React.ElementType;
95
+ asChild?: React.ElementType;
96
+ };
97
+
98
+ const defaultContainerVariants: Variants = {
99
+ visible: {
100
+ transition: {
101
+ staggerChildren: 0.1,
102
+ },
103
+ },
104
+ };
105
+
106
+ const defaultItemVariants: Variants = {
107
+ hidden: { opacity: 0 },
108
+ visible: { opacity: 1 },
109
+ };
110
+
111
+ const presetVariants: Record<PresetType, Variants> = {
112
+ fade: {},
113
+ slide: {
114
+ hidden: { y: 20 },
115
+ visible: { y: 0 },
116
+ },
117
+ scale: {
118
+ hidden: { scale: 0.8 },
119
+ visible: { scale: 1 },
120
+ },
121
+ blur: {
122
+ hidden: { filter: 'blur(4px)' },
123
+ visible: { filter: 'blur(0px)' },
124
+ },
125
+ 'blur-slide': {
126
+ hidden: { filter: 'blur(4px)', y: 20 },
127
+ visible: { filter: 'blur(0px)', y: 0 },
128
+ },
129
+ zoom: {
130
+ hidden: { scale: 0.5 },
131
+ visible: {
132
+ scale: 1,
133
+ transition: { type: 'spring', stiffness: 300, damping: 20 },
134
+ },
135
+ },
136
+ flip: {
137
+ hidden: { rotateX: -90 },
138
+ visible: {
139
+ rotateX: 0,
140
+ transition: { type: 'spring', stiffness: 300, damping: 20 },
141
+ },
142
+ },
143
+ bounce: {
144
+ hidden: { y: -50 },
145
+ visible: {
146
+ y: 0,
147
+ transition: { type: 'spring', stiffness: 400, damping: 10 },
148
+ },
149
+ },
150
+ rotate: {
151
+ hidden: { rotate: -180 },
152
+ visible: {
153
+ rotate: 0,
154
+ transition: { type: 'spring', stiffness: 200, damping: 15 },
155
+ },
156
+ },
157
+ swing: {
158
+ hidden: { rotate: -10 },
159
+ visible: {
160
+ rotate: 0,
161
+ transition: { type: 'spring', stiffness: 300, damping: 8 },
162
+ },
163
+ },
164
+ };
165
+
166
+ const addDefaultVariants = (variants: Variants) => ({
167
+ hidden: { ...defaultItemVariants.hidden, ...variants.hidden },
168
+ visible: { ...defaultItemVariants.visible, ...variants.visible },
169
+ });
170
+
171
+ function AnimatedGroup({
172
+ children,
173
+ className,
174
+ variants,
175
+ preset,
176
+ as = 'div',
177
+ asChild = 'div',
178
+ }: AnimatedGroupProps) {
179
+ const selectedVariants = {
180
+ item: addDefaultVariants(preset ? presetVariants[preset] : {}),
181
+ container: addDefaultVariants(defaultContainerVariants),
182
+ };
183
+ const containerVariants = variants?.container || selectedVariants.container;
184
+ const itemVariants = variants?.item || selectedVariants.item;
185
+
186
+ // Use motion.div as default, but allow custom element types
187
+ const MotionComponent =
188
+ typeof as === 'string'
189
+ ? (motion[as as keyof typeof motion] as typeof motion.div) || motion.div
190
+ : motion.div;
191
+
192
+ const MotionChild =
193
+ typeof asChild === 'string'
194
+ ? (motion[asChild as keyof typeof motion] as typeof motion.div) ||
195
+ motion.div
196
+ : motion.div;
197
+
198
+ return (
199
+ <MotionComponent
200
+ initial='hidden'
201
+ animate='visible'
202
+ variants={containerVariants}
203
+ className={className}
204
+ >
205
+ {React.Children.map(children, (child, index) => (
206
+ <MotionChild key={index} variants={itemVariants}>
207
+ {child}
208
+ </MotionChild>
209
+ ))}
210
+ </MotionComponent>
211
+ );
212
+ }
213
+
214
+ export { AnimatedGroup };`,
215
+
216
+ 'components/ui/avatar.tsx': `'use client';
217
+
218
+ import * as React from 'react';
219
+ import * as AvatarPrimitive from '@radix-ui/react-avatar';
220
+
221
+ import { cn } from '@/lib/utils';
222
+
223
+ function Avatar({
224
+ className,
225
+ ...props
226
+ }: React.ComponentProps<typeof AvatarPrimitive.Root>) {
227
+ return (
228
+ <AvatarPrimitive.Root
229
+ data-slot='avatar'
230
+ className={cn(
231
+ 'relative flex size-8 shrink-0 overflow-hidden rounded-full',
232
+ className
233
+ )}
234
+ {...props}
235
+ />
236
+ );
237
+ }
238
+
239
+ function AvatarImage({
240
+ className,
241
+ ...props
242
+ }: React.ComponentProps<typeof AvatarPrimitive.Image>) {
243
+ return (
244
+ <AvatarPrimitive.Image
245
+ data-slot='avatar-image'
246
+ className={cn('aspect-square size-full', className)}
247
+ {...props}
248
+ />
249
+ );
250
+ }
251
+
252
+ function AvatarFallback({
253
+ className,
254
+ ...props
255
+ }: React.ComponentProps<typeof AvatarPrimitive.Fallback>) {
256
+ return (
257
+ <AvatarPrimitive.Fallback
258
+ data-slot='avatar-fallback'
259
+ className={cn(
260
+ 'bg-muted flex size-full items-center justify-center rounded-full',
261
+ className
262
+ )}
263
+ {...props}
264
+ />
265
+ );
266
+ }
267
+
268
+ export { Avatar, AvatarImage, AvatarFallback };`,
269
+
270
+ 'components/ui/badge.tsx': `import * as React from 'react';
271
+ import { cn } from '@/lib/utils';
272
+ import { cva, type VariantProps } from 'class-variance-authority';
273
+ import { Slot as SlotPrimitive } from '@radix-ui/react-slot';
274
+
275
+ export interface BadgeProps
276
+ extends
277
+ React.HTMLAttributes<HTMLDivElement>,
278
+ VariantProps<typeof badgeVariants> {
279
+ asChild?: boolean;
280
+ dotClassName?: string;
281
+ disabled?: boolean;
282
+ }
283
+
284
+ export interface BadgeButtonProps
285
+ extends
286
+ React.ButtonHTMLAttributes<HTMLButtonElement>,
287
+ VariantProps<typeof badgeButtonVariants> {
288
+ asChild?: boolean;
289
+ }
290
+
291
+ export type BadgeDotProps = React.HTMLAttributes<HTMLSpanElement>;
292
+
293
+ const badgeVariants = cva(
294
+ 'inline-flex items-center whitespace-nowrap justify-center border border-transparent font-medium focus:outline-hidden focus:ring-2 focus:ring-ring focus:ring-offset-2 [&_svg]:-ms-px [&_svg]:shrink-0',
295
+ {
296
+ variants: {
297
+ variant: {
298
+ primary: 'bg-primary text-primary-foreground',
299
+ secondary: 'bg-secondary text-secondary-foreground',
300
+ success:
301
+ 'bg-[var(--color-success-accent,var(--color-green-500))] text-[var(--color-success-foreground,var(--color-white))]',
302
+ warning:
303
+ 'bg-[var(--color-warning-accent,var(--color-yellow-500))] text-[var(--color-warning-foreground,var(--color-white))]',
304
+ info: 'bg-[var(--color-info-accent,var(--color-violet-500))] text-[var(--color-info-foreground,var(--color-white))]',
305
+ outline:
306
+ 'bg-transparent border border-border text-secondary-foreground',
307
+ destructive: 'bg-destructive text-destructive-foreground',
308
+ },
309
+ appearance: {
310
+ default: '',
311
+ light: '',
312
+ outline: '',
313
+ ghost: 'border-transparent bg-transparent',
314
+ },
315
+ disabled: {
316
+ true: 'opacity-50 pointer-events-none',
317
+ },
318
+ size: {
319
+ lg: 'rounded-md px-[0.5rem] h-7 min-w-7 gap-1.5 text-xs [&_svg]:size-3.5',
320
+ md: 'rounded-md px-[0.45rem] h-6 min-w-6 gap-1.5 text-xs [&_svg]:size-3.5 ',
321
+ sm: 'rounded-sm px-[0.325rem] h-5 min-w-5 gap-1 text-[0.6875rem] leading-[0.75rem] [&_svg]:size-3',
322
+ xs: 'rounded-sm px-[0.25rem] h-4 min-w-4 gap-1 text-[0.625rem] leading-[0.5rem] [&_svg]:size-3',
323
+ },
324
+ shape: {
325
+ default: '',
326
+ circle: 'rounded-full',
327
+ },
328
+ },
329
+ compoundVariants: [
330
+ /* Light */
331
+ {
332
+ variant: 'primary',
333
+ appearance: 'light',
334
+ className:
335
+ 'text-[var(--color-primary-accent,var(--color-blue-700))] bg-[var(--color-primary-soft,var(--color-blue-50))] dark:bg-[var(--color-primary-soft,var(--color-blue-950))] dark:text-[var(--color-primary-soft,var(--color-blue-600))]',
336
+ },
337
+ {
338
+ variant: 'secondary',
339
+ appearance: 'light',
340
+ className:
341
+ 'bg-secondary dark:bg-secondary/50 text-secondary-foreground',
342
+ },
343
+ {
344
+ variant: 'success',
345
+ appearance: 'light',
346
+ className:
347
+ 'text-[var(--color-success-accent,var(--color-green-800))] bg-[var(--color-success-soft,var(--color-green-100))] dark:bg-[var(--color-success-soft,var(--color-green-950))] dark:text-[var(--color-success-soft,var(--color-green-600))]',
348
+ },
349
+ {
350
+ variant: 'warning',
351
+ appearance: 'light',
352
+ className:
353
+ 'text-[var(--color-warning-accent,var(--color-yellow-700))] bg-[var(--color-warning-soft,var(--color-yellow-100))] dark:bg-[var(--color-warning-soft,var(--color-yellow-950))] dark:text-[var(--color-warning-soft,var(--color-yellow-600))]',
354
+ },
355
+ {
356
+ variant: 'info',
357
+ appearance: 'light',
358
+ className:
359
+ 'text-[var(--color-info-accent,var(--color-violet-700))] bg-[var(--color-info-soft,var(--color-violet-100))] dark:bg-[var(--color-info-soft,var(--color-violet-950))] dark:text-[var(--color-info-soft,var(--color-violet-400))]',
360
+ },
361
+ {
362
+ variant: 'destructive',
363
+ appearance: 'light',
364
+ className:
365
+ 'text-[var(--color-destructive-accent,var(--color-red-700))] bg-[var(--color-destructive-soft,var(--color-red-50))] dark:bg-[var(--color-destructive-soft,var(--color-red-950))] dark:text-[var(--color-destructive-soft,var(--color-red-600))]',
366
+ },
367
+ /* Outline */
368
+ {
369
+ variant: 'primary',
370
+ appearance: 'outline',
371
+ className:
372
+ 'text-[var(--color-primary-accent,var(--color-blue-700))] border-[var(--color-primary-soft,var(--color-blue-100))] bg-[var(--color-primary-soft,var(--color-blue-50))] dark:bg-[var(--color-primary-soft,var(--color-blue-950))] dark:border-[var(--color-primary-soft,var(--color-blue-900))] dark:text-[var(--color-primary-soft,var(--color-blue-600))]',
373
+ },
374
+ {
375
+ variant: 'success',
376
+ appearance: 'outline',
377
+ className:
378
+ 'text-[var(--color-success-accent,var(--color-green-700))] border-[var(--color-success-soft,var(--color-green-200))] bg-[var(--color-success-soft,var(--color-green-50))] dark:bg-[var(--color-success-soft,var(--color-green-950))] dark:border-[var(--color-success-soft,var(--color-green-900))] dark:text-[var(--color-success-soft,var(--color-green-600))]',
379
+ },
380
+ {
381
+ variant: 'warning',
382
+ appearance: 'outline',
383
+ className:
384
+ 'text-[var(--color-warning-accent,var(--color-yellow-700))] border-[var(--color-warning-soft,var(--color-yellow-200))] bg-[var(--color-warning-soft,var(--color-yellow-50))] dark:bg-[var(--color-warning-soft,var(--color-yellow-950))] dark:border-[var(--color-warning-soft,var(--color-yellow-900))] dark:text-[var(--color-warning-soft,var(--color-yellow-600))]',
385
+ },
386
+ {
387
+ variant: 'info',
388
+ appearance: 'outline',
389
+ className:
390
+ 'text-[var(--color-info-accent,var(--color-violet-700))] border-[var(--color-info-soft,var(--color-violet-100))] bg-[var(--color-info-soft,var(--color-violet-50))] dark:bg-[var(--color-info-soft,var(--color-violet-950))] dark:border-[var(--color-info-soft,var(--color-violet-900))] dark:text-[var(--color-info-soft,var(--color-violet-400))]',
391
+ },
392
+ {
393
+ variant: 'destructive',
394
+ appearance: 'outline',
395
+ className:
396
+ 'text-[var(--color-destructive-accent,var(--color-red-700))] border-[var(--color-destructive-soft,var(--color-red-100))] bg-[var(--color-destructive-soft,var(--color-red-50))] dark:bg-[var(--color-destructive-soft,var(--red-950))] dark:border-[var(--color-destructive-soft,var(--red-900))] dark:text-[var(--color-destructive-soft,var(--red-600))]',
397
+ },
398
+ /* Ghost */
399
+ {
400
+ variant: 'primary',
401
+ appearance: 'ghost',
402
+ className: 'text-primary',
403
+ },
404
+ {
405
+ variant: 'secondary',
406
+ appearance: 'ghost',
407
+ className: 'text-secondary-foreground',
408
+ },
409
+ {
410
+ variant: 'success',
411
+ appearance: 'ghost',
412
+ className: 'text-[var(--color-success-accent,var(--color-green-500))]',
413
+ },
414
+ {
415
+ variant: 'warning',
416
+ appearance: 'ghost',
417
+ className: 'text-[var(--color-warning-accent,var(--color-yellow-500))]',
418
+ },
419
+ {
420
+ variant: 'info',
421
+ appearance: 'ghost',
422
+ className: 'text-[var(--color-info-accent,var(--color-violet-500))]',
423
+ },
424
+ {
425
+ variant: 'destructive',
426
+ appearance: 'ghost',
427
+ className: 'text-destructive',
428
+ },
429
+
430
+ { size: 'lg', appearance: 'ghost', className: 'px-0' },
431
+ { size: 'md', appearance: 'ghost', className: 'px-0' },
432
+ { size: 'sm', appearance: 'ghost', className: 'px-0' },
433
+ { size: 'xs', appearance: 'ghost', className: 'px-0' },
434
+ ],
435
+ defaultVariants: {
436
+ variant: 'primary',
437
+ appearance: 'default',
438
+ size: 'md',
439
+ },
440
+ }
441
+ );
442
+
443
+ const badgeButtonVariants = cva(
444
+ 'cursor-pointer transition-all inline-flex items-center justify-center leading-none size-3.5 [&>svg]:opacity-100! [&>svg]:size-3.5! p-0 rounded-md -me-0.5 opacity-60 hover:opacity-100',
445
+ {
446
+ variants: {
447
+ variant: {
448
+ default: '',
449
+ },
450
+ },
451
+ defaultVariants: {
452
+ variant: 'default',
453
+ },
454
+ }
455
+ );
456
+
457
+ function Badge({
458
+ className,
459
+ variant,
460
+ size,
461
+ appearance,
462
+ shape,
463
+ asChild = false,
464
+ disabled,
465
+ ...props
466
+ }: React.ComponentProps<'span'> &
467
+ VariantProps<typeof badgeVariants> & { asChild?: boolean }) {
468
+ const Comp = asChild ? SlotPrimitive : 'span';
469
+
470
+ return (
471
+ <Comp
472
+ data-slot='badge'
473
+ className={cn(
474
+ badgeVariants({ variant, size, appearance, shape, disabled }),
475
+ className
476
+ )}
477
+ {...props}
478
+ />
479
+ );
480
+ }
481
+
482
+ function BadgeButton({
483
+ className,
484
+ variant,
485
+ asChild = false,
486
+ ...props
487
+ }: React.ComponentProps<'button'> &
488
+ VariantProps<typeof badgeButtonVariants> & { asChild?: boolean }) {
489
+ const Comp = asChild ? SlotPrimitive : 'span';
490
+ return (
491
+ <Comp
492
+ data-slot='badge-button'
493
+ className={cn(badgeButtonVariants({ variant, className }))}
494
+ role='button'
495
+ {...props}
496
+ />
497
+ );
498
+ }
499
+
500
+ function BadgeDot({ className, ...props }: React.ComponentProps<'span'>) {
501
+ return (
502
+ <span
503
+ data-slot='badge-dot'
504
+ className={cn(
505
+ 'size-1.5 rounded-full bg-[currentColor] opacity-75',
506
+ className
507
+ )}
508
+ {...props}
509
+ />
510
+ );
511
+ }
512
+
513
+ export { Badge, BadgeButton, BadgeDot, badgeVariants };`,
514
+
515
+ 'components/ui/breadcrumb.tsx': `import * as React from 'react';
516
+ import { cn } from '@/lib/utils';
517
+ import { ChevronRight, MoreHorizontal } from 'lucide-react';
518
+ import { Slot as SlotPrimitive } from '@radix-ui/react-slot';
519
+
520
+ function Breadcrumb({
521
+ ...props
522
+ }: React.ComponentProps<'nav'> & {
523
+ separator?: React.ReactNode;
524
+ }) {
525
+ return <nav data-slot='breadcrumb' aria-label='breadcrumb' {...props} />;
526
+ }
527
+
528
+ function BreadcrumbList({ className, ...props }: React.ComponentProps<'ol'>) {
529
+ return (
530
+ <ol
531
+ data-slot='breadcrumb-list'
532
+ className={cn(
533
+ 'flex flex-wrap items-center gap-1.5 break-words text-sm text-muted-foreground',
534
+ className
535
+ )}
536
+ {...props}
537
+ />
538
+ );
539
+ }
540
+
541
+ function BreadcrumbItem({ className, ...props }: React.ComponentProps<'li'>) {
542
+ return (
543
+ <li
544
+ data-slot='breadcrumb-item'
545
+ className={cn('inline-flex items-center gap-1.5', className)}
546
+ {...props}
547
+ />
548
+ );
549
+ }
550
+
551
+ function BreadcrumbLink({
552
+ asChild,
553
+ className,
554
+ ...props
555
+ }: React.ComponentProps<'a'> & {
556
+ asChild?: boolean;
557
+ }) {
558
+ const Comp = asChild ? SlotPrimitive : 'a';
559
+
560
+ return (
561
+ <Comp
562
+ data-slot='breadcrumb-link'
563
+ className={cn('transition-colors hover:text-foreground', className)}
564
+ {...props}
565
+ />
566
+ );
567
+ }
568
+
569
+ function BreadcrumbPage({ className, ...props }: React.ComponentProps<'span'>) {
570
+ return (
571
+ <span
572
+ data-slot='breadcrumb-page'
573
+ role='link'
574
+ aria-disabled='true'
575
+ aria-current='page'
576
+ className={cn('font-normal text-foreground', className)}
577
+ {...props}
578
+ />
579
+ );
580
+ }
581
+
582
+ const BreadcrumbSeparator = ({
583
+ children,
584
+ className,
585
+ ...props
586
+ }: React.ComponentProps<'li'>) => (
587
+ <li
588
+ data-slot='breadcrumb-separator'
589
+ role='presentation'
590
+ aria-hidden='true'
591
+ className={cn('[&>svg]:w-3.5 [&>svg]:h-3.5', className)}
592
+ {...props}
593
+ >
594
+ {children ?? <ChevronRight className='rtl:rotate-180' />}
595
+ </li>
596
+ );
597
+
598
+ const BreadcrumbEllipsis = ({
599
+ className,
600
+ ...props
601
+ }: React.ComponentProps<'span'>) => (
602
+ <span
603
+ data-slot='breadcrumb-ellipsis'
604
+ role='presentation'
605
+ aria-hidden='true'
606
+ className={cn('flex h-9 w-9 items-center justify-center', className)}
607
+ {...props}
608
+ >
609
+ <MoreHorizontal className='h-4 w-4' />
610
+ <span className='sr-only'>More</span>
611
+ </span>
612
+ );
613
+
614
+ export {
615
+ Breadcrumb,
616
+ BreadcrumbEllipsis,
617
+ BreadcrumbItem,
618
+ BreadcrumbLink,
619
+ BreadcrumbList,
620
+ BreadcrumbPage,
621
+ BreadcrumbSeparator,
622
+ };`,
623
+
624
+ 'components/ui/button.tsx': `import * as React from 'react';
625
+ import { Slot } from '@radix-ui/react-slot';
626
+ import { cva, type VariantProps } from 'class-variance-authority';
627
+
628
+ import { cn } from '@/lib/utils';
629
+
630
+ const buttonVariants = cva(
631
+ "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
632
+ {
633
+ variants: {
634
+ variant: {
635
+ default: 'bg-primary text-primary-foreground hover:bg-primary/90',
636
+ destructive:
637
+ 'bg-destructive text-white hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60',
638
+ outline:
639
+ 'border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50',
640
+ secondary:
641
+ 'bg-secondary text-secondary-foreground hover:bg-secondary/80',
642
+ ghost:
643
+ 'hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50',
644
+ link: 'text-primary underline-offset-4 hover:underline',
645
+ },
646
+ size: {
647
+ default: 'h-9 px-4 py-2 has-[>svg]:px-3',
648
+ sm: 'h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5',
649
+ lg: 'h-10 rounded-md px-6 has-[>svg]:px-4',
650
+ icon: 'size-9',
651
+ 'icon-sm': 'size-8',
652
+ 'icon-lg': 'size-10',
653
+ },
654
+ },
655
+ defaultVariants: {
656
+ variant: 'default',
657
+ size: 'default',
658
+ },
659
+ }
660
+ );
661
+
662
+ function Button({
663
+ className,
664
+ variant,
665
+ size,
666
+ asChild = false,
667
+ ...props
668
+ }: React.ComponentProps<'button'> &
669
+ VariantProps<typeof buttonVariants> & {
670
+ asChild?: boolean;
671
+ }) {
672
+ const Comp = asChild ? Slot : 'button';
673
+
674
+ return (
675
+ <Comp
676
+ data-slot='button'
677
+ className={cn(buttonVariants({ variant, size, className }))}
678
+ {...props}
679
+ />
680
+ );
681
+ }
682
+
683
+ export { Button, buttonVariants };`,
684
+
685
+ 'components/ui/card.tsx': `import * as React from 'react';
686
+
687
+ import { cn } from '@/lib/utils';
688
+
689
+ function Card({ className, ...props }: React.ComponentProps<'div'>) {
690
+ return (
691
+ <div
692
+ data-slot='card'
693
+ className={cn(
694
+ 'bg-crm-bg-card border-2 border-crm-secondary/40 text-card-foreground flex flex-col gap-6 rounded-xl py-6 shadow-sm',
695
+ className
696
+ )}
697
+ {...props}
698
+ />
699
+ );
700
+ }
701
+
702
+ function CardHeader({ className, ...props }: React.ComponentProps<'div'>) {
703
+ return (
704
+ <div
705
+ data-slot='card-header'
706
+ className={cn(
707
+ '@container/card-header grid auto-rows-min grid-rows-[auto_auto] items-start gap-2 px-6 has-data-[slot=card-action]:grid-cols-[1fr_auto] [.border-b]:pb-6',
708
+ className
709
+ )}
710
+ {...props}
711
+ />
712
+ );
713
+ }
714
+
715
+ function CardTitle({ className, ...props }: React.ComponentProps<'div'>) {
716
+ return (
717
+ <div
718
+ data-slot='card-title'
719
+ className={cn('leading-none font-semibold', className)}
720
+ {...props}
721
+ />
722
+ );
723
+ }
724
+
725
+ function CardDescription({ className, ...props }: React.ComponentProps<'div'>) {
726
+ return (
727
+ <div
728
+ data-slot='card-description'
729
+ className={cn('text-muted-foreground text-sm', className)}
730
+ {...props}
731
+ />
732
+ );
733
+ }
734
+
735
+ function CardAction({ className, ...props }: React.ComponentProps<'div'>) {
736
+ return (
737
+ <div
738
+ data-slot='card-action'
739
+ className={cn(
740
+ 'col-start-2 row-span-2 row-start-1 self-start justify-self-end',
741
+ className
742
+ )}
743
+ {...props}
744
+ />
745
+ );
746
+ }
747
+
748
+ function CardContent({ className, ...props }: React.ComponentProps<'div'>) {
749
+ return (
750
+ <div
751
+ data-slot='card-content'
752
+ className={cn('px-6', className)}
753
+ {...props}
754
+ />
755
+ );
756
+ }
757
+
758
+ function CardFooter({ className, ...props }: React.ComponentProps<'div'>) {
759
+ return (
760
+ <div
761
+ data-slot='card-footer'
762
+ className={cn('flex items-center px-6 [.border-t]:pt-6', className)}
763
+ {...props}
764
+ />
765
+ );
766
+ }
767
+
768
+ export {
769
+ Card,
770
+ CardHeader,
771
+ CardFooter,
772
+ CardTitle,
773
+ CardAction,
774
+ CardDescription,
775
+ CardContent,
776
+ };`,
777
+ };