import clsx from "clsx"; import { createContext, forwardRef, useContext } from "react"; type Recipe> = (( props?: Props, ) => string) & { splitVariantProps: (props: T) => [Props, Omit]; }; export function createRecipeContext>( recipe: Recipe, ) { const PropsContext = createContext(null); const PropsProvider = ({ children, value }: { children: React.ReactNode; value: Props }) => { return {children}; }; function useProps() { return useContext(PropsContext); } const withContext = ( Component: React.ElementType, options?: { defaultProps?: Partial

; }, ): React.ForwardRefExoticComponent & React.RefAttributes> => { const { defaultProps } = options ?? {}; const StyledComponent = forwardRef((innerProps, ref) => { const props = { ...(defaultProps ?? {}), ...useProps(), ...innerProps } as Props & React.HTMLAttributes; const [variantProps, otherProps] = recipe.splitVariantProps(props); const className = recipe(variantProps); // TODO: should we memoize this? return ; }); StyledComponent.displayName = (Component as any).displayName || (Component as any).name; return StyledComponent as any; }; function withPropsProvider

(): React.Provider> { return PropsProvider as any; } return { PropsProvider, useProps, withContext, withPropsProvider, }; }