<!--


Provides a standardized way of specifying variants of a component. Variants are typically css-based
modifications to a component and might be defined by the component or declared in the app. Typical
usage might look like:

    Component code:
    <div :class="'bem(variantsMap)'" />

    User code:
    <my-control variant="one two" />

    This would produce:
    <div class="my-component my-component--one my-component--two" />

-->

<script>
import variants from '../utils/variants.js';
import { ensureArray, arrayHasCommonItem } from '../utils/utils.js';

export default {
    props: {
        /**
         * The variant property is intepreted in different ways by different components, but
         * typically used to trigger a different style or layout otherwise effect the way the
         * component is rendered or used.
         */
        variant: { type: [String, Array], default: null },
    },
    computed: {
        // get the value for variant (allows derived classes to provide a different source)
        variantValue() {
            return this.variant;
        },

        // return the variant as an array
        variantArray() {
            return this.toVariantsArray(this.variantValue);
        },

        // return the variant as a string
        variantString() {
            return this.variantArray.join(' ');
        },

        // variants as a map like {one: true, two: true}
        variantsMap() {
            return this.toVariantsMap(this.variantValue);
        },

        // all variants as an array
        variants() {
            return this.variantArray;
        },
    },
    methods: {
        // true if the given variant is present
        isVariant(variantStringOrArray) {
            const array = ensureArray(variantStringOrArray);
            return arrayHasCommonItem(this.variants, array);
        },

        // find the first matching variant key in a map and return the corresponding value (e.g. a
        // component with the variant "secondary" would return "black" for the map {primary: 'blue',
        // secondary: 'black'}})
        variantsToValue(valueMap, fallback) {
            for (let key in valueMap) {
                if (this.isVariant(key)) {
                    return valueMap[key];
                }
            }
            return fallback;
        },

        // convert a string or array to an array of variants
        toVariantsArray: stringOrArray => {
            return variants.toVariantsArray(stringOrArray);
        },

        // convert a string or array to a map of variants
        toVariantsMap: stringOrArray => {
            return variants.toVariantsMap(stringOrArray);
        },
    },
};
</script>
