import type { ElementType } from 'react' ; import { BoxElements } from '@xstyled/core' ; import { string } from '@xstyled/util' ; import { StyleGenerator , StyleGeneratorProps , Theme } from '@xstyled/system' ; import { StyledConfig , ThemedBaseStyledInterface , ThemedStyledFunction , } from 'styled-components' ; import { scStyled } from './scStyled' ; import { createCssFunction , XCSSFunction } from './createCssFunction' ; const getCreateStyle = ( baseCreateStyle , css , generator ? ) => { const createStyle = ( ... args ) => baseCreateStyle `${ css ( ... args ) }${ generator }` ; createStyle . attrs = ( attrs ) => getCreateStyle ( baseCreateStyle . attrs ( attrs ) , css , generator ) ; createStyle . withConfig = ( config ) => getCreateStyle ( baseCreateStyle . withConfig ( config ) , css , generator ) ; return createStyle ; } ; type BoxStyledTags < TProps extends object > = { [ Key in keyof BoxElements ] : ThemedStyledFunction < BoxElements [ Key ] , Theme , TProps > ; } ; export interface XStyled < TGen extends StyleGenerator > extends ThemedBaseStyledInterface < Theme > , BoxStyledTags < StyleGeneratorProps < TGen > > { } const createShouldForwardProp = ( generator ) : ( ( prop : string | number | symbol , defaultValidatorFn : ( prop : string | number | symbol ) => boolean , elementToBeCreated ? : ElementType ) => boolean ) => { const propSet = new Set < string > ( generator . meta . props ) ; return ( prop , defaultValidatorFn , elementToBeCreated ? ) => { if ( string ( prop ) && propSet . has ( prop ) ) { return false ; } if ( typeof elementToBeCreated === 'string' ) { return defaultValidatorFn ( prop ) ; } return true ; } ; } ; export const createBaseStyled = < TGen extends StyleGenerator > ( css , generator ? ) : XStyled < TGen > => { const config = generator ? { shouldForwardProp : createShouldForwardProp ( generator ) , } : { } ; return ( ( component ) => { const baseStyled = scStyled ( component ) ; return getCreateStyle ( config ? baseStyled . withConfig ( config ) : baseStyled , css , generator ) ; } ) as XStyled < TGen > ; } ; export const createStyled = < TGen extends StyleGenerator > ( generator ) : XStyled < TGen > => { const css = createCssFunction ( generator ) ; const styled = createBaseStyled ( css ) ; const xstyled = createBaseStyled ( css , generator ) ; styled . box = xstyled ( 'div' ) ; Object . keys ( scStyled ) . forEach ( ( key ) => { styled [ key ] = styled ( key ) ; styled [ `${ key }Box` ] = xstyled ( key ) ; } ) ; return styled ; } ;