Skip to content

Commit

Permalink
feat: add pagination component (#4522)
Browse files Browse the repository at this point in the history
* feat: add pagination component

* chore: update
  • Loading branch information
anncwb authored Sep 26, 2024
1 parent 26646d4 commit 639d2e1
Show file tree
Hide file tree
Showing 33 changed files with 364 additions and 55 deletions.
1 change: 0 additions & 1 deletion packages/@core/ui-kit/shadcn-ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@
}
},
"dependencies": {
"@radix-icons/vue": "catalog:",
"@vben-core/composables": "workspace:*",
"@vben-core/icons": "workspace:*",
"@vben-core/shared": "workspace:*",
Expand Down
2 changes: 2 additions & 0 deletions packages/@core/ui-kit/shadcn-ui/src/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export * from './input-password';
export * from './link';
export * from './logo';
export * from './menu-badge';
export * from './pagination';
export * from './pin-input';
export * from './popover';
export * from './render-content';
Expand All @@ -38,6 +39,7 @@ export * from './ui/hover-card';
export * from './ui/input';
export * from './ui/label';
export * from './ui/number-field';
export * from './ui/pagination';
export * from './ui/pin-input';
export * from './ui/popover';
export * from './ui/radio-group';
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export type { PaginationProps as VbenPaginationProps } from './pagination';
export { default as VbenPagination } from './pagination.vue';
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
export interface PaginationProps {
/**
* 是否禁用
*/
disabled?: boolean;
/**
* 每页记录数选项
*/
pageSizeOptions?: number[];
/**
* 当 时true,始终显示第一页、最后一页和省略号
*/
showEdges?: boolean;
/**
* 显示当前页选择下拉框
*/
showRowsPerPage?: boolean;
/**
* 显示总条数文本
*/
showTotalText?: boolean;
/**
* 当前页面周围应显示的兄弟页面数量
*/
siblingCount?: number;
/**
* 组件尺寸
*/
size?: 'default' | 'large' | 'small';

/**
* 总条数
*/
total?: number;
}

export const SIZE_CLASS_MAP = {
default: 'size-8',
large: 'size-9',
small: 'size-7',
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
<script setup lang="ts">
import { computed } from 'vue';
import { cn } from '@vben-core/shared/utils';
import { Button } from '../ui/button';
import {
Pagination,
PaginationEllipsis,
PaginationFirst,
PaginationLast,
PaginationList,
PaginationListItem,
PaginationNext,
PaginationPrev,
} from '../ui/pagination';
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from '../ui/select';
import { type PaginationProps, SIZE_CLASS_MAP } from './pagination';
interface Props extends PaginationProps {}
const {
disabled = false,
pageSizeOptions = [10, 20, 30, 50, 100, 200],
showEdges = true,
showRowsPerPage = true,
showTotalText = true,
siblingCount = 1,
size = 'default',
total = 500,
} = defineProps<Props>();
const currentPage = defineModel<number>('currentPage', { default: 1 });
const itemPerPage = defineModel<number>('itemPerPage', { default: 20 });
const itemSize = computed(() => {
return SIZE_CLASS_MAP[size];
});
const options = computed(() => {
return pageSizeOptions.map((item) => ({
label: `${item} 条/页`,
value: `${item}`,
}));
});
function handleUpdateModelValue(value: string) {
itemPerPage.value = Number(value);
}
</script>

<template>
<Pagination
v-model:page="currentPage"
:disabled="disabled"
:items-per-page="itemPerPage"
:show-edges="showEdges"
:sibling-count="siblingCount"
:total="total"
>
<PaginationList
v-slot="{ items }"
class="flex w-full items-center justify-end gap-1"
>
<span v-if="showTotalText" class="mr-2">共 {{ total }} 条</span>

<Select
v-if="showRowsPerPage"
:model-value="`${itemPerPage}`"
@update:model-value="handleUpdateModelValue"
>
<SelectTrigger class="w-30 mr-auto h-8">
<SelectValue />
</SelectTrigger>
<SelectContent>
<template v-for="item in options" :key="item.value">
<SelectItem :value="item.value"> {{ item.label }} </SelectItem>
</template>
</SelectContent>
</Select>

<PaginationFirst :class="cn('size-8', itemSize)" />
<PaginationPrev :class="cn('size-8', itemSize)" />
<template v-for="(item, index) in items">
<PaginationListItem
v-if="item.type === 'page'"
:key="index"
:value="item.value"
as-child
>
<Button
:class="cn('size-8 p-0 shadow-none', itemSize)"
:variant="item.value === currentPage ? 'default' : 'outline'"
>
{{ item.value }}
</Button>
</PaginationListItem>
<PaginationEllipsis v-else :key="item.type" :index="index" />
</template>

<PaginationNext :class="cn('size-8', itemSize)" />
<PaginationLast :class="cn('size-8', itemSize)" />
</PaginationList>
</Pagination>
</template>
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { computed } from 'vue';
import { cn } from '@vben-core/shared/utils';
import { ChevronDownIcon } from '@radix-icons/vue';
import { ChevronDown } from 'lucide-vue-next';
import {
AccordionHeader,
AccordionTrigger,
Expand Down Expand Up @@ -32,7 +32,7 @@ const delegatedProps = computed(() => {
>
<slot></slot>
<slot name="icon">
<ChevronDownIcon
<ChevronDown
class="text-muted-foreground h-4 w-4 shrink-0 transition-transform duration-200"
/>
</slot>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<script lang="ts" setup>
import { cn } from '@vben-core/shared/utils';
import { DotsHorizontalIcon } from '@radix-icons/vue';
import { MoreHorizontal } from 'lucide-vue-next';
const props = defineProps<{
class?: any;
Expand All @@ -15,7 +15,7 @@ const props = defineProps<{
role="presentation"
>
<slot>
<DotsHorizontalIcon class="h-4 w-4" />
<MoreHorizontal class="h-4 w-4" />
</slot>
<span class="sr-only">More</span>
</span>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<script lang="ts" setup>
import { cn } from '@vben-core/shared/utils';
import { ChevronRightIcon } from '@radix-icons/vue';
import { ChevronRight } from 'lucide-vue-next';
const props = defineProps<{
class?: any;
Expand All @@ -15,7 +15,7 @@ const props = defineProps<{
role="presentation"
>
<slot>
<ChevronRightIcon />
<ChevronRight />
</slot>
</li>
</template>
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { buttonVariants } from './button';
interface Props extends PrimitiveProps {
class?: any;
size?: ButtonVariantSize;
variant?: 'heavy' & ButtonVariants;
variant?: ButtonVariants;
}
const props = withDefaults(defineProps<Props>(), {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { computed } from 'vue';
import { cn } from '@vben-core/shared/utils';
import { CheckIcon } from '@radix-icons/vue';
import { Check } from 'lucide-vue-next';
import {
CheckboxIndicator,
CheckboxRoot,
Expand Down Expand Up @@ -38,7 +38,7 @@ const forwarded = useForwardPropsEmits(delegatedProps, emits);
class="flex h-full w-full items-center justify-center text-current"
>
<slot>
<CheckIcon class="h-4 w-4" />
<Check class="h-4 w-4" />
</slot>
</CheckboxIndicator>
</CheckboxRoot>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { computed } from 'vue';
import { cn } from '@vben-core/shared/utils';
import { CheckIcon } from '@radix-icons/vue';
import { Check } from 'lucide-vue-next';
import {
ContextMenuCheckboxItem,
type ContextMenuCheckboxItemEmits,
Expand Down Expand Up @@ -36,7 +36,7 @@ const forwarded = useForwardPropsEmits(delegatedProps, emits);
>
<span class="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
<ContextMenuItemIndicator>
<CheckIcon class="h-4 w-4" />
<Check class="h-4 w-4" />
</ContextMenuItemIndicator>
</span>
<slot></slot>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { computed } from 'vue';
import { cn } from '@vben-core/shared/utils';
import { DotFilledIcon } from '@radix-icons/vue';
import { Circle } from 'lucide-vue-next';
import {
ContextMenuItemIndicator,
ContextMenuRadioItem,
Expand Down Expand Up @@ -36,7 +36,7 @@ const forwarded = useForwardPropsEmits(delegatedProps, emits);
>
<span class="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
<ContextMenuItemIndicator>
<DotFilledIcon class="h-4 w-4 fill-current" />
<Circle class="h-2 w-2 fill-current" />
</ContextMenuItemIndicator>
</span>
<slot></slot>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { computed } from 'vue';
import { cn } from '@vben-core/shared/utils';
import { ChevronRightIcon } from '@radix-icons/vue';
import { ChevronRight } from 'lucide-vue-next';
import {
ContextMenuSubTrigger,
type ContextMenuSubTriggerProps,
Expand Down Expand Up @@ -38,6 +38,6 @@ const forwardedProps = useForwardProps(delegatedProps);
"
>
<slot></slot>
<ChevronRightIcon class="ml-auto h-4 w-4" />
<ChevronRight class="ml-auto h-4 w-4" />
</ContextMenuSubTrigger>
</template>
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { computed, ref } from 'vue';
import { cn } from '@vben-core/shared/utils';
import { Cross2Icon } from '@radix-icons/vue';
import { X } from 'lucide-vue-next';
import {
DialogClose,
DialogContent,
Expand Down Expand Up @@ -77,7 +77,7 @@ defineExpose({
"
@click="() => emits('close')"
>
<Cross2Icon class="h-4 w-4" />
<X class="h-4 w-4" />
</DialogClose>
</DialogContent>
</DialogPortal>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { computed } from 'vue';
import { cn } from '@vben-core/shared/utils';
import { X } from 'lucide-vue-next';
import {
DialogClose,
DialogContent,
Expand Down Expand Up @@ -56,7 +57,7 @@ const forwarded = useForwardPropsEmits(delegatedProps, emits);
<DialogClose
class="hover:bg-secondary absolute right-4 top-4 rounded-md p-0.5 transition-colors"
>
<Cross2Icon class="h-4 w-4" />
<X class="h-4 w-4" />
<span class="sr-only">Close</span>
</DialogClose>
</DialogContent>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { computed } from 'vue';
import { cn } from '@vben-core/shared/utils';
import { CheckIcon } from '@radix-icons/vue';
import { Check } from 'lucide-vue-next';
import {
DropdownMenuCheckboxItem,
type DropdownMenuCheckboxItemEmits,
Expand Down Expand Up @@ -36,7 +36,7 @@ const forwarded = useForwardPropsEmits(delegatedProps, emits);
>
<span class="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
<DropdownMenuItemIndicator>
<CheckIcon class="h-4 w-4" />
<Check class="h-4 w-4" />
</DropdownMenuItemIndicator>
</span>
<slot></slot>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { computed } from 'vue';
import { cn } from '@vben-core/shared/utils';
import { DotFilledIcon } from '@radix-icons/vue';
import { Circle } from 'lucide-vue-next';
import {
DropdownMenuItemIndicator,
DropdownMenuRadioItem,
Expand Down Expand Up @@ -37,7 +37,7 @@ const forwarded = useForwardPropsEmits(delegatedProps, emits);
>
<span class="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
<DropdownMenuItemIndicator>
<DotFilledIcon class="h-4 w-4 fill-current" />
<Circle class="h-2 w-2 fill-current" />
</DropdownMenuItemIndicator>
</span>
<slot></slot>
Expand Down
Loading

0 comments on commit 639d2e1

Please sign in to comment.