UNPKG

@area17/a17-tailwind-plugins

Version:

A collection of Tailwind plugins to help build responsive design systems in collaboration with A17 design and development build methodologies

149 lines (133 loc) 4.16 kB
module.exports = function ({ addBase, matchUtilities, theme }) { const spacingGroups = theme('spacingGroups', {}); const breakpoints = theme('screens'); const firstBp = Object.keys(breakpoints)[0]; const cssSpacingProps = { m: ['margin'], mt: ['margin-top'], mb: ['margin-bottom'], mr: ['margin-right'], ml: ['margin-left'], mx: ['margin-inline'], my: ['margin-block'], ms: ['margin-inline-start'], me: ['margin-inline-end'], p: ['padding'], pt: ['padding-top'], pb: ['padding-bottom'], pr: ['padding-right'], pl: ['padding-left'], ps: ['padding-inline-start'], pe: ['padding-inline-end'], px: ['padding-inline'], py: ['padding-block'], gap: ['gap'], 'gap-x': ['column-gap'], 'gap-y': ['row-gap'], top: ['top'], bottom: ['bottom'], left: ['left'], right: ['right'], start: ['inset-inline-start'], end: ['inset-inline-end'], inset: ['inset'], 'inset-x': ['inset-inline'], 'inset-y': ['inset-block'], }; const rootStyles = { ':root': {}, }; // create root bp keys in bp order Object.keys(breakpoints).forEach((bp) => { if (bp !== firstBp) { rootStyles[`@media (width >= ${breakpoints[bp]})`] = { ':root': {} }; } }); // fill in root bp sizing info and make classes Object.entries(spacingGroups).forEach((group) => { const [name, spacings] = group; Object.entries(spacings).forEach((spacing) => { let [bp, space] = spacing; if (space && typeof space === 'number') { space = parseInt(space, 10) / 16 + 'rem'; } if (bp === firstBp) { rootStyles[':root'][`--spacing-${name}`] = space; } else { rootStyles[`@media (width >= ${breakpoints[bp]})`][':root'][`--spacing-${name}`] = space; } }); }); // clean up empty keys Object.keys(rootStyles).forEach((key) => { if ( key !== ':root' && rootStyles[key][':root'] && Object.keys(rootStyles[key][':root']).length === 0 && rootStyles[key][':root'].constructor === Object ) { delete rootStyles[key]; } }); // add root styles addBase(rootStyles); // add utility classes const valuesCalc = () => { let obj = {}; Object.keys(spacingGroups).forEach((group) => { obj[group] = group; }); return obj; }; const values = valuesCalc(); const spacingStyles = {}; function add(cssSelector, cssAttributes) { let selector = {}; selector[`${cssSelector}`] = (value) => { if(!value || typeof value !== 'string') { return {}; } // clean up the value to match spacing groups // e.g. 'calc(spacing-1 * -1)' becomes 'spacing-1' const cleanedValue = value.replace(/calc\(/i, '').replace(/ \* -1\)/i, ''); if ( !(cleanedValue in spacingGroups) || cleanedValue.indexOf('var(') > -1 ) { return {}; } let negative = typeof(value) === 'string' && value.indexOf('calc') > -1; let attributes = {}; if (negative) { value = value.replace(/calc\(/i, ''); value = value.replace(/ \* -1\)/i, ''); if (typeof(cssAttributes) === 'string') { attributes[cssAttributes] = `calc(var(--spacing-${value}) * -1)`; } if (typeof(cssAttributes) === 'object' && Array.isArray(cssAttributes)) { cssAttributes.forEach(cssAttribute => { attributes[cssAttribute] = `calc(var(--spacing-${value}) * -1)`; }); } } else { if (typeof(cssAttributes) === 'string') { attributes[cssAttributes] = `var(--spacing-${value})`; } if (typeof(cssAttributes) === 'object' && Array.isArray(cssAttributes)) { cssAttributes.forEach(cssAttribute => { attributes[cssAttribute] = `var(--spacing-${value})`; }); } } return attributes; }; matchUtilities(selector, { values: values, supportsNegativeValues: true, }); } Object.keys(cssSpacingProps).forEach(prop => { let attributes = cssSpacingProps[prop]; add(prop, attributes); }); };