UNPKG

@ishitatsuyuki/oruga-next

Version:

UI components for Vue.js and CSS framework agnostic

536 lines (525 loc) 18 kB
'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;