@dilipod/ui 0.1.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,140 @@
1
+ 'use client'
2
+
3
+ import * as React from 'react'
4
+ import * as SheetPrimitive from '@radix-ui/react-dialog'
5
+ import { cva, type VariantProps } from 'class-variance-authority'
6
+ import { X } from '@phosphor-icons/react'
7
+
8
+ import { cn } from '../lib/utils'
9
+
10
+ const Sheet = SheetPrimitive.Root
11
+
12
+ const SheetTrigger = SheetPrimitive.Trigger
13
+
14
+ const SheetClose = SheetPrimitive.Close
15
+
16
+ const SheetPortal = SheetPrimitive.Portal
17
+
18
+ const SheetOverlay = React.forwardRef<
19
+ React.ElementRef<typeof SheetPrimitive.Overlay>,
20
+ React.ComponentPropsWithoutRef<typeof SheetPrimitive.Overlay>
21
+ >(({ className, ...props }, ref) => (
22
+ <SheetPrimitive.Overlay
23
+ className={cn(
24
+ 'fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0',
25
+ className
26
+ )}
27
+ {...props}
28
+ ref={ref}
29
+ />
30
+ ))
31
+ SheetOverlay.displayName = SheetPrimitive.Overlay.displayName
32
+
33
+ const sheetVariants = cva(
34
+ 'fixed z-50 gap-4 bg-white p-6 shadow-lg transition ease-in-out data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:duration-300 data-[state=open]:duration-500',
35
+ {
36
+ variants: {
37
+ side: {
38
+ top: 'inset-x-0 top-0 border-b data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top',
39
+ bottom:
40
+ 'inset-x-0 bottom-0 border-t data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom',
41
+ left: 'inset-y-0 left-0 h-full w-3/4 border-r data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left sm:max-w-sm',
42
+ right:
43
+ 'inset-y-0 right-0 h-full w-3/4 border-l data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right sm:max-w-sm',
44
+ },
45
+ },
46
+ defaultVariants: {
47
+ side: 'right',
48
+ },
49
+ }
50
+ )
51
+
52
+ interface SheetContentProps
53
+ extends React.ComponentPropsWithoutRef<typeof SheetPrimitive.Content>,
54
+ VariantProps<typeof sheetVariants> {}
55
+
56
+ const SheetContent = React.forwardRef<
57
+ React.ElementRef<typeof SheetPrimitive.Content>,
58
+ SheetContentProps
59
+ >(({ side = 'right', className, children, ...props }, ref) => (
60
+ <SheetPortal>
61
+ <SheetOverlay />
62
+ <SheetPrimitive.Content
63
+ ref={ref}
64
+ className={cn(sheetVariants({ side }), className)}
65
+ {...props}
66
+ >
67
+ {children}
68
+ <SheetPrimitive.Close className="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-white transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-[var(--cyan)] focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-gray-100">
69
+ <X className="h-4 w-4" />
70
+ <span className="sr-only">Close</span>
71
+ </SheetPrimitive.Close>
72
+ </SheetPrimitive.Content>
73
+ </SheetPortal>
74
+ ))
75
+ SheetContent.displayName = SheetPrimitive.Content.displayName
76
+
77
+ const SheetHeader = ({
78
+ className,
79
+ ...props
80
+ }: React.HTMLAttributes<HTMLDivElement>) => (
81
+ <div
82
+ className={cn(
83
+ 'flex flex-col space-y-2 text-center sm:text-left',
84
+ className
85
+ )}
86
+ {...props}
87
+ />
88
+ )
89
+ SheetHeader.displayName = 'SheetHeader'
90
+
91
+ const SheetFooter = ({
92
+ className,
93
+ ...props
94
+ }: React.HTMLAttributes<HTMLDivElement>) => (
95
+ <div
96
+ className={cn(
97
+ 'flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2',
98
+ className
99
+ )}
100
+ {...props}
101
+ />
102
+ )
103
+ SheetFooter.displayName = 'SheetFooter'
104
+
105
+ const SheetTitle = React.forwardRef<
106
+ React.ElementRef<typeof SheetPrimitive.Title>,
107
+ React.ComponentPropsWithoutRef<typeof SheetPrimitive.Title>
108
+ >(({ className, ...props }, ref) => (
109
+ <SheetPrimitive.Title
110
+ ref={ref}
111
+ className={cn('text-lg font-semibold text-[var(--black)]', className)}
112
+ {...props}
113
+ />
114
+ ))
115
+ SheetTitle.displayName = SheetPrimitive.Title.displayName
116
+
117
+ const SheetDescription = React.forwardRef<
118
+ React.ElementRef<typeof SheetPrimitive.Description>,
119
+ React.ComponentPropsWithoutRef<typeof SheetPrimitive.Description>
120
+ >(({ className, ...props }, ref) => (
121
+ <SheetPrimitive.Description
122
+ ref={ref}
123
+ className={cn('text-sm text-gray-500', className)}
124
+ {...props}
125
+ />
126
+ ))
127
+ SheetDescription.displayName = SheetPrimitive.Description.displayName
128
+
129
+ export {
130
+ Sheet,
131
+ SheetPortal,
132
+ SheetOverlay,
133
+ SheetTrigger,
134
+ SheetClose,
135
+ SheetContent,
136
+ SheetHeader,
137
+ SheetFooter,
138
+ SheetTitle,
139
+ SheetDescription,
140
+ }
@@ -0,0 +1,127 @@
1
+ import type { Meta, StoryObj } from '@storybook/react'
2
+ import { Stat } from './stat'
3
+
4
+ const meta: Meta<typeof Stat> = {
5
+ title: 'Components/Stat',
6
+ component: Stat,
7
+ tags: ['autodocs'],
8
+ argTypes: {
9
+ variant: {
10
+ control: 'select',
11
+ options: ['default', 'card'],
12
+ },
13
+ align: {
14
+ control: 'select',
15
+ options: ['left', 'center', 'right'],
16
+ },
17
+ valueSize: {
18
+ control: 'select',
19
+ options: ['sm', 'default', 'lg', 'xl'],
20
+ },
21
+ valueColor: {
22
+ control: 'select',
23
+ options: ['default', 'primary', 'white', 'gradient'],
24
+ },
25
+ },
26
+ }
27
+
28
+ export default meta
29
+ type Story = StoryObj<typeof Stat>
30
+
31
+ export const Default: Story = {
32
+ args: {
33
+ value: '1,247',
34
+ label: 'Docs Reviewed',
35
+ },
36
+ }
37
+
38
+ export const WithSuffix: Story = {
39
+ args: {
40
+ value: '80%',
41
+ suffix: 'cheaper',
42
+ label: '€6-12K/year vs €40-60K for an employee',
43
+ },
44
+ }
45
+
46
+ export const Primary: Story = {
47
+ args: {
48
+ value: '99.8%',
49
+ label: 'Accuracy',
50
+ valueColor: 'primary',
51
+ },
52
+ }
53
+
54
+ export const Large: Story = {
55
+ args: {
56
+ value: '24h',
57
+ suffix: 'to deploy',
58
+ label: 'From call to working agent in one day',
59
+ valueSize: 'lg',
60
+ },
61
+ }
62
+
63
+ export const Card: Story = {
64
+ args: {
65
+ value: '1,247',
66
+ label: 'Docs Reviewed',
67
+ variant: 'card',
68
+ align: 'center',
69
+ },
70
+ }
71
+
72
+ export const Centered: Story = {
73
+ args: {
74
+ value: '24/7',
75
+ label: 'Available',
76
+ align: 'center',
77
+ valueColor: 'primary',
78
+ valueSize: 'lg',
79
+ },
80
+ }
81
+
82
+ export const StatsGrid: Story = {
83
+ render: () => (
84
+ <div className="grid grid-cols-2 gap-4 w-80">
85
+ <Stat value="1,247" label="Docs Reviewed" variant="card" align="center" />
86
+ <Stat value="99.8%" label="Accuracy" variant="card" align="center" valueColor="primary" />
87
+ </div>
88
+ ),
89
+ }
90
+
91
+ export const SolutionStats: Story = {
92
+ render: () => (
93
+ <div className="grid grid-cols-4 gap-8">
94
+ <Stat value="80%" suffix="cheaper" label="€6-12K/year vs €40-60K" valueSize="lg" />
95
+ <Stat value="24h" suffix="to deploy" label="From call to working agent" valueSize="lg" />
96
+ <Stat value="Zero" suffix="maintenance" label="We handle everything" valueSize="lg" />
97
+ <Stat value="Instant" suffix="capacity" label="Add more agents on demand" valueSize="lg" />
98
+ </div>
99
+ ),
100
+ }
101
+
102
+ export const UseCaseStats: Story = {
103
+ render: () => (
104
+ <div className="flex gap-8">
105
+ <Stat value="40hrs" label="saved/week" valueColor="primary" />
106
+ <Stat value="99.8%" label="accuracy" valueColor="primary" />
107
+ <Stat value="10x" label="faster" valueColor="primary" />
108
+ <Stat value="24/7" label="available" valueColor="primary" />
109
+ </div>
110
+ ),
111
+ }
112
+
113
+ export const OnDarkBackground: Story = {
114
+ render: () => (
115
+ <div className="bg-[var(--black)] p-8 rounded-lg">
116
+ <div className="grid grid-cols-4 gap-8">
117
+ <Stat value="80%" suffix="cheaper" valueSize="lg" valueColor="white" />
118
+ <Stat value="24h" suffix="to deploy" valueSize="lg" valueColor="white" />
119
+ <Stat value="Zero" suffix="maintenance" valueSize="lg" valueColor="white" />
120
+ <Stat value="Instant" suffix="capacity" valueSize="lg" valueColor="white" />
121
+ </div>
122
+ </div>
123
+ ),
124
+ parameters: {
125
+ backgrounds: { default: 'dark' },
126
+ },
127
+ }
@@ -0,0 +1,115 @@
1
+ 'use client'
2
+
3
+ import * as React from 'react'
4
+ import { cva, type VariantProps } from 'class-variance-authority'
5
+ import { cn } from '../lib/utils'
6
+
7
+ const statVariants = cva('', {
8
+ variants: {
9
+ variant: {
10
+ default: '',
11
+ card: 'p-3 rounded-sm bg-gray-50 text-center',
12
+ },
13
+ align: {
14
+ left: 'text-left',
15
+ center: 'text-center',
16
+ right: 'text-right',
17
+ },
18
+ },
19
+ defaultVariants: {
20
+ variant: 'default',
21
+ align: 'left',
22
+ },
23
+ })
24
+
25
+ const valueVariants = cva('font-bold', {
26
+ variants: {
27
+ size: {
28
+ sm: 'text-xl',
29
+ default: 'text-3xl md:text-4xl',
30
+ lg: 'text-4xl md:text-5xl',
31
+ xl: 'text-5xl md:text-6xl',
32
+ },
33
+ color: {
34
+ default: 'text-[var(--black)]',
35
+ primary: 'text-[var(--cyan)]',
36
+ white: 'text-white',
37
+ gradient: 'text-gradient',
38
+ },
39
+ },
40
+ defaultVariants: {
41
+ size: 'default',
42
+ color: 'default',
43
+ },
44
+ })
45
+
46
+ export interface StatProps
47
+ extends React.HTMLAttributes<HTMLDivElement>,
48
+ VariantProps<typeof statVariants> {
49
+ /** The main value to display */
50
+ value: string | number
51
+ /** Label below the value */
52
+ label?: string
53
+ /** Optional suffix after value (e.g., "faster", "cheaper") */
54
+ suffix?: string
55
+ /** Size of the value text */
56
+ valueSize?: 'sm' | 'default' | 'lg' | 'xl'
57
+ /** Color of the value */
58
+ valueColor?: 'default' | 'primary' | 'white' | 'gradient'
59
+ }
60
+
61
+ const Stat = React.forwardRef<HTMLDivElement, StatProps>(
62
+ (
63
+ {
64
+ className,
65
+ variant,
66
+ align,
67
+ value,
68
+ label,
69
+ suffix,
70
+ valueSize = 'default',
71
+ valueColor = 'default',
72
+ ...props
73
+ },
74
+ ref
75
+ ) => {
76
+ const justifyClass = {
77
+ left: 'justify-start',
78
+ center: 'justify-center',
79
+ right: 'justify-end',
80
+ }[align || 'left']
81
+
82
+ return (
83
+ <div
84
+ ref={ref}
85
+ className={cn(statVariants({ variant, align }), className)}
86
+ {...props}
87
+ >
88
+ <div className={cn('flex items-baseline gap-2', justifyClass)}>
89
+ <span className={cn(valueVariants({ size: valueSize, color: valueColor }))}>
90
+ {value}
91
+ </span>
92
+ {suffix && (
93
+ <span className={cn(
94
+ "font-medium text-[var(--cyan)]",
95
+ valueSize === 'lg' || valueSize === 'xl' ? 'text-lg md:text-xl' : 'text-base md:text-lg'
96
+ )}>
97
+ {suffix}
98
+ </span>
99
+ )}
100
+ </div>
101
+ {label && (
102
+ <div className={cn(
103
+ "font-medium mt-1",
104
+ valueColor === 'white' ? 'text-white/70 text-sm md:text-base' : 'text-gray-500 text-xs md:text-sm'
105
+ )}>
106
+ {label}
107
+ </div>
108
+ )}
109
+ </div>
110
+ )
111
+ }
112
+ )
113
+ Stat.displayName = 'Stat'
114
+
115
+ export { Stat, statVariants, valueVariants }
@@ -0,0 +1,107 @@
1
+ import type { Meta, StoryObj } from '@storybook/react'
2
+ import { Buildings, Briefcase, FirstAid, ShoppingCart } from '@phosphor-icons/react'
3
+ import { Tag } from './tag'
4
+
5
+ const meta: Meta<typeof Tag> = {
6
+ title: 'Components/Tag',
7
+ component: Tag,
8
+ tags: ['autodocs'],
9
+ argTypes: {
10
+ variant: {
11
+ control: 'select',
12
+ options: ['default', 'primary', 'outline', 'dark'],
13
+ },
14
+ size: {
15
+ control: 'select',
16
+ options: ['sm', 'default', 'lg'],
17
+ },
18
+ },
19
+ }
20
+
21
+ export default meta
22
+ type Story = StoryObj<typeof Tag>
23
+
24
+ export const Default: Story = {
25
+ args: {
26
+ children: 'Tag Label',
27
+ variant: 'default',
28
+ },
29
+ }
30
+
31
+ export const Primary: Story = {
32
+ args: {
33
+ children: 'Active',
34
+ variant: 'primary',
35
+ },
36
+ }
37
+
38
+ export const Outline: Story = {
39
+ args: {
40
+ children: 'Real Estate',
41
+ variant: 'outline',
42
+ icon: <Buildings size={14} weight="fill" />,
43
+ },
44
+ }
45
+
46
+ export const Dark: Story = {
47
+ args: {
48
+ children: 'Premium',
49
+ variant: 'dark',
50
+ },
51
+ }
52
+
53
+ export const WithIcon: Story = {
54
+ args: {
55
+ children: 'Healthcare',
56
+ variant: 'outline',
57
+ icon: <FirstAid size={14} weight="fill" />,
58
+ },
59
+ }
60
+
61
+ export const Sizes: Story = {
62
+ render: () => (
63
+ <div className="flex gap-2 items-center">
64
+ <Tag size="sm">Small</Tag>
65
+ <Tag size="default">Default</Tag>
66
+ <Tag size="lg">Large</Tag>
67
+ </div>
68
+ ),
69
+ }
70
+
71
+ export const Industries: Story = {
72
+ render: () => (
73
+ <div className="flex flex-wrap gap-2">
74
+ <Tag variant="outline" icon={<Buildings size={14} weight="fill" />}>Real Estate</Tag>
75
+ <Tag variant="outline" icon={<Briefcase size={14} weight="fill" />}>Professional Services</Tag>
76
+ <Tag variant="outline" icon={<FirstAid size={14} weight="fill" />}>Healthcare</Tag>
77
+ <Tag variant="outline" icon={<ShoppingCart size={14} weight="fill" />}>E-commerce</Tag>
78
+ </div>
79
+ ),
80
+ }
81
+
82
+ export const FeatureTags: Story = {
83
+ render: () => (
84
+ <div className="flex flex-wrap gap-2">
85
+ <Tag>Walk through your workflow</Tag>
86
+ <Tag>Show us your tools</Tag>
87
+ <Tag>Describe edge cases</Tag>
88
+ </div>
89
+ ),
90
+ }
91
+
92
+ export const AllVariants: Story = {
93
+ render: () => (
94
+ <div className="flex flex-col gap-4">
95
+ <div className="flex gap-2 items-center flex-wrap">
96
+ <Tag variant="default">Default</Tag>
97
+ <Tag variant="primary">Primary</Tag>
98
+ <Tag variant="outline">Outline</Tag>
99
+ <Tag variant="dark">Dark</Tag>
100
+ </div>
101
+ <div className="flex gap-2 items-center flex-wrap">
102
+ <Tag variant="outline" icon={<Buildings size={14} weight="fill" />}>With Icon</Tag>
103
+ <Tag variant="primary" icon={<Briefcase size={14} weight="fill" />}>Primary Icon</Tag>
104
+ </div>
105
+ </div>
106
+ ),
107
+ }
@@ -0,0 +1,53 @@
1
+ 'use client'
2
+
3
+ import * as React from 'react'
4
+ import { cva, type VariantProps } from 'class-variance-authority'
5
+ import { cn } from '../lib/utils'
6
+
7
+ const tagVariants = cva(
8
+ 'inline-flex items-center gap-2 font-medium transition-colors cursor-pointer',
9
+ {
10
+ variants: {
11
+ variant: {
12
+ default: 'bg-gray-100 text-[var(--black)]',
13
+ primary: 'bg-[var(--cyan)]/10 text-[var(--cyan)]',
14
+ outline: 'border border-gray-200 bg-white text-gray-700 hover:border-[var(--black)] hover:text-[var(--black)]',
15
+ dark: 'bg-[var(--black)] text-white',
16
+ },
17
+ size: {
18
+ sm: 'px-2 py-1 text-[10px] rounded',
19
+ default: 'px-3 py-1.5 text-xs rounded-full',
20
+ lg: 'px-4 py-2 text-sm rounded-full',
21
+ },
22
+ },
23
+ defaultVariants: {
24
+ variant: 'default',
25
+ size: 'default',
26
+ },
27
+ }
28
+ )
29
+
30
+ export interface TagProps
31
+ extends React.HTMLAttributes<HTMLSpanElement>,
32
+ VariantProps<typeof tagVariants> {
33
+ /** Optional icon to display before text */
34
+ icon?: React.ReactNode
35
+ }
36
+
37
+ const Tag = React.forwardRef<HTMLSpanElement, TagProps>(
38
+ ({ className, variant, size, icon, children, ...props }, ref) => {
39
+ return (
40
+ <span
41
+ ref={ref}
42
+ className={cn(tagVariants({ variant, size }), className)}
43
+ {...props}
44
+ >
45
+ {icon && <span className="shrink-0">{icon}</span>}
46
+ {children}
47
+ </span>
48
+ )
49
+ }
50
+ )
51
+ Tag.displayName = 'Tag'
52
+
53
+ export { Tag, tagVariants }
package/src/icons.ts ADDED
@@ -0,0 +1,107 @@
1
+ /**
2
+ * Dilipod Icon Library
3
+ *
4
+ * Re-exports Phosphor icons used across the design system.
5
+ * Import icons from '@dilipod/ui' instead of '@phosphor-icons/react' directly.
6
+ *
7
+ * @example
8
+ * import { ArrowRight, Brain, CheckCircle } from '@dilipod/ui'
9
+ */
10
+
11
+ // Navigation & Actions
12
+ export {
13
+ ArrowRight,
14
+ ArrowUpRight,
15
+ ArrowLeft,
16
+ CaretRight,
17
+ CaretDown,
18
+ CaretUp,
19
+ List,
20
+ X,
21
+ Plus,
22
+ Minus,
23
+ Check,
24
+ Play,
25
+ Pause,
26
+ Stop,
27
+ } from '@phosphor-icons/react'
28
+
29
+ // Business & Work
30
+ export {
31
+ Brain,
32
+ Robot,
33
+ Gear,
34
+ GearSix,
35
+ Files,
36
+ File,
37
+ FileText,
38
+ Database,
39
+ Receipt,
40
+ Wallet,
41
+ Clock,
42
+ Calendar,
43
+ VideoCamera,
44
+ ChatCircle,
45
+ ChartBar,
46
+ ChartLineUp,
47
+ Handshake,
48
+ UserPlus,
49
+ UsersThree,
50
+ User,
51
+ Users,
52
+ SignOut,
53
+ SignIn,
54
+ } from '@phosphor-icons/react'
55
+
56
+ // Industries
57
+ export {
58
+ Buildings,
59
+ Briefcase,
60
+ FirstAid,
61
+ ShoppingCart,
62
+ AddressBook,
63
+ } from '@phosphor-icons/react'
64
+
65
+ // Status & Feedback
66
+ export {
67
+ CheckCircle,
68
+ CheckSquare,
69
+ WarningCircle,
70
+ Warning,
71
+ Info,
72
+ Question,
73
+ Circle,
74
+ } from '@phosphor-icons/react'
75
+
76
+ // Social & Communication
77
+ export {
78
+ LinkedinLogo,
79
+ XLogo,
80
+ EnvelopeSimple,
81
+ Envelope,
82
+ Phone,
83
+ Globe,
84
+ } from '@phosphor-icons/react'
85
+
86
+ // UI Elements
87
+ export {
88
+ House,
89
+ MagnifyingGlass,
90
+ Trash,
91
+ PencilSimple,
92
+ Copy,
93
+ DotsThree,
94
+ DotsThreeVertical,
95
+ Eye,
96
+ EyeSlash,
97
+ Funnel,
98
+ SortAscending,
99
+ SortDescending,
100
+ Download,
101
+ Upload,
102
+ Link,
103
+ ArrowSquareOut,
104
+ } from '@phosphor-icons/react'
105
+
106
+ // Re-export Icon type for TypeScript
107
+ export type { Icon, IconProps } from '@phosphor-icons/react'
package/src/index.ts ADDED
@@ -0,0 +1,50 @@
1
+ // Core Components
2
+ export { Button, buttonVariants } from './components/button'
3
+ export type { ButtonProps } from './components/button'
4
+
5
+ export {
6
+ Sheet,
7
+ SheetPortal,
8
+ SheetOverlay,
9
+ SheetTrigger,
10
+ SheetClose,
11
+ SheetContent,
12
+ SheetHeader,
13
+ SheetFooter,
14
+ SheetTitle,
15
+ SheetDescription,
16
+ } from './components/sheet'
17
+
18
+ export { Logo } from './components/logo'
19
+ export type { LogoProps } from './components/logo'
20
+
21
+ // New Design System Components
22
+ export { Badge, badgeVariants } from './components/badge'
23
+ export type { BadgeProps } from './components/badge'
24
+
25
+ export {
26
+ Card,
27
+ CardHeader,
28
+ CardFooter,
29
+ CardTitle,
30
+ CardDescription,
31
+ CardContent,
32
+ } from './components/card'
33
+
34
+ export { Progress, progressVariants } from './components/progress'
35
+ export type { ProgressProps } from './components/progress'
36
+
37
+ export { IconBox, iconBoxVariants } from './components/icon-box'
38
+ export type { IconBoxProps } from './components/icon-box'
39
+
40
+ export { Tag, tagVariants } from './components/tag'
41
+ export type { TagProps } from './components/tag'
42
+
43
+ export { Stat, statVariants, valueVariants } from './components/stat'
44
+ export type { StatProps } from './components/stat'
45
+
46
+ // Utilities
47
+ export { cn } from './lib/utils'
48
+
49
+ // Icons - Re-exported from @phosphor-icons/react
50
+ export * from './icons'
@@ -0,0 +1,6 @@
1
+ import { type ClassValue, clsx } from 'clsx'
2
+ import { twMerge } from 'tailwind-merge'
3
+
4
+ export function cn(...inputs: ClassValue[]) {
5
+ return twMerge(clsx(inputs))
6
+ }