<template> <div v-if="pageNumbers.length > 1" class="tw-flex tw-justify-center"> <div role="menubar" class="tw-flex"> <button :class="BUTTON_CLASS" type="button" v-bind="getNavAttrs(modelValue === 1)" :aria-label="t('paginator.gotoFirst')" @click="setPage(1)" > <icon-system-uicons-push-left /> </button> <button :class="BUTTON_CLASS" type="button" v-bind="getNavAttrs(modelValue === 1)" :aria-label="t('paginator.gotoPrev')" @click="setPage(modelValue - 1)" > <icon-system-uicons-chevron-left /> </button> <template v-for="page in pageNumbers" :key="page"> <button :class="[BUTTON_CLASS, { 'tw-bg-aura-primary tw-text-white': modelValue === page }]" type="button" :aria-current="modelValue === page ? 'page' : undefined" :aria-setsize="lastPage" :aria-posinset="page" :aria-checked="modelValue === page" :aria-label="t('paginator.goto', { page })" role="menuitemradio" @click="setPage(page)" > {{ page }} </button> </template> <button :class="BUTTON_CLASS" type="button" v-bind="getNavAttrs(modelValue === lastPage)" :aria-label="t('paginator.gotoNext')" @click="setPage(modelValue + 1)" > <icon-system-uicons-chevron-right /> </button> <button :class="BUTTON_CLASS" type="button" v-bind="getNavAttrs(modelValue === lastPage)" :aria-label="t('paginator.gotoLast')" @click="setPage(lastPage)" > <icon-system-uicons-push-right /> </button> </div> </div> </template> <script lang="ts" setup> import { computed } from 'vue' import { useI18n } from '@/i18n' const BUTTON_CLASS = 'btn btn-default tw-border tw-border-solid tw-border-r-0 last:tw-border-r first:tw-rounded-l last:tw-rounded-r tw-rounded-none' const props = defineProps<{ modelValue: number itemsPerPage: number count: number maxVisiblePages?: number }>() const emit = defineEmits<{ (e: 'update:modelValue', value: number): void }>() const { t } = useI18n() const maxVisiblePages = computed(() => props.maxVisiblePages ?? 5) const lastPage = computed(() => Math.max(1, Math.ceil(props.count / props.itemsPerPage))) const pageNumbers = computed(() => { const result: number[] = [] const pageOffset = Math.floor(maxVisiblePages.value / 2) let page = Math.max(1, props.modelValue - pageOffset) if (props.modelValue + pageOffset > lastPage.value) page = Math.max(1, page + lastPage.value - (props.modelValue + pageOffset)) while (result.length < maxVisiblePages.value) { result.push(page) if (page === lastPage.value) break page++ } return result }) function getNavAttrs(isActive: boolean) { return isActive ? { disabled: true, role: 'presentation', 'aria-hidden': true, 'aria-disabled': true, } : { role: 'menuitem' } } function setPage(page: number) { if (page !== props.modelValue) { emit('update:modelValue', page) } } </script> <script lang="ts"> export default { compatConfig: { MODE: 3, }, } </script>