import React, { ComponentType, PropsWithChildren } from 'react' import type { ThemedOptions, StyledProps, DripsyVariant } from './types' import { useDripsyTheme } from '../use-dripsy-theme' import { useBreakpointIndex } from './breakpoint-context' import { mapPropsToStyledComponent } from './map-props' import { DripsyFinalTheme } from '../declarations' import { useStableMemo } from '../utils/use-stable-memo' type MergeProps = Omit & P2 type PropsWithoutVariants

= Omit type PropsWithStyledProps = P & StyledProps // prettier-ignore export type Props = C extends ComponentType ? MergeProps, PropsWithStyledProps> : never export function createThemedComponent< C extends ComponentType, ExtraProps, ThemeKey extends keyof DripsyFinalTheme >( Component: C, { defaultStyle: baseStyle, ...options }: ThemedOptions = {} ): React.ForwardRefExoticComponent< React.PropsWithoutRef>> & React.RefAttributes> > { const WrappedComponent = React.forwardRef< any, Props & { style?: any } >(function Wrapped(prop, ref) { const { sx: _sx, as: SuperComponent, variant, style, themeKey = options.themeKey, variants = options.defaultVariants, ...props } = prop if (typeof __DEV__ !== 'undefined' && typeof SuperComponent === 'string') { console.error( `[dripsy] Looks like you used an invalid "as" prop. "${SuperComponent}" can't be string. Please pass a valid React component. HTML elements are not supported.` ) } const defaultStyle = typeof baseStyle == 'function' ? baseStyle(prop) : baseStyle const { theme } = useDripsyTheme() // make the sx factory out here so that it's a stable dependency for useStableMemo const sx = typeof _sx == 'function' ? _sx(theme) : _sx const breakpoint = useBreakpointIndex() const { styles } = useStableMemo( () => mapPropsToStyledComponent( { theme, breakpoint, variant, sx, style, variants: variants as DripsyVariant[] | undefined, }, { ...options, themeKey, defaultStyle, } ), [theme, breakpoint, variant, sx, style, variants, themeKey, defaultStyle] ) const TheComponent = SuperComponent || Component return }) WrappedComponent.displayName = `Dripsy.${ Component?.displayName ?? 'NoNameComponent' }` return WrappedComponent }