feat: add pagination component (#4522)
* feat: add pagination component * chore: updatepull/48/MERGE
							parent
							
								
									26646d42f7
								
							
						
					
					
						commit
						639d2e1525
					
				|  | @ -40,7 +40,6 @@ | ||||||
|     } |     } | ||||||
|   }, |   }, | ||||||
|   "dependencies": { |   "dependencies": { | ||||||
|     "@radix-icons/vue": "catalog:", |  | ||||||
|     "@vben-core/composables": "workspace:*", |     "@vben-core/composables": "workspace:*", | ||||||
|     "@vben-core/icons": "workspace:*", |     "@vben-core/icons": "workspace:*", | ||||||
|     "@vben-core/shared": "workspace:*", |     "@vben-core/shared": "workspace:*", | ||||||
|  |  | ||||||
|  | @ -14,6 +14,7 @@ export * from './input-password'; | ||||||
| export * from './link'; | export * from './link'; | ||||||
| export * from './logo'; | export * from './logo'; | ||||||
| export * from './menu-badge'; | export * from './menu-badge'; | ||||||
|  | export * from './pagination'; | ||||||
| export * from './pin-input'; | export * from './pin-input'; | ||||||
| export * from './popover'; | export * from './popover'; | ||||||
| export * from './render-content'; | export * from './render-content'; | ||||||
|  | @ -38,6 +39,7 @@ export * from './ui/hover-card'; | ||||||
| export * from './ui/input'; | export * from './ui/input'; | ||||||
| export * from './ui/label'; | export * from './ui/label'; | ||||||
| export * from './ui/number-field'; | export * from './ui/number-field'; | ||||||
|  | export * from './ui/pagination'; | ||||||
| export * from './ui/pin-input'; | export * from './ui/pin-input'; | ||||||
| export * from './ui/popover'; | export * from './ui/popover'; | ||||||
| export * from './ui/radio-group'; | export * from './ui/radio-group'; | ||||||
|  |  | ||||||
|  | @ -0,0 +1,2 @@ | ||||||
|  | export type { PaginationProps as VbenPaginationProps } from './pagination'; | ||||||
|  | export { default as VbenPagination } from './pagination.vue'; | ||||||
|  | @ -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', | ||||||
|  | }; | ||||||
|  | @ -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> | ||||||
|  | @ -3,7 +3,7 @@ import { computed } from 'vue'; | ||||||
| 
 | 
 | ||||||
| import { cn } from '@vben-core/shared/utils'; | import { cn } from '@vben-core/shared/utils'; | ||||||
| 
 | 
 | ||||||
| import { ChevronDownIcon } from '@radix-icons/vue'; | import { ChevronDown } from 'lucide-vue-next'; | ||||||
| import { | import { | ||||||
|   AccordionHeader, |   AccordionHeader, | ||||||
|   AccordionTrigger, |   AccordionTrigger, | ||||||
|  | @ -32,7 +32,7 @@ const delegatedProps = computed(() => { | ||||||
|     > |     > | ||||||
|       <slot></slot> |       <slot></slot> | ||||||
|       <slot name="icon"> |       <slot name="icon"> | ||||||
|         <ChevronDownIcon |         <ChevronDown | ||||||
|           class="text-muted-foreground h-4 w-4 shrink-0 transition-transform duration-200" |           class="text-muted-foreground h-4 w-4 shrink-0 transition-transform duration-200" | ||||||
|         /> |         /> | ||||||
|       </slot> |       </slot> | ||||||
|  |  | ||||||
|  | @ -1,7 +1,7 @@ | ||||||
| <script lang="ts" setup> | <script lang="ts" setup> | ||||||
| import { cn } from '@vben-core/shared/utils'; | import { cn } from '@vben-core/shared/utils'; | ||||||
| 
 | 
 | ||||||
| import { DotsHorizontalIcon } from '@radix-icons/vue'; | import { MoreHorizontal } from 'lucide-vue-next'; | ||||||
| 
 | 
 | ||||||
| const props = defineProps<{ | const props = defineProps<{ | ||||||
|   class?: any; |   class?: any; | ||||||
|  | @ -15,7 +15,7 @@ const props = defineProps<{ | ||||||
|     role="presentation" |     role="presentation" | ||||||
|   > |   > | ||||||
|     <slot> |     <slot> | ||||||
|       <DotsHorizontalIcon class="h-4 w-4" /> |       <MoreHorizontal class="h-4 w-4" /> | ||||||
|     </slot> |     </slot> | ||||||
|     <span class="sr-only">More</span> |     <span class="sr-only">More</span> | ||||||
|   </span> |   </span> | ||||||
|  |  | ||||||
|  | @ -1,7 +1,7 @@ | ||||||
| <script lang="ts" setup> | <script lang="ts" setup> | ||||||
| import { cn } from '@vben-core/shared/utils'; | import { cn } from '@vben-core/shared/utils'; | ||||||
| 
 | 
 | ||||||
| import { ChevronRightIcon } from '@radix-icons/vue'; | import { ChevronRight } from 'lucide-vue-next'; | ||||||
| 
 | 
 | ||||||
| const props = defineProps<{ | const props = defineProps<{ | ||||||
|   class?: any; |   class?: any; | ||||||
|  | @ -15,7 +15,7 @@ const props = defineProps<{ | ||||||
|     role="presentation" |     role="presentation" | ||||||
|   > |   > | ||||||
|     <slot> |     <slot> | ||||||
|       <ChevronRightIcon /> |       <ChevronRight /> | ||||||
|     </slot> |     </slot> | ||||||
|   </li> |   </li> | ||||||
| </template> | </template> | ||||||
|  |  | ||||||
|  | @ -10,7 +10,7 @@ import { buttonVariants } from './button'; | ||||||
| interface Props extends PrimitiveProps { | interface Props extends PrimitiveProps { | ||||||
|   class?: any; |   class?: any; | ||||||
|   size?: ButtonVariantSize; |   size?: ButtonVariantSize; | ||||||
|   variant?: 'heavy' & ButtonVariants; |   variant?: ButtonVariants; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| const props = withDefaults(defineProps<Props>(), { | const props = withDefaults(defineProps<Props>(), { | ||||||
|  |  | ||||||
|  | @ -5,7 +5,7 @@ import { computed } from 'vue'; | ||||||
| 
 | 
 | ||||||
| import { cn } from '@vben-core/shared/utils'; | import { cn } from '@vben-core/shared/utils'; | ||||||
| 
 | 
 | ||||||
| import { CheckIcon } from '@radix-icons/vue'; | import { Check } from 'lucide-vue-next'; | ||||||
| import { | import { | ||||||
|   CheckboxIndicator, |   CheckboxIndicator, | ||||||
|   CheckboxRoot, |   CheckboxRoot, | ||||||
|  | @ -38,7 +38,7 @@ const forwarded = useForwardPropsEmits(delegatedProps, emits); | ||||||
|       class="flex h-full w-full items-center justify-center text-current" |       class="flex h-full w-full items-center justify-center text-current" | ||||||
|     > |     > | ||||||
|       <slot> |       <slot> | ||||||
|         <CheckIcon class="h-4 w-4" /> |         <Check class="h-4 w-4" /> | ||||||
|       </slot> |       </slot> | ||||||
|     </CheckboxIndicator> |     </CheckboxIndicator> | ||||||
|   </CheckboxRoot> |   </CheckboxRoot> | ||||||
|  |  | ||||||
|  | @ -3,7 +3,7 @@ import { computed } from 'vue'; | ||||||
| 
 | 
 | ||||||
| import { cn } from '@vben-core/shared/utils'; | import { cn } from '@vben-core/shared/utils'; | ||||||
| 
 | 
 | ||||||
| import { CheckIcon } from '@radix-icons/vue'; | import { Check } from 'lucide-vue-next'; | ||||||
| import { | import { | ||||||
|   ContextMenuCheckboxItem, |   ContextMenuCheckboxItem, | ||||||
|   type ContextMenuCheckboxItemEmits, |   type ContextMenuCheckboxItemEmits, | ||||||
|  | @ -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"> |     <span class="absolute left-2 flex h-3.5 w-3.5 items-center justify-center"> | ||||||
|       <ContextMenuItemIndicator> |       <ContextMenuItemIndicator> | ||||||
|         <CheckIcon class="h-4 w-4" /> |         <Check class="h-4 w-4" /> | ||||||
|       </ContextMenuItemIndicator> |       </ContextMenuItemIndicator> | ||||||
|     </span> |     </span> | ||||||
|     <slot></slot> |     <slot></slot> | ||||||
|  |  | ||||||
|  | @ -3,7 +3,7 @@ import { computed } from 'vue'; | ||||||
| 
 | 
 | ||||||
| import { cn } from '@vben-core/shared/utils'; | import { cn } from '@vben-core/shared/utils'; | ||||||
| 
 | 
 | ||||||
| import { DotFilledIcon } from '@radix-icons/vue'; | import { Circle } from 'lucide-vue-next'; | ||||||
| import { | import { | ||||||
|   ContextMenuItemIndicator, |   ContextMenuItemIndicator, | ||||||
|   ContextMenuRadioItem, |   ContextMenuRadioItem, | ||||||
|  | @ -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"> |     <span class="absolute left-2 flex h-3.5 w-3.5 items-center justify-center"> | ||||||
|       <ContextMenuItemIndicator> |       <ContextMenuItemIndicator> | ||||||
|         <DotFilledIcon class="h-4 w-4 fill-current" /> |         <Circle class="h-2 w-2 fill-current" /> | ||||||
|       </ContextMenuItemIndicator> |       </ContextMenuItemIndicator> | ||||||
|     </span> |     </span> | ||||||
|     <slot></slot> |     <slot></slot> | ||||||
|  |  | ||||||
|  | @ -3,7 +3,7 @@ import { computed } from 'vue'; | ||||||
| 
 | 
 | ||||||
| import { cn } from '@vben-core/shared/utils'; | import { cn } from '@vben-core/shared/utils'; | ||||||
| 
 | 
 | ||||||
| import { ChevronRightIcon } from '@radix-icons/vue'; | import { ChevronRight } from 'lucide-vue-next'; | ||||||
| import { | import { | ||||||
|   ContextMenuSubTrigger, |   ContextMenuSubTrigger, | ||||||
|   type ContextMenuSubTriggerProps, |   type ContextMenuSubTriggerProps, | ||||||
|  | @ -38,6 +38,6 @@ const forwardedProps = useForwardProps(delegatedProps); | ||||||
|     " |     " | ||||||
|   > |   > | ||||||
|     <slot></slot> |     <slot></slot> | ||||||
|     <ChevronRightIcon class="ml-auto h-4 w-4" /> |     <ChevronRight class="ml-auto h-4 w-4" /> | ||||||
|   </ContextMenuSubTrigger> |   </ContextMenuSubTrigger> | ||||||
| </template> | </template> | ||||||
|  |  | ||||||
|  | @ -3,7 +3,7 @@ import { computed, ref } from 'vue'; | ||||||
| 
 | 
 | ||||||
| import { cn } from '@vben-core/shared/utils'; | import { cn } from '@vben-core/shared/utils'; | ||||||
| 
 | 
 | ||||||
| import { Cross2Icon } from '@radix-icons/vue'; | import { X } from 'lucide-vue-next'; | ||||||
| import { | import { | ||||||
|   DialogClose, |   DialogClose, | ||||||
|   DialogContent, |   DialogContent, | ||||||
|  | @ -77,7 +77,7 @@ defineExpose({ | ||||||
|         " |         " | ||||||
|         @click="() => emits('close')" |         @click="() => emits('close')" | ||||||
|       > |       > | ||||||
|         <Cross2Icon class="h-4 w-4" /> |         <X class="h-4 w-4" /> | ||||||
|       </DialogClose> |       </DialogClose> | ||||||
|     </DialogContent> |     </DialogContent> | ||||||
|   </DialogPortal> |   </DialogPortal> | ||||||
|  |  | ||||||
|  | @ -3,6 +3,7 @@ import { computed } from 'vue'; | ||||||
| 
 | 
 | ||||||
| import { cn } from '@vben-core/shared/utils'; | import { cn } from '@vben-core/shared/utils'; | ||||||
| 
 | 
 | ||||||
|  | import { X } from 'lucide-vue-next'; | ||||||
| import { | import { | ||||||
|   DialogClose, |   DialogClose, | ||||||
|   DialogContent, |   DialogContent, | ||||||
|  | @ -56,7 +57,7 @@ const forwarded = useForwardPropsEmits(delegatedProps, emits); | ||||||
|         <DialogClose |         <DialogClose | ||||||
|           class="hover:bg-secondary absolute right-4 top-4 rounded-md p-0.5 transition-colors" |           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> |           <span class="sr-only">Close</span> | ||||||
|         </DialogClose> |         </DialogClose> | ||||||
|       </DialogContent> |       </DialogContent> | ||||||
|  |  | ||||||
|  | @ -3,7 +3,7 @@ import { computed } from 'vue'; | ||||||
| 
 | 
 | ||||||
| import { cn } from '@vben-core/shared/utils'; | import { cn } from '@vben-core/shared/utils'; | ||||||
| 
 | 
 | ||||||
| import { CheckIcon } from '@radix-icons/vue'; | import { Check } from 'lucide-vue-next'; | ||||||
| import { | import { | ||||||
|   DropdownMenuCheckboxItem, |   DropdownMenuCheckboxItem, | ||||||
|   type DropdownMenuCheckboxItemEmits, |   type DropdownMenuCheckboxItemEmits, | ||||||
|  | @ -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"> |     <span class="absolute left-2 flex h-3.5 w-3.5 items-center justify-center"> | ||||||
|       <DropdownMenuItemIndicator> |       <DropdownMenuItemIndicator> | ||||||
|         <CheckIcon class="h-4 w-4" /> |         <Check class="h-4 w-4" /> | ||||||
|       </DropdownMenuItemIndicator> |       </DropdownMenuItemIndicator> | ||||||
|     </span> |     </span> | ||||||
|     <slot></slot> |     <slot></slot> | ||||||
|  |  | ||||||
|  | @ -3,7 +3,7 @@ import { computed } from 'vue'; | ||||||
| 
 | 
 | ||||||
| import { cn } from '@vben-core/shared/utils'; | import { cn } from '@vben-core/shared/utils'; | ||||||
| 
 | 
 | ||||||
| import { DotFilledIcon } from '@radix-icons/vue'; | import { Circle } from 'lucide-vue-next'; | ||||||
| import { | import { | ||||||
|   DropdownMenuItemIndicator, |   DropdownMenuItemIndicator, | ||||||
|   DropdownMenuRadioItem, |   DropdownMenuRadioItem, | ||||||
|  | @ -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"> |     <span class="absolute left-2 flex h-3.5 w-3.5 items-center justify-center"> | ||||||
|       <DropdownMenuItemIndicator> |       <DropdownMenuItemIndicator> | ||||||
|         <DotFilledIcon class="h-4 w-4 fill-current" /> |         <Circle class="h-2 w-2 fill-current" /> | ||||||
|       </DropdownMenuItemIndicator> |       </DropdownMenuItemIndicator> | ||||||
|     </span> |     </span> | ||||||
|     <slot></slot> |     <slot></slot> | ||||||
|  |  | ||||||
|  | @ -3,7 +3,7 @@ import { computed } from 'vue'; | ||||||
| 
 | 
 | ||||||
| import { cn } from '@vben-core/shared/utils'; | import { cn } from '@vben-core/shared/utils'; | ||||||
| 
 | 
 | ||||||
| import { ChevronRightIcon } from '@radix-icons/vue'; | import { ChevronRight } from 'lucide-vue-next'; | ||||||
| import { | import { | ||||||
|   DropdownMenuSubTrigger, |   DropdownMenuSubTrigger, | ||||||
|   type DropdownMenuSubTriggerProps, |   type DropdownMenuSubTriggerProps, | ||||||
|  | @ -32,6 +32,6 @@ const forwardedProps = useForwardProps(delegatedProps); | ||||||
|     " |     " | ||||||
|   > |   > | ||||||
|     <slot></slot> |     <slot></slot> | ||||||
|     <ChevronRightIcon class="ml-auto h-4 w-4" /> |     <ChevronRight class="ml-auto h-4 w-4" /> | ||||||
|   </DropdownMenuSubTrigger> |   </DropdownMenuSubTrigger> | ||||||
| </template> | </template> | ||||||
|  |  | ||||||
|  | @ -0,0 +1,27 @@ | ||||||
|  | <script setup lang="ts"> | ||||||
|  | import { computed } from 'vue'; | ||||||
|  | 
 | ||||||
|  | import { cn } from '@vben-core/shared/utils'; | ||||||
|  | 
 | ||||||
|  | import { MoreHorizontal } from 'lucide-vue-next'; | ||||||
|  | import { PaginationEllipsis, type PaginationEllipsisProps } from 'radix-vue'; | ||||||
|  | 
 | ||||||
|  | const props = defineProps<{ class?: any } & PaginationEllipsisProps>(); | ||||||
|  | 
 | ||||||
|  | const delegatedProps = computed(() => { | ||||||
|  |   const { class: _, ...delegated } = props; | ||||||
|  | 
 | ||||||
|  |   return delegated; | ||||||
|  | }); | ||||||
|  | </script> | ||||||
|  | 
 | ||||||
|  | <template> | ||||||
|  |   <PaginationEllipsis | ||||||
|  |     v-bind="delegatedProps" | ||||||
|  |     :class="cn('flex size-8 items-center justify-center', props.class)" | ||||||
|  |   > | ||||||
|  |     <slot> | ||||||
|  |       <MoreHorizontal class="size-4" /> | ||||||
|  |     </slot> | ||||||
|  |   </PaginationEllipsis> | ||||||
|  | </template> | ||||||
|  | @ -0,0 +1,33 @@ | ||||||
|  | <script setup lang="ts"> | ||||||
|  | import { computed } from 'vue'; | ||||||
|  | 
 | ||||||
|  | import { cn } from '@vben-core/shared/utils'; | ||||||
|  | 
 | ||||||
|  | import { ChevronsLeft } from 'lucide-vue-next'; | ||||||
|  | import { PaginationFirst, type PaginationFirstProps } from 'radix-vue'; | ||||||
|  | 
 | ||||||
|  | import { Button } from '../button'; | ||||||
|  | 
 | ||||||
|  | const props = withDefaults( | ||||||
|  |   defineProps<{ class?: any } & PaginationFirstProps>(), | ||||||
|  |   { | ||||||
|  |     asChild: true, | ||||||
|  |   }, | ||||||
|  | ); | ||||||
|  | 
 | ||||||
|  | const delegatedProps = computed(() => { | ||||||
|  |   const { class: _, ...delegated } = props; | ||||||
|  | 
 | ||||||
|  |   return delegated; | ||||||
|  | }); | ||||||
|  | </script> | ||||||
|  | 
 | ||||||
|  | <template> | ||||||
|  |   <PaginationFirst v-bind="delegatedProps"> | ||||||
|  |     <Button :class="cn('size-8 p-0', props.class)" variant="outline"> | ||||||
|  |       <slot> | ||||||
|  |         <ChevronsLeft class="size-4" /> | ||||||
|  |       </slot> | ||||||
|  |     </Button> | ||||||
|  |   </PaginationFirst> | ||||||
|  | </template> | ||||||
|  | @ -0,0 +1,33 @@ | ||||||
|  | <script setup lang="ts"> | ||||||
|  | import { computed } from 'vue'; | ||||||
|  | 
 | ||||||
|  | import { cn } from '@vben-core/shared/utils'; | ||||||
|  | 
 | ||||||
|  | import { ChevronsRight } from 'lucide-vue-next'; | ||||||
|  | import { PaginationLast, type PaginationLastProps } from 'radix-vue'; | ||||||
|  | 
 | ||||||
|  | import { Button } from '../button'; | ||||||
|  | 
 | ||||||
|  | const props = withDefaults( | ||||||
|  |   defineProps<{ class?: any } & PaginationLastProps>(), | ||||||
|  |   { | ||||||
|  |     asChild: true, | ||||||
|  |   }, | ||||||
|  | ); | ||||||
|  | 
 | ||||||
|  | const delegatedProps = computed(() => { | ||||||
|  |   const { class: _, ...delegated } = props; | ||||||
|  | 
 | ||||||
|  |   return delegated; | ||||||
|  | }); | ||||||
|  | </script> | ||||||
|  | 
 | ||||||
|  | <template> | ||||||
|  |   <PaginationLast v-bind="delegatedProps"> | ||||||
|  |     <Button :class="cn('size-8 p-0', props.class)" variant="outline"> | ||||||
|  |       <slot> | ||||||
|  |         <ChevronsRight class="size-4" /> | ||||||
|  |       </slot> | ||||||
|  |     </Button> | ||||||
|  |   </PaginationLast> | ||||||
|  | </template> | ||||||
|  | @ -0,0 +1,33 @@ | ||||||
|  | <script setup lang="ts"> | ||||||
|  | import { computed } from 'vue'; | ||||||
|  | 
 | ||||||
|  | import { cn } from '@vben-core/shared/utils'; | ||||||
|  | 
 | ||||||
|  | import { ChevronRight } from 'lucide-vue-next'; | ||||||
|  | import { PaginationNext, type PaginationNextProps } from 'radix-vue'; | ||||||
|  | 
 | ||||||
|  | import { Button } from '../button'; | ||||||
|  | 
 | ||||||
|  | const props = withDefaults( | ||||||
|  |   defineProps<{ class?: any } & PaginationNextProps>(), | ||||||
|  |   { | ||||||
|  |     asChild: true, | ||||||
|  |   }, | ||||||
|  | ); | ||||||
|  | 
 | ||||||
|  | const delegatedProps = computed(() => { | ||||||
|  |   const { class: _, ...delegated } = props; | ||||||
|  | 
 | ||||||
|  |   return delegated; | ||||||
|  | }); | ||||||
|  | </script> | ||||||
|  | 
 | ||||||
|  | <template> | ||||||
|  |   <PaginationNext v-bind="delegatedProps"> | ||||||
|  |     <Button :class="cn('size-8 p-0', props.class)" variant="outline"> | ||||||
|  |       <slot> | ||||||
|  |         <ChevronRight class="size-4" /> | ||||||
|  |       </slot> | ||||||
|  |     </Button> | ||||||
|  |   </PaginationNext> | ||||||
|  | </template> | ||||||
|  | @ -0,0 +1,33 @@ | ||||||
|  | <script setup lang="ts"> | ||||||
|  | import { computed } from 'vue'; | ||||||
|  | 
 | ||||||
|  | import { cn } from '@vben-core/shared/utils'; | ||||||
|  | 
 | ||||||
|  | import { ChevronLeft } from 'lucide-vue-next'; | ||||||
|  | import { PaginationPrev, type PaginationPrevProps } from 'radix-vue'; | ||||||
|  | 
 | ||||||
|  | import { Button } from '../button'; | ||||||
|  | 
 | ||||||
|  | const props = withDefaults( | ||||||
|  |   defineProps<{ class?: any } & PaginationPrevProps>(), | ||||||
|  |   { | ||||||
|  |     asChild: true, | ||||||
|  |   }, | ||||||
|  | ); | ||||||
|  | 
 | ||||||
|  | const delegatedProps = computed(() => { | ||||||
|  |   const { class: _, ...delegated } = props; | ||||||
|  | 
 | ||||||
|  |   return delegated; | ||||||
|  | }); | ||||||
|  | </script> | ||||||
|  | 
 | ||||||
|  | <template> | ||||||
|  |   <PaginationPrev v-bind="delegatedProps"> | ||||||
|  |     <Button :class="cn('size-8 p-0', props.class)" variant="outline"> | ||||||
|  |       <slot> | ||||||
|  |         <ChevronLeft class="size-4" /> | ||||||
|  |       </slot> | ||||||
|  |     </Button> | ||||||
|  |   </PaginationPrev> | ||||||
|  | </template> | ||||||
|  | @ -0,0 +1,10 @@ | ||||||
|  | export { default as PaginationEllipsis } from './PaginationEllipsis.vue'; | ||||||
|  | export { default as PaginationFirst } from './PaginationFirst.vue'; | ||||||
|  | export { default as PaginationLast } from './PaginationLast.vue'; | ||||||
|  | export { default as PaginationNext } from './PaginationNext.vue'; | ||||||
|  | export { default as PaginationPrev } from './PaginationPrev.vue'; | ||||||
|  | export { | ||||||
|  |   PaginationList, | ||||||
|  |   PaginationListItem, | ||||||
|  |   PaginationRoot as Pagination, | ||||||
|  | } from 'radix-vue'; | ||||||
|  | @ -1,5 +1,5 @@ | ||||||
| <script setup lang="ts"> | <script setup lang="ts"> | ||||||
| import { DashIcon } from '@radix-icons/vue'; | import { Dot } from 'lucide-vue-next'; | ||||||
| import { Primitive, type PrimitiveProps, useForwardProps } from 'radix-vue'; | import { Primitive, type PrimitiveProps, useForwardProps } from 'radix-vue'; | ||||||
| 
 | 
 | ||||||
| const props = defineProps<PrimitiveProps>(); | const props = defineProps<PrimitiveProps>(); | ||||||
|  | @ -9,7 +9,7 @@ const forwardedProps = useForwardProps(props); | ||||||
| <template> | <template> | ||||||
|   <Primitive v-bind="forwardedProps"> |   <Primitive v-bind="forwardedProps"> | ||||||
|     <slot> |     <slot> | ||||||
|       <DashIcon /> |       <Dot /> | ||||||
|     </slot> |     </slot> | ||||||
|   </Primitive> |   </Primitive> | ||||||
| </template> | </template> | ||||||
|  |  | ||||||
|  | @ -3,7 +3,7 @@ import { computed } from 'vue'; | ||||||
| 
 | 
 | ||||||
| import { cn } from '@vben-core/shared/utils'; | import { cn } from '@vben-core/shared/utils'; | ||||||
| 
 | 
 | ||||||
| import { CheckIcon } from '@radix-icons/vue'; | import { Circle } from 'lucide-vue-next'; | ||||||
| import { | import { | ||||||
|   RadioGroupIndicator, |   RadioGroupIndicator, | ||||||
|   RadioGroupItem, |   RadioGroupItem, | ||||||
|  | @ -33,7 +33,7 @@ const forwardedProps = useForwardProps(delegatedProps); | ||||||
|     " |     " | ||||||
|   > |   > | ||||||
|     <RadioGroupIndicator class="flex items-center justify-center"> |     <RadioGroupIndicator class="flex items-center justify-center"> | ||||||
|       <CheckIcon class="fill-primary h-3.5 w-3.5" /> |       <Circle class="h-2.5 w-2.5 fill-current text-current" /> | ||||||
|     </RadioGroupIndicator> |     </RadioGroupIndicator> | ||||||
|   </RadioGroupItem> |   </RadioGroupItem> | ||||||
| </template> | </template> | ||||||
|  |  | ||||||
|  | @ -3,7 +3,7 @@ import { computed } from 'vue'; | ||||||
| 
 | 
 | ||||||
| import { cn } from '@vben-core/shared/utils'; | import { cn } from '@vben-core/shared/utils'; | ||||||
| 
 | 
 | ||||||
| import { CheckIcon } from '@radix-icons/vue'; | import { Check } from 'lucide-vue-next'; | ||||||
| import { | import { | ||||||
|   SelectItem, |   SelectItem, | ||||||
|   SelectItemIndicator, |   SelectItemIndicator, | ||||||
|  | @ -35,7 +35,7 @@ const forwardedProps = useForwardProps(delegatedProps); | ||||||
|   > |   > | ||||||
|     <span class="absolute right-2 flex h-3.5 w-3.5 items-center justify-center"> |     <span class="absolute right-2 flex h-3.5 w-3.5 items-center justify-center"> | ||||||
|       <SelectItemIndicator> |       <SelectItemIndicator> | ||||||
|         <CheckIcon class="h-4 w-4" /> |         <Check class="h-4 w-4" /> | ||||||
|       </SelectItemIndicator> |       </SelectItemIndicator> | ||||||
|     </span> |     </span> | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -3,7 +3,7 @@ import { computed } from 'vue'; | ||||||
| 
 | 
 | ||||||
| import { cn } from '@vben-core/shared/utils'; | import { cn } from '@vben-core/shared/utils'; | ||||||
| 
 | 
 | ||||||
| import { ChevronDownIcon } from '@radix-icons/vue'; | import { ChevronDown } from 'lucide-vue-next'; | ||||||
| import { | import { | ||||||
|   SelectScrollDownButton, |   SelectScrollDownButton, | ||||||
|   type SelectScrollDownButtonProps, |   type SelectScrollDownButtonProps, | ||||||
|  | @ -29,7 +29,7 @@ const forwardedProps = useForwardProps(delegatedProps); | ||||||
|     " |     " | ||||||
|   > |   > | ||||||
|     <slot> |     <slot> | ||||||
|       <ChevronDownIcon /> |       <ChevronDown class="h-4 w-4" /> | ||||||
|     </slot> |     </slot> | ||||||
|   </SelectScrollDownButton> |   </SelectScrollDownButton> | ||||||
| </template> | </template> | ||||||
|  |  | ||||||
|  | @ -3,7 +3,7 @@ import { computed } from 'vue'; | ||||||
| 
 | 
 | ||||||
| import { cn } from '@vben-core/shared/utils'; | import { cn } from '@vben-core/shared/utils'; | ||||||
| 
 | 
 | ||||||
| import { ChevronUpIcon } from '@radix-icons/vue'; | import { ChevronUp } from 'lucide-vue-next'; | ||||||
| import { | import { | ||||||
|   SelectScrollUpButton, |   SelectScrollUpButton, | ||||||
|   type SelectScrollUpButtonProps, |   type SelectScrollUpButtonProps, | ||||||
|  | @ -29,7 +29,7 @@ const forwardedProps = useForwardProps(delegatedProps); | ||||||
|     " |     " | ||||||
|   > |   > | ||||||
|     <slot> |     <slot> | ||||||
|       <ChevronUpIcon /> |       <ChevronUp class="h-4 w-4" /> | ||||||
|     </slot> |     </slot> | ||||||
|   </SelectScrollUpButton> |   </SelectScrollUpButton> | ||||||
| </template> | </template> | ||||||
|  |  | ||||||
|  | @ -3,7 +3,7 @@ import { computed } from 'vue'; | ||||||
| 
 | 
 | ||||||
| import { cn } from '@vben-core/shared/utils'; | import { cn } from '@vben-core/shared/utils'; | ||||||
| 
 | 
 | ||||||
| import { CaretSortIcon } from '@radix-icons/vue'; | import { ChevronDown } from 'lucide-vue-next'; | ||||||
| import { | import { | ||||||
|   SelectIcon, |   SelectIcon, | ||||||
|   SelectTrigger, |   SelectTrigger, | ||||||
|  | @ -34,7 +34,7 @@ const forwardedProps = useForwardProps(delegatedProps); | ||||||
|   > |   > | ||||||
|     <slot></slot> |     <slot></slot> | ||||||
|     <SelectIcon as-child> |     <SelectIcon as-child> | ||||||
|       <CaretSortIcon class="h-4 w-4 opacity-50" /> |       <ChevronDown class="h-4 w-4 opacity-50" /> | ||||||
|     </SelectIcon> |     </SelectIcon> | ||||||
|   </SelectTrigger> |   </SelectTrigger> | ||||||
| </template> | </template> | ||||||
|  |  | ||||||
|  | @ -3,7 +3,7 @@ import { computed } from 'vue'; | ||||||
| 
 | 
 | ||||||
| import { cn } from '@vben-core/shared/utils'; | import { cn } from '@vben-core/shared/utils'; | ||||||
| 
 | 
 | ||||||
| import { Cross2Icon } from '@radix-icons/vue'; | import { X } from 'lucide-vue-next'; | ||||||
| import { ToastClose, type ToastCloseProps } from 'radix-vue'; | import { ToastClose, type ToastCloseProps } from 'radix-vue'; | ||||||
| 
 | 
 | ||||||
| const props = defineProps< | const props = defineProps< | ||||||
|  | @ -29,6 +29,6 @@ const delegatedProps = computed(() => { | ||||||
|       ) |       ) | ||||||
|     " |     " | ||||||
|   > |   > | ||||||
|     <Cross2Icon class="h-4 w-4" /> |     <X class="size-4" /> | ||||||
|   </ToastClose> |   </ToastClose> | ||||||
| </template> | </template> | ||||||
|  |  | ||||||
|  | @ -54,9 +54,6 @@ catalogs: | ||||||
|     '@playwright/test': |     '@playwright/test': | ||||||
|       specifier: ^1.47.2 |       specifier: ^1.47.2 | ||||||
|       version: 1.47.2 |       version: 1.47.2 | ||||||
|     '@radix-icons/vue': |  | ||||||
|       specifier: ^1.0.0 |  | ||||||
|       version: 1.0.0 |  | ||||||
|     '@stylistic/stylelint-plugin': |     '@stylistic/stylelint-plugin': | ||||||
|       specifier: ^3.1.0 |       specifier: ^3.1.0 | ||||||
|       version: 3.1.0 |       version: 3.1.0 | ||||||
|  | @ -1373,9 +1370,6 @@ importers: | ||||||
| 
 | 
 | ||||||
|   packages/@core/ui-kit/shadcn-ui: |   packages/@core/ui-kit/shadcn-ui: | ||||||
|     dependencies: |     dependencies: | ||||||
|       '@radix-icons/vue': |  | ||||||
|         specifier: 'catalog:' |  | ||||||
|         version: 1.0.0(vue@3.5.8(typescript@5.6.2)) |  | ||||||
|       '@vben-core/composables': |       '@vben-core/composables': | ||||||
|         specifier: workspace:* |         specifier: workspace:* | ||||||
|         version: link:../../composables |         version: link:../../composables | ||||||
|  | @ -4212,11 +4206,6 @@ packages: | ||||||
|   '@polka/url@1.0.0-next.28': |   '@polka/url@1.0.0-next.28': | ||||||
|     resolution: {integrity: sha512-8LduaNlMZGwdZ6qWrKlfa+2M4gahzFkprZiAt2TF8uS0qQgBizKXpXURqvTJ4WtmupWxaLqjRb2UCTe72mu+Aw==} |     resolution: {integrity: sha512-8LduaNlMZGwdZ6qWrKlfa+2M4gahzFkprZiAt2TF8uS0qQgBizKXpXURqvTJ4WtmupWxaLqjRb2UCTe72mu+Aw==} | ||||||
| 
 | 
 | ||||||
|   '@radix-icons/vue@1.0.0': |  | ||||||
|     resolution: {integrity: sha512-gKWWk9tTK/laDRRNe5KLLR8A0qUwx4q4+DN8Fq48hJ904u78R82ayAO3TrxbNLgyn2D0h6rRiGdLzQWj7rPcvA==} |  | ||||||
|     peerDependencies: |  | ||||||
|       vue: 3.5.8 |  | ||||||
| 
 |  | ||||||
|   '@rollup/plugin-alias@5.1.1': |   '@rollup/plugin-alias@5.1.1': | ||||||
|     resolution: {integrity: sha512-PR9zDb+rOzkRb2VD+EuKB7UC41vU5DIwZ5qqCpk0KJudcWAyi8rvYOhS7+L5aZCspw1stTViLgN5v6FF1p5cgQ==} |     resolution: {integrity: sha512-PR9zDb+rOzkRb2VD+EuKB7UC41vU5DIwZ5qqCpk0KJudcWAyi8rvYOhS7+L5aZCspw1stTViLgN5v6FF1p5cgQ==} | ||||||
|     engines: {node: '>=14.0.0'} |     engines: {node: '>=14.0.0'} | ||||||
|  | @ -13050,10 +13039,6 @@ snapshots: | ||||||
| 
 | 
 | ||||||
|   '@polka/url@1.0.0-next.28': {} |   '@polka/url@1.0.0-next.28': {} | ||||||
| 
 | 
 | ||||||
|   '@radix-icons/vue@1.0.0(vue@3.5.8(typescript@5.6.2))': |  | ||||||
|     dependencies: |  | ||||||
|       vue: 3.5.8(typescript@5.6.2) |  | ||||||
| 
 |  | ||||||
|   '@rollup/plugin-alias@5.1.1(rollup@3.29.5)': |   '@rollup/plugin-alias@5.1.1(rollup@3.29.5)': | ||||||
|     optionalDependencies: |     optionalDependencies: | ||||||
|       rollup: 3.29.5 |       rollup: 3.29.5 | ||||||
|  |  | ||||||
|  | @ -30,7 +30,6 @@ catalog: | ||||||
|   '@manypkg/get-packages': ^2.2.2 |   '@manypkg/get-packages': ^2.2.2 | ||||||
|   '@nolebase/vitepress-plugin-git-changelog': ^2.5.0 |   '@nolebase/vitepress-plugin-git-changelog': ^2.5.0 | ||||||
|   '@playwright/test': ^1.47.2 |   '@playwright/test': ^1.47.2 | ||||||
|   '@radix-icons/vue': ^1.0.0 |  | ||||||
|   '@stylistic/stylelint-plugin': ^3.1.0 |   '@stylistic/stylelint-plugin': ^3.1.0 | ||||||
|   '@tailwindcss/nesting': 0.0.0-insiders.565cd3e |   '@tailwindcss/nesting': 0.0.0-insiders.565cd3e | ||||||
|   '@tailwindcss/typography': ^0.5.15 |   '@tailwindcss/typography': ^0.5.15 | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue
	
	 Vben
						Vben