UNPKG

@inkline/inkline

Version:

Inkline is the Vue.js UI/UX Library built for creating your next design system

230 lines (212 loc) 6.82 kB
import { defineComponent } from 'vue'; import { defaultPropValue, colorVariantClass, sizePropValidator } from '@inkline/inkline/mixins'; import { breakpointKeys, breakpoints } from '@inkline/inkline/constants'; import { debounce } from '@inkline/inkline/helpers'; import { Classes } from '@inkline/inkline/types'; /** * Slot for previous button content * @name previous * @kind slot */ /** * Slot for next button content * @name next * @kind slot */ const componentName = 'IPagination'; export default defineComponent({ name: componentName, props: { /** * The aria-label of the pagination * @type String * @default Pagination * @name ariaLabel */ ariaLabel: { type: String, default: 'Pagination' }, /** * The color variant of the pagination * @type light | dark * @default light * @name color */ color: { type: String, default: defaultPropValue<string>(componentName, 'color') }, /** * The number of items per page to be displayed * @type Number * @default 20 * @name itemsPerPage */ itemsPerPage: { type: Number, default: 20 }, /** * The total number of items * @type Number * @default 0 * @name itemsTotal */ itemsTotal: { type: Number, default: 0 }, /** * The maximum number of pagination buttons to show on each breakpoint * @type Number | Object * @name limit * @default { xs: 3, sm: 5 } */ limit: { type: [Number, Object], default (): { [key: string]: number } { return { xs: 3, sm: 5 }; } }, /** * Display the quick link buttons * @type Boolean * @default false * @name quickLink */ quickLink: { type: Boolean, default: false }, /** * Used to determine the current page * @type Number * @default 1 * @name modelValue */ modelValue: { type: Number, default: 1 }, /** * The size variant of the pagination * @type sm | md | lg * @default md * @name size */ size: { type: String, default: defaultPropValue<string>(componentName, 'size'), validator: sizePropValidator } }, emits: [ /** * Event emitted for setting the modelValue * @event update:modelValue */ 'update:modelValue' ], data (): { pageLimit: number } { return { pageLimit: 5 }; }, computed: { classes (): Classes { return { ...colorVariantClass(this), [`-${(this as any).size}`]: Boolean((this as any).size) }; }, pageCount (): number { return Math.ceil((this as any).itemsTotal / (this as any).itemsPerPage); }, showQuickPrevious (): boolean { return this.pageCount > this.pageLimit && // Has more pages than limit (this as any).modelValue > this.pageLimit - (this.pageLimit - 1) / 2; // Active page is after limit - (limit - 1) / 2 }, showQuickNext (): boolean { return this.pageCount > this.pageLimit && // Has more pages than limit (this as any).modelValue < this.pageCount - (this.pageLimit - 1) / 2; // Active page is before pageCount - (limit - 1) / 2 }, pages (): number[] { const pages = []; if (this.showQuickPrevious && !this.showQuickNext) { const startPage = this.pageCount - (this.pageLimit - 2); for (let i = startPage; i < this.pageCount; i++) { pages.push(i); } } else if (!this.showQuickPrevious && this.showQuickNext) { for (let i = 2; i < this.pageLimit; i++) { pages.push(i); } } else if (this.showQuickPrevious && this.showQuickNext) { const offset = Math.floor(this.pageLimit / 2) - 1; for (let i = (this as any).modelValue - offset; i <= (this as any).modelValue + offset; i++) { pages.push(i); } } else { for (let i = 2; i < this.pageCount; i++) { pages.push(i); } } return pages; } }, created () { (this as any).debouncedOnWindowResize = debounce(this.onWindowResize, 250); if (typeof window !== 'undefined') { window.addEventListener('resize', (this as any).debouncedOnWindowResize); this.onWindowResize(); } }, unmounted () { if (typeof window !== 'undefined') { window.removeEventListener('resize', (this as any).debouncedOnWindowResize); } }, methods: { next () { if ((this as any).modelValue === this.pageCount) { return; } this.onClick((this as any).modelValue + 1); }, quickNext () { if (!(this as any).quickLink) { return; } const jumpTo = (this as any).modelValue + (this.pageLimit - 2); this.onClick(jumpTo > this.pageCount ? this.pageCount : jumpTo); }, previous () { if ((this as any).modelValue === 1) { return; } this.onClick((this as any).modelValue - 1); }, quickPrevious () { if (!(this as any).quickLink) { return; } const jumpTo = (this as any).modelValue - (this.pageLimit - 2); this.onClick(jumpTo < 1 ? 1 : jumpTo); }, onClick (item: number) { this.$emit('update:modelValue', item); }, onWindowResize () { if (typeof (this as any).limit === 'number') { this.pageLimit = (this as any).limit; return this.pageLimit; } for (const breakpointKey of breakpointKeys.slice().reverse()) { if ((this as any).limit.hasOwnProperty(breakpointKey) && (typeof window !== 'undefined' && window.innerWidth >= breakpoints[breakpointKey][0])) { this.pageLimit = (this as any).limit[breakpointKey]; return this.pageLimit; } } } } });