UNPKG

buefy

Version:

Lightweight UI components for Vue.js (v3) based on Bulma

1,596 lines (1,587 loc) 87.4 kB
'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var vue = require('vue'); var helpers = require('./helpers.js'); var Pagination = require('./Pagination-D1MVdiLp.js'); var CompatFallthroughMixin = require('./CompatFallthroughMixin-hhK0Gkhr.js'); var Checkbox = require('./Checkbox-GPzAMQqM.js'); var Icon = require('./Icon-lsDKE2wQ.js'); var Input = require('./Input-BcloGeZ3.js'); var Loading = require('./Loading-GqqqjipO.js'); var SlotComponent = require('./SlotComponent-BruGdRW3.js'); var Select = require('./Select-DayPKwCY.js'); var _pluginVue_exportHelper = require('./_plugin-vue_export-helper-Die8u8yB.js'); var plugins = require('./plugins-DbyYGVpp.js'); require('./config-DR826Ki2.js'); require('./CheckRadioMixin-CDu0SN3g.js'); require('./FormElementMixin-DavX4iOv.js'); require('./ssr-DVRFTu_P.js'); var _sfc_main$3 = vue.defineComponent({ name: "BTableMobileSort", components: { BSelect: Select.BSelect, BIcon: Icon.BIcon }, props: { currentSortColumn: Object, sortMultipleData: Array, isAsc: Boolean, columns: Array, placeholder: String, iconPack: String, sortIcon: { type: String, default: "arrow-up" }, sortIconSize: { type: String, default: "is-small" }, sortMultiple: { type: Boolean, default: false } }, emits: { /* eslint-disable @typescript-eslint/no-unused-vars */ removePriority: (_column) => true, sort: (_column, _event) => true /* eslint-enable @typescript-eslint/no-unused-vars */ }, data() { return { sortMultipleSelect: null, sortMultipleSelectIndex: -1, mobileSort: this.currentSortColumn, mobileSortIndex: this.columns ? this.columns.indexOf(this.currentSortColumn) : -1, defaultEvent: { shiftKey: true, altKey: true, ctrlKey: true }, ignoreSort: false }; }, computed: { showPlaceholder() { return !this.columns || !this.columns.some((column) => column === this.mobileSort); }, sortableColumns() { return this.columns && this.columns.filter((column) => column.sortable); } }, watch: { sortMultipleSelect(column) { if (this.ignoreSort) { this.ignoreSort = false; } else { this.$emit("sort", column, this.defaultEvent); } }, sortMultipleSelectIndex(index) { if (index !== -1) { this.sortMultipleSelect = this.columns[index]; } else { this.sortMultipleSelect = null; } }, mobileSort(column) { if (this.currentSortColumn === column) return; this.$emit("sort", column, this.defaultEvent); }, mobileSortIndex(index) { if (index !== -1) { this.mobileSort = this.columns[index]; } }, currentSortColumn(column) { this.mobileSort = column; this.mobileSortIndex = this.columns ? this.columns.indexOf(column) : -1; }, columns(newColumns) { if (this.sortMultiple) { this.sortMultipleSelectIndex = newColumns.indexOf( this.sortMultipleSelect ); } else { this.mobileSortIndex = newColumns.indexOf(this.mobileSort); } } }, methods: { removePriority() { this.$emit("removePriority", this.sortMultipleSelect); this.ignoreSort = true; const remainingFields = this.sortMultipleData.filter((data) => data.field !== this.sortMultipleSelect.field).map((data) => data.field); this.sortMultipleSelectIndex = this.columns.findIndex((column) => remainingFields.includes(column.field)); }, getSortingObjectOfColumn(column) { return this.sortMultipleData.filter((i) => i.field === column.field)[0]; }, columnIsDesc(column) { const sortingObject = column && this.getSortingObjectOfColumn(column); if (sortingObject) { return !!(sortingObject.order && sortingObject.order === "desc"); } return true; }, getLabel(column) { const sortingObject = this.getSortingObjectOfColumn(column); if (sortingObject) { return column.label + "(" + (this.sortMultipleData.indexOf(sortingObject) + 1) + ")"; } return column.label; }, sort() { this.$emit("sort", this.sortMultiple ? this.sortMultipleSelect : this.mobileSort, this.defaultEvent); } } }); const _hoisted_1$2 = { class: "field table-mobile-sort" }; const _hoisted_2$2 = { class: "field has-addons" }; const _hoisted_3$2 = ["value"]; const _hoisted_4$2 = ["value"]; const _hoisted_5$1 = { class: "control" }; function _sfc_render$2(_ctx, _cache, $props, $setup, $data, $options) { const _component_b_select = vue.resolveComponent("b-select"); const _component_b_icon = vue.resolveComponent("b-icon"); return vue.openBlock(), vue.createElementBlock("div", _hoisted_1$2, [ vue.createElementVNode("div", _hoisted_2$2, [ _ctx.sortMultiple ? (vue.openBlock(), vue.createBlock(_component_b_select, { key: 0, modelValue: _ctx.sortMultipleSelectIndex, "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => _ctx.sortMultipleSelectIndex = $event), expanded: "" }, { default: vue.withCtx(() => [ (vue.openBlock(true), vue.createElementBlock( vue.Fragment, null, vue.renderList(_ctx.sortableColumns, (column, index) => { return vue.openBlock(), vue.createElementBlock("option", { key: index, value: index }, [ vue.createTextVNode( vue.toDisplayString(_ctx.getLabel(column)) + " ", 1 /* TEXT */ ), _ctx.getSortingObjectOfColumn(column) ? (vue.openBlock(), vue.createElementBlock( vue.Fragment, { key: 0 }, [ _ctx.columnIsDesc(column) ? (vue.openBlock(), vue.createElementBlock( vue.Fragment, { key: 0 }, [ vue.createTextVNode(" ↓ ") ], 64 /* STABLE_FRAGMENT */ )) : (vue.openBlock(), vue.createElementBlock( vue.Fragment, { key: 1 }, [ vue.createTextVNode(" ↑ ") ], 64 /* STABLE_FRAGMENT */ )) ], 64 /* STABLE_FRAGMENT */ )) : vue.createCommentVNode("v-if", true) ], 8, _hoisted_3$2); }), 128 /* KEYED_FRAGMENT */ )) ]), _: 1 /* STABLE */ }, 8, ["modelValue"])) : (vue.openBlock(), vue.createBlock(_component_b_select, { key: 1, modelValue: _ctx.mobileSortIndex, "onUpdate:modelValue": _cache[1] || (_cache[1] = ($event) => _ctx.mobileSortIndex = $event), expanded: "" }, { default: vue.withCtx(() => [ _ctx.placeholder ? vue.withDirectives((vue.openBlock(), vue.createElementBlock( "option", { key: 0, value: {}, selected: "", disabled: "", hidden: "" }, vue.toDisplayString(_ctx.placeholder), 513 /* TEXT, NEED_PATCH */ )), [ [vue.vShow, _ctx.showPlaceholder] ]) : vue.createCommentVNode("v-if", true), (vue.openBlock(true), vue.createElementBlock( vue.Fragment, null, vue.renderList(_ctx.sortableColumns, (column, index) => { return vue.openBlock(), vue.createElementBlock("option", { key: index, value: index }, vue.toDisplayString(column.label), 9, _hoisted_4$2); }), 128 /* KEYED_FRAGMENT */ )) ]), _: 1 /* STABLE */ }, 8, ["modelValue"])), vue.createElementVNode("div", _hoisted_5$1, [ _ctx.sortMultiple && _ctx.sortMultipleData.length > 0 ? (vue.openBlock(), vue.createElementBlock( vue.Fragment, { key: 0 }, [ vue.createElementVNode("button", { class: "button is-primary", onClick: _cache[2] || (_cache[2] = (...args) => _ctx.sort && _ctx.sort(...args)) }, [ vue.createVNode(_component_b_icon, { class: vue.normalizeClass({ "is-desc": _ctx.columnIsDesc(_ctx.sortMultipleSelect) }), icon: _ctx.sortIcon, pack: _ctx.iconPack, size: _ctx.sortIconSize, both: "" }, null, 8, ["class", "icon", "pack", "size"]) ]), vue.createElementVNode("button", { class: "button is-primary", onClick: _cache[3] || (_cache[3] = (...args) => _ctx.removePriority && _ctx.removePriority(...args)) }, [ vue.createVNode(_component_b_icon, { icon: "delete", size: _ctx.sortIconSize, both: "" }, null, 8, ["size"]) ]) ], 64 /* STABLE_FRAGMENT */ )) : !_ctx.sortMultiple ? (vue.openBlock(), vue.createElementBlock("button", { key: 1, class: "button is-primary", onClick: _cache[4] || (_cache[4] = (...args) => _ctx.sort && _ctx.sort(...args)) }, [ vue.withDirectives(vue.createVNode(_component_b_icon, { class: vue.normalizeClass({ "is-desc": !_ctx.isAsc }), icon: _ctx.sortIcon, pack: _ctx.iconPack, size: _ctx.sortIconSize, both: "" }, null, 8, ["class", "icon", "pack", "size"]), [ [vue.vShow, _ctx.currentSortColumn === _ctx.mobileSort] ]) ])) : vue.createCommentVNode("v-if", true) ]) ]) ]); } var BTableMobileSort = /* @__PURE__ */ _pluginVue_exportHelper._export_sfc(_sfc_main$3, [["render", _sfc_render$2]]); var _sfc_main$2 = vue.defineComponent({ name: "BTablePagination", components: { BPagination: Pagination.BPagination }, props: { paginated: Boolean, total: [Number, String], perPage: [Number, String], currentPage: [Number, String], paginationSimple: Boolean, paginationSize: String, rounded: Boolean, iconPack: String, ariaNextLabel: String, ariaPreviousLabel: String, ariaPageLabel: String, ariaCurrentLabel: String, pageInput: Boolean, paginationOrder: String, pageInputPosition: String, debouncePageInput: [Number, String] }, emits: { /* eslint-disable @typescript-eslint/no-unused-vars */ "page-change": (_page) => true, "update:currentPage": (_page) => true /* eslint-enable @typescript-eslint/no-unused-vars */ }, data() { return { newCurrentPage: this.currentPage }; }, watch: { currentPage(newVal) { this.newCurrentPage = newVal; } }, methods: { /* * Paginator change listener. */ pageChanged(page) { this.newCurrentPage = page > 0 ? page : 1; this.$emit("update:currentPage", this.newCurrentPage); this.$emit("page-change", this.newCurrentPage); } } }); const _hoisted_1$1 = { class: "top level" }; const _hoisted_2$1 = { class: "level-left" }; const _hoisted_3$1 = { class: "level-right" }; const _hoisted_4$1 = { key: 0, class: "level-item" }; function _sfc_render$1(_ctx, _cache, $props, $setup, $data, $options) { const _component_b_pagination = vue.resolveComponent("b-pagination"); return vue.openBlock(), vue.createElementBlock("div", _hoisted_1$1, [ vue.createElementVNode("div", _hoisted_2$1, [ vue.renderSlot(_ctx.$slots, "default") ]), vue.createElementVNode("div", _hoisted_3$1, [ _ctx.paginated ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_4$1, [ vue.createVNode(_component_b_pagination, { "icon-pack": _ctx.iconPack, total: _ctx.total, "per-page": _ctx.perPage, simple: _ctx.paginationSimple, size: _ctx.paginationSize, "model-value": _ctx.newCurrentPage, rounded: _ctx.rounded, onChange: _ctx.pageChanged, "aria-next-label": _ctx.ariaNextLabel, "aria-previous-label": _ctx.ariaPreviousLabel, "aria-page-label": _ctx.ariaPageLabel, "aria-current-label": _ctx.ariaCurrentLabel, "page-input": _ctx.pageInput, order: _ctx.paginationOrder, "page-input-position": _ctx.pageInputPosition, "debounce-page-input": _ctx.debouncePageInput }, null, 8, ["icon-pack", "total", "per-page", "simple", "size", "model-value", "rounded", "onChange", "aria-next-label", "aria-previous-label", "aria-page-label", "aria-current-label", "page-input", "order", "page-input-position", "debounce-page-input"]) ])) : vue.createCommentVNode("v-if", true) ]) ]); } var BTablePagination = /* @__PURE__ */ _pluginVue_exportHelper._export_sfc(_sfc_main$2, [["render", _sfc_render$1]]); var __defProp = Object.defineProperty; var __defProps = Object.defineProperties; var __getOwnPropDescs = Object.getOwnPropertyDescriptors; var __getOwnPropSymbols = Object.getOwnPropertySymbols; var __hasOwnProp = Object.prototype.hasOwnProperty; var __propIsEnum = Object.prototype.propertyIsEnumerable; var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; var __spreadValues = (a, b) => { for (var prop in b || (b = {})) if (__hasOwnProp.call(b, prop)) __defNormalProp(a, prop, b[prop]); if (__getOwnPropSymbols) for (var prop of __getOwnPropSymbols(b)) { if (__propIsEnum.call(b, prop)) __defNormalProp(a, prop, b[prop]); } return a; }; var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b)); function mockTableColumn(table, column) { const defaultProps = { label: void 0, customKey: void 0, field: void 0, meta: void 0, width: void 0, numeric: void 0, centered: void 0, searchable: void 0, sortable: void 0, visible: true, subheading: void 0, customSort: void 0, customSearch: void 0, sticky: void 0, headerSelectable: void 0, headerClass: void 0, /* eslint-disable @typescript-eslint/no-explicit-any */ thAttrs: () => ({}), tdAttrs: () => ({}) /* eslint-enable @typescript-eslint/no-explicit-any */ }; return __spreadProps(__spreadValues(__spreadValues({}, defaultProps), column), { // data newKey: column.customKey || column.label, _isTableColumn: true, // public computed get thClasses() { const attrs = this.thAttrs(this); const classes = [this.headerClass, { "is-sortable": this.sortable, "is-sticky": this.sticky, "is-unselectable": this.isHeaderUnSelectable }]; if (attrs && attrs.class) { classes.push(attrs.class); } return classes; }, get thStyle() { const attrs = this.thAttrs(this); const style = [this.style]; if (attrs && attrs.style) { style.push(attrs.style); } return style; }, get thWrapStyle() { return this.style; }, get style() { var _a; return { width: (_a = helpers.toCssWidth(this.width)) != null ? _a : void 0 // null → undefined to satisfy StyleValue }; }, getRootClasses(row) { const attrs = this.tdAttrs(row, this); const classes = [this.rootClasses]; if (attrs && attrs.class) { classes.push(attrs.class); } return classes; }, getRootStyle(row) { const attrs = this.tdAttrs(row, this); const style = []; if (attrs && attrs.style) { style.push(attrs.style); } return style; }, $slots: { default: (props) => { const vnode = vue.h("span", { innerHTML: helpers.getValueByPath(props.row, column.field) }); return [vnode]; } }, // private properties get rootClasses() { return [this.cellClass, { "has-text-right": this.numeric && !this.centered, "has-text-centered": this.centered, "is-sticky": this.sticky }]; }, get isHeaderUnSelectable() { return !this.headerSelectable && !!this.sortable; } }); } const BLANK_COLUMN = { thAttrs: () => ({}), tdAttrs: () => ({}), getRootClasses: () => [], getRootStyle: () => void 0, $slots: {} }; var _sfc_main$1 = vue.defineComponent({ name: "BTable", components: { BCheckbox: Checkbox.BCheckbox, BIcon: Icon.BIcon, BInput: Input.BInput, BLoading: Loading.BLoading, BSlotComponent: SlotComponent.BSlotComponent, BTableMobileSort, BTablePagination }, mixins: [CompatFallthroughMixin.CompatFallthroughMixin], provide() { return { $table: this }; }, props: { data: { type: Array, default: () => [] }, columns: { type: Array, default: () => [] }, bordered: Boolean, striped: Boolean, narrowed: Boolean, hoverable: Boolean, loading: Boolean, detailed: Boolean, checkable: Boolean, headerCheckable: { type: Boolean, default: true }, checkboxType: { type: String, default: "is-primary" }, checkboxPosition: { type: String, default: "left", validator: (value) => { return [ "left", "right" ].indexOf(value) >= 0; } }, stickyCheckbox: { type: Boolean, default: false }, selected: Object, isRowSelectable: { type: Function, default: () => true }, focusable: Boolean, customIsChecked: Function, isRowCheckable: { type: Function, default: () => true }, checkedRows: { type: Array, default: () => [] }, mobileCards: { type: Boolean, default: true }, defaultSort: [String, Array], defaultSortDirection: { type: String, default: "asc" }, sortIcon: { type: String, default: "arrow-up" }, sortIconSize: { type: String, default: "is-small" }, sortMultiple: { type: Boolean, default: false }, sortMultipleData: { type: Array, default: () => [] }, sortMultipleKey: { type: String, default: null }, paginated: Boolean, currentPage: { type: Number, default: 1 }, perPage: { type: [Number, String], default: 20 }, showDetailIcon: { type: Boolean, default: true }, detailIcon: { type: String, default: "chevron-right" }, paginationPosition: { type: String, default: "bottom", validator: (value) => { return [ "bottom", "top", "both" ].indexOf(value) >= 0; } }, paginationRounded: Boolean, backendSorting: Boolean, backendFiltering: Boolean, rowClass: { type: Function, default: () => "" }, openedDetailed: { type: Array, default: () => [] }, hasDetailedVisible: { type: Function, default: () => true }, detailKey: { type: String, default: "" }, detailTransition: { type: String, default: "" }, customDetailRow: { type: Boolean, default: false }, backendPagination: Boolean, total: { type: [Number, String], default: 0 }, iconPack: String, mobileSortPlaceholder: String, customRowKey: String, draggable: { type: Boolean, default: false }, draggableColumn: { type: Boolean, default: false }, scrollable: Boolean, ariaNextLabel: String, ariaPreviousLabel: String, ariaPageLabel: String, ariaCurrentLabel: String, stickyHeader: Boolean, height: [Number, String], filtersEvent: { type: String, default: "" }, cardLayout: Boolean, showHeader: { type: Boolean, default: true }, debounceSearch: Number, caption: String, showCaption: { type: Boolean, default: true }, pageInput: { type: Boolean, default: false }, paginationOrder: String, pageInputPosition: String, debouncePageInput: [Number, String] }, emits: { /* eslint-disable @typescript-eslint/no-unused-vars */ cellclick: (_row, _column, _rowIndex, _colIndex) => true, check: (_checkedRows, _row) => true, "check-all": (_rows) => true, click: (_row) => true, columndragend: (_event) => true, columndragleave: (_event) => true, columndragover: (_event) => true, columndragstart: (_event) => true, columndrop: (_event) => true, contextmenu: (_row, _event) => true, dblclick: (_row) => true, "details-close": (_row) => true, "details-open": (_row) => true, dragend: (_event) => true, dragleave: (_event) => true, dragover: (_event) => true, dragstart: (_event) => true, drop: (_event) => true, "filters-change": (_value) => true, "page-change": (_page) => true, select: (_new, _old) => true, sort: (_field, _order, _event) => true, "sorting-priority-removed": (_field) => true, "update:checkedRows": (_rows) => true, "update:currentPage": (_page) => true, "update:openedDetailed": (_rows) => true, "update:selected": (_row) => true /* eslint-enable @typescript-eslint/no-unused-vars */ }, data() { return { sortMultipleDataLocal: [], getValueByPath: helpers.getValueByPath, visibleDetailRows: this.openedDetailed, newData: this.data, newDataTotal: this.backendPagination ? this.total : this.data.length, newCheckedRows: [...this.checkedRows], lastCheckedRowIndex: null, newCurrentPage: this.currentPage, currentSortColumn: {}, isAsc: true, filters: {}, defaultSlots: [], firstTimeSort: true, // Used by first time initSort isDraggingRow: false, isDraggingColumn: false, debouncedHandleFiltersChange: void 0, // for touch-enabled devices _selectedRow: null, mayBeTouchDragging: false, touchDragoverTarget: null, _draggedCellEl: void 0, draggedCellContent: "" }; }, computed: { sortMultipleDataComputed() { return this.backendSorting ? this.sortMultipleData : this.sortMultipleDataLocal; }, tableClasses() { return { "is-bordered": this.bordered, "is-striped": this.striped, "is-narrow": this.narrowed, "is-hoverable": (this.hoverable || this.focusable) && this.visibleData.length }; }, tableWrapperClasses() { return { "has-mobile-cards": this.mobileCards, "has-sticky-header": this.stickyHeader, "is-card-list": this.cardLayout, "table-container": this.isScrollable }; }, tableStyle() { return { height: helpers.toCssWidth(this.height) }; }, touchDraggedCellClasses() { return { "has-mobile-cards": this.mobileCards }; }, /* * Splitted data based on the pagination. */ visibleData() { if (!this.paginated) return this.newData; const currentPage = this.newCurrentPage; const perPage = +this.perPage; if (this.newData.length <= perPage) { return this.newData; } else { const start = (currentPage - 1) * perPage; const end = parseInt(start + "", 10) + parseInt(perPage + "", 10); return this.newData.slice(start, end); } }, visibleColumns() { if (!this.newColumns) return this.newColumns; return this.newColumns.filter((column) => { return column.visible || column.visible === void 0; }); }, /* * Check if all rows in the page are checked. */ isAllChecked() { const validVisibleData = this.visibleData.filter( (row) => this.isRowCheckable(row) ); if (validVisibleData.length === 0) return false; const isAllChecked = validVisibleData.some((currentVisibleRow) => { return helpers.indexOf(this.newCheckedRows, currentVisibleRow, this.customIsChecked) < 0; }); return !isAllChecked; }, /* * Check if all rows in the page are checkable. */ isAllUncheckable() { const validVisibleData = this.visibleData.filter( (row) => this.isRowCheckable(row) ); return validVisibleData.length === 0; }, /* * Check if has any sortable column. */ hasSortablenewColumns() { return this.newColumns.some((column) => { return column.sortable; }); }, /* * Check if has any searchable column. */ hasSearchablenewColumns() { return this.newColumns.some((column) => { return column.searchable; }); }, /* * Check if has any column using subheading. */ hasCustomSubheadings() { if (this.$slots && this.$slots.subheading) return true; return this.newColumns.some((column) => { return column.subheading || column.$slots.subheading; }); }, /* * Return total column count based if it's checkable or expanded */ columnCount() { let count = this.visibleColumns.length; count += this.checkable ? 1 : 0; count += this.detailed && this.showDetailIcon ? 1 : 0; return count; }, /* * return if detailed row tabled * will be with chevron column & icon or not */ showDetailRowIcon() { return this.detailed && this.showDetailIcon; }, /* * return if scrollable table */ isScrollable() { if (this.scrollable) return true; if (!this.newColumns) return false; return this.newColumns.some((column) => { return column.sticky; }); }, newColumns() { if (this.columns && this.columns.length) { return this.columns.map((column) => { return mockTableColumn(this, column); }); } return this.defaultSlots; }, canDragRow() { return this.draggable && !this.isDraggingColumn; }, canDragColumn() { return this.draggableColumn && !this.isDraggingRow; } }, watch: { /* * When data prop change: * 1. Update internal value. * 2. Filter data if it's not backend-filtered. * 3. Sort again if it's not backend-sorted. * 4. Set new total if it's not backend-paginated. */ data(value) { this.newData = value; if (!this.backendFiltering) { this.newData = value.filter( (row) => this.isRowFiltered(row) ); } if (!this.backendSorting) { this.sort(this.currentSortColumn, true); } if (!this.backendPagination) { this.newDataTotal = this.newData.length; } }, /* * When Pagination total change, update internal total * only if it's backend-paginated. */ total(newTotal) { if (!this.backendPagination) return; this.newDataTotal = newTotal; }, currentPage(newVal) { this.newCurrentPage = newVal; }, newCurrentPage(newVal) { this.$emit("update:currentPage", newVal); }, /* * When checkedRows prop change, update internal value without * mutating original data. */ checkedRows(rows) { this.newCheckedRows = [...rows]; }, debounceSearch: { handler(value) { this.debouncedHandleFiltersChange = Pagination.debounce(this.handleFiltersChange, value); }, immediate: true }, filters: { handler(value) { if (this.debounceSearch) { this.debouncedHandleFiltersChange(value); } else { this.handleFiltersChange(value); } }, deep: true }, /* * When the user wants to control the detailed rows via props. * Or wants to open the details of certain row with the router for example. */ openedDetailed(expandedRows) { this.visibleDetailRows = expandedRows; } }, methods: { onFiltersEvent(event) { this.$emit(`filters-event-${this.filtersEvent}`, { event, filters: this.filters }); }, handleFiltersChange(value) { if (this.backendFiltering) { this.$emit("filters-change", value); } else { this.newData = this.data.filter( (row) => this.isRowFiltered(row) ); if (!this.backendPagination) { this.newDataTotal = this.newData.length; } if (!this.backendSorting) { if (this.sortMultiple && this.sortMultipleDataLocal && this.sortMultipleDataLocal.length > 0) { this.doSortMultiColumn(); } else if (Object.keys(this.currentSortColumn).length > 0) { this.doSortSingleColumn(this.currentSortColumn); } } } }, findIndexOfSortData(column) { const sortObj = this.sortMultipleDataComputed.filter((i) => i.field === column.field)[0]; return this.sortMultipleDataComputed.indexOf(sortObj) + 1; }, removeSortingPriority(column) { if (this.backendSorting) { this.$emit("sorting-priority-removed", column.field); } else { this.sortMultipleDataLocal = this.sortMultipleDataLocal.filter( (priority) => priority.field !== column.field ); if (this.sortMultipleDataLocal.length === 0) { this.resetMultiSorting(); } else { this.newData = helpers.multiColumnSort(this.newData, this.sortMultipleDataLocal); } } }, resetMultiSorting() { this.sortMultipleDataLocal = []; this.currentSortColumn = BLANK_COLUMN; this.newData = this.data; }, /* * Sort an array by key without mutating original data. * Call the user sort function if it was passed. */ sortBy(array, key, fn, isAsc) { let sorted = []; if (fn && typeof fn === "function") { sorted = [...array].sort((a, b) => fn(a, b, isAsc)); } else { sorted = [...array].sort((a, b) => { let newA = helpers.getValueByPath(a, key); let newB = helpers.getValueByPath(b, key); if (typeof newA === "boolean" && typeof newB === "boolean") { return isAsc ? +newA - +newB : +newB - +newA; } if (!helpers.isNil(newB) && helpers.isNil(newA)) return isAsc ? 1 : -1; if (!helpers.isNil(newA) && helpers.isNil(newB)) return isAsc ? -1 : 1; if (newA === newB) return 0; newA = typeof newA === "string" ? newA.toUpperCase() : newA; newB = typeof newB === "string" ? newB.toUpperCase() : newB; return isAsc ? newA > newB ? 1 : -1 : newA > newB ? -1 : 1; }); } return sorted; }, sortMultiColumn(column) { this.currentSortColumn = BLANK_COLUMN; if (!this.backendSorting) { const existingPriority = this.sortMultipleDataLocal.filter((i) => i.field === column.field)[0]; if (existingPriority) { existingPriority.order = existingPriority.order === "desc" ? "asc" : "desc"; } else { this.sortMultipleDataLocal.push({ field: column.field, order: this.isAsc ? "asc" : "desc", customSort: column.customSort }); } this.doSortMultiColumn(); } }, doSortMultiColumn() { this.newData = helpers.multiColumnSort(this.newData, this.sortMultipleDataLocal); }, /* * Sort the column. * Toggle current direction on column if it's sortable * and not just updating the prop. */ sort(column, updatingData = false, event = null) { if (!column || !column.sortable) return; if ( // if backend sorting is enabled, just emit the sort press like usual // if the correct key combination isnt pressed, sort like usual !this.backendSorting && this.sortMultiple && (this.sortMultipleKey && event[this.sortMultipleKey] || !this.sortMultipleKey) ) { if (updatingData) { this.doSortMultiColumn(); } else { this.sortMultiColumn(column); } } else { if (this.sortMultiple) { this.sortMultipleDataLocal = []; } if (!updatingData) { this.isAsc = vue.toRaw(column) === vue.toRaw(this.currentSortColumn) ? !this.isAsc : this.defaultSortDirection.toLowerCase() !== "desc"; } if (!this.firstTimeSort) { this.$emit("sort", column.field, this.isAsc ? "asc" : "desc", event); } if (!this.backendSorting) { this.doSortSingleColumn(column); } this.currentSortColumn = column; } }, doSortSingleColumn(column) { this.newData = this.sortBy( this.newData, column.field, column.customSort, this.isAsc ); }, isRowSelected(row, selected) { if (!selected) { return false; } if (this.customRowKey) { return row[this.customRowKey] === selected[this.customRowKey]; } return row === selected; }, /* * Check if the row is checked (is added to the array). */ isRowChecked(row) { return helpers.indexOf(this.newCheckedRows, row, this.customIsChecked) >= 0; }, /* * Remove a checked row from the array. */ removeCheckedRow(row) { const index = helpers.indexOf(this.newCheckedRows, row, this.customIsChecked); if (index >= 0) { this.newCheckedRows.splice(index, 1); } }, /* * Header checkbox click listener. * Add or remove all rows in current page. */ checkAll() { const isAllChecked = this.isAllChecked; this.visibleData.forEach((currentRow) => { if (this.isRowCheckable(currentRow)) { this.removeCheckedRow(currentRow); } if (!isAllChecked) { if (this.isRowCheckable(currentRow)) { this.newCheckedRows.push(currentRow); } } }); this.$emit("check", this.newCheckedRows); this.$emit("check-all", this.newCheckedRows); this.$emit("update:checkedRows", this.newCheckedRows); }, /* * Row checkbox click listener. */ checkRow(row, index, event) { if (!this.isRowCheckable(row)) return; const lastIndex = this.lastCheckedRowIndex; this.lastCheckedRowIndex = index; if (event.shiftKey && lastIndex !== null && index !== lastIndex) { this.shiftCheckRow(row, index, lastIndex); } else if (!this.isRowChecked(row)) { this.newCheckedRows.push(row); } else { this.removeCheckedRow(row); } this.$emit("check", this.newCheckedRows, row); this.$emit("update:checkedRows", this.newCheckedRows); }, /* * Check row when shift is pressed. */ shiftCheckRow(row, index, lastCheckedRowIndex) { const subset = this.visibleData.slice( Math.min(index, lastCheckedRowIndex), Math.max(index, lastCheckedRowIndex) + 1 ); const shouldCheck = !this.isRowChecked(row); subset.forEach((item) => { this.removeCheckedRow(item); if (shouldCheck && this.isRowCheckable(item)) { this.newCheckedRows.push(item); } }); }, /* * Row click listener. * Emit all necessary events. */ selectRow(row) { this.$emit("click", row); this._selectedRow = row; if (this.selected === row) return; if (!this.isRowSelectable(row)) return; this.$emit("select", row, this.selected); this.$emit("update:selected", row); }, /* * Toggle to show/hide details slot */ toggleDetails(obj) { const found = this.isVisibleDetailRow(obj); if (found) { this.closeDetailRow(obj); this.$emit("details-close", obj); } else { this.openDetailRow(obj); this.$emit("details-open", obj); } this.$emit("update:openedDetailed", this.visibleDetailRows); }, openDetailRow(obj) { const index = this.handleDetailKey(obj); this.visibleDetailRows.push(index); }, closeDetailRow(obj) { const index = this.handleDetailKey(obj); const i = this.visibleDetailRows.indexOf(index); if (i >= 0) { this.visibleDetailRows.splice(i, 1); } }, isVisibleDetailRow(obj) { const index = this.handleDetailKey(obj); return this.visibleDetailRows.indexOf(index) >= 0; }, isActiveDetailRow(row) { return this.detailed && !this.customDetailRow && this.isVisibleDetailRow(row); }, isActiveCustomDetailRow(row) { return this.detailed && this.customDetailRow && this.isVisibleDetailRow(row); }, isRowFiltered(row) { for (const key in this.filters) { if (!this.filters[key]) continue; const input = this.filters[key]; const column = this.newColumns.filter((c) => c.field === key)[0]; if (column && column.customSearch && typeof column.customSearch === "function") { if (!column.customSearch(row, input)) return false; } else { const value = this.getValueByPath(row, key); if (value == null) return false; if (Number.isInteger(value)) { if (value !== Number(input)) return false; } else { const re = new RegExp(helpers.escapeRegExpChars(input + ""), "i"); if (Array.isArray(value)) { const valid = value.some( (val) => re.test(helpers.removeDiacriticsFromString(val)) || re.test(val) ); if (!valid) return false; } else { if (!re.test(helpers.removeDiacriticsFromString(value)) && !re.test(value)) { return false; } } } } } return true; }, /* * When the detailKey is defined we use the object[detailKey] as index. * If not, use the object reference by default. */ handleDetailKey(index) { const key = this.detailKey; return !key.length || !index ? index : index[key]; }, checkPredefinedDetailedRows() { const defaultExpandedRowsDefined = this.openedDetailed.length > 0; if (defaultExpandedRowsDefined && !this.detailKey.length) { throw new Error('If you set a predefined opened-detailed, you must provide a unique key using the prop "detail-key"'); } }, /* * Call initSort only first time (For example async data). */ checkSort() { if (this.newColumns.length && this.firstTimeSort) { this.initSort(); this.firstTimeSort = false; } else if (this.newColumns.length) { if (vue.toRaw(this.currentSortColumn) !== BLANK_COLUMN) { for (let i = 0; i < this.newColumns.length; i++) { if (this.newColumns[i].field === this.currentSortColumn.field) { this.currentSortColumn = this.newColumns[i]; break; } } } } }, /* * Check if footer slot has custom content. * * Assumes that `$slots.footer` is specified. */ hasCustomFooterSlot() { var _a; const footer = this.$slots.footer(); if (footer.length > 1) return true; if (helpers.isFragment(footer[0])) return true; const tag = (_a = footer[0].el) == null ? void 0 : _a.tag; if (tag !== "th" && tag !== "td") return false; return true; }, /* * Check if bottom-left slot exists. */ hasBottomLeftSlot() { return typeof this.$slots["bottom-left"] !== "undefined"; }, /* * Table arrow keys listener, change selection. */ pressedArrow(pos) { if (!this.visibleData.length) return; let index = this.visibleData.indexOf(this.selected) + pos; index = index < 0 ? 0 : index > this.visibleData.length - 1 ? this.visibleData.length - 1 : index; const row = this.visibleData[index]; if (!this.isRowSelectable(row)) { let newIndex = null; if (pos > 0) { for (let i = index; i < this.visibleData.length && newIndex === null; i++) { if (this.isRowSelectable(this.visibleData[i])) newIndex = i; } } else { for (let i = index; i >= 0 && newIndex === null; i--) { if (this.isRowSelectable(this.visibleData[i])) newIndex = i; } } if (newIndex >= 0) { this.selectRow(this.visibleData[newIndex]); } } else { this.selectRow(row); } }, /* * Focus table element if has selected prop. */ focus() { if (!this.focusable) return; this.$el.querySelector("table").focus(); }, /* * Initial sorted column based on the default-sort prop. */ initSort() { if (this.sortMultiple && this.sortMultipleData) { this.sortMultipleData.forEach((column) => { this.sortMultiColumn(column); }); } else { if (!this.defaultSort) return; let sortField = ""; let sortDirection = this.defaultSortDirection; if (Array.isArray(this.defaultSort)) { sortField = this.defaultSort[0]; if (this.defaultSort[1]) { sortDirection = this.defaultSort[1]; } } else { sortField = this.defaultSort; } const sortColumn = this.newColumns.filter( (column) => column.field === sortField )[0]; if (sortColumn) { this.isAsc = sortDirection.toLowerCase() !== "desc"; this.sort(sortColumn, true); } } }, /* * Emits drag start event (row) */ handleDragStart(event, row, index) { if (!this.canDragRow) return; this.isDraggingRow = true; this.$emit("dragstart", { event, row, index }); }, /* * Emits drag leave event (row) */ handleDragEnd(event, row, index) { if (!this.canDragRow) return; this.isDraggingRow = false; this.$emit("dragend", { event, row, index }); }, /* * Emits drop event (row) */ handleDrop(event, row, index) { if (!this.canDragRow) return; this.$emit("drop", { event, row, index }); }, /* * Emits drag over event (row) */ handleDragOver(event, row, index) { if (!this.canDragRow) return; this.$emit("dragover", { event, row, index }); }, /* * Emits drag leave event (row) */ handleDragLeave(event, row, index) { if (!this.canDragRow) return; this.$emit("dragleave", { event, row, index }); }, // this method is for "mouseenter", and "mouseleave" events. // the original idea of this method was introduced by the PR // https://github.com/buefy/buefy/pull/2150 // to address some performance issues related to these events. // I am not sure whether the justification made at the PR is still // relevant to Vue 3. // btw, this function was made by the PR https://github.com/buefy/buefy/pull/3236 emitEventForRow(eventName, event, row) { const listener = this.$attrs[vue.toHandlerKey(eventName)] || this.$attrs[vue.toHandlerKey(vue.camelize(eventName))]; return listener != null ? this.$emit(eventName, row, event) : null; }, /* * Emits drag start event (column) */ handleColumnDragStart(event, column, index) { if (!this.canDragColumn) return; this.isDraggingColumn = true; this.$emit("columndragstart", { event, column, index }); }, /* * Emits drag leave event (column) */ handleColumnDragEnd(event, column, index) { if (!this.canDragColumn) return; this.isDraggingColumn = false; this.$emit("columndragend", { event, column, index }); }, /* * Emits drop event (column) */ handleColumnDrop(event, column, index) { if (!this.canDragColumn) return; this.$emit("columndrop", { event, column, index }); }, /* * Emits drag over event (column) */ handleColumnDragOver(event, column, index) { if (!this.canDragColumn) return; this.$emit("columndragover", { event, column, index }); }, /* * Emits drag leave event (column) */ handleColumnDragLeave(event, column, index) { if (!this.canDragColumn) return; this.$emit("columndragleave", { event, column, index }); }, /* * Starts monitoring drag-by-touch events (row on touch-enabled devices) */ handleTouchStart(event, row) { if (!this.canDragRow) return; if (this.isDraggingColumn) return; if (this._selectedRow !== row) return; event.preventDefault(); this.mayBeTouchDragging = true; }, /* * Emits dragover and dragleave events (row on touch-enabled devices) * * Emits also dragstart if this is the first touchmove after touchstart. */ handleTouchMove(event) { if (!this.canDragRow) return; if (!this.mayBeTouchDragging) return; if (!this.isDraggingRow) { const eventTarget = event.target; const tr = eventTarget.closest("tr"); this.draggedCellContent = tr ? `<table class="table"><tr>${tr.innerHTML}</tr></table>` : eventTarget.innerHTML; this.$refs.draggedCell.style.width = tr ? `${tr.offsetWidth}px` : `${eventTarget.offsetWidth}px`; eventTarget.dispatchEvent(helpers.translateTouchAsDragEvent(event, { type: "dragstart" })); } const touch = event.touches[0]; const target = document.elementFromPoint(touch.clientX, touch.clientY); if (target != null) { if (target !== this.touchDragoverTarget) { if (this.touchDragoverTarget != null) { this.touchDragoverTarget.dispatchEvent( helpers.translateTouchAsDragEvent(event, { type: "dragleave", target: this.touchDragoverTarget }) ); } this.touchDragoverTarget = target; target.dispatchEvent( helpers.translateTouchAsDragEvent(event, { type: "dragover", target }) ); } } else if (this.touchDragoverTarget != null) { this.touchDragoverTarget.dispatchEvent( helpers.translateTouchAsDragEvent(event, { type: "dragleave", target: this.touchDragoverTarget }) ); this.touchDragoverTarget = null; } this.updateDraggedCell(touch); }, /* * Emits drop and dragend events (row on touch-enabled devices) */ handleTouchEnd(event) { if (!this.canDragRow) return; if (this.isDraggingRow) { const touch = event.changedTouches[0]; const target = document.elementFromPoint(touch.clientX, touch.clientY); if (target != null) { target.dispatchEvent(helpers.translateTouchAsDragEvent(event, { type: "drop", target })); } event.target.dispatchEvent(helpers.translateTouchAsDragEvent(event, { type: "dragend" })); this._selectedRow = null; } this.mayBeTouchDragging = false; }, /* * Starts monitoring drag-by-touch events (column on touch-enabled devices) */ handleColumnTouchStart(event) { if (!this.canDragColumn) return; if (this.isDraggingRow) return; event.preventDefault(); this.mayBeTouchDragging = true; }, /* * Emits dragover and dragleave events (column on touch-enabled devices) * * Also emits dragstart if this is the first touchmove after touchstart. */ handleColumnTouchMove(event) { if (!this.canDragColumn) return; if (!this.mayBeTouchDragging) return; if (!this.isDraggingColumn) { const eventTarget = event.target; this.draggedCellContent = eventTarget.innerHTML; this.$refs.draggedCell.style.width = `${eventTarget.offsetWidth}px`; eventTarget.dispatchEvent(helpers.translateTouchAsDragEvent(event, { type: "dragstart" })); } const touch = event.touches[0]; const target = document.elementFromPoint(touch.clientX, touch.clientY); if (target != null) { if (target !== this.touchDragoverTarget) { if (this.touchDragoverTarget != null) { this.touchDragoverTarget.dispatchEvent( helpers.translateTouchAsDragEvent(event, { type: "dragleave", target: this.touchDragoverTarget }) ); } this.touchDragoverTarget = target; target.dispatchEvent( helpers.translateTouchAsDragEvent(event, { type: "dragover", target }) ); } } else if (this.touchDragoverTarget != null) { this.touchDragoverTarget.dispatchEvent( helpers.translateTouchAsDragEvent(event, { type: "dragleave", target: this.touchDragoverTarget }) ); this.touchDragoverTarget = null; } this.updateDraggedCell(touch); }, /* * Emits drop and dragend events (column on touch-enabled devices) */ handleColumnTouchEnd(event) { if (!this.canDragColumn) return; if (this.isDraggingColumn) {