UNPKG

tailwind-system

Version:

Inspired by [Styled System](https://styled-system.com), tailwind-system allow you add props to your components which are then converted to [Tailwind](https://tailwindcss.com) utility classes. It can be used with Vue or React.

117 lines (105 loc) 3.39 kB
const dashCase = str => str.replace(/[A-Z]/g, m => '-' + m.toLowerCase()) /* // Small (sm) @media (min-width: 640px) {} // Medium (md) @media (min-width: 768px) { } // Large (lg) @media (min-width: 1024px) { } // Extra Large (xl) @media (min-width: 1280px) { } */ const getBreakPointsDefault = values => (['', 'sm', 'md', 'lg', 'xl']) const objectToClassNames = ({ value, key, mapKeys }) => { const breakpoints = Object.keys(value) const names = breakpoints.reduce((acc, breakpoint) => { const val = value[breakpoint] return [...acc, toClassName({ value: val, key, breakpoint, mapKeys })] }, []) return names.join(' ') } const arrayToClassNames = ({ value, key, mapKeys, getBreakPoints }) => { const classNameBreakpoints = getBreakPoints ? getBreakPoints(value) : getBreakPointsDefault(value) const names = value.reduce((acc, val, index) => { const breakpoint = classNameBreakpoints[index] return [...acc, toClassName({ value: val, key, breakpoint, mapKeys })] }, []) return names.join(' ') } /** * * @param value * @param key * @param mapKeys * @param breakpoint * @returns {string|null} */ const toClassName = ({ value, key, mapKeys, breakpoint = '' }) => { const classNameKey = dashCase(key) const name = mapKeys && mapKeys[classNameKey] !== undefined ? mapKeys[classNameKey] : classNameKey const breakpointPrefix = breakpoint ? breakpoint + ':' : '' if (typeof value === 'boolean') { return value ? `${breakpointPrefix}${name}` : null } else if (value === '') { //assume is true return `${breakpointPrefix}${name}` } else { const prefix = name === '' ? '' : `${name}-` if (parseInt(value) < 0) { return `${breakpointPrefix}-${prefix}${Math.abs(value)}` } return `${breakpointPrefix}${prefix}${value}` } } /*** * * @param props * @param mapKeys * @returns {*[]} */ const reduceClassNames = ({ props, mapKeys, getBreakPoints }) => { const propsKeys = Object.keys(props) return Object.keys(props) .filter(name => propsKeys.find(key => key === name)) .reduce((acc, key) => { let value = props[key] if (value !== undefined) { let className = toClassName({ value, key, mapKeys }) if (Array.isArray(value)) { // css classname exists for breakpoint className = arrayToClassNames({ value, key, mapKeys, getBreakPoints }) } else if (typeof value === 'object') { className = objectToClassNames({ value, key, mapKeys }) } if (className) { return [...acc, className] } } return acc }, []) } const classesToString = arr => arr.filter(arr => arr.length > 0).join(' ') /** * const mapKeys = { 'text-align': 'text', display: '' } const classNameProps = propTypes.box const classNames = propsToClasses(props, classNameProps, { mapKeys }) const classNames = computed( () => propsToClasses(props, classNameProps, { mapKeys })) * * @param data * @param props * @param options * @returns {string|*} */ const propsToClasses = (props, classNameProps, options = {}) => { const { mapKeys, getBreakPoints } = options const classProps = {} Object.keys(classNameProps).forEach((key) => { classProps[key] = props[key] }) return classesToString(reduceClassNames({ props:classProps, mapKeys, getBreakPoints })) } export default propsToClasses