@empathyco/x-components
Version:
Empathy X Components
126 lines (123 loc) • 5.17 kB
JavaScript
import { defineComponent, computed, ref, inject, provide, watch } from 'vue';
import { useXBus } from '../../composables/use-x-bus.js';
import { RESULT_WITH_VARIANTS_KEY, SELECTED_VARIANTS_KEY, SELECT_RESULT_VARIANT_KEY } from '../decorators/injection.consts.js';
/**
* Component that exposes the result merged with its selected variant in the default slot.
*
* It receives the original result and keeps track of the selected variant.
*
* It provides the original result, the array containing the selected variants and a callback to
* set the selected variant to be used from a child.
*
* @public
*/
var _sfc_main = defineComponent({
name: 'ResultVariantsProvider',
props: {
/** The original result containing the variants. */
result: {
type: Object,
required: true,
},
/**
* The provider by default will auto select the first variants of all levels.
* This prop allows to limit the number of variants auto selected when the provider is created.
* Take into account that the depth will be the variants level + 1, so, setting autoSelectDepth
* to 0 will not select any variant, setting it to 1 will select only the first variant of the
* first level, and so on.
*/
autoSelectDepth: {
type: Number,
default: Number.POSITIVE_INFINITY,
},
},
setup(props, { slots }) {
const xBus = useXBus();
/**
* The original result containing the variants as a computed ref object to enable watching
* prop changes.
*/
const result = computed(() => props.result);
/**
* Array to keep track of the selected variants of the result.
* Each position of the array is a nest level in the variants' hierarchy, so,
* the second position will contain a variant that is present inside the variant of the first
* position, and so on.
*/
const selectedVariants = ref([]);
/**
* It injects the queryPreviewHash provided by a query-preview.
*
* @internal
*/
const queryPreviewHash = inject('queryPreviewHash', null);
/**
* Selects a variant of the result.
* When called, it slices the array of selected variants to remove the selected child variants.
* Emits the {@link XEventsTypes.UserSelectedAResultVariant} when called.
*
* @param variant - The variant to set.
* @param level - The nest level where the variant is placed inside the result.
*/
function selectResultVariant(variant, level = 0) {
if (selectedVariants.value[level] === variant) {
return;
}
selectedVariants.value.splice(level, Number.POSITIVE_INFINITY, variant);
xBus.emit('UserSelectedAResultVariant', {
variant,
level,
result: result.value,
queryPreviewHash,
});
}
/**
* Merges the original result with the selected variant.
* The merge is done with all the selected variants of the array.
*
* @returns - The result with the selected variant merged.
*/
const resultToProvide = computed(() => {
if (!selectedVariants.value.length) {
return result.value;
}
const mergedResult = selectedVariants.value.reduce((result, variant) => {
return {
...result,
...variant,
};
}, result.value);
mergedResult.variants = result.value.variants;
return mergedResult;
});
/**
* Adds to the selectedVariants array the variants up to the autoSelectDepth level.
*
* @param variant - Variant to add to the array.
*/
function selectFirstVariants(variant) {
if (!!variant && selectedVariants.value.length <= props.autoSelectDepth - 1) {
selectedVariants.value.push(variant);
selectFirstVariants(variant.variants?.[0]);
}
}
/** Provides the original result passed as a prop. */
provide(RESULT_WITH_VARIANTS_KEY, result);
/** The selected variants of the result. */
provide(SELECTED_VARIANTS_KEY, selectedVariants);
/** The result variant key that will be selected. */
provide(SELECT_RESULT_VARIANT_KEY, selectResultVariant);
/**
* Resets the selected variants when the result changes.
* That includes doing the auto selection of the variants when the component is created
* and when the result is changed.
*/
watch(result, () => {
selectedVariants.value = [];
selectFirstVariants(result.value?.variants?.[0]);
}, { immediate: true });
return () => slots.default?.({ result: resultToProvide.value })[0] ?? '';
},
});
export { _sfc_main as default };
//# sourceMappingURL=result-variants-provider.vue.js.map