UNPKG

@shopware-ag/meteor-component-library

Version:

The meteor component library is a Vue component library developed by Shopware. It is based on the [Meteor Design System](https://shopware.design/).

95 lines (79 loc) 2.76 kB
import { reactiveComputed, unrefElement, useElementSize, type MaybeElementRef } from "@vueuse/core"; import { computed, onMounted, ref, toRefs, watch } from "vue"; export function usePriorityPlusNavigation< T extends { id: string; }, >( items: T[], { container, overflowButton }: { container: MaybeElementRef; overflowButton: MaybeElementRef }, ) { const containerSize = useElementSize(container); const overflowButtonSize = useElementSize(overflowButton); // We need to wait for the fonts to load. Otherwise, we measure the width // of elements, the fonts loads and the elements change size. const areFontsLoaded = ref(false); onMounted(() => { document.fonts.ready.then(() => { areFontsLoaded.value = true; }); }); const widthsOfItems = computed<number[]>(() => { const containerElement = unrefElement(container); if (!containerElement || !areFontsLoaded.value) return []; const items = Array.from(containerElement.querySelectorAll("[data-priority-plus]")); const result = items.reduce<{ accumulatedWidth: number; widthsOfItems: number[]; }>( (accumulated, item) => ({ accumulatedWidth: accumulated.accumulatedWidth + item.clientWidth, widthsOfItems: [ ...accumulated.widthsOfItems, accumulated.accumulatedWidth + item.clientWidth, ], }), { accumulatedWidth: 0, widthsOfItems: [] }, ); return result.widthsOfItems; }); const prioritizedItems = reactiveComputed<{ priorityItems: T[]; overflowItems: T[]; }>(() => { const hasOverflow = widthsOfItems.value.some((width) => width > containerSize.width.value); if (!hasOverflow) { return { priorityItems: items, overflowItems: [], }; } const priorityItems = items.filter((_, index) => { const overflows = widthsOfItems.value[index] > containerSize.width.value - overflowButtonSize.width.value; return !overflows; }); const overflowItems = items.filter((_, index) => { const overflows = widthsOfItems.value[index] > containerSize.width.value - overflowButtonSize.width.value; return overflows; }); return { priorityItems, overflowItems, }; }); const hasOverflow = computed(() => prioritizedItems.overflowItems.length > 0); watch(hasOverflow, () => { const overflowButtonElement = unrefElement(overflowButton); if (!overflowButtonElement) return; if (!hasOverflow.value) { overflowButtonElement.style.visibility = "hidden"; } }); const showNavigation = computed(() => areFontsLoaded.value && widthsOfItems.value.length > 0); return { showNavigation, ...toRefs(prioritizedItems), }; }