PronounsPage/components/ExpandableList.vue

90 lines
2.3 KiB
Vue

<script setup lang="ts" generic="T">
import { useMainStore } from '~/store/index.ts';
const props = withDefaults(defineProps<{
values: T[];
limit: number;
reducedLimit?: number;
isStatic?: boolean;
expand?: boolean;
itemClass?: string;
}>(), {
reducedLimit: 4,
});
const store = useMainStore();
const allShown = ref(false);
const showLimit = ref(props.values.length);
const hiddenCount = ref(0);
const reducedItems = computed(() => {
return store.reducedItems;
});
const visibleValues = computed((): T[] => {
if (allShown.value) {
return props.values;
}
return props.values.slice(0, showLimit.value);
});
watch(() => props.expand, () => {
if (props.expand) {
allShown.value = true;
}
});
watch(reducedItems, () => {
updateData();
});
onMounted(() => {
updateData();
});
const updateData = (): void => {
let newShowLimit = props.values.length;
let newHiddenCount = 0;
const limit = reducedItems.value === undefined || reducedItems.value ? props.reducedLimit : props.limit;
if (props.values.length > limit) {
newShowLimit = limit;
newHiddenCount = props.values.length - limit;
}
if (newHiddenCount === 1) {
newShowLimit++;
newHiddenCount--;
}
allShown.value = props.expand;
showLimit.value = newShowLimit;
hiddenCount.value = newHiddenCount;
};
</script>
<template>
<ul>
<li v-for="(el, i) in visibleValues" :key="i" :class="itemClass">
<slot :el="el" :i="i">
{{ el }}
</slot>
</li>
<li v-show="!allShown && hiddenCount > 0" :class="[itemClass, 'small']">
<span v-if="isStatic">
<Icon v="plus-circle" />
<T :params="{ count: hiddenCount }">profile.expendableList.more</T>
</span>
<a v-else href="#" @click.prevent="allShown = true">
<Icon v="plus-circle" />
<T :params="{ count: hiddenCount }">profile.expendableList.more</T>
<template v-if="!(itemClass || '').includes('list-inline-item')">
<br>
<Icon v="spacer" />
</template>
<T>profile.expendableList.show</T>
</a>
</li>
</ul>
</template>