@ishitatsuyuki/oruga-next
Version:
UI components for Vue.js and CSS framework agnostic
536 lines (525 loc) • 18 kB
JavaScript
'use strict';
var vue = require('vue');
var helpers = require('./helpers.js');
var config = require('./config.js');
var BaseComponentMixin = require('./BaseComponentMixin-a03c02e3.js');
var Icon = require('./Icon-172f9998.js');
var MatchMediaMixin = require('./MatchMediaMixin-08658b15.js');
var script = vue.defineComponent({
name: 'OPaginationButton',
inject: ['$pagination'],
configField: 'pagination',
props: {
page: {
type: Object,
required: true
},
tag: {
type: String,
default: 'a',
validator: (value) => helpers.getValueByPath(config.getOptions(), 'linkTags', ['a', 'button', 'input', 'router-link', 'nuxt-link']).indexOf(value) >= 0
},
disabled: {
type: Boolean,
default: false
},
linkClass: [String, Array, Object],
linkCurrentClass: [String, Array, Object]
},
computed: {
linkClasses() {
return [
this.linkClass || [...this.$pagination.linkClasses],
this.page.class,
{ [this.linkCurrentClass || this.$pagination.linkCurrentClasses]: this.page.isCurrent }
];
},
href() {
if (this.tag === 'a') {
return '#';
}
return '';
},
isDisabled() {
if (this.tag === 'a')
return null;
return this.disabled || this.page.disabled;
}
}
});
function render(_ctx, _cache, $props, $setup, $data, $options) {
return vue.openBlock(), vue.createBlock(vue.resolveDynamicComponent(_ctx.tag), vue.mergeProps({
role: "button",
href: _ctx.href,
disabled: _ctx.isDisabled,
class: _ctx.linkClasses
}, _ctx.$attrs, {
onClick: vue.withModifiers(_ctx.page.click, ["prevent"]),
"aria-label": _ctx.page['aria-label'],
"aria-current": _ctx.page.isCurrent
}), {
default: vue.withCtx(() => [vue.renderSlot(_ctx.$slots, "default", {}, () => [vue.createTextVNode(vue.toDisplayString(_ctx.page.number), 1
/* TEXT */
)])]),
_: 3
}, 16
/* FULL_PROPS */
, ["href", "disabled", "class", "onClick", "aria-label", "aria-current"]);
}
script.render = render;
script.__file = "src/components/pagination/PaginationButton.vue";
/**
* A responsive and flexible pagination
* @displayName Pagination
* @style _pagination.scss
*/
var script$1 = vue.defineComponent({
name: 'OPagination',
components: {
[Icon.script.name]: Icon.script,
[script.name]: script
},
configField: 'pagination',
mixins: [BaseComponentMixin.BaseComponentMixin, MatchMediaMixin.MatchMediaMixin],
provide() {
return {
$pagination: this
};
},
emits: ['update:active', 'change', 'update:current'],
props: {
/** Total count of items */
total: [Number, String],
/** Items count for each page */
perPage: {
type: [Number, String],
default: () => { return helpers.getValueByPath(config.getOptions(), 'pagination.perPage', 20); }
},
/** Current page number, use v-model:current to make it two-way binding */
current: {
type: [Number, String],
default: 1
},
/** Number of pagination items to show before current page */
rangeBefore: {
type: [Number, String],
default: 1
},
/** Number of pagination items to show after current page */
rangeAfter: {
type: [Number, String],
default: 1
},
/**
* Pagination size, optional
* @values small, medium, large
*/
size: String,
/** Simple style */
simple: Boolean,
/** Rounded button styles */
rounded: Boolean,
/**
* Buttons order, optional
* @values centered, right, left
*/
order: String,
/**
* Icon pack to use
* @values mdi, fa, fas and any other custom icon pack
*/
iconPack: String,
/** Icon to use for previous button */
iconPrev: {
type: String,
default: () => { return helpers.getValueByPath(config.getOptions(), 'pagination.iconPrev', 'chevron-left'); }
},
/** Icon to use for next button */
iconNext: {
type: String,
default: () => { return helpers.getValueByPath(config.getOptions(), 'pagination.iconNext', 'chevron-right'); }
},
ariaNextLabel: String,
ariaPreviousLabel: String,
ariaPageLabel: String,
ariaCurrentLabel: String,
rootClass: [String, Function, Array],
prevBtnClass: [String, Function, Array],
nextBtnClass: [String, Function, Array],
listClass: [String, Function, Array],
linkClass: [String, Function, Array],
linkCurrentClass: [String, Function, Array],
ellipsisClass: [String, Function, Array],
infoClass: [String, Function, Array],
orderClass: [String, Function, Array],
simpleClass: [String, Function, Array],
roundedClass: [String, Function, Array],
linkDisabledClass: [String, Function, Array],
sizeClass: [String, Function, Array],
mobileClass: [String, Function, Array]
},
computed: {
rootClasses() {
return [
this.computedClass('rootClass', 'o-pag'),
{ [this.computedClass('orderClass', 'o-pag--', this.order)]: this.order },
{ [this.computedClass('sizeClass', 'o-pag--', this.size)]: this.size },
{ [this.computedClass('simpleClass', 'o-pag--simple')]: this.simple },
{ [this.computedClass('mobileClass', 'o-pag--mobile')]: this.isMatchMedia },
];
},
prevBtnClasses() {
return [
this.computedClass('prevBtnClass', 'o-pag__previous'),
{ [this.computedClass('linkDisabledClass', 'o-pag__link--disabled')]: !this.hasPrev }
];
},
nextBtnClasses() {
return [
this.computedClass('nextBtnClass', 'o-pag__next'),
{ [this.computedClass('linkDisabledClass', 'o-pag__link--disabled')]: !this.hasNext }
];
},
infoClasses() {
return [
this.computedClass('infoClass', 'o-pag__info')
];
},
ellipsisClasses() {
return [
this.computedClass('ellipsisClass', 'o-pag__ellipsis')
];
},
listClasses() {
return [
this.computedClass('listClass', 'o-pag__list')
];
},
linkClasses() {
return [
this.computedClass('linkClass', 'o-pag__link'),
{ [this.computedClass('roundedClass', 'o-pag__link--rounded')]: this.rounded }
];
},
linkCurrentClasses() {
return [
this.computedClass('linkCurrentClass', 'o-pag__link--current'),
];
},
beforeCurrent() {
return parseInt(this.rangeBefore);
},
afterCurrent() {
return parseInt(this.rangeAfter);
},
/**
* Total page size (count).
*/
pageCount() {
return Math.ceil(this.total / this.perPage);
},
/**
* First item of the page (count).
*/
firstItem() {
const firstItem = this.current * this.perPage - this.perPage + 1;
return firstItem >= 0 ? firstItem : 0;
},
/**
* Check if previous button is available.
*/
hasPrev() {
return this.current > 1;
},
/**
* Check if first page button should be visible.
*/
hasFirst() {
return this.current >= (2 + this.beforeCurrent);
},
/**
* Check if first ellipsis should be visible.
*/
hasFirstEllipsis() {
return this.current >= (this.beforeCurrent + 4);
},
/**
* Check if last page button should be visible.
*/
hasLast() {
return this.current <= this.pageCount - (1 + this.afterCurrent);
},
/**
* Check if last ellipsis should be visible.
*/
hasLastEllipsis() {
return this.current < this.pageCount - (2 + this.afterCurrent);
},
/**
* Check if next button is available.
*/
hasNext() {
return this.current < this.pageCount;
},
/**
* Get near pages, 1 before and 1 after the current.
* Also add the click event to the array.
*/
pagesInRange() {
if (this.simple)
return;
let left = Math.max(1, this.current - this.beforeCurrent);
if (left - 1 === 2) {
left--; // Do not show the ellipsis if there is only one to hide
}
let right = Math.min(this.current + this.afterCurrent, this.pageCount);
if (this.pageCount - right === 2) {
right++; // Do not show the ellipsis if there is only one to hide
}
const pages = [];
for (let i = left; i <= right; i++) {
pages.push(this.getPage(i));
}
return pages;
},
hasDefaultSlot() {
return this.$slots.default;
},
hasPreviousSlot() {
return this.$slots.previous;
},
hasNextSlot() {
return this.$slots.next;
}
},
watch: {
/**
* If current page is trying to be greater than page count, set to last.
*/
pageCount(value) {
if (this.current > value)
this.last();
}
},
methods: {
/**
* Previous button click listener.
*/
prev(event) {
this.changePage(this.current - 1, event);
},
/**
* Next button click listener.
*/
next(event) {
this.changePage(this.current + 1, event);
},
/**
* First button click listener.
*/
first(event) {
this.changePage(1, event);
},
/**
* Last button click listener.
*/
last(event) {
this.changePage(this.pageCount, event);
},
changePage(num, event) {
if (this.current === num || num < 1 || num > this.pageCount)
return;
this.$emit('change', num);
this.$emit('update:current', num);
// Set focus on element to keep tab order
if (event && event.target) {
this.$nextTick(() => event.target.focus());
}
},
getPage(num, options = {}) {
return {
number: num,
isCurrent: this.current === num,
click: (event) => this.changePage(num, event),
disabled: options.disabled || false,
class: options.class || '',
'aria-label': options['aria-label'] || this.getAriaPageLabel(num, this.current === num)
};
},
/**
* Get text for aria-label according to page number.
*/
getAriaPageLabel(pageNumber, isCurrent) {
if (this.ariaPageLabel && (!isCurrent || !this.ariaCurrentLabel)) {
return this.ariaPageLabel + ' ' + pageNumber + '.';
}
else if (this.ariaPageLabel && isCurrent && this.ariaCurrentLabel) {
return this.ariaCurrentLabel + ', ' + this.ariaPageLabel + ' ' + pageNumber + '.';
}
return null;
}
}
});
const _hoisted_1 = {
key: 0
};
const _hoisted_2 = {
key: 1
};
const _hoisted_3 = {
key: 2
};
const _hoisted_4 = {
key: 3
};
function render$1(_ctx, _cache, $props, $setup, $data, $options) {
const _component_o_icon = vue.resolveComponent("o-icon");
const _component_o_pagination_button = vue.resolveComponent("o-pagination-button");
return vue.openBlock(), vue.createBlock("nav", {
class: _ctx.rootClasses
}, [_ctx.hasPreviousSlot ? vue.renderSlot(_ctx.$slots, "previous", {
key: 0,
linkClass: _ctx.linkClasses,
linkCurrentClass: _ctx.linkCurrentClasses,
page: _ctx.getPage(_ctx.current - 1, {
class: _ctx.prevBtnClasses,
'aria-label': _ctx.ariaPreviousLabel
})
}, () => [vue.createVNode(_component_o_icon, {
icon: _ctx.iconPrev,
pack: _ctx.iconPack,
both: "",
"aria-hidden": "true"
}, null, 8
/* PROPS */
, ["icon", "pack"])]) : vue.createVNode(_component_o_pagination_button, {
key: 1,
class: _ctx.prevBtnClasses,
linkClass: _ctx.linkClasses,
linkCurrentClass: _ctx.linkCurrentClasses,
page: _ctx.getPage(_ctx.current - 1)
}, {
default: vue.withCtx(() => [vue.createVNode(_component_o_icon, {
icon: _ctx.iconPrev,
pack: _ctx.iconPack,
both: "",
"aria-hidden": "true"
}, null, 8
/* PROPS */
, ["icon", "pack"])]),
_: 1
}, 8
/* PROPS */
, ["class", "linkClass", "linkCurrentClass", "page"]), _ctx.hasNextSlot ? vue.renderSlot(_ctx.$slots, "next", {
key: 2,
linkClass: _ctx.linkClasses,
linkCurrentClass: _ctx.linkCurrentClasses,
page: _ctx.getPage(_ctx.current + 1, {
class: _ctx.nextBtnClasses,
'aria-label': _ctx.ariaNextLabel
})
}, () => [vue.createVNode(_component_o_icon, {
icon: _ctx.iconNext,
pack: _ctx.iconPack,
both: "",
"aria-hidden": "true"
}, null, 8
/* PROPS */
, ["icon", "pack"])]) : vue.createVNode(_component_o_pagination_button, {
key: 3,
class: _ctx.nextBtnClasses,
linkClass: _ctx.linkClasses,
linkCurrentClass: _ctx.linkCurrentClasses,
page: _ctx.getPage(_ctx.current + 1)
}, {
default: vue.withCtx(() => [vue.createVNode(_component_o_icon, {
icon: _ctx.iconNext,
pack: _ctx.iconPack,
both: "",
"aria-hidden": "true"
}, null, 8
/* PROPS */
, ["icon", "pack"])]),
_: 1
}, 8
/* PROPS */
, ["class", "linkClass", "linkCurrentClass", "page"]), _ctx.simple ? (vue.openBlock(), vue.createBlock("small", {
key: 4,
class: _ctx.infoClasses
}, [_ctx.perPage == 1 ? (vue.openBlock(), vue.createBlock(vue.Fragment, {
key: 0
}, [vue.createTextVNode(vue.toDisplayString(_ctx.firstItem) + " / " + vue.toDisplayString(_ctx.total), 1
/* TEXT */
)], 64
/* STABLE_FRAGMENT */
)) : (vue.openBlock(), vue.createBlock(vue.Fragment, {
key: 1
}, [vue.createTextVNode(vue.toDisplayString(_ctx.firstItem) + "-" + vue.toDisplayString(Math.min(_ctx.current * _ctx.perPage, _ctx.total)) + " / " + vue.toDisplayString(_ctx.total), 1
/* TEXT */
)], 64
/* STABLE_FRAGMENT */
))], 2
/* CLASS */
)) : (vue.openBlock(), vue.createBlock("ul", {
key: 5,
class: _ctx.listClasses
}, [vue.createCommentVNode("First"), _ctx.hasFirst ? (vue.openBlock(), vue.createBlock("li", _hoisted_1, [_ctx.hasDefaultSlot ? vue.renderSlot(_ctx.$slots, "default", {
key: 0,
page: _ctx.getPage(1),
linkClass: _ctx.linkClasses,
linkCurrentClass: _ctx.linkCurrentClasses
}) : vue.createVNode(_component_o_pagination_button, {
key: 1,
linkClass: _ctx.linkClasses,
linkCurrentClass: _ctx.linkCurrentClasses,
page: _ctx.getPage(1)
}, null, 8
/* PROPS */
, ["linkClass", "linkCurrentClass", "page"])])) : vue.createCommentVNode("v-if", true), _ctx.hasFirstEllipsis ? (vue.openBlock(), vue.createBlock("li", _hoisted_2, [vue.createVNode("span", {
class: _ctx.ellipsisClasses
}, "…", 2
/* CLASS */
)])) : vue.createCommentVNode("v-if", true), vue.createCommentVNode("Pages"), (vue.openBlock(true), vue.createBlock(vue.Fragment, null, vue.renderList(_ctx.pagesInRange, page => {
return vue.openBlock(), vue.createBlock("li", {
key: page.number
}, [_ctx.hasDefaultSlot ? vue.renderSlot(_ctx.$slots, "default", {
key: 0,
page: page,
linkClass: _ctx.linkClasses,
linkCurrentClass: _ctx.linkCurrentClasses
}) : vue.createVNode(_component_o_pagination_button, {
key: 1,
linkClass: _ctx.linkClasses,
linkCurrentClass: _ctx.linkCurrentClasses,
page: page
}, null, 8
/* PROPS */
, ["linkClass", "linkCurrentClass", "page"])]);
}), 128
/* KEYED_FRAGMENT */
)), vue.createCommentVNode("Last"), _ctx.hasLastEllipsis ? (vue.openBlock(), vue.createBlock("li", _hoisted_3, [vue.createVNode("span", {
class: _ctx.ellipsisClasses
}, "…", 2
/* CLASS */
)])) : vue.createCommentVNode("v-if", true), _ctx.hasLast ? (vue.openBlock(), vue.createBlock("li", _hoisted_4, [_ctx.hasDefaultSlot ? vue.renderSlot(_ctx.$slots, "default", {
key: 0,
page: _ctx.getPage(_ctx.pageCount),
linkClass: _ctx.linkClasses,
linkCurrentClass: _ctx.linkCurrentClasses
}) : vue.createVNode(_component_o_pagination_button, {
key: 1,
linkClass: _ctx.linkClasses,
linkCurrentClass: _ctx.linkCurrentClasses,
page: _ctx.getPage(_ctx.pageCount)
}, null, 8
/* PROPS */
, ["linkClass", "linkCurrentClass", "page"])])) : vue.createCommentVNode("v-if", true)], 2
/* CLASS */
))], 2
/* CLASS */
);
}
script$1.render = render$1;
script$1.__file = "src/components/pagination/Pagination.vue";
exports.script = script$1;
exports.script$1 = script;