cartesian combinations for component variants

50 views Asked by At

Let's say I have an object specifying inputs for a button component, and the possible values of that input.

const buttonVariants = {
  colorMode: ['on-dark','on-light'],
  size: ['small','medium','large']
};

How could I create a cartesian function to generate templates for all possible combinations of the variants? I'd like to be able to re-use this function for multiple components, so it's important to specify that I'd need this to work for n variants.

I'm hoping to achieve something like this but where the output would be:

[
  '<button colorMode="on-dark" size="small">button</button>',
  '<button colorMode="on-dark" size="medium">button</button>',
  '<button colorMode="on-dark" size="large">button</button>',
  '<button colorMode="on-light" size="small">button</button>',
  '<button colorMode="on-light" size="medium">button</button>',
  '<button colorMode="on-light" size="large">button</button>'
]
2

There are 2 answers

0
Gladitor On BEST ANSWER

You can achieve this by first creating a generic function to generate the Cartesian product of multiple arrays. This function will be useful for generating all possible combinations of the variants you have. Then, you can map these combinations to generate the desired button templates. Let's implement this in JavaScript:

function cartesianProduct(arrays) {
    return arrays.reduce((acc, currentValue) => 
        acc.flatMap(c => currentValue.map(value => [...c, value])), 
        [[]]);
}

function generateButtonTemplates(variants) {
    // Extract variant keys and their possible values
    const keys = Object.keys(variants);
    const values = keys.map(key => variants[key]);
    
    // Generate all combinations of variant values
    const combinations = cartesianProduct(values);
    
    // Map each combination to a button template
    return combinations.map(combination => {
        const attributes = combination.map((value, index) => `${keys[index]}="${value}"`).join(' ');
        return `<button ${attributes}>button</button>`;
    });
}

const buttonVariants = {
  colorMode: ['on-dark', 'on-light'],
  size: ['small', 'medium', 'large']
};

console.log(generateButtonTemplates(buttonVariants));

By running this code, you will get the output in the format you specified, allowing you to generate templates for all possible combinations of the variants.

0
Alexander Nenashev On

You can use Array::flatMap() to map all color/size combinations:

const buttonVariants = {
  colorMode: ['on-dark','on-light'],
  size: ['small','medium','large']
};

const buttons = buttonVariants.colorMode.flatMap(c => 
  buttonVariants.size.map(s => `<button colorMode="${c}" size="${s}">button</button>`)
);

console.log(buttons);