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.
- package/LICENSE +21 -0
- package/README.md +43 -0
- package/index.js +164 -0
- package/package.json +32 -0
- package/src/constants.js +62 -0
- package/src/templates/app.js +527 -0
- package/src/templates/configs.js +303 -0
- package/src/templates/core.js +328 -0
- package/src/templates/folder-structure.js +21 -0
- package/src/templates/layout.js +279 -0
- package/src/templates/misc.js +277 -0
- package/src/templates/packages.js +42 -0
- package/src/templates/ui-2.js +585 -0
- package/src/templates/ui-3.js +606 -0
- package/src/templates/ui-4.js +615 -0
- package/src/templates/ui.js +777 -0
- package/src/utils.js +38 -0
|
@@ -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
|
+
};
|