@ardly/bunext 1.0.6 → 1.0.7
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 +33 -16
- package/cli.mjs +126 -0
- package/package.json +14 -58
- package/.eslintrc.json +0 -8
- package/.prettierignore +0 -4
- package/STRUCTURE.md +0 -77
- package/bin/cli.mjs +0 -126
- package/components.json +0 -21
- package/next.config.ts +0 -22
- package/postcss.config.mjs +0 -8
- package/prettier.config.js +0 -7
- package/public/android-chrome-192x192.png +0 -0
- package/public/android-chrome-512x512.png +0 -0
- package/public/favicon.svg +0 -1
- package/public/loading-dots.gif +0 -0
- package/public/logo.svg +0 -1
- package/public/ogImage.webp +0 -0
- package/public/site.webmanifest +0 -19
- package/src/actions/placeholder.ts +0 -30
- package/src/actions/sampleAction.ts +0 -39
- package/src/app/(index)/intr/TestCard.tsx +0 -31
- package/src/app/(index)/intr/page.tsx +0 -17
- package/src/app/(index)/page.tsx +0 -156
- package/src/app/(index)/pagetr/page.tsx +0 -37
- package/src/app/error-wrapper.tsx +0 -32
- package/src/app/global-error.tsx +0 -53
- package/src/app/layout.tsx +0 -56
- package/src/app/loading.tsx +0 -11
- package/src/app/not-found.tsx +0 -45
- package/src/app/sitemap.ts +0 -14
- package/src/components/Providers/root-provider.tsx +0 -22
- package/src/components/Providers/theme-provider.tsx +0 -27
- package/src/components/TestComp.tsx +0 -11
- package/src/components/brand.tsx +0 -35
- package/src/components/navigation/footer.tsx +0 -32
- package/src/components/navigation/main-nav.tsx +0 -55
- package/src/components/navigation/mobile-nav.tsx +0 -154
- package/src/components/navigation/site-header.tsx +0 -67
- package/src/components/ui/avatar.tsx +0 -50
- package/src/components/ui/badge.tsx +0 -36
- package/src/components/ui/button.tsx +0 -56
- package/src/components/ui/card.tsx +0 -79
- package/src/components/ui/command.tsx +0 -153
- package/src/components/ui/dialog.tsx +0 -122
- package/src/components/ui/drawer.tsx +0 -118
- package/src/components/ui/dropdown-menu.tsx +0 -200
- package/src/components/ui/input.tsx +0 -22
- package/src/components/ui/label.tsx +0 -26
- package/src/components/ui/multi-select.tsx +0 -380
- package/src/components/ui/origin/multiselect.tsx +0 -645
- package/src/components/ui/popover.tsx +0 -31
- package/src/components/ui/radio-group.tsx +0 -44
- package/src/components/ui/separator.tsx +0 -31
- package/src/components/ui/skeleton.tsx +0 -15
- package/src/components/ui/themeSelector.tsx +0 -157
- package/src/components/ui/toast.tsx +0 -129
- package/src/components/ui/toaster.tsx +0 -31
- package/src/components/ui/tooltip.tsx +0 -39
- package/src/components/utils/ConditionalLink.tsx +0 -46
- package/src/components/utils/Image.tsx +0 -57
- package/src/components/utils/Img.tsx +0 -104
- package/src/components/utils/Spinner.tsx +0 -29
- package/src/components/utils/TopButton.tsx +0 -67
- package/src/components/utils/TransitionLink.tsx +0 -67
- package/src/components/utils/copy.tsx +0 -98
- package/src/components/utils/featureFlag.tsx +0 -22
- package/src/components/utils/icons.tsx +0 -155
- package/src/components/utils/share-modal.tsx +0 -159
- package/src/hooks/use-intersection.ts +0 -52
- package/src/hooks/use-lazy-load.ts +0 -33
- package/src/hooks/use-meta-color.ts +0 -25
- package/src/hooks/use-toast.ts +0 -191
- package/src/lib/config/featureflags.ts +0 -63
- package/src/lib/config/siteConfig.ts +0 -172
- package/src/lib/config/user.ts +0 -9
- package/src/lib/data/footer-data.ts +0 -85
- package/src/lib/data/nav-data.ts +0 -30
- package/src/lib/data/siteData.ts +0 -52
- package/src/lib/utils/index.ts +0 -190
- package/src/styles/customGlobal.css +0 -141
- package/src/styles/globals.css +0 -72
- package/src/styles/tailwind/base.ts +0 -46
- package/src/styles/tailwind/fonts/ClashDisplay-Bold.eot +0 -0
- package/src/styles/tailwind/fonts/ClashDisplay-Bold.ttf +0 -0
- package/src/styles/tailwind/fonts/ClashDisplay-Bold.woff +0 -0
- package/src/styles/tailwind/fonts/ClashDisplay-Bold.woff2 +0 -0
- package/src/styles/tailwind/fonts/ClashDisplay-Extralight.eot +0 -0
- package/src/styles/tailwind/fonts/ClashDisplay-Extralight.ttf +0 -0
- package/src/styles/tailwind/fonts/ClashDisplay-Extralight.woff +0 -0
- package/src/styles/tailwind/fonts/ClashDisplay-Extralight.woff2 +0 -0
- package/src/styles/tailwind/fonts/ClashDisplay-Light.eot +0 -0
- package/src/styles/tailwind/fonts/ClashDisplay-Light.ttf +0 -0
- package/src/styles/tailwind/fonts/ClashDisplay-Light.woff +0 -0
- package/src/styles/tailwind/fonts/ClashDisplay-Light.woff2 +0 -0
- package/src/styles/tailwind/fonts/ClashDisplay-Medium.eot +0 -0
- package/src/styles/tailwind/fonts/ClashDisplay-Medium.ttf +0 -0
- package/src/styles/tailwind/fonts/ClashDisplay-Medium.woff +0 -0
- package/src/styles/tailwind/fonts/ClashDisplay-Medium.woff2 +0 -0
- package/src/styles/tailwind/fonts/ClashDisplay-Regular.eot +0 -0
- package/src/styles/tailwind/fonts/ClashDisplay-Regular.ttf +0 -0
- package/src/styles/tailwind/fonts/ClashDisplay-Regular.woff +0 -0
- package/src/styles/tailwind/fonts/ClashDisplay-Regular.woff2 +0 -0
- package/src/styles/tailwind/fonts/ClashDisplay-Semibold.eot +0 -0
- package/src/styles/tailwind/fonts/ClashDisplay-Semibold.ttf +0 -0
- package/src/styles/tailwind/fonts/ClashDisplay-Semibold.woff +0 -0
- package/src/styles/tailwind/fonts/ClashDisplay-Semibold.woff2 +0 -0
- package/src/styles/tailwind/fonts/ClashDisplay-Variable.eot +0 -0
- package/src/styles/tailwind/fonts/ClashDisplay-Variable.ttf +0 -0
- package/src/styles/tailwind/fonts/ClashDisplay-Variable.woff +0 -0
- package/src/styles/tailwind/fonts/ClashDisplay-Variable.woff2 +0 -0
- package/src/styles/tailwind/fonts/GeistMonoVF.woff +0 -0
- package/src/styles/tailwind/fonts/GeistVF.woff +0 -0
- package/src/styles/tailwind/fonts.ts +0 -51
- package/src/styles/tailwind/tailwindUtils.ts +0 -29
- package/src/types/index.ts +0 -80
- package/tailwind.config.ts +0 -104
- package/tsconfig.json +0 -28
- package/vercel.json +0 -6
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
'use client'
|
|
2
|
-
|
|
3
|
-
import * as RadioGroupPrimitive from '@radix-ui/react-radio-group'
|
|
4
|
-
import { Circle } from 'lucide-react'
|
|
5
|
-
import * as React from 'react'
|
|
6
|
-
|
|
7
|
-
import { cn } from '@/lib/utils'
|
|
8
|
-
|
|
9
|
-
const RadioGroup = React.forwardRef<
|
|
10
|
-
React.ElementRef<typeof RadioGroupPrimitive.Root>,
|
|
11
|
-
React.ComponentPropsWithoutRef<typeof RadioGroupPrimitive.Root>
|
|
12
|
-
>(({ className, ...props }, ref) => {
|
|
13
|
-
return (
|
|
14
|
-
<RadioGroupPrimitive.Root
|
|
15
|
-
className={cn('grid gap-2', className)}
|
|
16
|
-
{...props}
|
|
17
|
-
ref={ref}
|
|
18
|
-
/>
|
|
19
|
-
)
|
|
20
|
-
})
|
|
21
|
-
RadioGroup.displayName = RadioGroupPrimitive.Root.displayName
|
|
22
|
-
|
|
23
|
-
const RadioGroupItem = React.forwardRef<
|
|
24
|
-
React.ElementRef<typeof RadioGroupPrimitive.Item>,
|
|
25
|
-
React.ComponentPropsWithoutRef<typeof RadioGroupPrimitive.Item>
|
|
26
|
-
>(({ className, ...props }, ref) => {
|
|
27
|
-
return (
|
|
28
|
-
<RadioGroupPrimitive.Item
|
|
29
|
-
ref={ref}
|
|
30
|
-
className={cn(
|
|
31
|
-
'aspect-square h-4 w-4 rounded-full border border-primary text-primary ring-offset-background focus:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50',
|
|
32
|
-
className
|
|
33
|
-
)}
|
|
34
|
-
{...props}
|
|
35
|
-
>
|
|
36
|
-
<RadioGroupPrimitive.Indicator className="flex items-center justify-center">
|
|
37
|
-
<Circle className="h-2.5 w-2.5 fill-current text-current" />
|
|
38
|
-
</RadioGroupPrimitive.Indicator>
|
|
39
|
-
</RadioGroupPrimitive.Item>
|
|
40
|
-
)
|
|
41
|
-
})
|
|
42
|
-
RadioGroupItem.displayName = RadioGroupPrimitive.Item.displayName
|
|
43
|
-
|
|
44
|
-
export { RadioGroup, RadioGroupItem }
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
'use client'
|
|
2
|
-
|
|
3
|
-
import * as React from 'react'
|
|
4
|
-
import * as SeparatorPrimitive from '@radix-ui/react-separator'
|
|
5
|
-
|
|
6
|
-
import { cn } from '@/lib/utils'
|
|
7
|
-
|
|
8
|
-
const Separator = React.forwardRef<
|
|
9
|
-
React.ElementRef<typeof SeparatorPrimitive.Root>,
|
|
10
|
-
React.ComponentPropsWithoutRef<typeof SeparatorPrimitive.Root>
|
|
11
|
-
>(
|
|
12
|
-
(
|
|
13
|
-
{ className, orientation = 'horizontal', decorative = true, ...props },
|
|
14
|
-
ref
|
|
15
|
-
) => (
|
|
16
|
-
<SeparatorPrimitive.Root
|
|
17
|
-
ref={ref}
|
|
18
|
-
decorative={decorative}
|
|
19
|
-
orientation={orientation}
|
|
20
|
-
className={cn(
|
|
21
|
-
'shrink-0 bg-border',
|
|
22
|
-
orientation === 'horizontal' ? 'h-[1px] w-full' : 'h-full w-[1px]',
|
|
23
|
-
className
|
|
24
|
-
)}
|
|
25
|
-
{...props}
|
|
26
|
-
/>
|
|
27
|
-
)
|
|
28
|
-
)
|
|
29
|
-
Separator.displayName = SeparatorPrimitive.Root.displayName
|
|
30
|
-
|
|
31
|
-
export { Separator }
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { cn } from '@/lib/utils'
|
|
2
|
-
|
|
3
|
-
function Skeleton({
|
|
4
|
-
className,
|
|
5
|
-
...props
|
|
6
|
-
}: React.HTMLAttributes<HTMLDivElement>) {
|
|
7
|
-
return (
|
|
8
|
-
<div
|
|
9
|
-
className={cn('animate-pulse rounded-md bg-muted', className)}
|
|
10
|
-
{...props}
|
|
11
|
-
/>
|
|
12
|
-
)
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export { Skeleton }
|
|
@@ -1,157 +0,0 @@
|
|
|
1
|
-
'use client'
|
|
2
|
-
|
|
3
|
-
import { LaptopIcon, Moon, Sun } from 'lucide-react'
|
|
4
|
-
import { useTheme } from 'next-themes'
|
|
5
|
-
import * as React from 'react'
|
|
6
|
-
|
|
7
|
-
import { Button } from '@/components/ui/button'
|
|
8
|
-
import {
|
|
9
|
-
DropdownMenu,
|
|
10
|
-
DropdownMenuContent,
|
|
11
|
-
DropdownMenuItem,
|
|
12
|
-
DropdownMenuTrigger,
|
|
13
|
-
} from '@/components/ui/dropdown-menu'
|
|
14
|
-
import { Label } from '@/components/ui/label'
|
|
15
|
-
import { RadioGroup, RadioGroupItem } from '@/components/ui/radio-group'
|
|
16
|
-
import {
|
|
17
|
-
Tooltip,
|
|
18
|
-
TooltipContent,
|
|
19
|
-
TooltipProvider,
|
|
20
|
-
TooltipTrigger,
|
|
21
|
-
} from '@/components/ui/tooltip'
|
|
22
|
-
import { cn } from '@/lib/utils'
|
|
23
|
-
|
|
24
|
-
export function ModeDropdown({ className }: { className?: string }) {
|
|
25
|
-
const { setTheme, theme } = useTheme()
|
|
26
|
-
const [mounted, setMounted] = React.useState(false)
|
|
27
|
-
|
|
28
|
-
React.useEffect(() => {
|
|
29
|
-
setMounted(true)
|
|
30
|
-
}, [])
|
|
31
|
-
|
|
32
|
-
if (!mounted) {
|
|
33
|
-
return null
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
return (
|
|
37
|
-
<DropdownMenu>
|
|
38
|
-
<DropdownMenuTrigger asChild>
|
|
39
|
-
<Button
|
|
40
|
-
variant="outline"
|
|
41
|
-
className={cn('bg-background/5', className)}
|
|
42
|
-
size="icon"
|
|
43
|
-
>
|
|
44
|
-
<Sun className="h-[1.2rem] w-[1.2rem] rotate-0 scale-100 transition-all dark:-rotate-90 dark:scale-0" />
|
|
45
|
-
<Moon className="absolute h-[1.2rem] w-[1.2rem] rotate-90 scale-0 transition-all dark:rotate-0 dark:scale-100" />
|
|
46
|
-
<span className="sr-only">Toggle theme</span>
|
|
47
|
-
</Button>
|
|
48
|
-
</DropdownMenuTrigger>
|
|
49
|
-
<DropdownMenuContent align="end">
|
|
50
|
-
<DropdownMenuItem onClick={() => setTheme('light')}>
|
|
51
|
-
Light
|
|
52
|
-
</DropdownMenuItem>
|
|
53
|
-
<DropdownMenuItem onClick={() => setTheme('dark')}>
|
|
54
|
-
Dark
|
|
55
|
-
</DropdownMenuItem>
|
|
56
|
-
<DropdownMenuItem onClick={() => setTheme('system')}>
|
|
57
|
-
System
|
|
58
|
-
</DropdownMenuItem>
|
|
59
|
-
</DropdownMenuContent>
|
|
60
|
-
</DropdownMenu>
|
|
61
|
-
)
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
export function ModeSelector({
|
|
65
|
-
className,
|
|
66
|
-
iconClassName,
|
|
67
|
-
}: {
|
|
68
|
-
className?: string
|
|
69
|
-
iconClassName?: string
|
|
70
|
-
}) {
|
|
71
|
-
const { theme, setTheme } = useTheme()
|
|
72
|
-
const [mounted, setMounted] = React.useState(false)
|
|
73
|
-
|
|
74
|
-
React.useEffect(() => {
|
|
75
|
-
setMounted(true)
|
|
76
|
-
}, [])
|
|
77
|
-
|
|
78
|
-
if (!mounted) {
|
|
79
|
-
return null
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
return (
|
|
83
|
-
<TooltipProvider>
|
|
84
|
-
<RadioGroup
|
|
85
|
-
value={theme}
|
|
86
|
-
defaultValue="system"
|
|
87
|
-
className={cn(
|
|
88
|
-
'flex gap-0 rounded-3xl border bg-background/65 backdrop-blur-2xl',
|
|
89
|
-
className
|
|
90
|
-
)}
|
|
91
|
-
>
|
|
92
|
-
<Tooltip>
|
|
93
|
-
<TooltipTrigger asChild>
|
|
94
|
-
<Label
|
|
95
|
-
htmlFor="light"
|
|
96
|
-
className="flex flex-col items-center justify-between rounded-full bg-popover p-2 hover:bg-accent hover:text-accent-foreground [&:has([data-state=checked])]:bg-accent"
|
|
97
|
-
onClick={() => setTheme('light')}
|
|
98
|
-
>
|
|
99
|
-
<RadioGroupItem
|
|
100
|
-
value="light"
|
|
101
|
-
id="light"
|
|
102
|
-
className="sr-only"
|
|
103
|
-
aria-label="light theme"
|
|
104
|
-
/>
|
|
105
|
-
<Sun className={cn('size-4', iconClassName)} />
|
|
106
|
-
</Label>
|
|
107
|
-
</TooltipTrigger>
|
|
108
|
-
<TooltipContent side="bottom" className="text-xs" showArrow={true}>
|
|
109
|
-
<p>Light</p>
|
|
110
|
-
</TooltipContent>
|
|
111
|
-
</Tooltip>
|
|
112
|
-
|
|
113
|
-
<Tooltip>
|
|
114
|
-
<TooltipTrigger asChild>
|
|
115
|
-
<Label
|
|
116
|
-
htmlFor="dark"
|
|
117
|
-
className="flex flex-col items-center justify-between rounded-full bg-popover p-2 hover:bg-accent hover:text-accent-foreground [&:has([data-state=checked])]:bg-accent"
|
|
118
|
-
onClick={() => setTheme('dark')}
|
|
119
|
-
>
|
|
120
|
-
<RadioGroupItem
|
|
121
|
-
value="dark"
|
|
122
|
-
id="dark"
|
|
123
|
-
className="sr-only"
|
|
124
|
-
aria-label="dark theme"
|
|
125
|
-
/>
|
|
126
|
-
<Moon className={cn('size-4', iconClassName)} />
|
|
127
|
-
</Label>
|
|
128
|
-
</TooltipTrigger>
|
|
129
|
-
<TooltipContent side="bottom" className="text-xs" showArrow={true}>
|
|
130
|
-
<p>Dark</p>
|
|
131
|
-
</TooltipContent>
|
|
132
|
-
</Tooltip>
|
|
133
|
-
|
|
134
|
-
<Tooltip>
|
|
135
|
-
<TooltipTrigger asChild>
|
|
136
|
-
<Label
|
|
137
|
-
htmlFor="system"
|
|
138
|
-
className="flex flex-col items-center justify-between rounded-full bg-popover p-2 hover:bg-accent hover:text-accent-foreground [&:has([data-state=checked])]:bg-accent"
|
|
139
|
-
onClick={() => setTheme('system')}
|
|
140
|
-
>
|
|
141
|
-
<RadioGroupItem
|
|
142
|
-
value="system"
|
|
143
|
-
id="system"
|
|
144
|
-
className="sr-only"
|
|
145
|
-
aria-label="system theme"
|
|
146
|
-
/>
|
|
147
|
-
<LaptopIcon className={cn('size-4', iconClassName)} />
|
|
148
|
-
</Label>
|
|
149
|
-
</TooltipTrigger>
|
|
150
|
-
<TooltipContent side="bottom" className="text-xs" showArrow={true}>
|
|
151
|
-
<p>System</p>
|
|
152
|
-
</TooltipContent>
|
|
153
|
-
</Tooltip>
|
|
154
|
-
</RadioGroup>
|
|
155
|
-
</TooltipProvider>
|
|
156
|
-
)
|
|
157
|
-
}
|
|
@@ -1,129 +0,0 @@
|
|
|
1
|
-
'use client'
|
|
2
|
-
|
|
3
|
-
import * as ToastPrimitives from '@radix-ui/react-toast'
|
|
4
|
-
import { type VariantProps, cva } from 'class-variance-authority'
|
|
5
|
-
import { X } from 'lucide-react'
|
|
6
|
-
import * as React from 'react'
|
|
7
|
-
|
|
8
|
-
import { cn } from '@/lib/utils'
|
|
9
|
-
|
|
10
|
-
const ToastProvider = ToastPrimitives.Provider
|
|
11
|
-
|
|
12
|
-
const ToastViewport = React.forwardRef<
|
|
13
|
-
React.ElementRef<typeof ToastPrimitives.Viewport>,
|
|
14
|
-
React.ComponentPropsWithoutRef<typeof ToastPrimitives.Viewport>
|
|
15
|
-
>(({ className, ...props }, ref) => (
|
|
16
|
-
<ToastPrimitives.Viewport
|
|
17
|
-
ref={ref}
|
|
18
|
-
className={cn(
|
|
19
|
-
'fixed top-0 z-[100] flex max-h-screen w-full flex-col-reverse p-4 sm:bottom-0 sm:right-0 sm:top-auto sm:flex-col md:max-w-[420px]',
|
|
20
|
-
className
|
|
21
|
-
)}
|
|
22
|
-
{...props}
|
|
23
|
-
/>
|
|
24
|
-
))
|
|
25
|
-
ToastViewport.displayName = ToastPrimitives.Viewport.displayName
|
|
26
|
-
|
|
27
|
-
const toastVariants = cva(
|
|
28
|
-
'group data-[state=closed]:fade-out-80 data-[state=closed]:slide-out-to-right-full data-[state=open]:slide-in-from-top-full data-[state=open]:sm:slide-in-from-bottom-full pointer-events-auto relative flex w-full items-center justify-between space-x-4 overflow-hidden rounded-md border p-6 pr-8 shadow-lg transition-all data-[swipe=cancel]:translate-x-0 data-[swipe=end]:translate-x-[var(--radix-toast-swipe-end-x)] data-[swipe=move]:translate-x-[var(--radix-toast-swipe-move-x)] data-[state=closed]:animate-out data-[state=open]:animate-in data-[swipe=end]:animate-out data-[swipe=move]:transition-none',
|
|
29
|
-
{
|
|
30
|
-
variants: {
|
|
31
|
-
variant: {
|
|
32
|
-
default: 'border bg-background text-foreground',
|
|
33
|
-
destructive:
|
|
34
|
-
'destructive group border-destructive bg-destructive text-destructive-foreground',
|
|
35
|
-
},
|
|
36
|
-
},
|
|
37
|
-
defaultVariants: {
|
|
38
|
-
variant: 'default',
|
|
39
|
-
},
|
|
40
|
-
}
|
|
41
|
-
)
|
|
42
|
-
|
|
43
|
-
const Toast = React.forwardRef<
|
|
44
|
-
React.ElementRef<typeof ToastPrimitives.Root>,
|
|
45
|
-
React.ComponentPropsWithoutRef<typeof ToastPrimitives.Root> &
|
|
46
|
-
VariantProps<typeof toastVariants>
|
|
47
|
-
>(({ className, variant, ...props }, ref) => {
|
|
48
|
-
return (
|
|
49
|
-
<ToastPrimitives.Root
|
|
50
|
-
ref={ref}
|
|
51
|
-
className={cn(toastVariants({ variant }), className)}
|
|
52
|
-
{...props}
|
|
53
|
-
/>
|
|
54
|
-
)
|
|
55
|
-
})
|
|
56
|
-
Toast.displayName = ToastPrimitives.Root.displayName
|
|
57
|
-
|
|
58
|
-
const ToastAction = React.forwardRef<
|
|
59
|
-
React.ElementRef<typeof ToastPrimitives.Action>,
|
|
60
|
-
React.ComponentPropsWithoutRef<typeof ToastPrimitives.Action>
|
|
61
|
-
>(({ className, ...props }, ref) => (
|
|
62
|
-
<ToastPrimitives.Action
|
|
63
|
-
ref={ref}
|
|
64
|
-
className={cn(
|
|
65
|
-
'inline-flex h-8 shrink-0 items-center justify-center rounded-md border bg-transparent px-3 text-sm font-medium ring-offset-background transition-colors hover:bg-secondary focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 group-[.destructive]:border-muted/40 group-[.destructive]:hover:border-destructive/30 group-[.destructive]:hover:bg-destructive group-[.destructive]:hover:text-destructive-foreground group-[.destructive]:focus:ring-destructive',
|
|
66
|
-
className
|
|
67
|
-
)}
|
|
68
|
-
{...props}
|
|
69
|
-
/>
|
|
70
|
-
))
|
|
71
|
-
ToastAction.displayName = ToastPrimitives.Action.displayName
|
|
72
|
-
|
|
73
|
-
const ToastClose = React.forwardRef<
|
|
74
|
-
React.ElementRef<typeof ToastPrimitives.Close>,
|
|
75
|
-
React.ComponentPropsWithoutRef<typeof ToastPrimitives.Close>
|
|
76
|
-
>(({ className, ...props }, ref) => (
|
|
77
|
-
<ToastPrimitives.Close
|
|
78
|
-
ref={ref}
|
|
79
|
-
className={cn(
|
|
80
|
-
'absolute right-2 top-2 rounded-md p-1 text-foreground/50 opacity-0 transition-opacity hover:text-foreground focus:opacity-100 focus:outline-none focus:ring-2 group-hover:opacity-100 group-[.destructive]:text-red-300 group-[.destructive]:hover:text-red-50 group-[.destructive]:focus:ring-red-400 group-[.destructive]:focus:ring-offset-red-600',
|
|
81
|
-
className
|
|
82
|
-
)}
|
|
83
|
-
toast-close=""
|
|
84
|
-
{...props}
|
|
85
|
-
>
|
|
86
|
-
<X className="h-4 w-4" />
|
|
87
|
-
</ToastPrimitives.Close>
|
|
88
|
-
))
|
|
89
|
-
ToastClose.displayName = ToastPrimitives.Close.displayName
|
|
90
|
-
|
|
91
|
-
const ToastTitle = React.forwardRef<
|
|
92
|
-
React.ElementRef<typeof ToastPrimitives.Title>,
|
|
93
|
-
React.ComponentPropsWithoutRef<typeof ToastPrimitives.Title>
|
|
94
|
-
>(({ className, ...props }, ref) => (
|
|
95
|
-
<ToastPrimitives.Title
|
|
96
|
-
ref={ref}
|
|
97
|
-
className={cn('text-sm font-semibold', className)}
|
|
98
|
-
{...props}
|
|
99
|
-
/>
|
|
100
|
-
))
|
|
101
|
-
ToastTitle.displayName = ToastPrimitives.Title.displayName
|
|
102
|
-
|
|
103
|
-
const ToastDescription = React.forwardRef<
|
|
104
|
-
React.ElementRef<typeof ToastPrimitives.Description>,
|
|
105
|
-
React.ComponentPropsWithoutRef<typeof ToastPrimitives.Description>
|
|
106
|
-
>(({ className, ...props }, ref) => (
|
|
107
|
-
<ToastPrimitives.Description
|
|
108
|
-
ref={ref}
|
|
109
|
-
className={cn('text-sm opacity-90', className)}
|
|
110
|
-
{...props}
|
|
111
|
-
/>
|
|
112
|
-
))
|
|
113
|
-
ToastDescription.displayName = ToastPrimitives.Description.displayName
|
|
114
|
-
|
|
115
|
-
type ToastProps = React.ComponentPropsWithoutRef<typeof Toast>
|
|
116
|
-
|
|
117
|
-
type ToastActionElement = React.ReactElement<typeof ToastAction>
|
|
118
|
-
|
|
119
|
-
export {
|
|
120
|
-
type ToastProps,
|
|
121
|
-
type ToastActionElement,
|
|
122
|
-
ToastProvider,
|
|
123
|
-
ToastViewport,
|
|
124
|
-
Toast,
|
|
125
|
-
ToastTitle,
|
|
126
|
-
ToastDescription,
|
|
127
|
-
ToastClose,
|
|
128
|
-
ToastAction,
|
|
129
|
-
}
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
'use client'
|
|
2
|
-
|
|
3
|
-
import {
|
|
4
|
-
Toast,
|
|
5
|
-
ToastClose,
|
|
6
|
-
ToastDescription,
|
|
7
|
-
ToastProvider,
|
|
8
|
-
ToastTitle,
|
|
9
|
-
ToastViewport,
|
|
10
|
-
} from '@/components/ui/toast'
|
|
11
|
-
import { useToast } from '@/hooks/use-toast'
|
|
12
|
-
|
|
13
|
-
export function Toaster() {
|
|
14
|
-
const { toasts } = useToast()
|
|
15
|
-
|
|
16
|
-
return (
|
|
17
|
-
<ToastProvider>
|
|
18
|
-
{toasts.map(({ id, title, description, action, ...props }) => (
|
|
19
|
-
<Toast key={id} {...props}>
|
|
20
|
-
<div className="grid gap-1">
|
|
21
|
-
{title && <ToastTitle>{title}</ToastTitle>}
|
|
22
|
-
{description && <ToastDescription>{description}</ToastDescription>}
|
|
23
|
-
</div>
|
|
24
|
-
{action}
|
|
25
|
-
<ToastClose />
|
|
26
|
-
</Toast>
|
|
27
|
-
))}
|
|
28
|
-
<ToastViewport />
|
|
29
|
-
</ToastProvider>
|
|
30
|
-
)
|
|
31
|
-
}
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
'use client'
|
|
2
|
-
|
|
3
|
-
import * as TooltipPrimitive from '@radix-ui/react-tooltip'
|
|
4
|
-
import * as React from 'react'
|
|
5
|
-
|
|
6
|
-
import { cn } from '@/lib/utils'
|
|
7
|
-
|
|
8
|
-
const TooltipProvider = TooltipPrimitive.Provider
|
|
9
|
-
|
|
10
|
-
const Tooltip = TooltipPrimitive.Root
|
|
11
|
-
|
|
12
|
-
const TooltipTrigger = TooltipPrimitive.Trigger
|
|
13
|
-
|
|
14
|
-
const TooltipContent = React.forwardRef<
|
|
15
|
-
React.ElementRef<typeof TooltipPrimitive.Content>,
|
|
16
|
-
React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Content> & {
|
|
17
|
-
showArrow?: boolean
|
|
18
|
-
}
|
|
19
|
-
>(({ className, sideOffset = 4, showArrow = false, ...props }, ref) => (
|
|
20
|
-
<TooltipPrimitive.Portal>
|
|
21
|
-
<TooltipPrimitive.Content
|
|
22
|
-
ref={ref}
|
|
23
|
-
sideOffset={sideOffset}
|
|
24
|
-
className={cn(
|
|
25
|
-
'relative z-50 max-w-[280px] rounded-lg border border-border bg-popover px-3 py-1.5 text-sm text-popover-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',
|
|
26
|
-
className
|
|
27
|
-
)}
|
|
28
|
-
{...props}
|
|
29
|
-
>
|
|
30
|
-
{props.children}
|
|
31
|
-
{showArrow && (
|
|
32
|
-
<TooltipPrimitive.Arrow className="-my-px fill-popover drop-shadow-[0_1px_0_hsl(var(--border))]" />
|
|
33
|
-
)}
|
|
34
|
-
</TooltipPrimitive.Content>
|
|
35
|
-
</TooltipPrimitive.Portal>
|
|
36
|
-
))
|
|
37
|
-
TooltipContent.displayName = TooltipPrimitive.Content.displayName
|
|
38
|
-
|
|
39
|
-
export { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger }
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
// components/UnstyledLink.tsx
|
|
2
|
-
import { cn } from '@/lib/utils'
|
|
3
|
-
import Link, { LinkProps } from 'next/link'
|
|
4
|
-
|
|
5
|
-
export type UnstyledLinkProps = {
|
|
6
|
-
href: string
|
|
7
|
-
children: React.ReactNode
|
|
8
|
-
openNewTab?: boolean
|
|
9
|
-
className?: string
|
|
10
|
-
} & React.ComponentPropsWithoutRef<'a'> &
|
|
11
|
-
LinkProps
|
|
12
|
-
|
|
13
|
-
export default function CLink({
|
|
14
|
-
children,
|
|
15
|
-
href,
|
|
16
|
-
openNewTab,
|
|
17
|
-
className,
|
|
18
|
-
...rest
|
|
19
|
-
}: UnstyledLinkProps) {
|
|
20
|
-
const isNewTab =
|
|
21
|
-
openNewTab !== undefined
|
|
22
|
-
? openNewTab
|
|
23
|
-
: href && !href.startsWith('/') && !href.startsWith('#')
|
|
24
|
-
|
|
25
|
-
if (!isNewTab) {
|
|
26
|
-
return (
|
|
27
|
-
<Link href={href}>
|
|
28
|
-
<a {...rest} className={className}>
|
|
29
|
-
{children}
|
|
30
|
-
</a>
|
|
31
|
-
</Link>
|
|
32
|
-
)
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
return (
|
|
36
|
-
<a
|
|
37
|
-
target="_blank"
|
|
38
|
-
rel="noopener noreferrer"
|
|
39
|
-
href={href}
|
|
40
|
-
{...rest}
|
|
41
|
-
className={cn(className, 'cursor-newtab')}
|
|
42
|
-
>
|
|
43
|
-
{children}
|
|
44
|
-
</a>
|
|
45
|
-
)
|
|
46
|
-
}
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
import NextImageComponent from 'next/image'
|
|
2
|
-
import type React from 'react'
|
|
3
|
-
import type { ImgProps } from '@/types'
|
|
4
|
-
import { cleanSrc, shimmer, svgToBase64 } from '@/lib/utils'
|
|
5
|
-
// auto generate placeholder image
|
|
6
|
-
|
|
7
|
-
function Img({ src, width, height, alt, ...props }: ImgProps) {
|
|
8
|
-
return (
|
|
9
|
-
<NextImageComponent
|
|
10
|
-
width={width || 500}
|
|
11
|
-
height={height || width || 300}
|
|
12
|
-
alt={
|
|
13
|
-
alt ||
|
|
14
|
-
src.substring(src.lastIndexOf('/') + 1).slice(0, 20) ||
|
|
15
|
-
'Picture Element'
|
|
16
|
-
}
|
|
17
|
-
src={cleanSrc(src as string)}
|
|
18
|
-
draggable="false"
|
|
19
|
-
sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw"
|
|
20
|
-
{...(props as any)}
|
|
21
|
-
/>
|
|
22
|
-
)
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
export const Image: React.FC<ImgProps> = ({ placeholder, ...props }) => {
|
|
26
|
-
const imgComp: Record<string, React.ReactNode> = {
|
|
27
|
-
blur: <BlurImg {...props} />,
|
|
28
|
-
shimmer: (
|
|
29
|
-
<Img
|
|
30
|
-
{...props}
|
|
31
|
-
placeholder={`data:image/svg+xml;base64,${svgToBase64(
|
|
32
|
-
shimmer(500, 300)
|
|
33
|
-
)}`}
|
|
34
|
-
alt={props.alt || ''}
|
|
35
|
-
/>
|
|
36
|
-
),
|
|
37
|
-
}
|
|
38
|
-
return (
|
|
39
|
-
(placeholder && imgComp[placeholder]) || (
|
|
40
|
-
<Img placeholder={placeholder} {...props} alt={props.alt || ''} />
|
|
41
|
-
)
|
|
42
|
-
)
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
const BlurImg = async (props: ImgProps) => {
|
|
46
|
-
const blurData = await import('@/actions/placeholder').then((f) =>
|
|
47
|
-
f.getPlaceholderImage(props.src)
|
|
48
|
-
)
|
|
49
|
-
return (
|
|
50
|
-
<Img
|
|
51
|
-
placeholder="blur"
|
|
52
|
-
blurDataURL={blurData}
|
|
53
|
-
alt={props.alt || ''}
|
|
54
|
-
{...props}
|
|
55
|
-
/>
|
|
56
|
-
)
|
|
57
|
-
}
|
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
'use client'
|
|
2
|
-
import { useState } from 'react'
|
|
3
|
-
import { Skeleton } from '@/components/ui/skeleton'
|
|
4
|
-
import { useLazyLoad } from '@/hooks/use-lazy-load'
|
|
5
|
-
import { cn } from '@/lib/utils'
|
|
6
|
-
// lazy loads imgs with a placeholder on the client side
|
|
7
|
-
// does not optimizes images, just lazy loads them client side with a skeleton placeholder
|
|
8
|
-
interface ResponsiveImageProps
|
|
9
|
-
extends React.ImgHTMLAttributes<HTMLImageElement> {
|
|
10
|
-
src: string
|
|
11
|
-
alt: string
|
|
12
|
-
width: number
|
|
13
|
-
height: number
|
|
14
|
-
className?: string
|
|
15
|
-
skeletonClassName?: string
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export function Img({
|
|
19
|
-
src,
|
|
20
|
-
alt,
|
|
21
|
-
width,
|
|
22
|
-
height,
|
|
23
|
-
className = '',
|
|
24
|
-
skeletonClassName = '',
|
|
25
|
-
...restProps
|
|
26
|
-
}: ResponsiveImageProps) {
|
|
27
|
-
const [imageRef, isInView] = useLazyLoad()
|
|
28
|
-
const [isLoaded, setIsLoaded] = useState(false)
|
|
29
|
-
const [hasError, setHasError] = useState(false)
|
|
30
|
-
const aspectRatio = `${width} / ${height}`
|
|
31
|
-
const showAltText = width > 100 && height > 100
|
|
32
|
-
|
|
33
|
-
return (
|
|
34
|
-
<div
|
|
35
|
-
ref={imageRef}
|
|
36
|
-
className={cn('relative w-full overflow-hidden', className)}
|
|
37
|
-
style={{
|
|
38
|
-
aspectRatio: aspectRatio,
|
|
39
|
-
maxWidth: `${width}px`,
|
|
40
|
-
}}
|
|
41
|
-
>
|
|
42
|
-
{/* fallback for users with JS disabled */}
|
|
43
|
-
<noscript>
|
|
44
|
-
<img
|
|
45
|
-
{...restProps}
|
|
46
|
-
src={src}
|
|
47
|
-
alt={alt}
|
|
48
|
-
width={width}
|
|
49
|
-
height={height}
|
|
50
|
-
className="absolute left-0 top-0 h-full w-full object-cover"
|
|
51
|
-
/>
|
|
52
|
-
</noscript>
|
|
53
|
-
|
|
54
|
-
{isInView ? (
|
|
55
|
-
<img
|
|
56
|
-
{...restProps}
|
|
57
|
-
src={src}
|
|
58
|
-
alt={alt}
|
|
59
|
-
width={width}
|
|
60
|
-
height={height}
|
|
61
|
-
className={cn(
|
|
62
|
-
'absolute left-0 top-0 h-full w-full object-cover transition-opacity duration-300',
|
|
63
|
-
isLoaded && !hasError ? 'opacity-100' : 'opacity-0'
|
|
64
|
-
)}
|
|
65
|
-
onLoad={() => setIsLoaded(true)}
|
|
66
|
-
onError={() => setHasError(true)}
|
|
67
|
-
loading="lazy"
|
|
68
|
-
/>
|
|
69
|
-
) : null}
|
|
70
|
-
{!isLoaded && (
|
|
71
|
-
<Skeleton
|
|
72
|
-
className={cn(
|
|
73
|
-
'absolute left-0 top-0 h-full w-full rounded-none',
|
|
74
|
-
skeletonClassName,
|
|
75
|
-
hasError && '[animation-play-state:paused]'
|
|
76
|
-
)}
|
|
77
|
-
/>
|
|
78
|
-
)}
|
|
79
|
-
{hasError && (
|
|
80
|
-
<div className="absolute inset-0 flex flex-col items-center justify-center text-red-600">
|
|
81
|
-
<svg
|
|
82
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
83
|
-
width="24"
|
|
84
|
-
height="24"
|
|
85
|
-
viewBox="0 0 24 24"
|
|
86
|
-
fill="none"
|
|
87
|
-
stroke="currentColor"
|
|
88
|
-
stroke-width="2"
|
|
89
|
-
stroke-linecap="round"
|
|
90
|
-
stroke-linejoin="round"
|
|
91
|
-
className="h-[30%] max-h-[40px] min-h-[30px] w-[30%] min-w-[30px] max-w-[40px]"
|
|
92
|
-
>
|
|
93
|
-
<circle cx="12" cy="12" r="10"></circle>
|
|
94
|
-
<line x1="12" y1="8" x2="12" y2="12"></line>
|
|
95
|
-
<line x1="12" y1="16" x2="12.01" y2="16"></line>
|
|
96
|
-
</svg>
|
|
97
|
-
{showAltText && (
|
|
98
|
-
<span className="mt-2 px-2 text-center text-sm">{alt}</span>
|
|
99
|
-
)}
|
|
100
|
-
</div>
|
|
101
|
-
)}
|
|
102
|
-
</div>
|
|
103
|
-
)
|
|
104
|
-
}
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import { Icons } from '@/components/utils/icons'
|
|
2
|
-
import { cn } from '@/lib/utils'
|
|
3
|
-
// a simple spinner fallback for suspanse components
|
|
4
|
-
export const SuspanseFallback = ({
|
|
5
|
-
className,
|
|
6
|
-
spinnerClassName,
|
|
7
|
-
}: {
|
|
8
|
-
className?: string
|
|
9
|
-
spinnerClassName?: string
|
|
10
|
-
}) => {
|
|
11
|
-
if (!Icons?.spinner)
|
|
12
|
-
return (
|
|
13
|
-
<div className={cn('grid h-full w-full place-items-center', className)}>
|
|
14
|
-
<div
|
|
15
|
-
className={cn(
|
|
16
|
-
'size-10 animate-spin rounded-full border-2 border-primary border-t-transparent',
|
|
17
|
-
spinnerClassName
|
|
18
|
-
)}
|
|
19
|
-
/>
|
|
20
|
-
</div>
|
|
21
|
-
)
|
|
22
|
-
return (
|
|
23
|
-
<div className={cn('grid h-full w-full place-items-center', className)}>
|
|
24
|
-
<Icons.spinner
|
|
25
|
-
className={cn('size-10 animate-spin text-primary', spinnerClassName)}
|
|
26
|
-
/>
|
|
27
|
-
</div>
|
|
28
|
-
)
|
|
29
|
-
}
|