@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.
- package/dist/index.js +24 -16
- package/package.json +2 -1
- package/src/registry/themes/v3/glass.css +154 -0
- package/src/registry/themes/v4/glass.css +181 -0
- package/src/registry/ui/alert-dialog.tsx +15 -10
- package/src/registry/ui/breadcrumb.tsx +4 -8
- package/src/registry/ui/button.tsx +7 -14
- package/src/registry/ui/collapsible.tsx +4 -9
- package/src/registry/ui/dialog.tsx +13 -10
- package/src/registry/ui/drawer.tsx +34 -10
- package/src/registry/ui/dropdown-menu.tsx +75 -31
- package/src/registry/ui/hover-card.tsx +92 -34
- package/src/registry/ui/popover.tsx +108 -20
- package/src/registry/ui/select.tsx +139 -39
- package/src/registry/ui/sheet.tsx +27 -10
- package/src/registry/ui/sidebar.tsx +28 -78
- package/src/registry/ui/slot.tsx +69 -0
- package/src/registry/ui/tooltip.tsx +15 -14
|
@@ -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
|
-
|
|
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
|
-
<
|
|
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
|
-
</
|
|
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"
|