@srcroot/ui 0.0.49 → 0.0.52

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,69 @@
1
+ import * as React from "react"
2
+ import { cn } from "@/lib/utils"
3
+
4
+ export interface SlotProps extends React.HTMLAttributes<HTMLElement> {
5
+ children?: React.ReactNode
6
+ }
7
+
8
+ const Slot = React.forwardRef<HTMLElement, SlotProps>(
9
+ ({ children, className, ...props }, ref) => {
10
+ if (React.isValidElement(children)) {
11
+ const child = children as React.ReactElement<any>
12
+
13
+ const mergedProps: Record<string, any> = { ...props }
14
+ if (className) {
15
+ mergedProps.className = className
16
+ }
17
+
18
+ for (const propName in child.props) {
19
+ const slotPropValue = mergedProps[propName]
20
+ const childPropValue = child.props[propName]
21
+
22
+ if (
23
+ /^on[A-Z]/.test(propName) &&
24
+ typeof slotPropValue === "function" &&
25
+ typeof childPropValue === "function"
26
+ ) {
27
+ mergedProps[propName] = (...args: any[]) => {
28
+ childPropValue(...args)
29
+ if (!args[0]?.defaultPrevented) {
30
+ slotPropValue(...args)
31
+ }
32
+ }
33
+ } else if (propName === "style") {
34
+ mergedProps[propName] = { ...slotPropValue, ...childPropValue }
35
+ } else if (propName === "className") {
36
+ mergedProps[propName] = cn(slotPropValue, childPropValue)
37
+ } else {
38
+ mergedProps[propName] = childPropValue
39
+ }
40
+ }
41
+
42
+ return React.cloneElement(child, {
43
+ ...mergedProps,
44
+ ref: (node: HTMLElement | null) => {
45
+ // Handle both function and object refs for the forwarded ref
46
+ if (typeof ref === "function") {
47
+ ref(node)
48
+ } else if (ref && "current" in ref) {
49
+ (ref as any).current = node
50
+ }
51
+
52
+ // Handle the child's existing ref
53
+ const childRef = (child as any).ref
54
+ if (typeof childRef === "function") {
55
+ childRef(node)
56
+ } else if (childRef && "current" in childRef) {
57
+ (childRef as any).current = node
58
+ }
59
+ },
60
+ })
61
+ }
62
+
63
+ return null
64
+ }
65
+ )
66
+
67
+ Slot.displayName = "Slot"
68
+
69
+ export { Slot }
@@ -1,5 +1,7 @@
1
1
  import * as React from "react"
2
+ import { createPortal } from "react-dom"
2
3
  import { cn } from "@/lib/utils"
4
+ import { Slot } from "@/components/ui/slot"
3
5
 
4
6
  interface TooltipContextValue {
5
7
  open: boolean
@@ -73,19 +75,10 @@ const TooltipTrigger = React.forwardRef<HTMLSpanElement, TooltipTriggerProps>(
73
75
  const handleFocus = () => context.setOpen(true)
74
76
  const handleBlur = () => context.setOpen(false)
75
77
 
76
- if (asChild && React.isValidElement(children)) {
77
- return React.cloneElement(children as React.ReactElement<any>, {
78
- onMouseEnter: handleMouseEnter,
79
- onMouseLeave: handleMouseLeave,
80
- onMouseMove: handleMouseMove,
81
- onFocus: handleFocus,
82
- onBlur: handleBlur,
83
- ref,
84
- })
85
- }
78
+ const Comp = asChild ? Slot : "span"
86
79
 
87
80
  return (
88
- <span
81
+ <Comp
89
82
  ref={ref}
90
83
  onMouseEnter={handleMouseEnter}
91
84
  onMouseLeave={handleMouseLeave}
@@ -96,7 +89,7 @@ const TooltipTrigger = React.forwardRef<HTMLSpanElement, TooltipTriggerProps>(
96
89
  {...props}
97
90
  >
98
91
  {children}
99
- </span>
92
+ </Comp>
100
93
  )
101
94
  }
102
95
  )
@@ -109,13 +102,20 @@ const TooltipContent = React.forwardRef<
109
102
  const context = React.useContext(TooltipContext)
110
103
  if (!context) throw new Error("TooltipContent must be used within Tooltip")
111
104
 
105
+ const [mounted, setMounted] = React.useState(false)
106
+
107
+ React.useEffect(() => {
108
+ setMounted(true)
109
+ }, [])
110
+
112
111
  if (!context.open) return null
112
+ if (!mounted) return null
113
113
 
114
114
  // Offset from cursor (slightly above and to the right)
115
115
  const offsetX = 10
116
116
  const offsetY = -10
117
117
 
118
- return (
118
+ return createPortal(
119
119
  <div
120
120
  ref={ref}
121
121
  role="tooltip"
@@ -132,7 +132,8 @@ const TooltipContent = React.forwardRef<
132
132
  {...props}
133
133
  >
134
134
  {children}
135
- </div>
135
+ </div>,
136
+ document.body
136
137
  )
137
138
  })
138
139
  TooltipContent.displayName = "TooltipContent"