@empathyco/x-components
Version:
Empathy X Components
82 lines (79 loc) • 3.33 kB
JavaScript
import { defineComponent, inject, computed, provide, h } from 'vue';
import { LIST_ITEMS_KEY } from '../../../components/decorators/injection.consts.js';
import ItemsList from '../../../components/items-list.vue.js';
import { use$x } from '../../../composables/use-_x.js';
import { useState } from '../../../composables/use-state.js';
import { AnimationProp } from '../../../types/animation-prop.js';
import { searchXModule } from '../x-module.js';
/**
* It renders a {@link ItemsList} of promoteds from {@link SearchState.promoteds}.
*
* The component provides a default slot which wraps the whole component with the `promoteds`
* plus the `injectedListItems` which also contains the injected list items from
* the ancestor.
*
* It also provides the parent slots to customize the items.
*
* @public
*/
var _sfc_main = defineComponent({
name: 'PromotedsList',
xModule: searchXModule.name,
props: {
/** Animation component that will be used to animate the promoteds. */
animation: {
type: AnimationProp,
default: 'ul',
},
},
setup(props, { slots }) {
const $x = use$x();
/** The promoteds to render from the state. */
const stateItems = useState('search').promoteds;
/** It injects {@link ListItem} provided by an ancestor as injectedListItems. */
const injectedListItems = inject(LIST_ITEMS_KEY);
/**
* The `stateItems` concatenated with the `injectedListItems` if there are.
*
* @remarks This computed defines the merging strategy of the `stateItems` and the
* `injectedListItems`.
*
* @returns List of {@link ListItem}.
*/
const items = computed(() => {
if (!injectedListItems?.value.length) {
return stateItems.value;
}
const items = [...injectedListItems.value];
for (const item of stateItems.value) {
const position = item.position ?? 1;
let index = position - 1;
while (items.at(index)?.modelName === 'Promoted') {
index++;
}
const isIndexInLoadedPages = index <= items.length;
const areAllPagesLoaded = $x.results.length === $x.totalResults;
if (!isIndexInLoadedPages && !areAllPagesLoaded) {
break;
}
items.splice(index, 0, item);
}
return items;
});
/**
* The computed list items of the entity that uses the mixin.
*
* @remarks It should be overridden in the component that uses the mixin and it's intended to be
* filled with items from the state. Vue doesn't allow mixins as abstract classes.
* @returns An empty array as fallback in case it is not overridden.
*/
provide(LIST_ITEMS_KEY, items);
return () => {
const innerProps = { items: items.value, animation: props.animation };
// https://vue-land.github.io/faq/forwarding-slots#passing-all-slots
return slots.default?.(innerProps)[0] ?? h(ItemsList, innerProps, slots);
};
},
});
export { _sfc_main as default };
//# sourceMappingURL=promoteds-list.vue.js.map