@gitlab/ui
Version:
GitLab UI Components
412 lines (369 loc) • 12.9 kB
JavaScript
import range from 'lodash/range';
import isFunction from 'lodash/isFunction';
import debounce from 'lodash/debounce';
import GlLink from '../link/link';
import GlIcon from '../icon/icon';
import Breakpoints, { breakpoints } from '../../../utils/breakpoints';
import { sizeOptions, alignOptions, resizeDebounceTime } from '../../../utils/constants';
import __vue_normalize__ from 'vue-runtime-helpers/dist/normalize-component.js';
function _defineProperty(obj, key, value) {
if (key in obj) {
Object.defineProperty(obj, key, {
value: value,
enumerable: true,
configurable: true,
writable: true
});
} else {
obj[key] = value;
}
return obj;
}
function ownKeys(object, enumerableOnly) {
var keys = Object.keys(object);
if (Object.getOwnPropertySymbols) {
var symbols = Object.getOwnPropertySymbols(object);
if (enumerableOnly) symbols = symbols.filter(function (sym) {
return Object.getOwnPropertyDescriptor(object, sym).enumerable;
});
keys.push.apply(keys, symbols);
}
return keys;
}
function _objectSpread2(target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i] != null ? arguments[i] : {};
if (i % 2) {
ownKeys(Object(source), true).forEach(function (key) {
_defineProperty(target, key, source[key]);
});
} else if (Object.getOwnPropertyDescriptors) {
Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
} else {
ownKeys(Object(source)).forEach(function (key) {
Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
});
}
}
return target;
}
var pageRange = function pageRange(from, to) {
return range(from, to + 1, 1);
};
var script = {
name: 'Pagination',
components: {
GlLink: GlLink,
GlIcon: GlIcon
},
model: {
prop: 'value',
event: 'input'
},
props: {
value: {
type: Number,
required: false,
default: 1,
validator: function validator(x) {
return x > 0;
}
},
perPage: {
type: Number,
required: false,
default: 20,
validator: function validator(x) {
return x > 0;
}
},
totalItems: {
type: Number,
required: false,
default: 0
},
limits: {
type: Object,
required: false,
default: function _default() {
return {
xs: 0,
sm: 3,
md: 9,
default: 9
};
},
validator: function validator(value) {
var missingSizes = Object.keys(breakpoints).filter(function (size) {
return !value[size];
}).length;
return missingSizes === 0 ? true : value.default;
}
},
linkGen: {
type: Function,
required: false,
default: null
},
prevPage: {
type: Number,
required: false,
default: null
},
prevText: {
type: String,
required: false,
default: 'Prev'
},
nextPage: {
type: Number,
required: false,
default: null
},
nextText: {
type: String,
required: false,
default: 'Next'
},
ellipsisText: {
type: String,
required: false,
default: '…'
},
labelFirstPage: {
type: String,
required: false,
default: 'Go to first page'
},
labelPrevPage: {
type: String,
required: false,
default: 'Go to previous page'
},
labelNextPage: {
type: String,
required: false,
default: 'Go to next page'
},
labelLastPage: {
type: String,
required: false,
default: 'Go to last page'
},
labelPage: {
type: Function,
required: false,
default: function _default(page) {
return "Go to page ".concat(page);
}
},
size: {
type: String,
required: false,
default: null,
validator: function validator(value) {
return Object.keys(sizeOptions).includes(value);
}
},
align: {
type: String,
required: false,
default: alignOptions.left,
validator: function validator(value) {
return Object.keys(alignOptions).includes(value);
}
},
disabled: {
type: Boolean,
required: false,
default: false
}
},
data: function data() {
return {
breakpoint: Breakpoints.getBreakpointSize(),
// If total pages count is below or equal to minTotalPagesToCollapse, collapsing is disabled
minTotalPagesToCollapse: 4
};
},
computed: {
isVisible: function isVisible() {
return this.totalPages > 1 || this.isCompactPagination;
},
isLinkBased: function isLinkBased() {
return isFunction(this.linkGen);
},
paginationLimit: function paginationLimit() {
return typeof this.limits[this.breakpoint] !== 'undefined' ? this.limits[this.breakpoint] : this.limits.default;
},
maxAdjacentPages: function maxAdjacentPages() {
return Math.max(Math.ceil((this.paginationLimit - 1) / 2), 0);
},
totalPages: function totalPages() {
return Math.ceil(this.totalItems / this.perPage);
},
isFillAlign: function isFillAlign() {
return this.align === alignOptions.fill;
},
wrapperClasses: function wrapperClasses() {
var classes = [];
if (this.align === alignOptions.center) {
classes.push('justify-content-center');
}
if (this.align === alignOptions.right) {
classes.push('justify-content-end');
}
if (this.isFillAlign) {
classes.push('text-center');
}
if (this.size) {
classes.push("pagination-".concat(this.size));
}
if (Object.keys(this.$slots).length > 0) {
classes.push('custom-rendering');
}
return classes;
},
shouldCollapseLeftSide: function shouldCollapseLeftSide() {
var diff = this.value - this.maxAdjacentPages; // Magic 3: prevents collapsing a single page on the left side
return diff >= this.maxAdjacentPages && diff > 3 && this.totalPages > this.minTotalPagesToCollapse;
},
shouldCollapseRightSide: function shouldCollapseRightSide() {
// Magic 2: prevents collapsing a single page on the right side
var diff = this.totalPages - 2 - this.value;
return diff > this.maxAdjacentPages && this.totalPages > this.minTotalPagesToCollapse;
},
visibleItems: function visibleItems() {
var _this = this;
var items = [];
if (!this.isCompactPagination) {
var firstPage = this.shouldCollapseLeftSide ? this.value - this.maxAdjacentPages : 1; // If we're on last page, show at least one page to the left
firstPage = Math.min(firstPage, this.totalPages - 1);
var lastPage = this.shouldCollapseRightSide ? this.value + this.maxAdjacentPages : this.totalPages; // If we're on first page, show at least one page to the right
lastPage = Math.max(lastPage, 2); // Default numbered items
items = pageRange(firstPage, lastPage).map(function (page) {
return _this.getPageItem(page);
});
if (this.shouldCollapseLeftSide) {
items.splice(0, 0, this.getPageItem(1, this.labelFirstPage), this.getEllipsisItem('left'));
}
if (this.shouldCollapseRightSide) {
items.push(this.getEllipsisItem('right'), this.getPageItem(this.totalPages, this.labelLastPage));
}
}
return items;
},
isCompactPagination: function isCompactPagination() {
return Boolean(!this.totalItems && (this.prevPage || this.nextPage));
},
prevPageIsDisabled: function prevPageIsDisabled() {
return this.pageIsDisabled(this.value - 1);
},
nextPageIsDisabled: function nextPageIsDisabled() {
return this.pageIsDisabled(this.value + 1);
}
},
created: function created() {
window.addEventListener('resize', debounce(this.setBreakpoint, resizeDebounceTime));
},
beforeDestroy: function beforeDestroy() {
window.removeEventListener('resize', debounce(this.setBreakpoint, resizeDebounceTime));
},
methods: {
setBreakpoint: function setBreakpoint() {
this.breakpoint = Breakpoints.getBreakpointSize();
},
pageIsDisabled: function pageIsDisabled(page) {
return this.disabled || page < 1 || this.isCompactPagination && page > this.value && !this.nextPage || !this.isCompactPagination && page > this.totalPages;
},
getPageItem: function getPageItem(page) {
var _this2 = this;
var label = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
var commonAttrs = {
'aria-label': label || this.labelPage(page),
href: '#',
class: []
};
var isActivePage = page === this.value;
var isDisabled = this.pageIsDisabled(page);
var attrs = _objectSpread2({}, commonAttrs);
var listeners = {};
if (isActivePage) {
attrs.class.push('active', 'btn-primary');
} // Disable previous and/or next buttons if needed
if (this.isLinkBased) {
attrs.href = this.linkGen(page);
}
listeners.click = function (e) {
return _this2.handleClick(e, page);
};
return {
content: page,
component: isDisabled ? 'span' : GlLink,
disabled: isDisabled,
key: "page_".concat(page),
slot: 'page-number',
slotData: {
page: page,
active: isActivePage,
disabled: isDisabled
},
attrs: attrs,
listeners: listeners
};
},
getEllipsisItem: function getEllipsisItem(side) {
return {
content: this.ellipsisText,
key: "ellipsis_".concat(side),
slot: "ellipsis-".concat(side),
component: 'span',
disabled: true
};
},
handleClick: function handleClick(event, value) {
if (!this.isLinkBased) {
event.preventDefault();
this.$emit('input', value);
}
}
}
};
/* script */
const __vue_script__ = script;
/* template */
var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return (_vm.isVisible)?_c('ul',{staticClass:"pagination gl-pagination text-nowrap",class:_vm.wrapperClasses,attrs:{"role":"navigation","aria-label":"Pagination"}},[_c('li',{staticClass:"page-item",class:{
disabled: _vm.prevPageIsDisabled,
'flex-fill': _vm.isFillAlign,
}},[_c(_vm.prevPageIsDisabled ? 'span' : 'a',{tag:"component",staticClass:"page-link prev-page-item",attrs:{"aria-disabled":_vm.prevPageIsDisabled,"aria-label":_vm.labelPrevPage || _vm.labelPage(_vm.value - 1),"href":_vm.isLinkBased ? _vm.linkGen(_vm.value - 1) : '#'},on:{"click":function($event){return _vm.handleClick($event, _vm.value - 1)}}},[_vm._t("previous",[_c('gl-icon',{attrs:{"name":"chevron-left"}}),_vm._v(" "),_c('span',[_vm._v(_vm._s(_vm.prevText))])],null,{ page: _vm.value - 1, disabled: _vm.prevPageIsDisabled })],2)],1),_vm._v(" "),_vm._l((_vm.visibleItems),function(item){return _c('li',{key:item.key,staticClass:"page-item",class:{
disabled: item.disabled,
'flex-fill': _vm.isFillAlign,
}},[_c(item.component,_vm._g(_vm._b({tag:"component",staticClass:"page-link",attrs:{"size":_vm.size,"aria-disabled":item.disabled}},'component',item.attrs,false),item.listeners),[_vm._t(item.slot,[_vm._v(_vm._s(item.content))],null,item.slotData)],2)],1)}),_vm._v(" "),_c('li',{staticClass:"page-item",class:{
disabled: _vm.nextPageIsDisabled,
'flex-fill': _vm.isFillAlign,
}},[_c(_vm.nextPageIsDisabled ? 'span' : 'a',{tag:"component",staticClass:"page-link next-page-item",attrs:{"aria-disabled":_vm.nextPageIsDisabled,"aria-label":_vm.labelNextPage || _vm.labelPage(_vm.value + 1),"href":_vm.isLinkBased ? _vm.linkGen(_vm.value + 1) : '#'},on:{"click":function($event){return _vm.handleClick($event, _vm.value + 1)}}},[_vm._t("next",[_c('span',[_vm._v(_vm._s(_vm.nextText))]),_vm._v(" "),_c('gl-icon',{attrs:{"name":"chevron-right"}})],null,{ page: _vm.value + 1, disabled: _vm.nextPageIsDisabled })],2)],1)],2):_vm._e()};
var __vue_staticRenderFns__ = [];
/* style */
const __vue_inject_styles__ = undefined;
/* scoped */
const __vue_scope_id__ = undefined;
/* module identifier */
const __vue_module_identifier__ = undefined;
/* functional template */
const __vue_is_functional_template__ = false;
/* style inject */
/* style inject SSR */
/* style inject shadow dom */
const __vue_component__ = __vue_normalize__(
{ render: __vue_render__, staticRenderFns: __vue_staticRenderFns__ },
__vue_inject_styles__,
__vue_script__,
__vue_scope_id__,
__vue_is_functional_template__,
__vue_module_identifier__,
false,
undefined,
undefined,
undefined
);
export default __vue_component__;