"use client"; import type { HTMLMotionProps } from "motion/react"; import { isMotionComponent, motion } from "motion/react"; import * as React from "react"; import { cn } from "@/lib/utils"; type AnyProps = Record; type DOMMotionProps = Omit< HTMLMotionProps, "ref" > & { ref?: React.Ref }; type WithAsChild = | (Base & { asChild: true; children: React.ReactElement }) | (Base & { asChild?: false | undefined }); type SlotProps = { children?: any; } & DOMMotionProps; function mergeRefs( ...refs: (React.Ref | undefined)[] ): React.RefCallback { return (node) => { refs.forEach((ref) => { if (!ref) return; if (typeof ref === "function") { ref(node); } else { (ref as React.RefObject).current = node; } }); }; } function mergeProps( childProps: AnyProps, slotProps: DOMMotionProps, ): AnyProps { const merged: AnyProps = { ...childProps, ...slotProps }; if (childProps.className || slotProps.className) { merged.className = cn( childProps.className as string, slotProps.className as string, ); } if (childProps.style || slotProps.style) { merged.style = { ...(childProps.style as React.CSSProperties), ...(slotProps.style as React.CSSProperties), }; } return merged; } function Slot({ children, ref, ...props }: SlotProps) { const isAlreadyMotion = typeof children.type === "object" && children.type !== null && isMotionComponent(children.type); const Base = React.useMemo( () => isAlreadyMotion ? (children.type as React.ElementType) : motion.create(children.type as React.ElementType), [isAlreadyMotion, children.type], ); if (!React.isValidElement(children)) return null; const { ref: childRef, ...childProps } = children.props as AnyProps; const mergedProps = mergeProps(childProps, props); return ( , ref)} /> ); } export { type AnyProps, type DOMMotionProps, Slot, type SlotProps, type WithAsChild, };