UNPKG

@empathyco/x-components

Version:
152 lines (149 loc) 5.88 kB
import { defineComponent, inject, computed, provide, h } from 'vue'; import { QUERY_KEY, HAS_MORE_ITEMS_KEY, LIST_ITEMS_KEY } from '../../../components/decorators/injection.consts.js'; import ItemsList from '../../../components/items-list.vue.js'; import { useState } from '../../../composables/use-state.js'; import { AnimationProp } from '../../../types/animation-prop.js'; import { groupItemsBy } from '../../../utils/array.js'; import { relatedPromptsXModule } from '../x-module.js'; /** * Component that inserts groups of related prompts in different positions of the injected search * items list, based on the provided configuration. * * @public */ var _sfc_main = defineComponent({ name: 'RelatedPromptsList', xModule: relatedPromptsXModule.name, props: { /** * Animation component that will be used to animate the related prompts groups. */ animation: { type: AnimationProp, default: 'ul', }, /** * The first index to insert a group of related prompts at. */ offset: { type: Number, default: 24, }, /** * The items cycle size to keep inserting related prompts groups at. */ frequency: { type: Number, default: 24, }, /** * The maximum amount of related prompts to add in a single group. */ maxRelatedPromptsPerGroup: { type: Number, default: 4, }, /** * The maximum number of groups to insert into the injected list items list. */ maxGroups: { type: Number, default: undefined, }, /** * Determines if a group is added to the injected items list in case the number * of items is smaller than the offset. */ showOnlyAfterOffset: { type: Boolean, default: false, }, }, setup(props, { slots }) { /** * The state related prompts. */ const { query, status, relatedPrompts } = useState('relatedPrompts'); /** * Injected query, updated when the related request(s) have succeeded. */ const injectedQuery = inject(QUERY_KEY); /** * Indicates if there are more available results than the injected. */ const hasMoreItems = inject(HAS_MORE_ITEMS_KEY); /** * The grouped related prompts based on the given config. * * @returns A list of related prompts groups. */ const relatedPromptsGroups = computed(() => Object.values(groupItemsBy(relatedPrompts.value, (_, index) => Math.floor(index / props.maxRelatedPromptsPerGroup))) .slice(0, props.maxGroups) .map((relatedPrompts, index) => ({ modelName: 'RelatedPromptsGroup', id: `related-prompts-group-${index}`, relatedPrompts, }))); /** * It injects {@link ListItem} provided by an ancestor as injectedListItems. */ const injectedListItems = inject(LIST_ITEMS_KEY); /** * Checks if the related prompts are outdated taking into account the injected query. * * @returns True if the related prompts are outdated, false if not. */ const relatedPromptsAreOutdated = computed(() => !!injectedQuery?.value && (query.value !== injectedQuery.value || status.value !== 'success')); /** * Checks if the number of items is smaller than the offset so a group * should be added to the injected items list. * * @returns True if a group should be added, false if not. */ const hasNotEnoughListItems = computed(() => !props.showOnlyAfterOffset && !hasMoreItems?.value && injectedListItems !== undefined && injectedListItems.value.length > 0 && props.offset > injectedListItems.value.length); /** * New list of {@link ListItem}s to render. * * @returns The new list of {@link ListItem}s with the related prompts groups inserted. */ const items = computed(() => { if (!injectedListItems?.value) { return relatedPromptsGroups.value; } if (relatedPromptsAreOutdated.value) { return injectedListItems.value; } if (hasNotEnoughListItems.value) { return injectedListItems.value.concat(relatedPromptsGroups.value[0] ?? []); } return relatedPromptsGroups?.value.reduce((items, relatedPromptsGroup, index) => { const targetIndex = props.offset + props.frequency * index; if (targetIndex <= items.length) { items.splice(targetIndex, 0, relatedPromptsGroup); } return items; }, [...injectedListItems.value]); }); /** * 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=related-prompts-list.vue.js.map