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,606 @@
|
|
|
1
|
+
export const uiTemplates3 = {
|
|
2
|
+
'components/ui/sonner.tsx': `'use client';
|
|
3
|
+
|
|
4
|
+
import {
|
|
5
|
+
CircleCheckIcon,
|
|
6
|
+
InfoIcon,
|
|
7
|
+
Loader2Icon,
|
|
8
|
+
OctagonXIcon,
|
|
9
|
+
TriangleAlertIcon,
|
|
10
|
+
} from 'lucide-react';
|
|
11
|
+
import { useTheme } from 'next-themes';
|
|
12
|
+
import { Toaster as Sonner, type ToasterProps } from 'sonner';
|
|
13
|
+
|
|
14
|
+
const Toaster = ({ ...props }: ToasterProps) => {
|
|
15
|
+
const { theme = 'system' } = useTheme();
|
|
16
|
+
|
|
17
|
+
return (
|
|
18
|
+
<Sonner
|
|
19
|
+
theme={theme as ToasterProps['theme']}
|
|
20
|
+
className='toaster group'
|
|
21
|
+
icons={{
|
|
22
|
+
success: <CircleCheckIcon className='size-4' />,
|
|
23
|
+
info: <InfoIcon className='size-4' />,
|
|
24
|
+
warning: <TriangleAlertIcon className='size-4' />,
|
|
25
|
+
error: <OctagonXIcon className='size-4' />,
|
|
26
|
+
loading: <Loader2Icon className='size-4 animate-spin' />,
|
|
27
|
+
}}
|
|
28
|
+
style={
|
|
29
|
+
{
|
|
30
|
+
'--normal-bg': 'var(--popover)',
|
|
31
|
+
'--normal-text': 'var(--popover-foreground)',
|
|
32
|
+
'--normal-border': 'var(--border)',
|
|
33
|
+
'--border-radius': 'var(--radius)',
|
|
34
|
+
} as React.CSSProperties
|
|
35
|
+
}
|
|
36
|
+
{...props}
|
|
37
|
+
/>
|
|
38
|
+
);
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
export { Toaster };`,
|
|
42
|
+
|
|
43
|
+
'components/ui/stepper.tsx': `'use client';
|
|
44
|
+
|
|
45
|
+
import * as React from 'react';
|
|
46
|
+
import { cva, type VariantProps } from 'class-variance-authority';
|
|
47
|
+
import { CheckIcon, Loader2Icon, OctagonXIcon } from 'lucide-react';
|
|
48
|
+
|
|
49
|
+
import { cn } from '@/lib/utils';
|
|
50
|
+
|
|
51
|
+
const StepperContext = React.createContext<{
|
|
52
|
+
activeStep: number;
|
|
53
|
+
orientation: 'horizontal' | 'vertical';
|
|
54
|
+
} | null>(null);
|
|
55
|
+
|
|
56
|
+
function useStepper() {
|
|
57
|
+
const context = React.useContext(StepperContext);
|
|
58
|
+
if (!context) {
|
|
59
|
+
throw new Error('useStepper must be used within a Stepper');
|
|
60
|
+
}
|
|
61
|
+
return context;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function Stepper({
|
|
65
|
+
activeStep,
|
|
66
|
+
orientation = 'horizontal',
|
|
67
|
+
className,
|
|
68
|
+
children,
|
|
69
|
+
...props
|
|
70
|
+
}: React.ComponentProps<'div'> & {
|
|
71
|
+
activeStep: number;
|
|
72
|
+
orientation?: 'horizontal' | 'vertical';
|
|
73
|
+
}) {
|
|
74
|
+
return (
|
|
75
|
+
<StepperContext.Provider value={{ activeStep, orientation }}>
|
|
76
|
+
<div
|
|
77
|
+
data-slot='stepper'
|
|
78
|
+
data-orientation={orientation}
|
|
79
|
+
className={cn(
|
|
80
|
+
'group/stepper flex w-full data-[orientation=horizontal]:flex-row data-[orientation=vertical]:flex-col',
|
|
81
|
+
className
|
|
82
|
+
)}
|
|
83
|
+
{...props}
|
|
84
|
+
>
|
|
85
|
+
{children}
|
|
86
|
+
</div>
|
|
87
|
+
</StepperContext.Provider>
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function Step({
|
|
92
|
+
step,
|
|
93
|
+
className,
|
|
94
|
+
children,
|
|
95
|
+
...props
|
|
96
|
+
}: React.ComponentProps<'div'> & {
|
|
97
|
+
step: number;
|
|
98
|
+
}) {
|
|
99
|
+
const { activeStep, orientation } = useStepper();
|
|
100
|
+
const state =
|
|
101
|
+
activeStep > step ? 'completed' : activeStep === step ? 'active' : 'queued';
|
|
102
|
+
|
|
103
|
+
return (
|
|
104
|
+
<div
|
|
105
|
+
data-slot='step'
|
|
106
|
+
data-state={state}
|
|
107
|
+
data-orientation={orientation}
|
|
108
|
+
className={cn(
|
|
109
|
+
'group/step flex items-center data-[orientation=horizontal]:flex-1 data-[orientation=vertical]:w-full data-[orientation=vertical]:flex-col data-[orientation=vertical]:items-start',
|
|
110
|
+
className
|
|
111
|
+
)}
|
|
112
|
+
{...props}
|
|
113
|
+
>
|
|
114
|
+
<div className='flex items-center group-last/step:flex-none data-[orientation=horizontal]:flex-1 data-[orientation=vertical]:w-full'>
|
|
115
|
+
{children}
|
|
116
|
+
<div
|
|
117
|
+
data-slot='step-separator'
|
|
118
|
+
className='bg-crm-secondary/20 group-last/step:hidden data-[orientation=horizontal]:mx-2 data-[orientation=horizontal]:h-px data-[orientation=horizontal]:flex-1 data-[orientation=vertical]:my-2 data-[orientation=vertical]:ml-4 data-[orientation=vertical]:h-8 data-[orientation=vertical]:w-px'
|
|
119
|
+
data-orientation={orientation}
|
|
120
|
+
/>
|
|
121
|
+
</div>
|
|
122
|
+
</div>
|
|
123
|
+
);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
const stepIndicatorVariants = cva(
|
|
127
|
+
'flex size-8 shrink-0 items-center justify-center rounded-full border-2 text-sm font-medium transition-colors',
|
|
128
|
+
{
|
|
129
|
+
variants: {
|
|
130
|
+
state: {
|
|
131
|
+
queued: 'border-muted text-muted-foreground bg-background',
|
|
132
|
+
active: 'border-primary text-primary bg-background',
|
|
133
|
+
completed: 'border-primary bg-primary text-primary-foreground',
|
|
134
|
+
error: 'border-destructive bg-destructive text-destructive-foreground',
|
|
135
|
+
},
|
|
136
|
+
},
|
|
137
|
+
defaultVariants: {
|
|
138
|
+
state: 'queued',
|
|
139
|
+
},
|
|
140
|
+
}
|
|
141
|
+
);
|
|
142
|
+
|
|
143
|
+
function StepIndicator({
|
|
144
|
+
step,
|
|
145
|
+
state: stateProp,
|
|
146
|
+
className,
|
|
147
|
+
children,
|
|
148
|
+
...props
|
|
149
|
+
}: React.ComponentProps<'div'> & {
|
|
150
|
+
step: number;
|
|
151
|
+
state?: 'queued' | 'active' | 'completed' | 'error' | 'loading';
|
|
152
|
+
}) {
|
|
153
|
+
const { activeStep } = useStepper();
|
|
154
|
+
const autoState =
|
|
155
|
+
activeStep > step ? 'completed' : activeStep === step ? 'active' : 'queued';
|
|
156
|
+
const state = stateProp || autoState;
|
|
157
|
+
|
|
158
|
+
return (
|
|
159
|
+
<div
|
|
160
|
+
data-slot='step-indicator'
|
|
161
|
+
data-state={state}
|
|
162
|
+
className={cn(
|
|
163
|
+
stepIndicatorVariants({
|
|
164
|
+
state: state === 'loading' ? 'active' : state,
|
|
165
|
+
className,
|
|
166
|
+
})
|
|
167
|
+
)}
|
|
168
|
+
{...props}
|
|
169
|
+
>
|
|
170
|
+
{state === 'completed' ? (
|
|
171
|
+
<CheckIcon className='size-4' />
|
|
172
|
+
) : state === 'error' ? (
|
|
173
|
+
<OctagonXIcon className='size-4' />
|
|
174
|
+
) : state === 'loading' ? (
|
|
175
|
+
<Loader2Icon className='size-4 animate-spin' />
|
|
176
|
+
) : (
|
|
177
|
+
children || step + 1
|
|
178
|
+
)}
|
|
179
|
+
</div>
|
|
180
|
+
);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
function StepContent({ className, ...props }: React.ComponentProps<'div'>) {
|
|
184
|
+
return (
|
|
185
|
+
<div
|
|
186
|
+
data-slot='step-content'
|
|
187
|
+
className={cn('flex flex-col gap-0.5 px-2', className)}
|
|
188
|
+
{...props}
|
|
189
|
+
/>
|
|
190
|
+
);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
function StepTitle({ className, ...props }: React.ComponentProps<'div'>) {
|
|
194
|
+
return (
|
|
195
|
+
<div
|
|
196
|
+
data-slot='step-title'
|
|
197
|
+
className={cn('text-sm font-medium leading-none', className)}
|
|
198
|
+
{...props}
|
|
199
|
+
/>
|
|
200
|
+
);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
function StepDescription({ className, ...props }: React.ComponentProps<'div'>) {
|
|
204
|
+
return (
|
|
205
|
+
<div
|
|
206
|
+
data-slot='step-description'
|
|
207
|
+
className={cn('text-muted-foreground text-xs', className)}
|
|
208
|
+
{...props}
|
|
209
|
+
/>
|
|
210
|
+
);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
export {
|
|
214
|
+
Stepper,
|
|
215
|
+
Step,
|
|
216
|
+
StepIndicator,
|
|
217
|
+
StepContent,
|
|
218
|
+
StepTitle,
|
|
219
|
+
StepDescription,
|
|
220
|
+
};`,
|
|
221
|
+
|
|
222
|
+
'components/ui/switch.tsx': `'use client';
|
|
223
|
+
|
|
224
|
+
import * as React from 'react';
|
|
225
|
+
import * as SwitchPrimitive from '@radix-ui/react-switch';
|
|
226
|
+
|
|
227
|
+
import { cn } from '@/lib/utils';
|
|
228
|
+
|
|
229
|
+
function Switch({
|
|
230
|
+
className,
|
|
231
|
+
...props
|
|
232
|
+
}: React.ComponentProps<typeof SwitchPrimitive.Root>) {
|
|
233
|
+
return (
|
|
234
|
+
<SwitchPrimitive.Root
|
|
235
|
+
data-slot='switch'
|
|
236
|
+
className={cn(
|
|
237
|
+
'peer data-[state=checked]:bg-primary data-[state=unchecked]:bg-setup-secondary focus-visible:ring-ring focus-visible:ring-offset-background inline-flex h-6 w-11 shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent transition-colors focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50',
|
|
238
|
+
className
|
|
239
|
+
)}
|
|
240
|
+
{...props}
|
|
241
|
+
>
|
|
242
|
+
<SwitchPrimitive.Thumb
|
|
243
|
+
data-slot='switch-thumb'
|
|
244
|
+
className={cn(
|
|
245
|
+
'bg-setup-primary pointer-events-none block h-5 w-5 rounded-full shadow-lg ring-0 transition-transform data-[state=checked]:translate-x-5 data-[state=unchecked]:translate-x-0'
|
|
246
|
+
)}
|
|
247
|
+
/>
|
|
248
|
+
</SwitchPrimitive.Root>
|
|
249
|
+
);
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
export { Switch };`,
|
|
253
|
+
|
|
254
|
+
'components/ui/table.tsx': `import * as React from 'react';
|
|
255
|
+
|
|
256
|
+
import { cn } from '@/lib/utils';
|
|
257
|
+
|
|
258
|
+
function Table({ className, ...props }: React.ComponentProps<'table'>) {
|
|
259
|
+
return (
|
|
260
|
+
<div className='relative w-full overflow-auto'>
|
|
261
|
+
<table
|
|
262
|
+
data-slot='table'
|
|
263
|
+
className={cn('w-full caption-bottom text-sm', className)}
|
|
264
|
+
{...props}
|
|
265
|
+
/>
|
|
266
|
+
</div>
|
|
267
|
+
);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
function TableHeader({ className, ...props }: React.ComponentProps<'thead'>) {
|
|
271
|
+
return (
|
|
272
|
+
<thead
|
|
273
|
+
data-slot='table-header'
|
|
274
|
+
className={cn('[&_tr]:border-b', className)}
|
|
275
|
+
{...props}
|
|
276
|
+
/>
|
|
277
|
+
);
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
function TableBody({ className, ...props }: React.ComponentProps<'tbody'>) {
|
|
281
|
+
return (
|
|
282
|
+
<tbody
|
|
283
|
+
data-slot='table-body'
|
|
284
|
+
className={cn('[&_tr:last-child]:border-0', className)}
|
|
285
|
+
{...props}
|
|
286
|
+
/>
|
|
287
|
+
);
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
function TableFooter({ className, ...props }: React.ComponentProps<'tfoot'>) {
|
|
291
|
+
return (
|
|
292
|
+
<tfoot
|
|
293
|
+
data-slot='table-footer'
|
|
294
|
+
className={cn(
|
|
295
|
+
'bg-muted/50 border-t font-medium [&>tr]:last:border-b-0',
|
|
296
|
+
className
|
|
297
|
+
)}
|
|
298
|
+
{...props}
|
|
299
|
+
/>
|
|
300
|
+
);
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
function TableRow({ className, ...props }: React.ComponentProps<'tr'>) {
|
|
304
|
+
return (
|
|
305
|
+
<tr
|
|
306
|
+
data-slot='table-row'
|
|
307
|
+
className={cn(
|
|
308
|
+
'hover:bg-muted/50 data-[state=selected]:bg-muted border-b transition-colors',
|
|
309
|
+
className
|
|
310
|
+
)}
|
|
311
|
+
{...props}
|
|
312
|
+
/>
|
|
313
|
+
);
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
function TableHead({ className, ...props }: React.ComponentProps<'th'>) {
|
|
317
|
+
return (
|
|
318
|
+
<th
|
|
319
|
+
data-slot='table-head'
|
|
320
|
+
className={cn(
|
|
321
|
+
'text-muted-foreground h-12 px-4 text-left align-middle font-medium [&:has([role=checkbox])]:pr-0',
|
|
322
|
+
className
|
|
323
|
+
)}
|
|
324
|
+
{...props}
|
|
325
|
+
/>
|
|
326
|
+
);
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
function TableCell({ className, ...props }: React.ComponentProps<'td'>) {
|
|
330
|
+
return (
|
|
331
|
+
<td
|
|
332
|
+
data-slot='table-cell'
|
|
333
|
+
className={cn('p-4 align-middle [&:has([role=checkbox])]:pr-0', className)}
|
|
334
|
+
{...props}
|
|
335
|
+
/>
|
|
336
|
+
);
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
function TableCaption({
|
|
340
|
+
className,
|
|
341
|
+
...props
|
|
342
|
+
}: React.ComponentProps<'caption'>) {
|
|
343
|
+
return (
|
|
344
|
+
<caption
|
|
345
|
+
data-slot='table-caption'
|
|
346
|
+
className={cn('text-muted-foreground mt-4 text-sm', className)}
|
|
347
|
+
{...props}
|
|
348
|
+
/>
|
|
349
|
+
);
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
export {
|
|
353
|
+
Table,
|
|
354
|
+
TableHeader,
|
|
355
|
+
TableBody,
|
|
356
|
+
TableFooter,
|
|
357
|
+
TableHead,
|
|
358
|
+
TableRow,
|
|
359
|
+
TableCell,
|
|
360
|
+
TableCaption,
|
|
361
|
+
};`,
|
|
362
|
+
|
|
363
|
+
'components/ui/text-effect.tsx': `'use client';
|
|
364
|
+
import {
|
|
365
|
+
type Variants,
|
|
366
|
+
motion,
|
|
367
|
+
TargetAndTransition,
|
|
368
|
+
Transition,
|
|
369
|
+
} from 'framer-motion';
|
|
370
|
+
import React from 'react';
|
|
371
|
+
import { cn } from '@/lib/utils';
|
|
372
|
+
|
|
373
|
+
type PresetType = 'blur' | 'shake' | 'scale' | 'fade' | 'slide';
|
|
374
|
+
|
|
375
|
+
interface TextEffectProps {
|
|
376
|
+
children: string;
|
|
377
|
+
per?: 'word' | 'char' | 'line';
|
|
378
|
+
as?: keyof React.JSX.IntrinsicElements;
|
|
379
|
+
variants?: {
|
|
380
|
+
container?: Variants;
|
|
381
|
+
item?: Variants;
|
|
382
|
+
};
|
|
383
|
+
className?: string;
|
|
384
|
+
preset?: PresetType;
|
|
385
|
+
delay?: number;
|
|
386
|
+
trigger?: boolean;
|
|
387
|
+
onAnimationComplete?: () => void;
|
|
388
|
+
segmentWrapperClassName?: string;
|
|
389
|
+
containerTransition?: Transition;
|
|
390
|
+
segmentTransition?: Transition;
|
|
391
|
+
style?: React.CSSProperties;
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
const defaultContainerVariants: Variants = {
|
|
395
|
+
hidden: { opacity: 0 },
|
|
396
|
+
visible: {
|
|
397
|
+
opacity: 1,
|
|
398
|
+
transition: {
|
|
399
|
+
staggerChildren: 0.05,
|
|
400
|
+
},
|
|
401
|
+
},
|
|
402
|
+
};
|
|
403
|
+
|
|
404
|
+
const defaultItemVariants: Variants = {
|
|
405
|
+
hidden: { opacity: 0 },
|
|
406
|
+
visible: {
|
|
407
|
+
opacity: 1,
|
|
408
|
+
},
|
|
409
|
+
};
|
|
410
|
+
|
|
411
|
+
const presetVariants: Record<
|
|
412
|
+
PresetType,
|
|
413
|
+
{ container?: Variants; item?: Variants }
|
|
414
|
+
> = {
|
|
415
|
+
blur: {
|
|
416
|
+
container: defaultContainerVariants,
|
|
417
|
+
item: {
|
|
418
|
+
hidden: { opacity: 0, filter: 'blur(12px)', y: 0 },
|
|
419
|
+
visible: { opacity: 1, filter: 'blur(0px)', y: 0 },
|
|
420
|
+
},
|
|
421
|
+
},
|
|
422
|
+
shake: {
|
|
423
|
+
container: defaultContainerVariants,
|
|
424
|
+
item: {
|
|
425
|
+
hidden: { x: 0 },
|
|
426
|
+
visible: { x: [-1, 1, -1, 1, 0], transition: { repeat: Infinity } },
|
|
427
|
+
},
|
|
428
|
+
},
|
|
429
|
+
scale: {
|
|
430
|
+
container: defaultContainerVariants,
|
|
431
|
+
item: {
|
|
432
|
+
hidden: { opacity: 0, scale: 0 },
|
|
433
|
+
visible: { opacity: 1, scale: 1 },
|
|
434
|
+
},
|
|
435
|
+
},
|
|
436
|
+
fade: {
|
|
437
|
+
container: defaultContainerVariants,
|
|
438
|
+
item: {
|
|
439
|
+
hidden: { opacity: 0 },
|
|
440
|
+
visible: { opacity: 1 },
|
|
441
|
+
},
|
|
442
|
+
},
|
|
443
|
+
slide: {
|
|
444
|
+
container: defaultContainerVariants,
|
|
445
|
+
item: {
|
|
446
|
+
hidden: { opacity: 0, y: 20 },
|
|
447
|
+
visible: { opacity: 1, y: 0 },
|
|
448
|
+
},
|
|
449
|
+
},
|
|
450
|
+
};
|
|
451
|
+
|
|
452
|
+
const AnimationComponent: React.FC<{
|
|
453
|
+
segment: string;
|
|
454
|
+
variants: Variants;
|
|
455
|
+
transition?: Transition;
|
|
456
|
+
className?: string;
|
|
457
|
+
}> = React.memo(({ segment, variants, transition, className }) => {
|
|
458
|
+
return (
|
|
459
|
+
<motion.span
|
|
460
|
+
variants={variants}
|
|
461
|
+
transition={transition}
|
|
462
|
+
className={cn('inline-block whitespace-pre', className)}
|
|
463
|
+
>
|
|
464
|
+
{segment}
|
|
465
|
+
</motion.span>
|
|
466
|
+
);
|
|
467
|
+
});
|
|
468
|
+
|
|
469
|
+
AnimationComponent.displayName = 'AnimationComponent';
|
|
470
|
+
|
|
471
|
+
export const TextEffect = React.memo(
|
|
472
|
+
({
|
|
473
|
+
children,
|
|
474
|
+
per = 'word',
|
|
475
|
+
as = 'p',
|
|
476
|
+
variants,
|
|
477
|
+
className,
|
|
478
|
+
preset,
|
|
479
|
+
delay = 0,
|
|
480
|
+
trigger = true,
|
|
481
|
+
onAnimationComplete,
|
|
482
|
+
segmentWrapperClassName,
|
|
483
|
+
containerTransition,
|
|
484
|
+
segmentTransition,
|
|
485
|
+
style,
|
|
486
|
+
}: TextEffectProps) => {
|
|
487
|
+
const segments = React.useMemo(() => {
|
|
488
|
+
if (per === 'line') return children.split('\\n');
|
|
489
|
+
if (per === 'word') return children.split(/(\\s+)/);
|
|
490
|
+
return children.split('');
|
|
491
|
+
}, [children, per]);
|
|
492
|
+
|
|
493
|
+
const MotionTag = motion[as as keyof typeof motion] as typeof motion.div;
|
|
494
|
+
const selectedVariants = preset
|
|
495
|
+
? presetVariants[preset]
|
|
496
|
+
: { container: defaultContainerVariants, item: defaultItemVariants };
|
|
497
|
+
const containerVariants = variants?.container || selectedVariants.container;
|
|
498
|
+
const itemVariants = (variants?.item || selectedVariants.item || defaultItemVariants) as Variants;
|
|
499
|
+
|
|
500
|
+
return (
|
|
501
|
+
<MotionTag
|
|
502
|
+
initial='hidden'
|
|
503
|
+
animate={trigger ? 'visible' : 'hidden'}
|
|
504
|
+
aria-label={children}
|
|
505
|
+
variants={containerVariants}
|
|
506
|
+
transition={{
|
|
507
|
+
...containerTransition,
|
|
508
|
+
delayChildren: delay,
|
|
509
|
+
}}
|
|
510
|
+
className={cn('whitespace-pre-wrap', className)}
|
|
511
|
+
onAnimationComplete={onAnimationComplete}
|
|
512
|
+
style={style}
|
|
513
|
+
>
|
|
514
|
+
{segments.map((segment, index) => (
|
|
515
|
+
<AnimationComponent
|
|
516
|
+
key={\`\${segment}-\${index}\`}
|
|
517
|
+
segment={segment}
|
|
518
|
+
variants={itemVariants}
|
|
519
|
+
transition={segmentTransition}
|
|
520
|
+
className={segmentWrapperClassName}
|
|
521
|
+
/>
|
|
522
|
+
))}
|
|
523
|
+
</MotionTag>
|
|
524
|
+
);
|
|
525
|
+
}
|
|
526
|
+
);
|
|
527
|
+
|
|
528
|
+
TextEffect.displayName = 'TextEffect';`,
|
|
529
|
+
|
|
530
|
+
'components/ui/textarea.tsx': `import * as React from 'react';
|
|
531
|
+
|
|
532
|
+
import { cn } from '@/lib/utils';
|
|
533
|
+
|
|
534
|
+
function Textarea({ className, ...props }: React.ComponentProps<'textarea'>) {
|
|
535
|
+
return (
|
|
536
|
+
<textarea
|
|
537
|
+
data-slot='textarea'
|
|
538
|
+
className={cn(
|
|
539
|
+
'border-input placeholder:text-muted-foreground focus-visible:ring-ring focus-visible:ring-offset-background flex min-h-[80px] w-full rounded-md border bg-transparent px-3 py-2 text-sm focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50',
|
|
540
|
+
className
|
|
541
|
+
)}
|
|
542
|
+
{...props}
|
|
543
|
+
/>
|
|
544
|
+
);
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
export { Textarea };`,
|
|
548
|
+
|
|
549
|
+
'components/ui/tooltip.tsx': `'use client';
|
|
550
|
+
|
|
551
|
+
import * as React from 'react';
|
|
552
|
+
import * as TooltipPrimitive from '@radix-ui/react-tooltip';
|
|
553
|
+
|
|
554
|
+
import { cn } from '@/lib/utils';
|
|
555
|
+
|
|
556
|
+
function TooltipProvider({
|
|
557
|
+
delayDuration = 0,
|
|
558
|
+
...props
|
|
559
|
+
}: React.ComponentProps<typeof TooltipPrimitive.Provider>) {
|
|
560
|
+
return (
|
|
561
|
+
<TooltipPrimitive.Provider
|
|
562
|
+
data-slot='tooltip-provider'
|
|
563
|
+
delayDuration={delayDuration}
|
|
564
|
+
{...props}
|
|
565
|
+
/>
|
|
566
|
+
);
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
function Tooltip({
|
|
570
|
+
...props
|
|
571
|
+
}: React.ComponentProps<typeof TooltipPrimitive.Root>) {
|
|
572
|
+
return (
|
|
573
|
+
<TooltipProvider>
|
|
574
|
+
<TooltipPrimitive.Root data-slot='tooltip' {...props} />
|
|
575
|
+
</TooltipProvider>
|
|
576
|
+
);
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
function TooltipTrigger({
|
|
580
|
+
...props
|
|
581
|
+
}: React.ComponentProps<typeof TooltipPrimitive.Trigger>) {
|
|
582
|
+
return <TooltipPrimitive.Trigger data-slot='tooltip-trigger' {...props} />;
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
function TooltipContent({
|
|
586
|
+
className,
|
|
587
|
+
sideOffset = 4,
|
|
588
|
+
...props
|
|
589
|
+
}: React.ComponentProps<typeof TooltipPrimitive.Content>) {
|
|
590
|
+
return (
|
|
591
|
+
<TooltipPrimitive.Portal>
|
|
592
|
+
<TooltipPrimitive.Content
|
|
593
|
+
data-slot='tooltip-content'
|
|
594
|
+
sideOffset={sideOffset}
|
|
595
|
+
className={cn(
|
|
596
|
+
'bg-primary text-primary-foreground animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 overflow-hidden rounded-md px-3 py-1.5 text-xs shadow-md',
|
|
597
|
+
className
|
|
598
|
+
)}
|
|
599
|
+
{...props}
|
|
600
|
+
/>
|
|
601
|
+
</TooltipPrimitive.Portal>
|
|
602
|
+
);
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider };`,
|
|
606
|
+
};
|