UNPKG

@variantjs/core

Version:

VariantJS common functions and utilities

175 lines (142 loc) 7.32 kB
import { ObjectWithClassesList, VariantsWithClassesList, WithVariantPropsAndClassesList, WithVariantProps, } from './types/Variants'; import pick from './helpers/pick'; import mergeClasses from './mergeClasses'; import { CSSClassesList, CSSRawClassesList } from './types'; import hasProperty from './helpers/hasProperty'; const getCustomPropsFromVariant = < P extends ObjectWithClassesList, ClassesKeys extends string, >( variants?: VariantsWithClassesList<P, ClassesKeys>, variant?: string, ): WithVariantPropsAndClassesList<P, ClassesKeys> | undefined => { if (variant !== undefined && variants) { return variants[variant]; } return undefined; }; const getShouldClearClasses = < P extends ObjectWithClassesList, ClassesKeys extends string, >(props: WithVariantPropsAndClassesList<P, ClassesKeys>, key: string, variant: string | undefined): boolean => { if (variant === undefined) { return hasProperty(props, key) && (props[key] === undefined || props[key] === null); } if (props.variants !== undefined && props.variants[variant] !== undefined) { const propsVariant = props.variants[variant] as WithVariantProps<P>; return hasProperty(propsVariant, key) && (propsVariant[key] === undefined || propsVariant[key] === null); } return false; }; const parseVariantWithClassesList = < P extends ObjectWithClassesList, ClassesKeys extends string, >( props: WithVariantPropsAndClassesList<P, ClassesKeys>, classesListKeys: Readonly<Array<ClassesKeys>>, globalConfiguration?: WithVariantPropsAndClassesList<P, ClassesKeys>, defaultConfiguration?: WithVariantPropsAndClassesList<P, ClassesKeys>, ): P => { const { variants, variant, ...mainProps } = { ...defaultConfiguration, ...globalConfiguration, ...props, }; const classes: Partial<CSSRawClassesList<ClassesKeys>> = {}; const fixedClasses: Partial<CSSRawClassesList<ClassesKeys>> = {}; const clearClasses = getShouldClearClasses(props, 'classes', variant); const clearFixedClasses = getShouldClearClasses(props, 'fixedClasses', variant); if (clearClasses) { classesListKeys.forEach((classItemKey) => { classes[classItemKey] = undefined; }); } else { classesListKeys.forEach((classItemKey) => { if (props.classes !== undefined && hasProperty(props.classes, classItemKey)) { classes[classItemKey] = props.classes[classItemKey]; } else if (globalConfiguration !== undefined && globalConfiguration.classes !== undefined && hasProperty(globalConfiguration.classes, classItemKey)) { classes[classItemKey] = globalConfiguration.classes[classItemKey]; } else if (defaultConfiguration !== undefined && defaultConfiguration.classes !== undefined && hasProperty(defaultConfiguration.classes, classItemKey)) { classes[classItemKey] = defaultConfiguration.classes[classItemKey]; } if (variant) { if (props.variants !== undefined && props.variants[variant] !== undefined) { const propsVariant = props.variants[variant] as WithVariantProps<P>; if (propsVariant.classes && hasProperty(propsVariant.classes, classItemKey)) { classes[classItemKey] = propsVariant.classes[classItemKey]; } } else if (globalConfiguration !== undefined && globalConfiguration.variants !== undefined && globalConfiguration.variants[variant] !== undefined) { const globalConfigurationVariant = globalConfiguration.variants[variant] as WithVariantProps<P>; if (globalConfigurationVariant.classes && hasProperty(globalConfigurationVariant.classes, classItemKey)) { classes[classItemKey] = globalConfigurationVariant.classes[classItemKey]; } } else if (defaultConfiguration !== undefined && defaultConfiguration.variants !== undefined && defaultConfiguration.variants[variant] !== undefined) { const defaultConfigurationVariant = defaultConfiguration.variants[variant] as WithVariantProps<P>; if (defaultConfigurationVariant.classes && hasProperty(defaultConfigurationVariant.classes, classItemKey)) { classes[classItemKey] = defaultConfigurationVariant.classes[classItemKey]; } } } }); } if (clearFixedClasses) { classesListKeys.forEach((classItemKey) => { fixedClasses[classItemKey] = undefined; }); } else { classesListKeys.forEach((classItemKey) => { if (props.fixedClasses !== undefined && hasProperty(props.fixedClasses, classItemKey)) { fixedClasses[classItemKey] = props.fixedClasses[classItemKey]; } else if (globalConfiguration !== undefined && globalConfiguration.fixedClasses !== undefined && hasProperty(globalConfiguration.fixedClasses, classItemKey)) { fixedClasses[classItemKey] = globalConfiguration.fixedClasses[classItemKey]; } else if (defaultConfiguration !== undefined && defaultConfiguration.fixedClasses !== undefined && hasProperty(defaultConfiguration.fixedClasses, classItemKey)) { fixedClasses[classItemKey] = defaultConfiguration.fixedClasses[classItemKey]; } if (variant) { if (props.variants !== undefined && props.variants[variant] !== undefined) { const propsVariant = props.variants[variant] as WithVariantProps<P>; if (propsVariant.fixedClasses && hasProperty(propsVariant.fixedClasses, classItemKey)) { fixedClasses[classItemKey] = propsVariant.fixedClasses[classItemKey]; } } else if (globalConfiguration !== undefined && globalConfiguration.variants !== undefined && globalConfiguration.variants[variant] !== undefined) { const globalConfigurationVariant = globalConfiguration.variants[variant] as WithVariantProps<P>; if (globalConfigurationVariant.fixedClasses && hasProperty(globalConfigurationVariant.fixedClasses, classItemKey)) { fixedClasses[classItemKey] = globalConfigurationVariant.fixedClasses[classItemKey]; } } else if (defaultConfiguration !== undefined && defaultConfiguration.variants !== undefined && defaultConfiguration.variants[variant] !== undefined) { const defaultConfigurationVariant = defaultConfiguration.variants[variant] as WithVariantProps<P>; if (defaultConfigurationVariant.fixedClasses && hasProperty(defaultConfigurationVariant.fixedClasses, classItemKey)) { fixedClasses[classItemKey] = defaultConfigurationVariant.fixedClasses[classItemKey]; } } } }); } const customProps = getCustomPropsFromVariant(variants, variant); const mergedProps = { ...mainProps, ...customProps, }; delete mergedProps.fixedClasses; delete mergedProps.classes; const mergedClasses: CSSClassesList = {}; classesListKeys.forEach((classItemKey) => { const classesForTheCurrentKey = classes[classItemKey]; const fixedClassesForTheCurrentKey = fixedClasses[classItemKey]; mergedClasses[classItemKey as string] = mergeClasses( classesForTheCurrentKey, fixedClassesForTheCurrentKey, ); }); const result = pick(mergedClasses); if (Object.keys(result).length > 0) { (mergedProps as P).classesList = result; } return mergedProps as P; }; export default parseVariantWithClassesList;