11import { FocusableProvider } from '@react-aria/focus' ;
22import {
33 HTMLAttributes ,
4+ isValidElement ,
45 ReactElement ,
56 ReactNode ,
67 RefObject ,
@@ -23,6 +24,15 @@ import { TooltipContext } from './context';
2324const DEFAULT_OFFSET = 8 ; // Offset needed to reach 4px/5px (med/large) distance between tooltip and trigger button
2425const DEFAULT_CROSS_OFFSET = 0 ;
2526
27+ // Type guards
28+ function isTriggerFunction ( value : unknown ) : value is TooltipTriggerFunction {
29+ return typeof value === 'function' ;
30+ }
31+
32+ function isReactElement ( value : unknown ) : value is ReactElement {
33+ return isValidElement ( value ) ;
34+ }
35+
2636export type TooltipTriggerFunction = (
2737 triggerProps : HTMLAttributes < HTMLElement > ,
2838 ref : RefObject < HTMLElement > ,
@@ -95,12 +105,26 @@ export function TooltipTrigger(props: CubeTooltipTriggerProps) {
95105 const rawChildrenArray = Array . isArray ( children )
96106 ? ( children as unknown [ ] )
97107 : ( [ children ] as unknown [ ] ) ;
98- const childrenArray = rawChildrenArray as unknown as [
99- ReactElement | string | TooltipTriggerFunction ,
100- ReactElement ,
101- ] ;
102- let [ trigger , tooltip ] = childrenArray ;
103- const isTriggerFunction = typeof trigger === 'function' ;
108+
109+ const [ trigger , tooltip ] = rawChildrenArray ;
110+
111+ // Type guard the tooltip
112+ if ( ! isReactElement ( tooltip ) ) {
113+ throw new Error (
114+ 'CubeUIKit: TooltipTrigger expects the second child to be a valid React element (Tooltip component).' ,
115+ ) ;
116+ }
117+
118+ // Type guard the trigger
119+ if (
120+ ! isTriggerFunction ( trigger ) &&
121+ ! isReactElement ( trigger ) &&
122+ typeof trigger !== 'string'
123+ ) {
124+ throw new Error (
125+ 'CubeUIKit: TooltipTrigger expects the first child to be a function, React element, or string.' ,
126+ ) ;
127+ }
104128
105129 // Show deprecation warning for activeWrap
106130 if ( activeWrap && process . env . NODE_ENV === 'development' ) {
@@ -151,12 +175,10 @@ export function TooltipTrigger(props: CubeTooltipTriggerProps) {
151175 } ;
152176
153177 // Function trigger pattern (new)
154- if ( isTriggerFunction ) {
155- const triggerFn = trigger as TooltipTriggerFunction ;
156-
178+ if ( isTriggerFunction ( trigger ) ) {
157179 return (
158180 < >
159- { triggerFn ( triggerProps , tooltipTriggerRef ) }
181+ { trigger ( triggerProps , tooltipTriggerRef ) }
160182 < TooltipContext . Provider value = { tooltipContextValue } >
161183 < OverlayWrapper
162184 isOpen = { state . isOpen }
0 commit comments