import React, { HTMLProps, MutableRefObject, ReactElement } from "react"; import { chainFunctions, chainRefFunctions } from "../../utils/function-utils"; import { VibeComponentProps } from "../../types"; export const Refable = React.forwardRef< ReactElement, React.PropsWithChildren & VibeComponentProps> & { children: ReactElement | ReactElement[] | string; } // @ts-expect-error React forwardRef type def doesn't seem to support multiple refs >(({ children, ...rest }, ref) => { return React.Children.map(children, child => { if (!React.isValidElement(child)) return null; if (typeof child.type !== "string") { return ( } {...rest}> {React.cloneElement(child, { ...child.props })} ); } return React.cloneElement(child, { ...rest, ...child.props, onClick: getChainedFunction("onClick", child.props, rest), onBlur: getChainedFunction("onBlur", child.props, rest), onMouseEnter: getChainedFunction("onMouseEnter", child.props, rest), onMouseLeave: getChainedFunction("onMouseLeave", child.props, rest), onMouseDown: getChainedFunction("onMouseDown", child.props, rest), onFocus: getChainedFunction("onFocus", child.props, rest), // @ts-expect-error ref: chainRefFunctions([child.ref, ref as MutableRefObject]) }); }); }); function getChainedFunction( name: keyof React.HTMLProps, childProps: React.PropsWithChildren>, wrapperProps: React.HTMLProps ) { return chainFunctions([childProps[name], wrapperProps[name]], true); }