feat: add pagination component

Signed-off-by: Ryan Wang <i@ryanc.cc>
pull/588/head
Ryan Wang 2022-07-11 18:16:45 +08:00
parent ebc9756a8d
commit 86be841e28
12 changed files with 160 additions and 483 deletions

View File

@ -14,3 +14,4 @@ export * from "./components/tag";
export * from "./components/textarea";
export * from "./components/switch";
export * from "./components/dialog";
export * from "./components/pagination";

View File

@ -0,0 +1,22 @@
<template>
<Story :init-state="initState" title="Pagination">
<template #default="{ state }">
<VPagination
:page="state.page"
:size="state.size"
:total="state.total"
></VPagination>
</template>
</Story>
</template>
<script lang="ts" setup>
import { VPagination } from "./index";
function initState() {
return {
page: 1,
size: 10,
total: 100,
};
}
</script>

View File

@ -0,0 +1,100 @@
<script lang="ts" setup>
import { useOffsetPagination } from "@vueuse/core";
import { IconArrowLeft, IconArrowRight } from "../../icons/icons";
import { defineProps } from "vue";
const props = defineProps({
page: {
type: Number,
default: 1,
},
size: {
type: Number,
default: 10,
},
total: {
type: Number,
default: 0,
},
});
const emit = defineEmits(["update:page", "update:size", "change"]);
const onPageChange = ({
currentPage,
currentPageSize,
}: {
currentPage: number;
currentPageSize: number;
}) => {
emit("update:size", props.size);
emit("update:page", props.page);
emit("change", {
page: currentPage,
size: currentPageSize,
});
};
const { currentPage, pageCount, prev, next } = useOffsetPagination({
total: props.total,
page: props.page,
pageSize: props.size,
onPageChange: onPageChange,
onPageSizeChange: onPageChange,
});
</script>
<template>
<div class="bg-white flex items-center justify-between">
<div class="flex-1 flex justify-between sm:hidden items-center">
<span
class="relative inline-flex items-center px-4 py-2 border border-gray-300 text-sm font-medium rounded-md text-gray-700 bg-white hover:bg-gray-50 cursor-pointer"
@click="prev"
>
<IconArrowLeft />
</span>
<span class="text-sm text-gray-500">
{{ currentPage }} / {{ pageCount }}
</span>
<span
class="ml-3 relative inline-flex items-center px-4 py-2 border border-gray-300 text-sm font-medium rounded-md text-gray-700 bg-white hover:bg-gray-50 cursor-pointer"
@click="next"
>
<IconArrowRight />
</span>
</div>
<div class="hidden sm:flex-1 sm:flex sm:items-center">
<nav
aria-label="Pagination"
class="relative z-0 inline-flex rounded-[4px] shadow-sm -space-x-px"
>
<span
class="relative inline-flex items-center px-2 py-2 rounded-l-[4px] border border-gray-300 bg-white text-sm font-medium text-gray-500 hover:bg-gray-50 cursor-pointer"
@click="prev"
>
<IconArrowLeft />
</span>
<span
v-for="i in pageCount"
:key="i"
:class="{
'z-10 bg-themeable-primary-50 border-themeable-primary-500 text-themeable-primary-600':
i === currentPage,
'bg-white border-gray-300 text-gray-500 hover:bg-gray-50 ':
i !== currentPage,
}"
aria-current="page"
class="relative inline-flex items-center px-4 py-2 border text-sm font-medium cursor-pointer select-none"
@click="currentPage = i"
>
{{ i }}
</span>
<span
class="relative inline-flex items-center px-2 py-2 rounded-r-[4px] border border-gray-300 bg-white text-sm font-medium text-gray-500 hover:bg-gray-50 cursor-pointer"
@click="next"
>
<IconArrowRight />
</span>
</nav>
</div>
</div>
</template>

View File

@ -0,0 +1,9 @@
import { describe, expect, it } from "vitest";
import { mount } from "@vue/test-utils";
import { VPagination } from "../index";
describe("Pagination", () => {
it("should be true", () => {
expect(mount(VPagination)).toBeDefined();
});
});

View File

@ -0,0 +1 @@
export { default as VPagination } from "./Pagination.vue";

View File

@ -12,6 +12,7 @@ import {
VCard,
VModal,
VPageHeader,
VPagination,
VSpace,
VTag,
} from "@halo-dev/components";
@ -686,75 +687,7 @@ onMounted(() => {
<template #footer>
<div class="flex items-center justify-end bg-white">
<div class="flex flex-1 items-center justify-end">
<div>
<nav
aria-label="Pagination"
class="relative z-0 inline-flex -space-x-px rounded-md shadow-sm"
>
<a
class="relative inline-flex items-center rounded-l-md border border-gray-300 bg-white px-2 py-2 text-sm font-medium text-gray-500 hover:bg-gray-50"
href="#"
>
<span class="sr-only">Previous</span>
<svg
aria-hidden="true"
class="h-5 w-5"
fill="currentColor"
viewBox="0 0 20 20"
xmlns="http://www.w3.org/2000/svg"
>
<path
clip-rule="evenodd"
d="M12.707 5.293a1 1 0 010 1.414L9.414 10l3.293 3.293a1 1 0 01-1.414 1.414l-4-4a1 1 0 010-1.414l4-4a1 1 0 011.414 0z"
fill-rule="evenodd"
/>
</svg>
</a>
<a
aria-current="page"
class="relative z-10 inline-flex items-center border border-indigo-500 bg-indigo-50 px-4 py-2 text-sm font-medium text-indigo-600"
href="#"
>
1
</a>
<a
class="relative inline-flex items-center border border-gray-300 bg-white px-4 py-2 text-sm font-medium text-gray-500 hover:bg-gray-50"
href="#"
>
2
</a>
<span
class="relative inline-flex items-center border border-gray-300 bg-white px-4 py-2 text-sm font-medium text-gray-700"
>
...
</span>
<a
class="relative hidden items-center border border-gray-300 bg-white px-4 py-2 text-sm font-medium text-gray-500 hover:bg-gray-50 md:inline-flex"
href="#"
>
4
</a>
<a
class="relative inline-flex items-center rounded-r-md border border-gray-300 bg-white px-2 py-2 text-sm font-medium text-gray-500 hover:bg-gray-50"
href="#"
>
<span class="sr-only">Next</span>
<svg
aria-hidden="true"
class="h-5 w-5"
fill="currentColor"
viewBox="0 0 20 20"
xmlns="http://www.w3.org/2000/svg"
>
<path
clip-rule="evenodd"
d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z"
fill-rule="evenodd"
/>
</svg>
</a>
</nav>
</div>
<VPagination :page="1" :size="10" :total="20" />
</div>
</div>
</template>

View File

@ -6,6 +6,7 @@ import {
VButton,
VCard,
VPageHeader,
VPagination,
VSpace,
} from "@halo-dev/components";
import { ref } from "vue";
@ -138,75 +139,7 @@ const checkAll = ref(false);
<template #footer>
<div class="flex items-center justify-end bg-white">
<div class="flex flex-1 items-center justify-end">
<div>
<nav
aria-label="Pagination"
class="relative z-0 inline-flex -space-x-px rounded-md shadow-sm"
>
<a
class="relative inline-flex items-center rounded-l-md border border-gray-300 bg-white px-2 py-2 text-sm font-medium text-gray-500 hover:bg-gray-50"
href="#"
>
<span class="sr-only">Previous</span>
<svg
aria-hidden="true"
class="h-5 w-5"
fill="currentColor"
viewBox="0 0 20 20"
xmlns="http://www.w3.org/2000/svg"
>
<path
clip-rule="evenodd"
d="M12.707 5.293a1 1 0 010 1.414L9.414 10l3.293 3.293a1 1 0 01-1.414 1.414l-4-4a1 1 0 010-1.414l4-4a1 1 0 011.414 0z"
fill-rule="evenodd"
/>
</svg>
</a>
<a
aria-current="page"
class="relative z-10 inline-flex items-center border border-indigo-500 bg-indigo-50 px-4 py-2 text-sm font-medium text-indigo-600"
href="#"
>
1
</a>
<a
class="relative inline-flex items-center border border-gray-300 bg-white px-4 py-2 text-sm font-medium text-gray-500 hover:bg-gray-50"
href="#"
>
2
</a>
<span
class="relative inline-flex items-center border border-gray-300 bg-white px-4 py-2 text-sm font-medium text-gray-700"
>
...
</span>
<a
class="relative hidden items-center border border-gray-300 bg-white px-4 py-2 text-sm font-medium text-gray-500 hover:bg-gray-50 md:inline-flex"
href="#"
>
4
</a>
<a
class="relative inline-flex items-center rounded-r-md border border-gray-300 bg-white px-2 py-2 text-sm font-medium text-gray-500 hover:bg-gray-50"
href="#"
>
<span class="sr-only">Next</span>
<svg
aria-hidden="true"
class="h-5 w-5"
fill="currentColor"
viewBox="0 0 20 20"
xmlns="http://www.w3.org/2000/svg"
>
<path
clip-rule="evenodd"
d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z"
fill-rule="evenodd"
/>
</svg>
</a>
</nav>
</div>
<VPagination :page="1" :size="10" :total="20" />
</div>
</div>
</template>

View File

@ -7,6 +7,7 @@ import {
VButton,
VCard,
VPageHeader,
VPagination,
VSpace,
VTabbar,
VTag,
@ -335,75 +336,7 @@ onMounted(() => {
<template #footer>
<div class="flex items-center justify-end bg-white">
<div class="flex flex-1 items-center justify-end">
<div>
<nav
aria-label="Pagination"
class="relative z-0 inline-flex -space-x-px rounded-md shadow-sm"
>
<a
class="relative inline-flex items-center rounded-l-md border border-gray-300 bg-white px-2 py-2 text-sm font-medium text-gray-500 hover:bg-gray-50"
href="#"
>
<span class="sr-only">Previous</span>
<svg
aria-hidden="true"
class="h-5 w-5"
fill="currentColor"
viewBox="0 0 20 20"
xmlns="http://www.w3.org/2000/svg"
>
<path
clip-rule="evenodd"
d="M12.707 5.293a1 1 0 010 1.414L9.414 10l3.293 3.293a1 1 0 01-1.414 1.414l-4-4a1 1 0 010-1.414l4-4a1 1 0 011.414 0z"
fill-rule="evenodd"
/>
</svg>
</a>
<a
aria-current="page"
class="relative z-10 inline-flex items-center border border-indigo-500 bg-indigo-50 px-4 py-2 text-sm font-medium text-indigo-600"
href="#"
>
1
</a>
<a
class="relative inline-flex items-center border border-gray-300 bg-white px-4 py-2 text-sm font-medium text-gray-500 hover:bg-gray-50"
href="#"
>
2
</a>
<span
class="relative inline-flex items-center border border-gray-300 bg-white px-4 py-2 text-sm font-medium text-gray-700"
>
...
</span>
<a
class="relative hidden items-center border border-gray-300 bg-white px-4 py-2 text-sm font-medium text-gray-500 hover:bg-gray-50 md:inline-flex"
href="#"
>
4
</a>
<a
class="relative inline-flex items-center rounded-r-md border border-gray-300 bg-white px-2 py-2 text-sm font-medium text-gray-500 hover:bg-gray-50"
href="#"
>
<span class="sr-only">Next</span>
<svg
aria-hidden="true"
class="h-5 w-5"
fill="currentColor"
viewBox="0 0 20 20"
xmlns="http://www.w3.org/2000/svg"
>
<path
clip-rule="evenodd"
d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z"
fill-rule="evenodd"
/>
</svg>
</a>
</nav>
</div>
<VPagination :page="1" :size="10" :total="20" />
</div>
</div>
</template>

View File

@ -8,6 +8,7 @@ import {
VButton,
VCard,
VPageHeader,
VPagination,
VSpace,
VTag,
} from "@halo-dev/components";
@ -401,75 +402,7 @@ onMounted(() => {
<template #footer>
<div class="flex items-center justify-end bg-white">
<div class="flex flex-1 items-center justify-end">
<div>
<nav
aria-label="Pagination"
class="relative z-0 inline-flex -space-x-px rounded-md shadow-sm"
>
<a
class="relative inline-flex items-center rounded-l-md border border-gray-300 bg-white px-2 py-2 text-sm font-medium text-gray-500 hover:bg-gray-50"
href="#"
>
<span class="sr-only">Previous</span>
<svg
aria-hidden="true"
class="h-5 w-5"
fill="currentColor"
viewBox="0 0 20 20"
xmlns="http://www.w3.org/2000/svg"
>
<path
clip-rule="evenodd"
d="M12.707 5.293a1 1 0 010 1.414L9.414 10l3.293 3.293a1 1 0 01-1.414 1.414l-4-4a1 1 0 010-1.414l4-4a1 1 0 011.414 0z"
fill-rule="evenodd"
/>
</svg>
</a>
<a
aria-current="page"
class="relative z-10 inline-flex items-center border border-indigo-500 bg-indigo-50 px-4 py-2 text-sm font-medium text-indigo-600"
href="#"
>
1
</a>
<a
class="relative inline-flex items-center border border-gray-300 bg-white px-4 py-2 text-sm font-medium text-gray-500 hover:bg-gray-50"
href="#"
>
2
</a>
<span
class="relative inline-flex items-center border border-gray-300 bg-white px-4 py-2 text-sm font-medium text-gray-700"
>
...
</span>
<a
class="relative hidden items-center border border-gray-300 bg-white px-4 py-2 text-sm font-medium text-gray-500 hover:bg-gray-50 md:inline-flex"
href="#"
>
4
</a>
<a
class="relative inline-flex items-center rounded-r-md border border-gray-300 bg-white px-2 py-2 text-sm font-medium text-gray-500 hover:bg-gray-50"
href="#"
>
<span class="sr-only">Next</span>
<svg
aria-hidden="true"
class="h-5 w-5"
fill="currentColor"
viewBox="0 0 20 20"
xmlns="http://www.w3.org/2000/svg"
>
<path
clip-rule="evenodd"
d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z"
fill-rule="evenodd"
/>
</svg>
</a>
</nav>
</div>
<VPagination :page="1" :size="10" :total="20" />
</div>
</div>
</template>

View File

@ -8,6 +8,7 @@ import {
VButton,
VCard,
VPageHeader,
VPagination,
VSpace,
VSwitch,
VTag,
@ -384,75 +385,7 @@ onMounted(handleFetchPlugins);
<template #footer>
<div class="flex items-center justify-end bg-white">
<div class="flex flex-1 items-center justify-end">
<div>
<nav
aria-label="Pagination"
class="relative z-0 inline-flex -space-x-px rounded-md shadow-sm"
>
<a
class="relative inline-flex items-center rounded-l-md border border-gray-300 bg-white px-2 py-2 text-sm font-medium text-gray-500 hover:bg-gray-50"
href="#"
>
<span class="sr-only">Previous</span>
<svg
aria-hidden="true"
class="h-5 w-5"
fill="currentColor"
viewBox="0 0 20 20"
xmlns="http://www.w3.org/2000/svg"
>
<path
clip-rule="evenodd"
d="M12.707 5.293a1 1 0 010 1.414L9.414 10l3.293 3.293a1 1 0 01-1.414 1.414l-4-4a1 1 0 010-1.414l4-4a1 1 0 011.414 0z"
fill-rule="evenodd"
/>
</svg>
</a>
<a
aria-current="page"
class="relative z-10 inline-flex items-center border border-indigo-500 bg-indigo-50 px-4 py-2 text-sm font-medium text-indigo-600"
href="#"
>
1
</a>
<a
class="relative inline-flex items-center border border-gray-300 bg-white px-4 py-2 text-sm font-medium text-gray-500 hover:bg-gray-50"
href="#"
>
2
</a>
<span
class="relative inline-flex items-center border border-gray-300 bg-white px-4 py-2 text-sm font-medium text-gray-700"
>
...
</span>
<a
class="relative hidden items-center border border-gray-300 bg-white px-4 py-2 text-sm font-medium text-gray-500 hover:bg-gray-50 md:inline-flex"
href="#"
>
4
</a>
<a
class="relative inline-flex items-center rounded-r-md border border-gray-300 bg-white px-2 py-2 text-sm font-medium text-gray-500 hover:bg-gray-50"
href="#"
>
<span class="sr-only">Next</span>
<svg
aria-hidden="true"
class="h-5 w-5"
fill="currentColor"
viewBox="0 0 20 20"
xmlns="http://www.w3.org/2000/svg"
>
<path
clip-rule="evenodd"
d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z"
fill-rule="evenodd"
/>
</svg>
</a>
</nav>
</div>
<VPagination :page="1" :size="10" :total="20" />
</div>
</div>
</template>

View File

@ -7,6 +7,7 @@ import {
VButton,
VCard,
VPageHeader,
VPagination,
VSpace,
VTag,
} from "@halo-dev/components";
@ -211,75 +212,7 @@ onMounted(() => {
<template #footer>
<div class="flex items-center justify-end bg-white">
<div class="flex flex-1 items-center justify-end">
<div>
<nav
aria-label="Pagination"
class="relative z-0 inline-flex -space-x-px rounded-md shadow-sm"
>
<a
class="relative inline-flex items-center rounded-l-md border border-gray-300 bg-white px-2 py-2 text-sm font-medium text-gray-500 hover:bg-gray-50"
href="#"
>
<span class="sr-only">Previous</span>
<svg
aria-hidden="true"
class="h-5 w-5"
fill="currentColor"
viewBox="0 0 20 20"
xmlns="http://www.w3.org/2000/svg"
>
<path
clip-rule="evenodd"
d="M12.707 5.293a1 1 0 010 1.414L9.414 10l3.293 3.293a1 1 0 01-1.414 1.414l-4-4a1 1 0 010-1.414l4-4a1 1 0 011.414 0z"
fill-rule="evenodd"
/>
</svg>
</a>
<a
aria-current="page"
class="relative z-10 inline-flex items-center border border-indigo-500 bg-indigo-50 px-4 py-2 text-sm font-medium text-indigo-600"
href="#"
>
1
</a>
<a
class="relative inline-flex items-center border border-gray-300 bg-white px-4 py-2 text-sm font-medium text-gray-500 hover:bg-gray-50"
href="#"
>
2
</a>
<span
class="relative inline-flex items-center border border-gray-300 bg-white px-4 py-2 text-sm font-medium text-gray-700"
>
...
</span>
<a
class="relative hidden items-center border border-gray-300 bg-white px-4 py-2 text-sm font-medium text-gray-500 hover:bg-gray-50 md:inline-flex"
href="#"
>
4
</a>
<a
class="relative inline-flex items-center rounded-r-md border border-gray-300 bg-white px-2 py-2 text-sm font-medium text-gray-500 hover:bg-gray-50"
href="#"
>
<span class="sr-only">Next</span>
<svg
aria-hidden="true"
class="h-5 w-5"
fill="currentColor"
viewBox="0 0 20 20"
xmlns="http://www.w3.org/2000/svg"
>
<path
clip-rule="evenodd"
d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z"
fill-rule="evenodd"
/>
</svg>
</a>
</nav>
</div>
<VPagination :page="1" :size="10" :total="20" />
</div>
</div>
</template>

View File

@ -8,6 +8,7 @@ import {
VButton,
VCard,
VPageHeader,
VPagination,
VSpace,
VTag,
} from "@halo-dev/components";
@ -20,6 +21,15 @@ const checkAll = ref(false);
const creationModal = ref<boolean>(false);
const users = ref<User[]>([]);
const selectedUser = ref<User | null>(null);
const pagination = ref<{
page: number;
size: number;
total: number;
}>({
page: 1,
size: 10,
total: 100,
});
const handleFetchUsers = async () => {
try {
@ -265,75 +275,11 @@ onMounted(() => {
<template #footer>
<div class="flex items-center justify-end bg-white">
<div class="flex flex-1 items-center justify-end">
<div>
<nav
aria-label="Pagination"
class="relative z-0 inline-flex -space-x-px rounded-md shadow-sm"
>
<a
class="relative inline-flex items-center rounded-l-md border border-gray-300 bg-white px-2 py-2 text-sm font-medium text-gray-500 hover:bg-gray-50"
href="#"
>
<span class="sr-only">Previous</span>
<svg
aria-hidden="true"
class="h-5 w-5"
fill="currentColor"
viewBox="0 0 20 20"
xmlns="http://www.w3.org/2000/svg"
>
<path
clip-rule="evenodd"
d="M12.707 5.293a1 1 0 010 1.414L9.414 10l3.293 3.293a1 1 0 01-1.414 1.414l-4-4a1 1 0 010-1.414l4-4a1 1 0 011.414 0z"
fill-rule="evenodd"
<VPagination
v-model:page="pagination.page"
v-model:size="pagination.size"
:total="pagination.total"
/>
</svg>
</a>
<a
aria-current="page"
class="relative z-10 inline-flex items-center border border-indigo-500 bg-indigo-50 px-4 py-2 text-sm font-medium text-indigo-600"
href="#"
>
1
</a>
<a
class="relative inline-flex items-center border border-gray-300 bg-white px-4 py-2 text-sm font-medium text-gray-500 hover:bg-gray-50"
href="#"
>
2
</a>
<span
class="relative inline-flex items-center border border-gray-300 bg-white px-4 py-2 text-sm font-medium text-gray-700"
>
...
</span>
<a
class="relative hidden items-center border border-gray-300 bg-white px-4 py-2 text-sm font-medium text-gray-500 hover:bg-gray-50 md:inline-flex"
href="#"
>
4
</a>
<a
class="relative inline-flex items-center rounded-r-md border border-gray-300 bg-white px-2 py-2 text-sm font-medium text-gray-500 hover:bg-gray-50"
href="#"
>
<span class="sr-only">Next</span>
<svg
aria-hidden="true"
class="h-5 w-5"
fill="currentColor"
viewBox="0 0 20 20"
xmlns="http://www.w3.org/2000/svg"
>
<path
clip-rule="evenodd"
d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z"
fill-rule="evenodd"
/>
</svg>
</a>
</nav>
</div>
</div>
</div>
</template>