89 lines
2.4 KiB
Vue
89 lines
2.4 KiB
Vue
|
<template>
|
||
|
<nav class="pagination" role="navigation" aria-label="pagination">
|
||
|
<nuxt-link
|
||
|
class="pagination-previous"
|
||
|
:disabled="!prev ? 'disabled' : undefined"
|
||
|
:tabindex="!prev ? -1 : undefined"
|
||
|
:to="genRouteQuery(prev)"
|
||
|
@click="checkAndUpdate(prev)"
|
||
|
>
|
||
|
Précédent
|
||
|
</nuxt-link>
|
||
|
<nuxt-link
|
||
|
class="pagination-next"
|
||
|
:disabled="!next ? 'disabled' : undefined"
|
||
|
:tabindex="!next ? -1 : undefined"
|
||
|
:to="genRouteQuery(next)"
|
||
|
@click="checkAndUpdate(next)"
|
||
|
>
|
||
|
Suivant
|
||
|
</nuxt-link>
|
||
|
<ul class="pagination-list">
|
||
|
<li v-for="(i, index) in items" :key="index">
|
||
|
<span v-if="i === ELLIPSIS" class="pagination-ellipsis">…</span>
|
||
|
<nuxt-link
|
||
|
v-else
|
||
|
class="pagination-link"
|
||
|
:class="{ 'is-current': current === i }"
|
||
|
:aria-label="current === i ? `Page ${i}` : `Aller à la page ${i}`"
|
||
|
:aria-current="current === i ? 'page' : undefined"
|
||
|
:to="genRouteQuery(i)"
|
||
|
@click="checkAndUpdate(i)"
|
||
|
>
|
||
|
{{ i }}
|
||
|
</nuxt-link>
|
||
|
</li>
|
||
|
</ul>
|
||
|
</nav>
|
||
|
</template>
|
||
|
|
||
|
<script setup lang="ts">
|
||
|
const router = useRouter()
|
||
|
const props = defineProps({
|
||
|
nbToShow: { type: Number, default: 2 },
|
||
|
max: { type: Number, required: true },
|
||
|
modelValue: { type: Number, required: true },
|
||
|
})
|
||
|
const current = useModel<number>("modelValue")
|
||
|
const ELLIPSIS = "…"
|
||
|
|
||
|
const prev = computed<number | null>(() =>
|
||
|
current.value === 1 ? null : current.value - 1
|
||
|
)
|
||
|
const next = computed<number | null>(() =>
|
||
|
current.value === props.max ? null : current.value + 1
|
||
|
)
|
||
|
const items = reactive<(number | string)[]>([1])
|
||
|
|
||
|
watch(current, () => paginate)
|
||
|
paginate()
|
||
|
|
||
|
function paginate() {
|
||
|
items.splice(1)
|
||
|
if (current.value === 1 && props.max === 1) return
|
||
|
if (current.value > 4) items.push(ELLIPSIS)
|
||
|
|
||
|
const r = props.nbToShow,
|
||
|
rLeft = current.value - r,
|
||
|
rRight = current.value + r
|
||
|
|
||
|
for (let i = rLeft > r ? rLeft : r; i <= Math.min(props.max, rRight); i++)
|
||
|
items.push(i)
|
||
|
|
||
|
if (rRight + 1 < props.max) items.push(ELLIPSIS)
|
||
|
if (rRight < props.max) items.push(props.max)
|
||
|
}
|
||
|
|
||
|
function checkAndUpdate(page: number | null) {
|
||
|
if (page) current.value = page
|
||
|
paginate()
|
||
|
}
|
||
|
|
||
|
function genRouteQuery(page: number) {
|
||
|
if (!page) return router.currentRoute
|
||
|
return { query: { ...router.currentRoute.value.query, page } }
|
||
|
}
|
||
|
</script>
|
||
|
|
||
|
<style scoped lang="sass"></style>
|