@srcroot/ui 0.0.54 → 0.0.56

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 (107) hide show
  1. package/README.md +151 -151
  2. package/dist/index.d.ts +0 -0
  3. package/dist/index.js +55 -1
  4. package/package.json +7 -2
  5. package/src/registry/analytics/google-analytics.tsx +36 -39
  6. package/src/registry/analytics/google-tag-manager.tsx +62 -65
  7. package/src/registry/analytics/meta-pixel.tsx +44 -47
  8. package/src/registry/analytics/microsoft-clarity.tsx +31 -34
  9. package/src/registry/analytics/tiktok-pixel.tsx +34 -37
  10. package/src/registry/lib/utils.ts +0 -0
  11. package/src/registry/themes/v3/blue.css +157 -157
  12. package/src/registry/themes/v3/glass.css +153 -153
  13. package/src/registry/themes/v3/gray.css +157 -157
  14. package/src/registry/themes/v3/green.css +157 -157
  15. package/src/registry/themes/v3/neutral.css +157 -157
  16. package/src/registry/themes/v3/orange.css +157 -157
  17. package/src/registry/themes/v3/rose.css +157 -157
  18. package/src/registry/themes/v3/slate.css +157 -157
  19. package/src/registry/themes/v3/stone.css +157 -157
  20. package/src/registry/themes/v3/violet.css +186 -186
  21. package/src/registry/themes/v3/zinc.css +157 -157
  22. package/src/registry/themes/v4/blue.css +184 -184
  23. package/src/registry/themes/v4/glass.css +180 -180
  24. package/src/registry/themes/v4/gray.css +184 -184
  25. package/src/registry/themes/v4/green.css +184 -184
  26. package/src/registry/themes/v4/neutral.css +184 -184
  27. package/src/registry/themes/v4/orange.css +184 -184
  28. package/src/registry/themes/v4/rose.css +184 -184
  29. package/src/registry/themes/v4/slate.css +184 -184
  30. package/src/registry/themes/v4/stone.css +184 -184
  31. package/src/registry/themes/v4/violet.css +184 -184
  32. package/src/registry/themes/v4/zinc.css +184 -184
  33. package/src/registry/ui/accordion.tsx +164 -165
  34. package/src/registry/ui/alert-dialog.tsx +213 -214
  35. package/src/registry/ui/alert.tsx +73 -76
  36. package/src/registry/ui/aspect-ratio.tsx +44 -47
  37. package/src/registry/ui/avatar.tsx +96 -97
  38. package/src/registry/ui/badge.tsx +52 -55
  39. package/src/registry/ui/breadcrumb.tsx +147 -150
  40. package/src/registry/ui/button-group.tsx +64 -67
  41. package/src/registry/ui/button.tsx +71 -72
  42. package/src/registry/ui/calendar.tsx +514 -515
  43. package/src/registry/ui/card.tsx +88 -91
  44. package/src/registry/ui/carousel.tsx +214 -214
  45. package/src/registry/ui/chart.tsx +373 -373
  46. package/src/registry/ui/chatbot.tsx +86 -13
  47. package/src/registry/ui/checkbox.tsx +93 -94
  48. package/src/registry/ui/collapsible.tsx +107 -108
  49. package/src/registry/ui/combobox.tsx +171 -171
  50. package/src/registry/ui/command.tsx +300 -300
  51. package/src/registry/ui/container.tsx +44 -47
  52. package/src/registry/ui/context-menu.tsx +221 -221
  53. package/src/registry/ui/date-picker.tsx +228 -228
  54. package/src/registry/ui/dialog.tsx +269 -270
  55. package/src/registry/ui/drawer.tsx +10 -4
  56. package/src/registry/ui/dropdown-menu.tsx +529 -530
  57. package/src/registry/ui/empty-state.tsx +0 -2
  58. package/src/registry/ui/file-upload.tsx +0 -0
  59. package/src/registry/ui/floating-dock.tsx +0 -0
  60. package/src/registry/ui/form-field.tsx +91 -94
  61. package/src/registry/ui/google-analytics.tsx +38 -0
  62. package/src/registry/ui/google-tag-manager.tsx +64 -0
  63. package/src/registry/ui/hover-card.tsx +223 -223
  64. package/src/registry/ui/image.tsx +144 -147
  65. package/src/registry/ui/input-group.tsx +82 -85
  66. package/src/registry/ui/input.tsx +125 -125
  67. package/src/registry/ui/kbd.tsx +60 -63
  68. package/src/registry/ui/label.tsx +36 -37
  69. package/src/registry/ui/loading-spinner.tsx +108 -111
  70. package/src/registry/ui/map.tsx +0 -0
  71. package/src/registry/ui/marquee.tsx +2 -0
  72. package/src/registry/ui/menubar.tsx +246 -246
  73. package/src/registry/ui/meta-pixel.tsx +46 -0
  74. package/src/registry/ui/microsoft-clarity.tsx +33 -0
  75. package/src/registry/ui/native-select.tsx +49 -52
  76. package/src/registry/ui/otp-input.tsx +152 -155
  77. package/src/registry/ui/pagination.tsx +149 -152
  78. package/src/registry/ui/patterns.tsx +28 -0
  79. package/src/registry/ui/popover.tsx +226 -227
  80. package/src/registry/ui/progress.tsx +51 -52
  81. package/src/registry/ui/radio.tsx +99 -102
  82. package/src/registry/ui/resizable.tsx +314 -314
  83. package/src/registry/ui/scroll-animation.tsx +45 -0
  84. package/src/registry/ui/scroll-area.tsx +121 -122
  85. package/src/registry/ui/scroll-to-top.tsx +0 -0
  86. package/src/registry/ui/search.tsx +147 -150
  87. package/src/registry/ui/select.tsx +292 -293
  88. package/src/registry/ui/separator.tsx +46 -47
  89. package/src/registry/ui/sheet.tsx +6 -3
  90. package/src/registry/ui/sidebar.tsx +628 -628
  91. package/src/registry/ui/skeleton.tsx +26 -29
  92. package/src/registry/ui/slider.tsx +196 -197
  93. package/src/registry/ui/slot.tsx +69 -72
  94. package/src/registry/ui/star-rating.tsx +131 -134
  95. package/src/registry/ui/switch.tsx +72 -73
  96. package/src/registry/ui/table-of-contents.tsx +96 -96
  97. package/src/registry/ui/table.tsx +138 -139
  98. package/src/registry/ui/tabs.tsx +124 -125
  99. package/src/registry/ui/text.tsx +61 -64
  100. package/src/registry/ui/textarea.tsx +41 -42
  101. package/src/registry/ui/theme-switcher.tsx +66 -66
  102. package/src/registry/ui/tiktok-pixel.tsx +36 -0
  103. package/src/registry/ui/toast.tsx +97 -98
  104. package/src/registry/ui/toggle-group.tsx +129 -129
  105. package/src/registry/ui/toggle.tsx +72 -72
  106. package/src/registry/ui/tooltip.tsx +143 -144
  107. package/src/registry/ui/whatsapp.tsx +0 -0
@@ -1,223 +1,223 @@
1
- "use client"
2
-
3
- import * as React from "react"
4
- import { createPortal } from "react-dom"
5
- import { cn } from "@/lib/utils"
6
- import { Slot } from "@/components/ui/slot"
7
-
8
- // HoverCard Context
9
- interface HoverCardContextValue {
10
- open: boolean
11
- triggerRef: React.RefObject<HTMLDivElement | null>
12
- }
13
-
14
- const HoverCardContext = React.createContext<HoverCardContextValue | null>(null)
15
-
16
- function useHoverCard() {
17
- const context = React.useContext(HoverCardContext)
18
- if (!context) {
19
- throw new Error("useHoverCard must be used within a HoverCard")
20
- }
21
- return context
22
- }
23
-
24
- // HoverCard Root
25
- interface HoverCardProps {
26
- children: React.ReactNode
27
- openDelay?: number
28
- closeDelay?: number
29
- }
30
-
31
- /**
32
- * HoverCard component for displaying content on hover
33
- *
34
- * @example
35
- * <HoverCard>
36
- * <HoverCardTrigger asChild>
37
- * <Button variant="link">@nextjs</Button>
38
- * </HoverCardTrigger>
39
- * <HoverCardContent>
40
- * The React Framework – created and maintained by @vercel.
41
- * </HoverCardContent>
42
- * </HoverCard>
43
- */
44
- const HoverCard = ({ children, openDelay = 200, closeDelay = 300 }: HoverCardProps) => {
45
- const [open, setOpen] = React.useState(false)
46
- const triggerRef = React.useRef<HTMLDivElement>(null)
47
- const openTimeoutRef = React.useRef<NodeJS.Timeout | null>(null)
48
- const closeTimeoutRef = React.useRef<NodeJS.Timeout | null>(null)
49
-
50
- const handleMouseEnter = React.useCallback(() => {
51
- if (closeTimeoutRef.current) {
52
- clearTimeout(closeTimeoutRef.current)
53
- closeTimeoutRef.current = null
54
- }
55
- openTimeoutRef.current = setTimeout(() => {
56
- setOpen(true)
57
- }, openDelay)
58
- }, [openDelay])
59
-
60
- const handleMouseLeave = React.useCallback(() => {
61
- if (openTimeoutRef.current) {
62
- clearTimeout(openTimeoutRef.current)
63
- openTimeoutRef.current = null
64
- }
65
- closeTimeoutRef.current = setTimeout(() => {
66
- setOpen(false)
67
- }, closeDelay)
68
- }, [closeDelay])
69
-
70
- React.useEffect(() => {
71
- return () => {
72
- if (openTimeoutRef.current) clearTimeout(openTimeoutRef.current)
73
- if (closeTimeoutRef.current) clearTimeout(closeTimeoutRef.current)
74
- }
75
- }, [])
76
-
77
- return (
78
- <HoverCardContext.Provider value={{ open, triggerRef }}>
79
- <div
80
- onMouseEnter={handleMouseEnter}
81
- onMouseLeave={handleMouseLeave}
82
- className="inline-block"
83
- >
84
- {children}
85
- </div>
86
- </HoverCardContext.Provider>
87
- )
88
- }
89
-
90
- // HoverCard Trigger
91
- interface HoverCardTriggerProps extends React.HTMLAttributes<HTMLDivElement> {
92
- asChild?: boolean
93
- }
94
-
95
- const HoverCardTrigger = React.forwardRef<HTMLDivElement, HoverCardTriggerProps>(
96
- ({ children, asChild, className, ...props }, ref) => {
97
- const { triggerRef } = useHoverCard()
98
-
99
- // Merge refs manually since we have two refs to attach (triggerRef and ref)
100
- const combinedRef = React.useCallback((node: HTMLDivElement | null) => {
101
- if (triggerRef) (triggerRef as any).current = node
102
-
103
- if (typeof ref === "function") ref(node)
104
- else if (ref) (ref as any).current = node
105
- }, [triggerRef, ref])
106
-
107
- const Comp = asChild ? Slot : "div"
108
-
109
- return (
110
- <Comp
111
- ref={combinedRef}
112
- className={cn("inline-block cursor-pointer", className)}
113
- {...props}
114
- >
115
- {children}
116
- </Comp>
117
- )
118
- }
119
- )
120
- HoverCardTrigger.displayName = "HoverCardTrigger"
121
-
122
- // HoverCard Content
123
- interface HoverCardContentProps extends React.HTMLAttributes<HTMLDivElement> {
124
- align?: "start" | "center" | "end"
125
- side?: "top" | "bottom"
126
- sideOffset?: number
127
- }
128
-
129
- const HoverCardContent = React.forwardRef<
130
- HTMLDivElement,
131
- HoverCardContentProps & { portal?: boolean }
132
- >(
133
- ({ children, className, align = "center", side = "bottom", sideOffset = 4, portal = true, ...props }, ref) => {
134
- const { open, triggerRef } = useHoverCard()
135
- const [position, setPosition] = React.useState({ top: 0, left: 0 })
136
- const contentRef = React.useRef<HTMLDivElement>(null)
137
- const [mounted, setMounted] = React.useState(false)
138
-
139
- React.useEffect(() => {
140
- setMounted(true)
141
- }, [])
142
-
143
- React.useEffect(() => {
144
- if (!open || !triggerRef.current || !contentRef.current) return
145
-
146
- const checkPosition = () => {
147
- if (!triggerRef.current || !contentRef.current) return
148
- const triggerRect = triggerRef.current.getBoundingClientRect()
149
- const contentRect = contentRef.current.getBoundingClientRect()
150
-
151
- let top = 0
152
- let left = 0
153
-
154
- // Calculate vertical position
155
- if (side === "bottom") {
156
- top = triggerRect.bottom + sideOffset
157
- } else {
158
- top = triggerRect.top - contentRect.height - sideOffset
159
- }
160
-
161
- // Calculate horizontal position
162
- if (align === "start") {
163
- left = triggerRect.left
164
- } else if (align === "end") {
165
- left = triggerRect.right - contentRect.width
166
- } else {
167
- left = triggerRect.left + (triggerRect.width - contentRect.width) / 2
168
- }
169
-
170
- // Clamp to viewport
171
- left = Math.max(8, Math.min(left, window.innerWidth - contentRect.width - 8))
172
- top = Math.max(8, Math.min(top, window.innerHeight - contentRect.height - 8))
173
-
174
- setPosition({ top, left })
175
- }
176
-
177
- checkPosition()
178
- window.addEventListener('resize', checkPosition)
179
- window.addEventListener('scroll', checkPosition, true)
180
-
181
- return () => {
182
- window.removeEventListener('resize', checkPosition)
183
- window.removeEventListener('scroll', checkPosition, true)
184
- }
185
- }, [open, triggerRef, align, side, sideOffset])
186
-
187
- if (!open) return null
188
-
189
- const content = (
190
- <div
191
- ref={(node) => {
192
- (contentRef as any).current = node
193
- if (typeof ref === 'function') ref(node)
194
- else if (ref) (ref as any).current = node
195
- }}
196
- className={cn(
197
- "z-50 w-64 rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-none",
198
- "animate-in fade-in-0 zoom-in-95",
199
- !portal && "absolute",
200
- portal && "fixed",
201
- className
202
- )}
203
- style={{
204
- top: portal ? position.top : undefined,
205
- left: portal ? position.left : undefined,
206
- ...props.style
207
- }}
208
- {...props}
209
- >
210
- {children}
211
- </div>
212
- )
213
-
214
- if (portal && mounted) {
215
- return createPortal(content, document.body)
216
- }
217
-
218
- return content
219
- }
220
- )
221
- HoverCardContent.displayName = "HoverCardContent"
222
-
223
- export { HoverCard, HoverCardTrigger, HoverCardContent }
1
+ "use client"
2
+
3
+ import * as React from "react"
4
+ import { createPortal } from "react-dom"
5
+ import { cn } from "@/lib/utils"
6
+ import { Slot } from "@/components/ui/slot"
7
+
8
+ // HoverCard Context
9
+ interface HoverCardContextValue {
10
+ open: boolean
11
+ triggerRef: React.RefObject<HTMLDivElement | null>
12
+ }
13
+
14
+ const HoverCardContext = React.createContext<HoverCardContextValue | null>(null)
15
+
16
+ function useHoverCard() {
17
+ const context = React.useContext(HoverCardContext)
18
+ if (!context) {
19
+ throw new Error("useHoverCard must be used within a HoverCard")
20
+ }
21
+ return context
22
+ }
23
+
24
+ // HoverCard Root
25
+ interface HoverCardProps {
26
+ children: React.ReactNode
27
+ openDelay?: number
28
+ closeDelay?: number
29
+ }
30
+
31
+ /**
32
+ * HoverCard component for displaying content on hover
33
+ *
34
+ * @example
35
+ * <HoverCard>
36
+ * <HoverCardTrigger asChild>
37
+ * <Button variant="link">@nextjs</Button>
38
+ * </HoverCardTrigger>
39
+ * <HoverCardContent>
40
+ * The React Framework – created and maintained by @vercel.
41
+ * </HoverCardContent>
42
+ * </HoverCard>
43
+ */
44
+ const HoverCard = ({ children, openDelay = 200, closeDelay = 300 }: HoverCardProps) => {
45
+ const [open, setOpen] = React.useState(false)
46
+ const triggerRef = React.useRef<HTMLDivElement>(null)
47
+ const openTimeoutRef = React.useRef<NodeJS.Timeout | null>(null)
48
+ const closeTimeoutRef = React.useRef<NodeJS.Timeout | null>(null)
49
+
50
+ const handleMouseEnter = React.useCallback(() => {
51
+ if (closeTimeoutRef.current) {
52
+ clearTimeout(closeTimeoutRef.current)
53
+ closeTimeoutRef.current = null
54
+ }
55
+ openTimeoutRef.current = setTimeout(() => {
56
+ setOpen(true)
57
+ }, openDelay)
58
+ }, [openDelay])
59
+
60
+ const handleMouseLeave = React.useCallback(() => {
61
+ if (openTimeoutRef.current) {
62
+ clearTimeout(openTimeoutRef.current)
63
+ openTimeoutRef.current = null
64
+ }
65
+ closeTimeoutRef.current = setTimeout(() => {
66
+ setOpen(false)
67
+ }, closeDelay)
68
+ }, [closeDelay])
69
+
70
+ React.useEffect(() => {
71
+ return () => {
72
+ if (openTimeoutRef.current) clearTimeout(openTimeoutRef.current)
73
+ if (closeTimeoutRef.current) clearTimeout(closeTimeoutRef.current)
74
+ }
75
+ }, [])
76
+
77
+ return (
78
+ <HoverCardContext.Provider value={{ open, triggerRef }}>
79
+ <div
80
+ onMouseEnter={handleMouseEnter}
81
+ onMouseLeave={handleMouseLeave}
82
+ className="inline-block"
83
+ >
84
+ {children}
85
+ </div>
86
+ </HoverCardContext.Provider>
87
+ )
88
+ }
89
+
90
+ // HoverCard Trigger
91
+ interface HoverCardTriggerProps extends React.HTMLAttributes<HTMLDivElement> {
92
+ asChild?: boolean
93
+ }
94
+
95
+ const HoverCardTrigger = React.forwardRef<HTMLDivElement, HoverCardTriggerProps>(
96
+ ({ children, asChild, className, ...props }, ref) => {
97
+ const { triggerRef } = useHoverCard()
98
+
99
+ // Merge refs manually since we have two refs to attach (triggerRef and ref)
100
+ const combinedRef = React.useCallback((node: HTMLDivElement | null) => {
101
+ if (triggerRef) (triggerRef as any).current = node
102
+
103
+ if (typeof ref === "function") ref(node)
104
+ else if (ref) (ref as any).current = node
105
+ }, [triggerRef, ref])
106
+
107
+ const Comp = asChild ? Slot : "div"
108
+
109
+ return (
110
+ <Comp
111
+ ref={combinedRef}
112
+ className={cn("inline-block cursor-pointer", className)}
113
+ {...props}
114
+ >
115
+ {children}
116
+ </Comp>
117
+ )
118
+ }
119
+ )
120
+ HoverCardTrigger.displayName = "HoverCardTrigger"
121
+
122
+ // HoverCard Content
123
+ interface HoverCardContentProps extends React.HTMLAttributes<HTMLDivElement> {
124
+ align?: "start" | "center" | "end"
125
+ side?: "top" | "bottom"
126
+ sideOffset?: number
127
+ }
128
+
129
+ const HoverCardContent = React.forwardRef<
130
+ HTMLDivElement,
131
+ HoverCardContentProps & { portal?: boolean }
132
+ >(
133
+ ({ children, className, align = "center", side = "bottom", sideOffset = 4, portal = true, ...props }, ref) => {
134
+ const { open, triggerRef } = useHoverCard()
135
+ const [position, setPosition] = React.useState({ top: 0, left: 0 })
136
+ const contentRef = React.useRef<HTMLDivElement>(null)
137
+ const [mounted, setMounted] = React.useState(false)
138
+
139
+ React.useEffect(() => {
140
+ setMounted(true)
141
+ }, [])
142
+
143
+ React.useEffect(() => {
144
+ if (!open || !triggerRef.current || !contentRef.current) return
145
+
146
+ const checkPosition = () => {
147
+ if (!triggerRef.current || !contentRef.current) return
148
+ const triggerRect = triggerRef.current.getBoundingClientRect()
149
+ const contentRect = contentRef.current.getBoundingClientRect()
150
+
151
+ let top = 0
152
+ let left = 0
153
+
154
+ // Calculate vertical position
155
+ if (side === "bottom") {
156
+ top = triggerRect.bottom + sideOffset
157
+ } else {
158
+ top = triggerRect.top - contentRect.height - sideOffset
159
+ }
160
+
161
+ // Calculate horizontal position
162
+ if (align === "start") {
163
+ left = triggerRect.left
164
+ } else if (align === "end") {
165
+ left = triggerRect.right - contentRect.width
166
+ } else {
167
+ left = triggerRect.left + (triggerRect.width - contentRect.width) / 2
168
+ }
169
+
170
+ // Clamp to viewport
171
+ left = Math.max(8, Math.min(left, window.innerWidth - contentRect.width - 8))
172
+ top = Math.max(8, Math.min(top, window.innerHeight - contentRect.height - 8))
173
+
174
+ setPosition({ top, left })
175
+ }
176
+
177
+ checkPosition()
178
+ window.addEventListener('resize', checkPosition)
179
+ window.addEventListener('scroll', checkPosition, true)
180
+
181
+ return () => {
182
+ window.removeEventListener('resize', checkPosition)
183
+ window.removeEventListener('scroll', checkPosition, true)
184
+ }
185
+ }, [open, triggerRef, align, side, sideOffset])
186
+
187
+ if (!open) return null
188
+
189
+ const content = (
190
+ <div
191
+ ref={(node) => {
192
+ (contentRef as any).current = node
193
+ if (typeof ref === 'function') ref(node)
194
+ else if (ref) (ref as any).current = node
195
+ }}
196
+ className={cn(
197
+ "z-50 w-64 rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-none",
198
+ "animate-in fade-in-0 zoom-in-95",
199
+ !portal && "absolute",
200
+ portal && "fixed",
201
+ className
202
+ )}
203
+ style={{
204
+ top: portal ? position.top : undefined,
205
+ left: portal ? position.left : undefined,
206
+ ...props.style
207
+ }}
208
+ {...props}
209
+ >
210
+ {children}
211
+ </div>
212
+ )
213
+
214
+ if (portal && mounted) {
215
+ return createPortal(content, document.body)
216
+ }
217
+
218
+ return content
219
+ }
220
+ )
221
+ HoverCardContent.displayName = "HoverCardContent"
222
+
223
+ export { HoverCard, HoverCardTrigger, HoverCardContent }