@traky-app/ui 0.0.0-stage → 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/README.md +30 -2
- package/package.json +26 -4
- package/registry/registry.json +6 -0
- package/registry/traky/hooks/use-mobile.ts +19 -0
- package/registry/traky/json/accordion.json +18 -0
- package/registry/traky/json/alert-dialog.json +20 -0
- package/registry/traky/json/alert.json +17 -0
- package/registry/traky/json/animated-beam.json +14 -0
- package/registry/traky/json/animated-list.json +14 -0
- package/registry/traky/json/avatar.json +17 -0
- package/registry/traky/json/badge.json +18 -0
- package/registry/traky/json/bento-grid.json +20 -0
- package/registry/traky/json/breadcrumb.json +18 -0
- package/registry/traky/json/bubble.json +18 -0
- package/registry/traky/json/button-group.json +21 -0
- package/registry/traky/json/button.json +18 -0
- package/registry/traky/json/calendar.json +21 -0
- package/registry/traky/json/card.json +14 -0
- package/registry/traky/json/carousel.json +21 -0
- package/registry/traky/json/chart.json +17 -0
- package/registry/traky/json/checkbox.json +18 -0
- package/registry/traky/json/checkpoint.json +22 -0
- package/registry/traky/json/code-block.json +21 -0
- package/registry/traky/json/collapsible.json +17 -0
- package/registry/traky/json/command.json +22 -0
- package/registry/traky/json/context-menu.json +18 -0
- package/registry/traky/json/dialog.json +18 -0
- package/registry/traky/json/drawer.json +17 -0
- package/registry/traky/json/dropdown-menu.json +18 -0
- package/registry/traky/json/empty.json +17 -0
- package/registry/traky/json/field.json +21 -0
- package/registry/traky/json/globe.json +17 -0
- package/registry/traky/json/hook-use-mobile.json +14 -0
- package/registry/traky/json/hover-card.json +17 -0
- package/registry/traky/json/input-group.json +22 -0
- package/registry/traky/json/input-otp.json +18 -0
- package/registry/traky/json/input.json +17 -0
- package/registry/traky/json/item.json +21 -0
- package/registry/traky/json/kbd.json +14 -0
- package/registry/traky/json/label.json +17 -0
- package/registry/traky/json/lib-disable-input-autofill.json +14 -0
- package/registry/traky/json/lib-sidebar-persistence.json +14 -0
- package/registry/traky/json/lib-utils.json +18 -0
- package/registry/traky/json/map.json +19 -0
- package/registry/traky/json/marker.json +18 -0
- package/registry/traky/json/marquee.json +14 -0
- package/registry/traky/json/message.json +14 -0
- package/registry/traky/json/navigation-menu.json +19 -0
- package/registry/traky/json/number-ticker.json +14 -0
- package/registry/traky/json/pagination.json +20 -0
- package/registry/traky/json/popover.json +17 -0
- package/registry/traky/json/progress.json +17 -0
- package/registry/traky/json/select.json +18 -0
- package/registry/traky/json/separator.json +17 -0
- package/registry/traky/json/sheet.json +18 -0
- package/registry/traky/json/sidebar.json +29 -0
- package/registry/traky/json/skeleton.json +14 -0
- package/registry/traky/json/sonner.json +18 -0
- package/registry/traky/json/spinner.json +17 -0
- package/registry/traky/json/switch.json +17 -0
- package/registry/traky/json/table.json +14 -0
- package/registry/traky/json/tabs.json +17 -0
- package/registry/traky/json/textarea.json +17 -0
- package/registry/traky/json/toggle-group.json +21 -0
- package/registry/traky/json/toggle.json +18 -0
- package/registry/traky/json/tooltip.json +17 -0
- package/registry/traky/json/trace.json +20 -0
- package/registry/traky/lib/disable-input-autofill.ts +23 -0
- package/registry/traky/lib/sidebar-persistence.ts +76 -0
- package/registry/traky/lib/utils.ts +6 -0
- package/registry/traky/registry.json +637 -0
- package/registry/traky/ui/accordion.tsx +65 -0
- package/registry/traky/ui/alert-dialog.tsx +163 -0
- package/registry/traky/ui/alert.tsx +66 -0
- package/registry/traky/ui/animated-beam.tsx +185 -0
- package/registry/traky/ui/animated-list.tsx +71 -0
- package/registry/traky/ui/avatar.tsx +53 -0
- package/registry/traky/ui/badge.tsx +46 -0
- package/registry/traky/ui/bento-grid.tsx +109 -0
- package/registry/traky/ui/breadcrumb.tsx +108 -0
- package/registry/traky/ui/bubble.tsx +125 -0
- package/registry/traky/ui/button-group.tsx +83 -0
- package/registry/traky/ui/button.tsx +64 -0
- package/registry/traky/ui/calendar.tsx +213 -0
- package/registry/traky/ui/card.tsx +92 -0
- package/registry/traky/ui/carousel.tsx +240 -0
- package/registry/traky/ui/chart.tsx +380 -0
- package/registry/traky/ui/checkbox.tsx +31 -0
- package/registry/traky/ui/checkpoint.tsx +94 -0
- package/registry/traky/ui/code-block.tsx +232 -0
- package/registry/traky/ui/collapsible.tsx +33 -0
- package/registry/traky/ui/command.tsx +190 -0
- package/registry/traky/ui/context-menu.tsx +251 -0
- package/registry/traky/ui/dialog.tsx +142 -0
- package/registry/traky/ui/drawer.tsx +135 -0
- package/registry/traky/ui/dropdown-menu.tsx +256 -0
- package/registry/traky/ui/empty.tsx +104 -0
- package/registry/traky/ui/field.tsx +248 -0
- package/registry/traky/ui/globe.tsx +234 -0
- package/registry/traky/ui/hover-card.tsx +44 -0
- package/registry/traky/ui/input-group.tsx +170 -0
- package/registry/traky/ui/input-otp.tsx +77 -0
- package/registry/traky/ui/input.tsx +24 -0
- package/registry/traky/ui/item.tsx +193 -0
- package/registry/traky/ui/kbd.tsx +28 -0
- package/registry/traky/ui/label.tsx +24 -0
- package/registry/traky/ui/map.tsx +2226 -0
- package/registry/traky/ui/marker.tsx +69 -0
- package/registry/traky/ui/marquee.tsx +74 -0
- package/registry/traky/ui/message.tsx +92 -0
- package/registry/traky/ui/navigation-menu.tsx +169 -0
- package/registry/traky/ui/number-ticker.tsx +90 -0
- package/registry/traky/ui/pagination.tsx +122 -0
- package/registry/traky/ui/popover.tsx +48 -0
- package/registry/traky/ui/progress.tsx +31 -0
- package/registry/traky/ui/select.tsx +193 -0
- package/registry/traky/ui/separator.tsx +28 -0
- package/registry/traky/ui/sheet.tsx +143 -0
- package/registry/traky/ui/sidebar.tsx +764 -0
- package/registry/traky/ui/skeleton.tsx +13 -0
- package/registry/traky/ui/sonner.tsx +71 -0
- package/registry/traky/ui/spinner.tsx +15 -0
- package/registry/traky/ui/switch.tsx +41 -0
- package/registry/traky/ui/table.tsx +116 -0
- package/registry/traky/ui/tabs.tsx +66 -0
- package/registry/traky/ui/textarea.tsx +20 -0
- package/registry/traky/ui/toggle-group.tsx +83 -0
- package/registry/traky/ui/toggle.tsx +47 -0
- package/registry/traky/ui/tooltip.tsx +61 -0
- package/registry/traky/ui/trace.tsx +165 -0
- package/schema/components.json +24 -0
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import * as React from "react"
|
|
2
|
+
import { cva, type VariantProps } from "class-variance-authority"
|
|
3
|
+
import { Slot } from "radix-ui"
|
|
4
|
+
|
|
5
|
+
import { cn } from "@/lib/utils"
|
|
6
|
+
|
|
7
|
+
const markerVariants = cva(
|
|
8
|
+
"group/marker relative flex min-h-4 w-full items-center gap-2 text-left text-sm text-muted-foreground [&_svg:not([class*='size-'])]:size-4 [a]:underline [a]:underline-offset-3 [a]:hover:text-foreground",
|
|
9
|
+
{
|
|
10
|
+
variants: {
|
|
11
|
+
variant: {
|
|
12
|
+
default: "",
|
|
13
|
+
separator:
|
|
14
|
+
"before:mr-1 before:h-px before:min-w-0 before:flex-1 before:bg-border after:ml-1 after:h-px after:min-w-0 after:flex-1 after:bg-border",
|
|
15
|
+
border: "border-b border-border pb-2",
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
}
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
function Marker({
|
|
22
|
+
className,
|
|
23
|
+
variant = "default",
|
|
24
|
+
asChild = false,
|
|
25
|
+
...props
|
|
26
|
+
}: React.ComponentProps<"div"> &
|
|
27
|
+
VariantProps<typeof markerVariants> & {
|
|
28
|
+
asChild?: boolean
|
|
29
|
+
}) {
|
|
30
|
+
const Comp = asChild ? Slot.Root : "div"
|
|
31
|
+
|
|
32
|
+
return (
|
|
33
|
+
<Comp
|
|
34
|
+
data-slot="marker"
|
|
35
|
+
data-variant={variant}
|
|
36
|
+
className={cn(markerVariants({ variant, className }))}
|
|
37
|
+
{...props}
|
|
38
|
+
/>
|
|
39
|
+
)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function MarkerIcon({ className, ...props }: React.ComponentProps<"span">) {
|
|
43
|
+
return (
|
|
44
|
+
<span
|
|
45
|
+
data-slot="marker-icon"
|
|
46
|
+
aria-hidden="true"
|
|
47
|
+
className={cn(
|
|
48
|
+
"size-4 shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
|
49
|
+
className
|
|
50
|
+
)}
|
|
51
|
+
{...props}
|
|
52
|
+
/>
|
|
53
|
+
)
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function MarkerContent({ className, ...props }: React.ComponentProps<"span">) {
|
|
57
|
+
return (
|
|
58
|
+
<span
|
|
59
|
+
data-slot="marker-content"
|
|
60
|
+
className={cn(
|
|
61
|
+
"min-w-0 wrap-break-word group-data-[variant=separator]/marker:flex-none group-data-[variant=separator]/marker:text-center *:[a]:underline *:[a]:underline-offset-3 *:[a]:hover:text-foreground",
|
|
62
|
+
className
|
|
63
|
+
)}
|
|
64
|
+
{...props}
|
|
65
|
+
/>
|
|
66
|
+
)
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export { Marker, MarkerIcon, MarkerContent, markerVariants }
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { ComponentPropsWithoutRef } from "react"
|
|
2
|
+
|
|
3
|
+
import { cn } from "@/lib/utils"
|
|
4
|
+
|
|
5
|
+
interface MarqueeProps extends ComponentPropsWithoutRef<"div"> {
|
|
6
|
+
/**
|
|
7
|
+
* Optional CSS class name to apply custom styles
|
|
8
|
+
*/
|
|
9
|
+
className?: string
|
|
10
|
+
/**
|
|
11
|
+
* Whether to reverse the animation direction
|
|
12
|
+
* @default false
|
|
13
|
+
*/
|
|
14
|
+
reverse?: boolean
|
|
15
|
+
/**
|
|
16
|
+
* Whether to pause the animation on hover
|
|
17
|
+
* @default false
|
|
18
|
+
*/
|
|
19
|
+
pauseOnHover?: boolean
|
|
20
|
+
/**
|
|
21
|
+
* Content to be displayed in the marquee
|
|
22
|
+
*/
|
|
23
|
+
children: React.ReactNode
|
|
24
|
+
/**
|
|
25
|
+
* Whether to animate vertically instead of horizontally
|
|
26
|
+
* @default false
|
|
27
|
+
*/
|
|
28
|
+
vertical?: boolean
|
|
29
|
+
/**
|
|
30
|
+
* Number of times to repeat the content
|
|
31
|
+
* @default 4
|
|
32
|
+
*/
|
|
33
|
+
repeat?: number
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function Marquee({
|
|
37
|
+
className,
|
|
38
|
+
reverse = false,
|
|
39
|
+
pauseOnHover = false,
|
|
40
|
+
children,
|
|
41
|
+
vertical = false,
|
|
42
|
+
repeat = 4,
|
|
43
|
+
...props
|
|
44
|
+
}: MarqueeProps) {
|
|
45
|
+
return (
|
|
46
|
+
<div
|
|
47
|
+
{...props}
|
|
48
|
+
className={cn(
|
|
49
|
+
"group flex [gap:var(--gap)] overflow-hidden p-2 [--duration:40s] [--gap:1rem]",
|
|
50
|
+
{
|
|
51
|
+
"flex-row": !vertical,
|
|
52
|
+
"flex-col": vertical,
|
|
53
|
+
},
|
|
54
|
+
className
|
|
55
|
+
)}
|
|
56
|
+
>
|
|
57
|
+
{Array(repeat)
|
|
58
|
+
.fill(0)
|
|
59
|
+
.map((_, i) => (
|
|
60
|
+
<div
|
|
61
|
+
key={i}
|
|
62
|
+
className={cn("flex shrink-0 justify-around [gap:var(--gap)]", {
|
|
63
|
+
"animate-marquee flex-row": !vertical,
|
|
64
|
+
"animate-marquee-vertical flex-col": vertical,
|
|
65
|
+
"group-hover:[animation-play-state:paused]": pauseOnHover,
|
|
66
|
+
"[animation-direction:reverse]": reverse,
|
|
67
|
+
})}
|
|
68
|
+
>
|
|
69
|
+
{children}
|
|
70
|
+
</div>
|
|
71
|
+
))}
|
|
72
|
+
</div>
|
|
73
|
+
)
|
|
74
|
+
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import * as React from "react"
|
|
2
|
+
|
|
3
|
+
import { cn } from "@/lib/utils"
|
|
4
|
+
|
|
5
|
+
function MessageGroup({ className, ...props }: React.ComponentProps<"div">) {
|
|
6
|
+
return (
|
|
7
|
+
<div
|
|
8
|
+
data-slot="message-group"
|
|
9
|
+
className={cn("flex min-w-0 flex-col gap-2", className)}
|
|
10
|
+
{...props}
|
|
11
|
+
/>
|
|
12
|
+
)
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function Message({
|
|
16
|
+
className,
|
|
17
|
+
align = "start",
|
|
18
|
+
...props
|
|
19
|
+
}: React.ComponentProps<"div"> & { align?: "start" | "end" }) {
|
|
20
|
+
return (
|
|
21
|
+
<div
|
|
22
|
+
data-slot="message"
|
|
23
|
+
data-align={align}
|
|
24
|
+
className={cn(
|
|
25
|
+
"group/message relative flex w-full min-w-0 gap-2 text-sm data-[align=end]:flex-row-reverse",
|
|
26
|
+
className
|
|
27
|
+
)}
|
|
28
|
+
{...props}
|
|
29
|
+
/>
|
|
30
|
+
)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function MessageAvatar({ className, ...props }: React.ComponentProps<"div">) {
|
|
34
|
+
return (
|
|
35
|
+
<div
|
|
36
|
+
data-slot="message-avatar"
|
|
37
|
+
className={cn(
|
|
38
|
+
"flex w-fit min-w-8 shrink-0 items-center justify-center self-end overflow-hidden rounded-full bg-muted group-has-data-[slot=message-footer]/message:-translate-y-8",
|
|
39
|
+
className
|
|
40
|
+
)}
|
|
41
|
+
{...props}
|
|
42
|
+
/>
|
|
43
|
+
)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function MessageContent({ className, ...props }: React.ComponentProps<"div">) {
|
|
47
|
+
return (
|
|
48
|
+
<div
|
|
49
|
+
data-slot="message-content"
|
|
50
|
+
className={cn(
|
|
51
|
+
"flex w-full min-w-0 flex-col gap-2.5 wrap-break-word group-data-[align=end]/message:*:data-slot:self-end",
|
|
52
|
+
className
|
|
53
|
+
)}
|
|
54
|
+
{...props}
|
|
55
|
+
/>
|
|
56
|
+
)
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function MessageHeader({ className, ...props }: React.ComponentProps<"div">) {
|
|
60
|
+
return (
|
|
61
|
+
<div
|
|
62
|
+
data-slot="message-header"
|
|
63
|
+
className={cn(
|
|
64
|
+
"flex max-w-full min-w-0 items-center px-3 text-xs font-medium text-muted-foreground group-has-data-[variant=ghost]/message:px-0",
|
|
65
|
+
className
|
|
66
|
+
)}
|
|
67
|
+
{...props}
|
|
68
|
+
/>
|
|
69
|
+
)
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function MessageFooter({ className, ...props }: React.ComponentProps<"div">) {
|
|
73
|
+
return (
|
|
74
|
+
<div
|
|
75
|
+
data-slot="message-footer"
|
|
76
|
+
className={cn(
|
|
77
|
+
"flex max-w-full min-w-0 items-center px-3 text-xs font-medium text-muted-foreground group-has-data-[variant=ghost]/message:px-0 group-data-[align=end]/message:justify-end",
|
|
78
|
+
className
|
|
79
|
+
)}
|
|
80
|
+
{...props}
|
|
81
|
+
/>
|
|
82
|
+
)
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export {
|
|
86
|
+
MessageGroup,
|
|
87
|
+
Message,
|
|
88
|
+
MessageAvatar,
|
|
89
|
+
MessageContent,
|
|
90
|
+
MessageFooter,
|
|
91
|
+
MessageHeader,
|
|
92
|
+
}
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import { IconChevronDown } from "@tabler/icons-react";
|
|
2
|
+
import * as React from "react"
|
|
3
|
+
import * as NavigationMenuPrimitive from "@radix-ui/react-navigation-menu"
|
|
4
|
+
import { cva } from "class-variance-authority"
|
|
5
|
+
import { cn } from "@/lib/utils"
|
|
6
|
+
|
|
7
|
+
function NavigationMenu({
|
|
8
|
+
className,
|
|
9
|
+
children,
|
|
10
|
+
viewport = true,
|
|
11
|
+
viewportClassName,
|
|
12
|
+
...props
|
|
13
|
+
}: React.ComponentProps<typeof NavigationMenuPrimitive.Root> & {
|
|
14
|
+
viewport?: boolean
|
|
15
|
+
viewportClassName?: string
|
|
16
|
+
}) {
|
|
17
|
+
return (
|
|
18
|
+
<NavigationMenuPrimitive.Root
|
|
19
|
+
data-slot="navigation-menu"
|
|
20
|
+
data-viewport={viewport}
|
|
21
|
+
className={cn(
|
|
22
|
+
"group/navigation-menu relative flex max-w-max flex-1 items-center justify-center",
|
|
23
|
+
className
|
|
24
|
+
)}
|
|
25
|
+
{...props}
|
|
26
|
+
>
|
|
27
|
+
{children}
|
|
28
|
+
{viewport && <NavigationMenuViewport className={viewportClassName} />}
|
|
29
|
+
</NavigationMenuPrimitive.Root>
|
|
30
|
+
)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function NavigationMenuList({
|
|
34
|
+
className,
|
|
35
|
+
...props
|
|
36
|
+
}: React.ComponentProps<typeof NavigationMenuPrimitive.List>) {
|
|
37
|
+
return (
|
|
38
|
+
<NavigationMenuPrimitive.List
|
|
39
|
+
data-slot="navigation-menu-list"
|
|
40
|
+
className={cn(
|
|
41
|
+
"group flex flex-1 list-none items-center justify-center gap-1",
|
|
42
|
+
className
|
|
43
|
+
)}
|
|
44
|
+
{...props}
|
|
45
|
+
/>
|
|
46
|
+
)
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function NavigationMenuItem({
|
|
50
|
+
className,
|
|
51
|
+
...props
|
|
52
|
+
}: React.ComponentProps<typeof NavigationMenuPrimitive.Item>) {
|
|
53
|
+
return (
|
|
54
|
+
<NavigationMenuPrimitive.Item
|
|
55
|
+
data-slot="navigation-menu-item"
|
|
56
|
+
className={cn("relative", className)}
|
|
57
|
+
{...props}
|
|
58
|
+
/>
|
|
59
|
+
)
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const navigationMenuTriggerStyle = cva(
|
|
63
|
+
"group inline-flex h-9 w-max items-center justify-center rounded-md bg-background px-4 py-2 text-sm font-medium hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground disabled:pointer-events-none disabled:opacity-50 data-[state=open]:hover:bg-accent data-[state=open]:text-accent-foreground data-[state=open]:focus:bg-accent data-[state=open]:bg-accent/50 focus-visible:ring-ring/50 outline-none transition-[color,box-shadow] focus-visible:ring-[3px] focus-visible:outline-1"
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
function NavigationMenuTrigger({
|
|
67
|
+
className,
|
|
68
|
+
children,
|
|
69
|
+
...props
|
|
70
|
+
}: React.ComponentProps<typeof NavigationMenuPrimitive.Trigger>) {
|
|
71
|
+
return (
|
|
72
|
+
<NavigationMenuPrimitive.Trigger
|
|
73
|
+
data-slot="navigation-menu-trigger"
|
|
74
|
+
className={cn(navigationMenuTriggerStyle(), "group", className)}
|
|
75
|
+
{...props}
|
|
76
|
+
>
|
|
77
|
+
{children}{" "}
|
|
78
|
+
<IconChevronDown
|
|
79
|
+
className="relative top-[1px] ml-1 size-3 transition duration-300 group-data-[state=open]:rotate-180"
|
|
80
|
+
aria-hidden="true"
|
|
81
|
+
/>
|
|
82
|
+
</NavigationMenuPrimitive.Trigger>
|
|
83
|
+
)
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function NavigationMenuContent({
|
|
87
|
+
className,
|
|
88
|
+
...props
|
|
89
|
+
}: React.ComponentProps<typeof NavigationMenuPrimitive.Content>) {
|
|
90
|
+
return (
|
|
91
|
+
<NavigationMenuPrimitive.Content
|
|
92
|
+
data-slot="navigation-menu-content"
|
|
93
|
+
className={cn(
|
|
94
|
+
"data-[motion^=from-]:animate-in data-[motion^=to-]:animate-out data-[motion^=from-]:fade-in data-[motion^=to-]:fade-out data-[motion=from-end]:slide-in-from-right-52 data-[motion=from-start]:slide-in-from-left-52 data-[motion=to-end]:slide-out-to-right-52 data-[motion=to-start]:slide-out-to-left-52 top-0 left-0 w-full p-2 pr-2.5 md:absolute md:w-auto",
|
|
95
|
+
"group-data-[viewport=false]/navigation-menu:bg-popover group-data-[viewport=false]/navigation-menu:text-popover-foreground group-data-[viewport=false]/navigation-menu:data-[state=open]:animate-in group-data-[viewport=false]/navigation-menu:data-[state=closed]:animate-out group-data-[viewport=false]/navigation-menu:data-[state=closed]:zoom-out-95 group-data-[viewport=false]/navigation-menu:data-[state=open]:zoom-in-95 group-data-[viewport=false]/navigation-menu:data-[state=open]:fade-in-0 group-data-[viewport=false]/navigation-menu:data-[state=closed]:fade-out-0 group-data-[viewport=false]/navigation-menu:top-full group-data-[viewport=false]/navigation-menu:mt-1.5 group-data-[viewport=false]/navigation-menu:overflow-hidden group-data-[viewport=false]/navigation-menu:rounded-md group-data-[viewport=false]/navigation-menu:border group-data-[viewport=false]/navigation-menu:shadow group-data-[viewport=false]/navigation-menu:duration-200 **:data-[slot=navigation-menu-link]:focus:ring-0 **:data-[slot=navigation-menu-link]:focus:outline-none",
|
|
96
|
+
className
|
|
97
|
+
)}
|
|
98
|
+
{...props}
|
|
99
|
+
/>
|
|
100
|
+
)
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function NavigationMenuViewport({
|
|
104
|
+
className,
|
|
105
|
+
...props
|
|
106
|
+
}: React.ComponentProps<typeof NavigationMenuPrimitive.Viewport>) {
|
|
107
|
+
return (
|
|
108
|
+
<div
|
|
109
|
+
className={cn(
|
|
110
|
+
"absolute top-full left-1/2 isolate z-50 flex -translate-x-1/2 justify-center"
|
|
111
|
+
)}
|
|
112
|
+
>
|
|
113
|
+
<NavigationMenuPrimitive.Viewport
|
|
114
|
+
data-slot="navigation-menu-viewport"
|
|
115
|
+
className={cn(
|
|
116
|
+
"origin-top-center bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-90 relative mt-1.5 h-[var(--radix-navigation-menu-viewport-height)] w-full overflow-hidden rounded-md border shadow md:w-[var(--radix-navigation-menu-viewport-width)]",
|
|
117
|
+
className
|
|
118
|
+
)}
|
|
119
|
+
{...props}
|
|
120
|
+
/>
|
|
121
|
+
</div>
|
|
122
|
+
)
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
function NavigationMenuLink({
|
|
126
|
+
className,
|
|
127
|
+
...props
|
|
128
|
+
}: React.ComponentProps<typeof NavigationMenuPrimitive.Link>) {
|
|
129
|
+
return (
|
|
130
|
+
<NavigationMenuPrimitive.Link
|
|
131
|
+
data-slot="navigation-menu-link"
|
|
132
|
+
className={cn(
|
|
133
|
+
"data-[active=true]:focus:bg-accent data-[active=true]:hover:bg-accent data-[active=true]:bg-accent/50 data-[active=true]:text-accent-foreground hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground focus-visible:ring-ring/50 [&_svg:not([class*='text-'])]:text-muted-foreground flex flex-col gap-1 rounded-sm p-2 text-sm transition-all outline-none focus-visible:ring-[3px] focus-visible:outline-1 [&_svg:not([class*='size-'])]:size-4",
|
|
134
|
+
className
|
|
135
|
+
)}
|
|
136
|
+
{...props}
|
|
137
|
+
/>
|
|
138
|
+
)
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
function NavigationMenuIndicator({
|
|
142
|
+
className,
|
|
143
|
+
...props
|
|
144
|
+
}: React.ComponentProps<typeof NavigationMenuPrimitive.Indicator>) {
|
|
145
|
+
return (
|
|
146
|
+
<NavigationMenuPrimitive.Indicator
|
|
147
|
+
data-slot="navigation-menu-indicator"
|
|
148
|
+
className={cn(
|
|
149
|
+
"data-[state=visible]:animate-in data-[state=hidden]:animate-out data-[state=hidden]:fade-out data-[state=visible]:fade-in top-full z-[1] flex h-1.5 items-end justify-center overflow-hidden",
|
|
150
|
+
className
|
|
151
|
+
)}
|
|
152
|
+
{...props}
|
|
153
|
+
>
|
|
154
|
+
<div className="bg-border relative top-[60%] h-2 w-2 rotate-45 rounded-tl-sm shadow-md" />
|
|
155
|
+
</NavigationMenuPrimitive.Indicator>
|
|
156
|
+
)
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
export {
|
|
160
|
+
NavigationMenu,
|
|
161
|
+
NavigationMenuList,
|
|
162
|
+
NavigationMenuItem,
|
|
163
|
+
NavigationMenuContent,
|
|
164
|
+
NavigationMenuTrigger,
|
|
165
|
+
NavigationMenuLink,
|
|
166
|
+
NavigationMenuIndicator,
|
|
167
|
+
NavigationMenuViewport,
|
|
168
|
+
navigationMenuTriggerStyle,
|
|
169
|
+
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
"use client"
|
|
2
|
+
|
|
3
|
+
import { useEffect, useRef, type ComponentPropsWithoutRef } from "react"
|
|
4
|
+
import { useInView, useMotionValue, useSpring } from "motion/react"
|
|
5
|
+
|
|
6
|
+
import { cn } from "@/lib/utils"
|
|
7
|
+
|
|
8
|
+
interface NumberTickerProps extends ComponentPropsWithoutRef<"span"> {
|
|
9
|
+
value: number
|
|
10
|
+
startValue?: number
|
|
11
|
+
direction?: "up" | "down"
|
|
12
|
+
delay?: number
|
|
13
|
+
decimalPlaces?: number
|
|
14
|
+
prefix?: string
|
|
15
|
+
suffix?: string
|
|
16
|
+
springDamping?: number
|
|
17
|
+
springStiffness?: number
|
|
18
|
+
springMass?: number
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function formatTickerValue(value: number, decimalPlaces: number): string {
|
|
22
|
+
return Intl.NumberFormat("en-US", {
|
|
23
|
+
minimumFractionDigits: decimalPlaces,
|
|
24
|
+
maximumFractionDigits: decimalPlaces,
|
|
25
|
+
}).format(Number(value.toFixed(decimalPlaces)))
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function NumberTicker({
|
|
29
|
+
value,
|
|
30
|
+
startValue = 0,
|
|
31
|
+
direction = "up",
|
|
32
|
+
delay = 0,
|
|
33
|
+
className,
|
|
34
|
+
decimalPlaces = 0,
|
|
35
|
+
prefix,
|
|
36
|
+
suffix,
|
|
37
|
+
springDamping = 60,
|
|
38
|
+
springStiffness = 100,
|
|
39
|
+
springMass = 1,
|
|
40
|
+
...props
|
|
41
|
+
}: NumberTickerProps) {
|
|
42
|
+
const containerRef = useRef<HTMLSpanElement>(null)
|
|
43
|
+
const displayRef = useRef<HTMLSpanElement>(null)
|
|
44
|
+
const motionValue = useMotionValue(direction === "down" ? value : startValue)
|
|
45
|
+
const springValue = useSpring(motionValue, {
|
|
46
|
+
damping: springDamping,
|
|
47
|
+
stiffness: springStiffness,
|
|
48
|
+
mass: springMass,
|
|
49
|
+
})
|
|
50
|
+
const isInView = useInView(containerRef, { once: true, amount: 0.3 })
|
|
51
|
+
|
|
52
|
+
useEffect(() => {
|
|
53
|
+
let timer: ReturnType<typeof setTimeout> | null = null
|
|
54
|
+
|
|
55
|
+
if (isInView) {
|
|
56
|
+
timer = setTimeout(() => {
|
|
57
|
+
motionValue.set(direction === "down" ? startValue : value)
|
|
58
|
+
}, delay * 1000)
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return () => {
|
|
62
|
+
if (timer !== null) {
|
|
63
|
+
clearTimeout(timer)
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}, [motionValue, isInView, delay, value, direction, startValue])
|
|
67
|
+
|
|
68
|
+
useEffect(() => {
|
|
69
|
+
const updateDisplay = (latest: number) => {
|
|
70
|
+
if (displayRef.current) {
|
|
71
|
+
displayRef.current.textContent = formatTickerValue(latest, decimalPlaces)
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
updateDisplay(springValue.get())
|
|
76
|
+
return springValue.on("change", updateDisplay)
|
|
77
|
+
}, [springValue, decimalPlaces])
|
|
78
|
+
|
|
79
|
+
return (
|
|
80
|
+
<span
|
|
81
|
+
ref={containerRef}
|
|
82
|
+
className={cn("inline-block tabular-nums tracking-wider", className)}
|
|
83
|
+
{...props}
|
|
84
|
+
>
|
|
85
|
+
{prefix}
|
|
86
|
+
<span ref={displayRef}>{formatTickerValue(startValue, decimalPlaces)}</span>
|
|
87
|
+
{suffix}
|
|
88
|
+
</span>
|
|
89
|
+
)
|
|
90
|
+
}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { IconChevronLeft, IconChevronRight, IconDots } from "@tabler/icons-react";
|
|
2
|
+
import * as React from "react"
|
|
3
|
+
import { cn } from "@/lib/utils"
|
|
4
|
+
import { Button, buttonVariants } from "@/components/ui/button"
|
|
5
|
+
|
|
6
|
+
function Pagination({ className, ...props }: React.ComponentProps<"nav">) {
|
|
7
|
+
return (
|
|
8
|
+
<nav
|
|
9
|
+
role="navigation"
|
|
10
|
+
aria-label="pagination"
|
|
11
|
+
data-slot="pagination"
|
|
12
|
+
className={cn("mx-auto flex w-full justify-center", className)}
|
|
13
|
+
{...props}
|
|
14
|
+
/>
|
|
15
|
+
)
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function PaginationContent({
|
|
19
|
+
className,
|
|
20
|
+
...props
|
|
21
|
+
}: React.ComponentProps<"ul">) {
|
|
22
|
+
return (
|
|
23
|
+
<ul
|
|
24
|
+
data-slot="pagination-content"
|
|
25
|
+
className={cn("flex flex-row items-center gap-1", className)}
|
|
26
|
+
{...props}
|
|
27
|
+
/>
|
|
28
|
+
)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function PaginationItem({ ...props }: React.ComponentProps<"li">) {
|
|
32
|
+
return <li data-slot="pagination-item" {...props} />
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
type PaginationLinkProps = {
|
|
36
|
+
isActive?: boolean
|
|
37
|
+
} & Pick<React.ComponentProps<typeof Button>, "size"> &
|
|
38
|
+
React.ComponentProps<"a">
|
|
39
|
+
|
|
40
|
+
function PaginationLink({
|
|
41
|
+
className,
|
|
42
|
+
isActive,
|
|
43
|
+
size = "icon",
|
|
44
|
+
...props
|
|
45
|
+
}: PaginationLinkProps) {
|
|
46
|
+
return (
|
|
47
|
+
<a
|
|
48
|
+
aria-current={isActive ? "page" : undefined}
|
|
49
|
+
data-slot="pagination-link"
|
|
50
|
+
data-active={isActive}
|
|
51
|
+
className={cn(
|
|
52
|
+
buttonVariants({
|
|
53
|
+
variant: isActive ? "outline" : "ghost",
|
|
54
|
+
size,
|
|
55
|
+
}),
|
|
56
|
+
className
|
|
57
|
+
)}
|
|
58
|
+
{...props}
|
|
59
|
+
/>
|
|
60
|
+
)
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function PaginationPrevious({
|
|
64
|
+
className,
|
|
65
|
+
...props
|
|
66
|
+
}: React.ComponentProps<typeof PaginationLink>) {
|
|
67
|
+
return (
|
|
68
|
+
<PaginationLink
|
|
69
|
+
aria-label="Go to previous page"
|
|
70
|
+
size="default"
|
|
71
|
+
className={cn("gap-1 px-2.5 sm:pl-2.5", className)}
|
|
72
|
+
{...props}
|
|
73
|
+
>
|
|
74
|
+
<IconChevronLeft />
|
|
75
|
+
{/* <span className="hidden sm:block text-xs">Anterior</span> */}
|
|
76
|
+
</PaginationLink>
|
|
77
|
+
)
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function PaginationNext({
|
|
81
|
+
className,
|
|
82
|
+
...props
|
|
83
|
+
}: React.ComponentProps<typeof PaginationLink>) {
|
|
84
|
+
return (
|
|
85
|
+
<PaginationLink
|
|
86
|
+
aria-label="Go to next page"
|
|
87
|
+
size="default"
|
|
88
|
+
className={cn("gap-1 px-2.5 sm:pr-2.5", className)}
|
|
89
|
+
{...props}
|
|
90
|
+
>
|
|
91
|
+
{/* <span className="hidden sm:block text-xs">Siguiente</span> */}
|
|
92
|
+
<IconChevronRight />
|
|
93
|
+
</PaginationLink>
|
|
94
|
+
)
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function PaginationEllipsis({
|
|
98
|
+
className,
|
|
99
|
+
...props
|
|
100
|
+
}: React.ComponentProps<"span">) {
|
|
101
|
+
return (
|
|
102
|
+
<span
|
|
103
|
+
aria-hidden
|
|
104
|
+
data-slot="pagination-ellipsis"
|
|
105
|
+
className={cn("flex size-9 items-center justify-center", className)}
|
|
106
|
+
{...props}
|
|
107
|
+
>
|
|
108
|
+
<IconDots className="size-4" />
|
|
109
|
+
<span className="sr-only">More pages</span>
|
|
110
|
+
</span>
|
|
111
|
+
)
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export {
|
|
115
|
+
Pagination,
|
|
116
|
+
PaginationContent,
|
|
117
|
+
PaginationLink,
|
|
118
|
+
PaginationItem,
|
|
119
|
+
PaginationPrevious,
|
|
120
|
+
PaginationNext,
|
|
121
|
+
PaginationEllipsis,
|
|
122
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"use client"
|
|
2
|
+
|
|
3
|
+
import * as React from "react"
|
|
4
|
+
import * as PopoverPrimitive from "@radix-ui/react-popover"
|
|
5
|
+
|
|
6
|
+
import { cn } from "@/lib/utils"
|
|
7
|
+
|
|
8
|
+
function Popover({
|
|
9
|
+
...props
|
|
10
|
+
}: React.ComponentProps<typeof PopoverPrimitive.Root>) {
|
|
11
|
+
return <PopoverPrimitive.Root data-slot="popover" {...props} />
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function PopoverTrigger({
|
|
15
|
+
...props
|
|
16
|
+
}: React.ComponentProps<typeof PopoverPrimitive.Trigger>) {
|
|
17
|
+
return <PopoverPrimitive.Trigger data-slot="popover-trigger" {...props} />
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function PopoverContent({
|
|
21
|
+
className,
|
|
22
|
+
align = "center",
|
|
23
|
+
sideOffset = 4,
|
|
24
|
+
...props
|
|
25
|
+
}: React.ComponentProps<typeof PopoverPrimitive.Content>) {
|
|
26
|
+
return (
|
|
27
|
+
<PopoverPrimitive.Portal>
|
|
28
|
+
<PopoverPrimitive.Content
|
|
29
|
+
data-slot="popover-content"
|
|
30
|
+
align={align}
|
|
31
|
+
sideOffset={sideOffset}
|
|
32
|
+
className={cn(
|
|
33
|
+
"bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-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 w-72 origin-(--radix-popover-content-transform-origin) rounded-md border p-4 shadow-md outline-hidden",
|
|
34
|
+
className
|
|
35
|
+
)}
|
|
36
|
+
{...props}
|
|
37
|
+
/>
|
|
38
|
+
</PopoverPrimitive.Portal>
|
|
39
|
+
)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function PopoverAnchor({
|
|
43
|
+
...props
|
|
44
|
+
}: React.ComponentProps<typeof PopoverPrimitive.Anchor>) {
|
|
45
|
+
return <PopoverPrimitive.Anchor data-slot="popover-anchor" {...props} />
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export { Popover, PopoverTrigger, PopoverContent, PopoverAnchor }
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use client"
|
|
2
|
+
|
|
3
|
+
import * as React from "react"
|
|
4
|
+
import { Progress as ProgressPrimitive } from "radix-ui"
|
|
5
|
+
|
|
6
|
+
import { cn } from "@/lib/utils"
|
|
7
|
+
|
|
8
|
+
function Progress({
|
|
9
|
+
className,
|
|
10
|
+
value,
|
|
11
|
+
...props
|
|
12
|
+
}: React.ComponentProps<typeof ProgressPrimitive.Root>) {
|
|
13
|
+
return (
|
|
14
|
+
<ProgressPrimitive.Root
|
|
15
|
+
data-slot="progress"
|
|
16
|
+
className={cn(
|
|
17
|
+
"relative h-2 w-full overflow-hidden rounded-full bg-primary/20",
|
|
18
|
+
className
|
|
19
|
+
)}
|
|
20
|
+
{...props}
|
|
21
|
+
>
|
|
22
|
+
<ProgressPrimitive.Indicator
|
|
23
|
+
data-slot="progress-indicator"
|
|
24
|
+
className="h-full w-full flex-1 bg-primary transition-all"
|
|
25
|
+
style={{ transform: `translateX(-${100 - (value || 0)}%)` }}
|
|
26
|
+
/>
|
|
27
|
+
</ProgressPrimitive.Root>
|
|
28
|
+
)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export { Progress }
|