import React from "react"; import { useMergeRefs } from "../../hooks"; import { mergeProps } from "./merge-props"; interface SlotProps extends React.HTMLAttributes { children?: React.ReactNode; } /** * Workaround for RSC related issue. * https://github.com/radix-ui/primitives/issues/3776#issuecomment-3649236326 */ function unwrapLazy(element: React.ReactNode) { const arr = React.Children.toArray(element); return arr.length === 1 ? arr[0] : element; } function getChildRef(children: React.ReactNode): React.Ref | null { if (!React.isValidElement(children)) { return null; } return Object.prototype.propertyIsEnumerable.call(children.props, "ref") ? (children.props as any).ref // React 19 (children.ref still works, but gives a warning) : (children as any).ref; // React <19 } const Slot = React.forwardRef((props, forwardedRef) => { const { children, ...slotProps } = props; const resolvedChildren = unwrapLazy(children); const childRef = getChildRef(resolvedChildren); const mergedRef = useMergeRefs(forwardedRef, childRef); if (React.isValidElement(resolvedChildren)) { return React.cloneElement(resolvedChildren, { ...mergeProps(slotProps, resolvedChildren.props as any), ref: mergedRef, }); } if (React.Children.count(resolvedChildren) > 1) { const error = new Error( "Aksel: Components using 'asChild' expects to recieve a single React element child.", ); error.name = "SlotError"; Error.captureStackTrace?.(error, Slot); throw error; } return null; }); export { Slot, type SlotProps };