@traky-app/ui 1.0.0 → 1.2.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.
Files changed (75) hide show
  1. package/README.md +12 -19
  2. package/package.json +50 -3
  3. package/registry/traky/json/command.json +1 -1
  4. package/registry/traky/json/icon.json +17 -0
  5. package/registry/traky/json/logo.json +17 -0
  6. package/registry/traky/registry.json +20 -0
  7. package/registry/traky/ui/command.tsx +2 -0
  8. package/registry/traky/ui/icon.tsx +71 -0
  9. package/registry/traky/ui/logo.tsx +77 -0
  10. package/src/hooks/use-document-theme.ts +25 -0
  11. package/src/hooks/use-mobile.ts +19 -0
  12. package/src/lib/disable-input-autofill.ts +23 -0
  13. package/src/lib/sidebar-persistence.ts +76 -0
  14. package/src/lib/utils.ts +30 -0
  15. package/src/ui/accordion.tsx +65 -0
  16. package/src/ui/alert-dialog.tsx +163 -0
  17. package/src/ui/alert.tsx +66 -0
  18. package/src/ui/animated-beam.tsx +185 -0
  19. package/src/ui/animated-list.tsx +71 -0
  20. package/src/ui/avatar.tsx +53 -0
  21. package/src/ui/badge.tsx +46 -0
  22. package/src/ui/bento-grid.tsx +109 -0
  23. package/src/ui/breadcrumb.tsx +108 -0
  24. package/src/ui/bubble.tsx +125 -0
  25. package/src/ui/button-group.tsx +83 -0
  26. package/src/ui/button.tsx +64 -0
  27. package/src/ui/calendar.tsx +213 -0
  28. package/src/ui/card.tsx +92 -0
  29. package/src/ui/carousel.tsx +240 -0
  30. package/src/ui/chart.tsx +380 -0
  31. package/src/ui/checkbox.tsx +31 -0
  32. package/src/ui/checkpoint.tsx +94 -0
  33. package/src/ui/code-block.tsx +232 -0
  34. package/src/ui/collapsible.tsx +33 -0
  35. package/src/ui/command.tsx +192 -0
  36. package/src/ui/context-menu.tsx +251 -0
  37. package/src/ui/dialog.tsx +142 -0
  38. package/src/ui/drawer.tsx +135 -0
  39. package/src/ui/dropdown-menu.tsx +256 -0
  40. package/src/ui/empty.tsx +104 -0
  41. package/src/ui/field.tsx +248 -0
  42. package/src/ui/globe.tsx +234 -0
  43. package/src/ui/hover-card.tsx +44 -0
  44. package/src/ui/icon.tsx +71 -0
  45. package/src/ui/input-group.tsx +170 -0
  46. package/src/ui/input-otp.tsx +77 -0
  47. package/src/ui/input.tsx +24 -0
  48. package/src/ui/item.tsx +193 -0
  49. package/src/ui/kbd.tsx +28 -0
  50. package/src/ui/label.tsx +24 -0
  51. package/src/ui/logo.tsx +77 -0
  52. package/src/ui/map.tsx +2226 -0
  53. package/src/ui/marker.tsx +69 -0
  54. package/src/ui/marquee.tsx +74 -0
  55. package/src/ui/message.tsx +92 -0
  56. package/src/ui/navigation-menu.tsx +169 -0
  57. package/src/ui/number-ticker.tsx +90 -0
  58. package/src/ui/pagination.tsx +122 -0
  59. package/src/ui/popover.tsx +48 -0
  60. package/src/ui/progress.tsx +31 -0
  61. package/src/ui/select.tsx +193 -0
  62. package/src/ui/separator.tsx +28 -0
  63. package/src/ui/sheet.tsx +143 -0
  64. package/src/ui/sidebar.tsx +764 -0
  65. package/src/ui/skeleton.tsx +13 -0
  66. package/src/ui/sonner.tsx +71 -0
  67. package/src/ui/spinner.tsx +15 -0
  68. package/src/ui/switch.tsx +41 -0
  69. package/src/ui/table.tsx +116 -0
  70. package/src/ui/tabs.tsx +66 -0
  71. package/src/ui/textarea.tsx +20 -0
  72. package/src/ui/toggle-group.tsx +83 -0
  73. package/src/ui/toggle.tsx +47 -0
  74. package/src/ui/tooltip.tsx +61 -0
  75. package/src/ui/trace.tsx +165 -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 "./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 }