@empathyco/x-components
Version:
Empathy X Components
93 lines (90 loc) • 3.65 kB
JavaScript
import { defineComponent, inject, computed } from 'vue';
import { SELECT_RESULT_VARIANT_KEY, RESULT_WITH_VARIANTS_KEY, SELECTED_VARIANTS_KEY } from '../decorators/injection.consts.js';
/**
* Component to show and select the available variants of a product for a given nest level.
* TODO: Log warning on mount when result is not injected.
*
* @public
*/
var _sfc_main = defineComponent({
name: 'ResultVariantSelector',
props: {
/** The nest level of the variants to be rendered. */
level: {
type: Number,
default: 0,
},
},
setup(props, { slots }) {
/**
* Callback to be called when a variant is selected.
*
* @public
* @returns The 'selectResultVariant' injection key.
*/
const selectResultVariant = inject(SELECT_RESULT_VARIANT_KEY);
/** The original result, used to retrieve the available variants for the level. */
const result = inject(RESULT_WITH_VARIANTS_KEY);
/** Array containing the selected variants. */
const selectedVariants = inject(SELECTED_VARIANTS_KEY);
/**
* It retrieves the available variants from the result.
*
* @returns - The variants of the result for the current level.
*/
const variants = computed(() => {
if (props.level === 0) {
return result.value?.variants;
}
return selectedVariants.value[props.level - 1]?.variants;
});
/**
* Gets the selected variant of the current level.
*
* @returns - The selected variant.
*/
const selectedVariant = computed(() => variants.value?.find(variant => variant === selectedVariants.value[props.level]));
/**
* Calls the provided method to select a variant.
*
* @param variant - Variant to select.
*/
const selectVariant = (variant) => {
selectResultVariant(variant, props.level);
};
/**
* Checks if a variant is selected.
*
* @param variant - Variant to check.
* @returns True if the variant is selected, false if not.
*/
const variantIsSelected = (variant) => {
return selectedVariant.value === variant;
};
/**
* Render function to execute the `default` slot, binding `slotsProps` and getting only the
* first `vNode` to avoid Fragments and Text root nodes.
* If there are no result or variants, nothing is rendered.
*
* @remarks `slotProps` must be values without Vue reactivity and located inside the
* render-function to update the binding data properly.
*
* @returns The root `vNode` of the `default` slot or empty string if there are
* no result or variants.
*/
function renderDefaultSlot() {
const slotProps = {
variants: variants.value,
selectedVariant: selectedVariant.value,
selectVariant,
};
return result && variants.value ? slots.default?.(slotProps)[0] : '';
}
/* Hack to render through a render-function, the `default` slot or, in its absence,
the component itself. It is the alternative for the NoElement antipattern. */
const componentProps = { result, variants, variantIsSelected, selectVariant };
return (slots.default ? renderDefaultSlot : componentProps);
},
});
export { _sfc_main as default };
//# sourceMappingURL=result-variant-selector.vue2.js.map