UNPKG

@limitless.developer/vue3-easy-data-table

Version:

A customizable and easy-to-use data table component made with Vue.js 3.x.

1,461 lines 63.7 kB
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)); import { defineComponent, useCssVars, unref, computed, inject, openBlock, createElementBlock, withModifiers, createElementVNode, normalizeClass, pushScopeId, popScopeId, ref, watch, onMounted, onBeforeUnmount, toDisplayString, Fragment, renderList, useSlots, renderSlot, createCommentVNode, toRefs, provide, normalizeStyle, createBlock, normalizeProps, mergeProps, guardReactiveProps, createTextVNode, createVNode, isRef, createSlots, withCtx } from "vue"; var MultipleSelectCheckBox_vue_vue_type_style_index_0_scoped_true_lang = ""; var _export_sfc = (sfc, props) => { const target = sfc.__vccOpts || sfc; for (const [key, val] of props) { target[key] = val; } return target; }; const _withScopeId$5 = (n) => (pushScopeId("data-v-e0a0b7f0"), n = n(), popScopeId(), n); const _hoisted_1$7 = ["onClick"]; const _hoisted_2$6 = ["checked"]; const _hoisted_3$4 = /* @__PURE__ */ _withScopeId$5(() => /* @__PURE__ */ createElementVNode("label", { for: "checbox" }, null, -1)); const _sfc_main$7 = /* @__PURE__ */ defineComponent({ __name: "MultipleSelectCheckBox", props: { status: { type: String, required: true } }, emits: ["change"], setup(__props, { emit: emits }) { const props = __props; useCssVars((_ctx) => ({ "51ab8a49": unref(themeColor) })); const isChecked = computed(() => props.status === "allSelected"); const toggleChecked = () => { emits("change", !isChecked.value); }; const themeColor = inject("themeColor"); return (_ctx, _cache) => { return openBlock(), createElementBlock("div", { class: "easy-checkbox", onClick: withModifiers(toggleChecked, ["stop", "prevent"]) }, [ createElementVNode("input", { type: "checkbox", checked: unref(isChecked), class: normalizeClass(__props.status) }, null, 10, _hoisted_2$6), _hoisted_3$4 ], 8, _hoisted_1$7); }; } }); var MultipleSelectCheckBox = /* @__PURE__ */ _export_sfc(_sfc_main$7, [["__scopeId", "data-v-e0a0b7f0"]]); var SingleSelectCheckBox_vue_vue_type_style_index_0_scoped_true_lang = ""; const _withScopeId$4 = (n) => (pushScopeId("data-v-7e69a276"), n = n(), popScopeId(), n); const _hoisted_1$6 = ["checked"]; const _hoisted_2$5 = /* @__PURE__ */ _withScopeId$4(() => /* @__PURE__ */ createElementVNode("label", { for: "checbox" }, null, -1)); const _sfc_main$6 = /* @__PURE__ */ defineComponent({ __name: "SingleSelectCheckBox", props: { checked: { type: Boolean, required: true } }, emits: ["change"], setup(__props, { emit: emits }) { useCssVars((_ctx) => ({ "fdaf7e9e": unref(themeColor) })); const themeColor = inject("themeColor"); return (_ctx, _cache) => { return openBlock(), createElementBlock("div", { class: "easy-checkbox", onClick: _cache[0] || (_cache[0] = withModifiers(($event) => emits("change"), ["stop", "prevent"])) }, [ createElementVNode("input", { type: "checkbox", checked: __props.checked }, null, 8, _hoisted_1$6), _hoisted_2$5 ]); }; } }); var SingleSelectCheckBox = /* @__PURE__ */ _export_sfc(_sfc_main$6, [["__scopeId", "data-v-7e69a276"]]); var RowsSelector_vue_vue_type_style_index_0_scoped_true_lang = ""; const _withScopeId$3 = (n) => (pushScopeId("data-v-4ca5de3a"), n = n(), popScopeId(), n); const _hoisted_1$5 = { class: "easy-data-table__rows-selector" }; const _hoisted_2$4 = { class: "rows-input" }; const _hoisted_3$3 = /* @__PURE__ */ _withScopeId$3(() => /* @__PURE__ */ createElementVNode("div", { class: "triangle" }, null, -1)); const _hoisted_4$3 = ["onClick"]; const _sfc_main$5 = /* @__PURE__ */ defineComponent({ __name: "RowsSelector", props: { modelValue: { type: Number, required: true }, rowsItems: { type: Array, required: true } }, emits: ["update:modelValue"], setup(__props, { emit: emits }) { const props = __props; useCssVars((_ctx) => ({ "1b889342": unref(themeColor) })); const showList = ref(false); const showInsideOfTable = ref(false); const dataTable = inject("dataTable"); watch(showList, (val) => { if (val && dataTable) { const windowHeight = window.innerHeight; const dataTableHeight = dataTable.value.getBoundingClientRect().height; const dataTableTop = dataTable.value.getBoundingClientRect().top; if (windowHeight - (dataTableHeight + dataTableTop) <= 100) { showInsideOfTable.value = true; } else { showInsideOfTable.value = false; } } }); const rowsComputed = computed({ get: () => props.modelValue, set: (value) => { emits("update:modelValue", value); } }); const changeSelectedRows = (value) => { rowsComputed.value = value; showList.value = false; }; const isDescendant = (child, className) => { let node = child.parentNode; while (node != null) { if (node.classList && node.classList.contains(className)) { return true; } node = node.parentNode; } return false; }; const closeRowsSelector = (e) => { if (!isDescendant(e.target, "easy-data-table__rows-selector")) showList.value = false; }; onMounted(() => { document.addEventListener("click", closeRowsSelector); }); onBeforeUnmount(() => { document.removeEventListener("click", closeRowsSelector); }); const themeColor = inject("themeColor"); return (_ctx, _cache) => { return openBlock(), createElementBlock("div", _hoisted_1$5, [ createElementVNode("div", { class: "rows-input__wrapper", onClick: _cache[0] || (_cache[0] = ($event) => showList.value = !showList.value) }, [ createElementVNode("div", _hoisted_2$4, toDisplayString(unref(rowsComputed)), 1), _hoisted_3$3 ]), createElementVNode("ul", { class: normalizeClass(["select-items", { show: showList.value, inside: showInsideOfTable.value }]) }, [ (openBlock(true), createElementBlock(Fragment, null, renderList(__props.rowsItems, (item) => { return openBlock(), createElementBlock("li", { key: item, class: normalizeClass({ selected: item === unref(rowsComputed) }), onClick: ($event) => changeSelectedRows(item) }, toDisplayString(item), 11, _hoisted_4$3); }), 128)) ], 2) ]); }; } }); var RowsSelector = /* @__PURE__ */ _export_sfc(_sfc_main$5, [["__scopeId", "data-v-4ca5de3a"]]); var Loading_vue_vue_type_style_index_0_scoped_true_lang = ""; const _withScopeId$2 = (n) => (pushScopeId("data-v-1fa3a520"), n = n(), popScopeId(), n); const _hoisted_1$4 = { class: "lds-ring" }; const _hoisted_2$3 = /* @__PURE__ */ _withScopeId$2(() => /* @__PURE__ */ createElementVNode("div", null, null, -1)); const _hoisted_3$2 = /* @__PURE__ */ _withScopeId$2(() => /* @__PURE__ */ createElementVNode("div", null, null, -1)); const _hoisted_4$2 = /* @__PURE__ */ _withScopeId$2(() => /* @__PURE__ */ createElementVNode("div", null, null, -1)); const _hoisted_5$1 = /* @__PURE__ */ _withScopeId$2(() => /* @__PURE__ */ createElementVNode("div", null, null, -1)); const _hoisted_6$1 = [ _hoisted_2$3, _hoisted_3$2, _hoisted_4$2, _hoisted_5$1 ]; const _sfc_main$4 = /* @__PURE__ */ defineComponent({ __name: "Loading", setup(__props) { useCssVars((_ctx) => ({ "26774109": unref(themeColor) })); const themeColor = inject("themeColor"); return (_ctx, _cache) => { return openBlock(), createElementBlock("div", _hoisted_1$4, _hoisted_6$1); }; } }); var Loading = /* @__PURE__ */ _export_sfc(_sfc_main$4, [["__scopeId", "data-v-1fa3a520"]]); var LoadingLine_vue_vue_type_style_index_0_scoped_true_lang = ""; const _hoisted_1$3 = { class: "loader-line" }; const _sfc_main$3 = /* @__PURE__ */ defineComponent({ __name: "LoadingLine", setup(__props) { useCssVars((_ctx) => ({ "0d327f57": unref(themeColor) })); const themeColor = inject("themeColor"); return (_ctx, _cache) => { return openBlock(), createElementBlock("div", _hoisted_1$3); }; } }); var LoadingLine = /* @__PURE__ */ _export_sfc(_sfc_main$3, [["__scopeId", "data-v-7d281cac"]]); var ButtonsPagination_vue_vue_type_style_index_0_scoped_true_lang = ""; const _hoisted_1$2 = { class: "buttons-pagination" }; const _hoisted_2$2 = ["onClick"]; const _sfc_main$2 = /* @__PURE__ */ defineComponent({ __name: "ButtonsPagination", props: { maxPaginationNumber: { type: Number, required: true }, currentPaginationNumber: { type: Number, required: true } }, emits: ["updatePage"], setup(__props, { emit: emits }) { const props = __props; useCssVars((_ctx) => ({ "40dd4f07": unref(themeColor) })); const totalVisible = 7; const changePage = (item) => { if (item.type === "button" && !item.active) emits("updatePage", item.page); }; const paginationItemsForRender = computed(() => { const paginationItems = []; if (props.maxPaginationNumber <= totalVisible) { for (let i = 1; i <= props.maxPaginationNumber; i += 1) { paginationItems.push({ type: "button", page: i, active: i === props.currentPaginationNumber, activePrev: i + 1 === props.currentPaginationNumber }); } } else if ([1, 2, props.maxPaginationNumber, props.maxPaginationNumber - 1].includes(props.currentPaginationNumber)) { for (let i = 1; i <= totalVisible; i += 1) { if (i <= 3) { paginationItems.push({ type: "button", page: i, active: i === props.currentPaginationNumber, activePrev: i + 1 === props.currentPaginationNumber }); } else if (i === 4) { paginationItems.push({ type: "omission" }); } else { const page = props.maxPaginationNumber - (totalVisible - i); paginationItems.push({ type: "button", page, active: page === props.currentPaginationNumber, activePrev: page + 1 === props.currentPaginationNumber }); } } } else if ([3, 4].includes(props.currentPaginationNumber)) { for (let i = 1; i <= totalVisible; i += 1) { if (i <= 5) { paginationItems.push({ type: "button", page: i, active: i === props.currentPaginationNumber, activePrev: i + 1 === props.currentPaginationNumber }); } else if (i === 6) { paginationItems.push({ type: "omission" }); } else { paginationItems.push({ type: "button", page: props.maxPaginationNumber, active: props.maxPaginationNumber === props.currentPaginationNumber, activePrev: i + 1 === props.currentPaginationNumber }); } } } else if ([props.maxPaginationNumber - 2, props.maxPaginationNumber - 3].includes(props.currentPaginationNumber)) { for (let i = 1; i <= totalVisible; i += 1) { if (i === 1) { paginationItems.push({ type: "button", page: 1, active: props.currentPaginationNumber === 1, activePrev: i + 1 === props.currentPaginationNumber }); } else if (i === 2) { paginationItems.push({ type: "omission" }); } else { const page = props.maxPaginationNumber - (totalVisible - i); paginationItems.push({ type: "button", page, active: page === props.currentPaginationNumber, activePrev: page + 1 === props.currentPaginationNumber }); } } } else { for (let i = 1; i <= totalVisible; i += 1) { if (i === 1) { paginationItems.push({ type: "button", page: 1, active: props.currentPaginationNumber === 1, activePrev: i + 1 === props.currentPaginationNumber }); } else if (i === 2 || i === 6) { paginationItems.push({ type: "omission" }); } else if (i === 7) { paginationItems.push({ type: "button", page: props.maxPaginationNumber, active: props.maxPaginationNumber === props.currentPaginationNumber, activePrev: i + 1 === props.currentPaginationNumber }); } else { const diff = 4 - i; const page = props.currentPaginationNumber - diff; paginationItems.push({ type: "button", page, active: page === props.currentPaginationNumber, activePrev: page + 1 === props.currentPaginationNumber }); } } } return paginationItems; }); const themeColor = inject("themeColor"); return (_ctx, _cache) => { return openBlock(), createElementBlock("div", _hoisted_1$2, [ (openBlock(true), createElementBlock(Fragment, null, renderList(unref(paginationItemsForRender), (item, i) => { return openBlock(), createElementBlock("div", { key: i, class: normalizeClass(["item", { button: item.type === "button", active: item.type === "button" && item.active, "active-prev": item.type === "button" && item.activePrev, omission: item.type === "omission" }]), onClick: ($event) => changePage(item) }, toDisplayString(item.type === "button" ? item.page : "..."), 11, _hoisted_2$2); }), 128)) ]); }; } }); var ButtonsPagination = /* @__PURE__ */ _export_sfc(_sfc_main$2, [["__scopeId", "data-v-4c681fa2"]]); var PaginationArrows_vue_vue_type_style_index_0_scoped_true_lang = ""; const _withScopeId$1 = (n) => (pushScopeId("data-v-c9da5286"), n = n(), popScopeId(), n); const _hoisted_1$1 = /* @__PURE__ */ _withScopeId$1(() => /* @__PURE__ */ createElementVNode("span", { class: "arrow arrow-right" }, null, -1)); const _hoisted_2$1 = [ _hoisted_1$1 ]; const _hoisted_3$1 = /* @__PURE__ */ _withScopeId$1(() => /* @__PURE__ */ createElementVNode("span", { class: "arrow arrow-left" }, null, -1)); const _hoisted_4$1 = [ _hoisted_3$1 ]; const _sfc_main$1 = /* @__PURE__ */ defineComponent({ __name: "PaginationArrows", props: { isFirstPage: { type: Boolean, required: false }, isLastPage: { type: Boolean, required: false } }, emits: ["clickPrevPage", "clickNextPage"], setup(__props, { emit: emits }) { const slots = useSlots(); return (_ctx, _cache) => { return openBlock(), createElementBlock(Fragment, null, [ createElementVNode("div", { class: normalizeClass(["previous-page__click-button", { "first-page": __props.isFirstPage }]), onClick: _cache[0] || (_cache[0] = ($event) => emits("clickPrevPage")) }, _hoisted_2$1, 2), unref(slots).buttonsPagination ? renderSlot(_ctx.$slots, "buttonsPagination", { key: 0 }, void 0, true) : createCommentVNode("", true), createElementVNode("div", { class: normalizeClass(["next-page__click-button", { "last-page": __props.isLastPage }]), onClick: _cache[1] || (_cache[1] = ($event) => emits("clickNextPage")) }, _hoisted_4$1, 2) ], 64); }; } }); var PaginationArrows = /* @__PURE__ */ _export_sfc(_sfc_main$1, [["__scopeId", "data-v-c9da5286"]]); function useClickRow(clickEventType, isMultipleSelectable, showIndex, emits) { const clickRow = (item, clickType, $event) => { if (clickEventType.value !== clickType) return; const clickRowArgument = __spreadValues({}, item); if (isMultipleSelectable.value) { const { checkbox } = item; delete clickRowArgument.checkbox; clickRowArgument.isSelected = checkbox; } if (showIndex.value) { const { index } = item; delete clickRowArgument.index; clickRowArgument.indexInCurrentPage = index; } emits("clickRow", clickRowArgument, $event); }; return { clickRow }; } function useExpandableRow(items, prevPageEndIndex, emits) { const expandingItemIndexList = ref([]); const updateExpandingItemIndexList = (expandingItemIndex, expandingItem, event) => { event.stopPropagation(); const index = expandingItemIndexList.value.indexOf(expandingItemIndex); if (index !== -1) { expandingItemIndexList.value.splice(index, 1); } else { const currentPageExpandIndex = items.value.findIndex((item) => JSON.stringify(item) === JSON.stringify(expandingItem)); emits("expandRow", prevPageEndIndex.value + currentPageExpandIndex, expandingItem); expandingItemIndexList.value.push(prevPageEndIndex.value + currentPageExpandIndex); } }; const clearExpandingItemIndexList = () => { expandingItemIndexList.value = []; }; return { expandingItemIndexList, updateExpandingItemIndexList, clearExpandingItemIndexList }; } function useFixedColumn(headersForRender) { const fixedHeaders = computed(() => headersForRender.value.filter((header) => header.fixed)); const lastFixedColumn = computed(() => { if (!fixedHeaders.value.length) return ""; return fixedHeaders.value[fixedHeaders.value.length - 1].value; }); const fixedColumnsInfos = computed(() => { if (!fixedHeaders.value.length) return []; const fixedHeadersWidthArr = fixedHeaders.value.map((header) => { var _a; return (_a = header.width) != null ? _a : 100; }); return fixedHeaders.value.map((header, index) => { var _a, _b; return { value: header.value, fixed: (_a = header.fixed) != null ? _a : true, width: (_b = header.width) != null ? _b : 100, distance: index === 0 ? 0 : fixedHeadersWidthArr.reduce((previous, current, i) => { let distance = previous; if (i < index) distance += current; return distance; }) }; }); }); return { fixedHeaders, lastFixedColumn, fixedColumnsInfos }; } function useHeaders(showIndexSymbol, checkboxColumnWidth, expandColumnWidth, fixedCheckbox, fixedExpand, fixedIndex, headers, ifHasExpandSlot, indexColumnWidth, isMultipleSelectable, isServerSideMode, mustSort, serverOptionsComputed, showIndex, sortBy, sortType, multiSort, updateServerOptionsSort, emits) { const hasFixedColumnsFromUser = computed(() => headers.value.findIndex((header) => header.fixed) !== -1); const fixedHeadersFromUser = computed(() => { if (hasFixedColumnsFromUser.value) return headers.value.filter((header) => header.fixed); return []; }); const unFixedHeaders = computed(() => headers.value.filter((header) => !header.fixed)); const generateClientSortOptions = (sortByValue, sortTypeValue) => { if (Array.isArray(sortByValue) && Array.isArray(sortTypeValue)) { return { sortBy: sortByValue, sortDesc: sortTypeValue.map((val) => val === "desc") }; } if (sortByValue !== "") { return { sortBy: sortBy.value, sortDesc: sortType.value === "desc" }; } return null; }; const clientSortOptions = ref(generateClientSortOptions(sortBy.value, sortType.value)); const headersForRender = computed(() => { var _a; const fixedHeaders = [ ...fixedHeadersFromUser.value, ...unFixedHeaders.value ]; const headersSorting = fixedHeaders.map((header) => { const headerSorting = Object.assign(header); if (headerSorting.sortable) headerSorting.sortType = "none"; if (serverOptionsComputed.value) { if (Array.isArray(serverOptionsComputed.value.sortBy) && Array.isArray(serverOptionsComputed.value.sortType) && serverOptionsComputed.value.sortBy.includes(headerSorting.value)) { const index = serverOptionsComputed.value.sortBy.indexOf(headerSorting.value); headerSorting.sortType = serverOptionsComputed.value.sortType[index]; } else if (headerSorting.value === serverOptionsComputed.value.sortBy && serverOptionsComputed.value.sortType) { headerSorting.sortType = serverOptionsComputed.value.sortType; } } if (clientSortOptions.value && Array.isArray(clientSortOptions.value.sortBy) && Array.isArray(clientSortOptions.value.sortDesc) && clientSortOptions.value.sortBy.includes(headerSorting.value)) { const index = clientSortOptions.value.sortBy.indexOf(headerSorting.value); headerSorting.sortType = clientSortOptions.value.sortDesc[index] ? "desc" : "asc"; } else if (clientSortOptions.value && headerSorting.value === clientSortOptions.value.sortBy) { headerSorting.sortType = clientSortOptions.value.sortDesc ? "desc" : "asc"; } return headerSorting; }); let headersWithExpand = []; if (!ifHasExpandSlot.value) { headersWithExpand = headersSorting; } else { const headerExpand = fixedExpand.value || hasFixedColumnsFromUser.value ? { text: "", value: "expand", fixed: true, width: expandColumnWidth.value } : { text: "", value: "expand" }; headersWithExpand = [headerExpand, ...headersSorting]; } let headersWithIndex = []; if (!showIndex.value) { headersWithIndex = headersWithExpand; } else { const headerIndex = fixedIndex.value || hasFixedColumnsFromUser.value ? { text: showIndexSymbol.value, value: "index", fixed: true, width: indexColumnWidth.value } : { text: showIndexSymbol.value, value: "index" }; headersWithIndex = [headerIndex, ...headersWithExpand]; } let headersWithCheckbox = []; if (!isMultipleSelectable.value) { headersWithCheckbox = headersWithIndex; } else { const headerCheckbox = fixedCheckbox.value || hasFixedColumnsFromUser.value ? { text: "checkbox", value: "checkbox", fixed: true, width: (_a = checkboxColumnWidth.value) != null ? _a : 36 } : { text: "checkbox", value: "checkbox" }; headersWithCheckbox = [headerCheckbox, ...headersWithIndex]; } return headersWithCheckbox; }); const headerColumns = computed(() => headersForRender.value.map((header) => header.value)); const updateSortField = (newSortBy, oldSortType) => { let newSortType = null; if (oldSortType === "none") { newSortType = "asc"; } else if (oldSortType === "asc") { newSortType = "desc"; } else { newSortType = mustSort.value ? "asc" : null; } if (isServerSideMode.value) { updateServerOptionsSort(newSortBy, newSortType); } if (clientSortOptions.value && Array.isArray(clientSortOptions.value.sortBy) && Array.isArray(clientSortOptions.value.sortDesc)) { const index = clientSortOptions.value.sortBy.indexOf(newSortBy); if (index === -1) { if (newSortType !== null) { clientSortOptions.value.sortBy.push(newSortBy); clientSortOptions.value.sortDesc.push(newSortType === "desc"); } } else if (newSortType === null) { clientSortOptions.value.sortDesc.splice(index, 1); clientSortOptions.value.sortBy.splice(index, 1); } else { clientSortOptions.value.sortDesc[index] = newSortType === "desc"; } } else if (newSortType === null) { clientSortOptions.value = null; } else { clientSortOptions.value = { sortBy: newSortBy, sortDesc: newSortType === "desc" }; } emits("updateSort", { sortType: newSortType, sortBy: newSortBy }); }; const isMultiSorting = (headerText) => { if (serverOptionsComputed.value) { if (Array.isArray(serverOptionsComputed.value.sortBy)) return serverOptionsComputed.value.sortBy.includes(headerText); } if (clientSortOptions.value && Array.isArray(clientSortOptions.value.sortBy)) { return clientSortOptions.value.sortBy.includes(headerText); } return false; }; const getMultiSortNumber = (headerText) => { if (serverOptionsComputed.value) { if (Array.isArray(serverOptionsComputed.value.sortBy)) return serverOptionsComputed.value.sortBy.indexOf(headerText) + 1; } if (clientSortOptions.value && Array.isArray(clientSortOptions.value.sortBy)) { return clientSortOptions.value.sortBy.indexOf(headerText) + 1; } return false; }; return { clientSortOptions, headerColumns, headersForRender, updateSortField, isMultiSorting, getMultiSortNumber }; } function usePageItems(currentPaginationNumber, isMultipleSelectable, isServerSideMode, items, rowsPerPageRef, selectItemsComputed, showIndex, totalItems, totalItemsLength) { const currentPageFirstIndex = computed(() => (currentPaginationNumber.value - 1) * rowsPerPageRef.value + 1); const currentPageLastIndex = computed(() => { if (isServerSideMode.value) { return Math.min(totalItemsLength.value, currentPaginationNumber.value * rowsPerPageRef.value); } return Math.min(totalItems.value.length, currentPaginationNumber.value * rowsPerPageRef.value); }); const itemsInPage = computed(() => { if (isServerSideMode.value) return items.value; return totalItems.value.slice(currentPageFirstIndex.value - 1, currentPageLastIndex.value); }); const itemsWithIndex = computed(() => { if (showIndex.value) { return itemsInPage.value.map((item, index) => __spreadValues({ index: currentPageFirstIndex.value + index }, item)); } return itemsInPage.value; }); const multipleSelectStatus = computed(() => { if (selectItemsComputed.value.length === 0) { return "noneSelected"; } const isNoneSelected = selectItemsComputed.value.every((itemSelected) => { if (totalItems.value.findIndex((item) => JSON.stringify(itemSelected) === JSON.stringify(item)) !== -1) { return false; } return true; }); if (isNoneSelected) return "noneSelected"; if (selectItemsComputed.value.length === totalItems.value.length) { const isAllSelected = selectItemsComputed.value.every((itemSelected) => { if (totalItems.value.findIndex((item) => JSON.stringify(itemSelected) === JSON.stringify(item)) === -1) { return false; } return true; }); return isAllSelected ? "allSelected" : "partSelected"; } return "partSelected"; }); const pageItems = computed(() => { if (!isMultipleSelectable.value) return itemsWithIndex.value; if (multipleSelectStatus.value === "allSelected") { return itemsWithIndex.value.map((item) => __spreadValues({ checkbox: true }, item)); } if (multipleSelectStatus.value === "noneSelected") { return itemsWithIndex.value.map((item) => __spreadValues({ checkbox: false }, item)); } return itemsWithIndex.value.map((item) => { const isSelected = selectItemsComputed.value.findIndex((selectItem) => { const itemDeepCloned = __spreadValues({}, item); delete itemDeepCloned.index; return JSON.stringify(selectItem) === JSON.stringify(itemDeepCloned); }) !== -1; return __spreadValues({ checkbox: isSelected }, item); }); }); return { currentPageFirstIndex, currentPageLastIndex, multipleSelectStatus, pageItems }; } function usePagination(currentPage, isServerSideMode, loading, totalItemsLength, rowsPerPage, serverOptions, updateServerOptionsPage) { const currentPaginationNumber = ref(serverOptions.value ? serverOptions.value.page : currentPage.value); const maxPaginationNumber = computed(() => Math.ceil(totalItemsLength.value / rowsPerPage.value)); const isLastPage = computed(() => maxPaginationNumber.value === 0 || currentPaginationNumber.value === maxPaginationNumber.value); const isFirstPage = computed(() => currentPaginationNumber.value === 1); const nextPage = () => { if (totalItemsLength.value === 0) return; if (isLastPage.value) return; if (loading.value) return; if (isServerSideMode.value) { const nextPaginationNumber = currentPaginationNumber.value + 1; updateServerOptionsPage(nextPaginationNumber); } else { currentPaginationNumber.value += 1; } }; const prevPage = () => { if (totalItemsLength.value === 0) return; if (isFirstPage.value) return; if (loading.value) return; if (isServerSideMode.value) { const prevPaginationNumber = currentPaginationNumber.value - 1; updateServerOptionsPage(prevPaginationNumber); } else { currentPaginationNumber.value -= 1; } }; const updatePage = (page) => { if (loading.value) return; if (isServerSideMode.value) { updateServerOptionsPage(page); } else { currentPaginationNumber.value = page; } }; const updateCurrentPaginationNumber = (page) => { currentPaginationNumber.value = page; }; return { currentPaginationNumber, maxPaginationNumber, isLastPage, isFirstPage, nextPage, prevPage, updatePage, updateCurrentPaginationNumber }; } function useRows(isServerSideMode, rowsItems, serverOptions, rowsPerPage) { const rowsItemsComputed = computed(() => { if (!isServerSideMode.value && rowsItems.value.findIndex((item) => item === rowsPerPage.value) === -1) { return [rowsPerPage.value, ...rowsItems.value]; } return rowsItems.value; }); const rowsPerPageRef = ref(serverOptions.value ? serverOptions.value.rowsPerPage : rowsPerPage.value); const updateRowsPerPage = (option) => { rowsPerPageRef.value = option; }; return { rowsItemsComputed, rowsPerPageRef, updateRowsPerPage }; } function useServerOptions(serverOptions, multiSort, emits) { const serverOptionsComputed = computed({ get: () => { if (serverOptions.value) { const { page, rowsPerPage, sortBy, sortType } = serverOptions.value; return { page, rowsPerPage, sortBy: sortBy != null ? sortBy : null, sortType: sortType != null ? sortType : null }; } return null; }, set: (value) => { emits("update:serverOptions", value); } }); const updateServerOptionsPage = (page) => { if (serverOptionsComputed.value) { serverOptionsComputed.value = __spreadProps(__spreadValues({}, serverOptionsComputed.value), { page }); } }; const updateServerOptionsRowsPerPage = (rowsPerPage) => { if (serverOptionsComputed.value) { serverOptionsComputed.value = __spreadProps(__spreadValues({}, serverOptionsComputed.value), { page: 1, rowsPerPage }); } }; const updateServerOptionsSort = (newSortBy, newSortType) => { if (serverOptionsComputed.value) { if (multiSort.value && Array.isArray(serverOptionsComputed.value.sortBy) && Array.isArray(serverOptionsComputed.value.sortType)) { const index = serverOptionsComputed.value.sortBy.findIndex((val) => val === newSortBy); if (index === -1 && newSortType !== null) { serverOptionsComputed.value.sortBy.push(newSortBy); serverOptionsComputed.value.sortType.push(newSortType); } if (newSortType === null) { serverOptionsComputed.value.sortBy.splice(index, 1); serverOptionsComputed.value.sortType.splice(index, 1); } else { serverOptionsComputed.value.sortType[index] = newSortType; } } else { serverOptionsComputed.value = __spreadProps(__spreadValues({}, serverOptionsComputed.value), { sortBy: newSortType !== null ? newSortBy : null, sortType: newSortType }); } } }; return { serverOptionsComputed, updateServerOptionsPage, updateServerOptionsSort, updateServerOptionsRowsPerPage }; } function getItemValue(column, item) { var _a; if (column.includes(".")) { const keys = column.split("."); const { length } = keys; let content; let i = 0; while (i < length) { if (i === 0) { content = item[keys[0]]; } else if (content && typeof content === "object") { content = content[keys[i]]; } else { content = ""; break; } i += 1; } return content != null ? content : ""; } return (_a = item[column]) != null ? _a : ""; } function generateColumnContent(column, item) { const content = getItemValue(column, item); return Array.isArray(content) ? content.join(",") : content; } function useTotalItems(clientSortOptions, filterOptions, isServerSideMode, items, itemsSelected, searchField, searchValue, serverItemsLength, multiSort, emits) { const generateSearchingTarget = (item) => { if (typeof searchField.value === "string" && searchField.value !== "") return getItemValue(searchField.value, item); if (Array.isArray(searchField.value)) { let searchString = ""; searchField.value.forEach((field) => { searchString += getItemValue(field, item); }); return searchString; } return Object.values(item).join(" "); }; const itemsSearching = computed(() => { if (!isServerSideMode.value && searchValue.value !== "") { const regex = new RegExp(searchValue.value, "i"); return items.value.filter((item) => regex.test(generateSearchingTarget(item))); } return items.value; }); const itemsFiltering = computed(() => { let itemsFiltered = [...itemsSearching.value]; if (filterOptions.value) { filterOptions.value.forEach((option) => { itemsFiltered = itemsFiltered.filter((item) => { const { field, comparison, criteria } = option; if (typeof comparison === "function") { return comparison(getItemValue(field, item), criteria); } const itemValue = getItemValue(field, item); switch (comparison) { case "=": return itemValue === criteria; case "!=": return itemValue !== criteria; case ">": return itemValue > criteria; case "<": return itemValue < criteria; case "<=": return itemValue <= criteria; case ">=": return itemValue >= criteria; case "between": return itemValue >= Math.min(...criteria) && itemValue <= Math.max(...criteria); case "in": return criteria.includes(itemValue); default: return itemValue === criteria; } }); }); return itemsFiltered; } return itemsSearching.value; }); watch(itemsFiltering, (newVal) => { if (filterOptions.value) { emits("updateFilter", newVal); } }, { immediate: true, deep: true }); function recursionMuiltSort(sortByArr, sortDescArr, itemsToSort, index) { const sortBy = sortByArr[index]; const sortDesc = sortDescArr[index]; const sorted = (index === 0 ? itemsToSort : recursionMuiltSort(sortByArr, sortDescArr, itemsToSort, index - 1)).sort((a, b) => { let isAllSame = true; for (let i = 0; i < index; i += 1) { if (getItemValue(sortByArr[i], a) !== getItemValue(sortByArr[i], b)) { isAllSame = false; break; } } if (isAllSame) { if (getItemValue(sortBy, a) < getItemValue(sortBy, b)) return sortDesc ? 1 : -1; if (getItemValue(sortBy, a) > getItemValue(sortBy, b)) return sortDesc ? -1 : 1; return 0; } return 0; }); return sorted; } const totalItems = computed(() => { if (isServerSideMode.value) return items.value; if (clientSortOptions.value === null) return itemsFiltering.value; const { sortBy, sortDesc } = clientSortOptions.value; const itemsFilteringSorted = [...itemsFiltering.value]; if (multiSort && Array.isArray(sortBy) && Array.isArray(sortDesc)) { if (sortBy.length === 0) return itemsFilteringSorted; return recursionMuiltSort(sortBy, sortDesc, itemsFilteringSorted, sortBy.length - 1); } return itemsFilteringSorted.sort((a, b) => { if (getItemValue(sortBy, a) < getItemValue(sortBy, b)) return sortDesc ? 1 : -1; if (getItemValue(sortBy, a) > getItemValue(sortBy, b)) return sortDesc ? -1 : 1; return 0; }); }); const totalItemsLength = computed(() => isServerSideMode.value ? serverItemsLength.value : totalItems.value.length); const selectItemsComputed = computed({ get: () => { var _a; return (_a = itemsSelected.value) != null ? _a : []; }, set: (value) => { emits("update:itemsSelected", value); } }); const toggleSelectAll = (isChecked) => { selectItemsComputed.value = isChecked ? totalItems.value : []; if (isChecked) emits("selectAll"); }; const toggleSelectItem = (item) => { const isAlreadyChecked = item.checkbox; delete item.checkbox; delete item.index; if (!isAlreadyChecked) { const selectItemsArr = selectItemsComputed.value; selectItemsArr.unshift(item); selectItemsComputed.value = selectItemsArr; emits("selectRow", item); } else { selectItemsComputed.value = selectItemsComputed.value.filter((selectedItem) => JSON.stringify(selectedItem) !== JSON.stringify(item)); emits("deselectRow", item); } }; return { totalItems, selectItemsComputed, totalItemsLength, toggleSelectAll, toggleSelectItem }; } var propsWithDefault = { alternating: { type: Boolean, default: false }, buttonsPagination: { type: Boolean, default: false }, checkboxColumnWidth: { type: Number, default: null }, currentPage: { type: Number, default: 1 }, emptyMessage: { type: String, default: "No Available Data" }, expandColumnWidth: { type: Number, default: 36 }, filterOptions: { type: Array, default: null }, fixedExpand: { type: Boolean, default: false }, fixedHeader: { type: Boolean, default: true }, fixedCheckbox: { type: Boolean, default: false }, fixedIndex: { type: Boolean, default: false }, headerTextDirection: { type: String, default: "left" }, bodyTextDirection: { type: String, default: "left" }, hideFooter: { type: Boolean, default: false }, hideRowsPerPage: { type: Boolean, default: false }, hideHeader: { type: Boolean, default: false }, indexColumnWidth: { type: Number, default: 60 }, itemsSelected: { type: Array, default: null }, loading: { type: Boolean, default: false }, rowsPerPage: { type: Number, default: 25 }, rowsItems: { type: Array, default: () => [25, 50, 100] }, rowsPerPageMessage: { type: String, default: "rows per page:" }, searchField: { type: [String, Array], default: "" }, searchValue: { type: String, default: "" }, serverOptions: { type: Object, default: null }, serverItemsLength: { type: Number, default: 0 }, showIndex: { type: Boolean, default: false }, sortBy: { type: [String, Array], default: "" }, sortType: { type: [String, Array], default: "asc" }, multiSort: { type: Boolean, default: false }, tableMinHeight: { type: Number, default: 180 }, tableHeight: { type: Number, default: null }, themeColor: { type: String, default: "#42b883" }, tableClassName: { type: String, default: "" }, headerClassName: { type: String, default: "" }, headerItemClassName: { type: [Function, String], default: "" }, bodyRowClassName: { type: [Function, String], default: "" }, bodyExpandRowClassName: { type: [Function, String], default: "" }, bodyItemClassName: { type: [Function, String], default: "" }, noHover: { type: Boolean, default: false }, borderCell: { type: Boolean, default: false }, mustSort: { type: Boolean, default: false }, rowsOfPageSeparatorMessage: { type: String, default: "of" }, clickEventType: { type: String, default: "single" }, clickRowToExpand: { type: Boolean, default: false }, tableNodeId: { type: String, default: "" }, showIndexSymbol: { type: String, default: "#" }, preventContextMenuRow: { type: Boolean, default: true } }; var DataTable_vue_vue_type_style_index_0_lang = ""; var DataTable_vue_vue_type_style_index_1_scoped_true_lang = ""; const _withScopeId = (n) => (pushScopeId("data-v-32683533"), n = n(), popScopeId(), n); const _hoisted_1 = ["id"]; const _hoisted_2 = ["onClick"]; const _hoisted_3 = { key: 3, class: "header-text" }; const _hoisted_4 = { key: 5, class: "multi-sort__number" }; const _hoisted_5 = ["onClick", "onDblclick", "onContextmenu"]; const _hoisted_6 = ["onClick"]; const _hoisted_7 = ["colspan"]; const _hoisted_8 = { key: 0, class: "vue3-easy-data-table__loading" }; const _hoisted_9 = /* @__PURE__ */ _withScopeId(() => /* @__PURE__ */ createElementVNode("div", { class: "vue3-easy-data-table__loading-mask" }, null, -1)); const _hoisted_10 = { class: "loading-entity" }; const _hoisted_11 = { key: 1, class: "vue3-easy-data-table__message" }; const _hoisted_12 = { key: 0, class: "vue3-easy-data-table__footer" }; const _hoisted_13 = { key: 0, class: "pagination__rows-per-page" }; const _hoisted_14 = { class: "pagination__items-index" }; const _sfc_main = /* @__PURE__ */ defineComponent({ __name: "DataTable", props: __spreadProps(__spreadValues({}, propsWithDefault), { items: { type: Array, required: true }, headers: { type: Array, required: true } }), emits: [ "clickRow", "contextmenuRow", "selectRow", "deselectRow", "expandRow", "updateSort", "updateFilter", "update:itemsSelected", "update:serverOptions", "updatePageItems", "updateTotalItems", "selectAll" ], setup(__props, { expose, emit: emits }) { const props = __props; useCssVars((_ctx) => ({ "da0d4328": unref(tableMinHeightPx), "3037e504": unref(tableHeightPx) })); const { tableNodeId, clickEventType, bodyTextDirection, checkboxColumnWidth, currentPage, expandColumnWidth, filterOptions, fixedCheckbox, fixedExpand, fixedHeader, fixedIndex, headers, headerTextDirection, indexColumnWidth, items, itemsSelected, loading, mustSort, multiSort, rowsItems, rowsPerPage, searchField, searchValue, serverItemsLength, serverOptions, showIndex, sortBy, sortType, tableHeight, tableMinHeight, themeColor, rowsOfPageSeparatorMessage, showIndexSymbol, preventContextMenuRow } = toRefs(props); const tableHeightPx = computed(() => tableHeight.value ? `${tableHeight.value}px` : null); const tableMinHeightPx = computed(() => `${tableMinHeight.value}px`); provide("themeColor", themeColor.value); const slots = useSlots(); const ifHasPaginationSlot = computed(() => !!slots.pagination); const ifHasLoadingSlot = computed(() => !!slots.loading); const ifHasExpandSlot = computed(() => !!slots.expand); const ifHasBodySlot = computed(() => !!slots.body); const dataTable = ref(); const tableBody = ref(); provide("dataTable", dataTable); const showShadow = ref(false); onMounted(() => { tableBody.value.addEventListener("scroll", () => { showShadow.value = tableBody.value.scrollLeft > 0; }); }); const isMultipleSelectable = computed(() => itemsSelected.value !== null); const isServerSideMode = computed(() => serverOptions.value !== null); const { serverOptionsComputed, updateServerOptionsPage, updateServerOptionsSort, updateServerOptionsRowsPerPage } = useServerOptions(serverOptions, multiSort, emits); const { clientSortOptions, headerColumns, headersForRender, updateSortField, isMultiSorting, getMultiSortNumber } = useHeaders(showIndexSymbol, checkboxColumnWidth, expandColumnWidth, fixedCheckbox, fixedExpand, fixedIndex, headers, ifHasExpandSlot, indexColumnWidth, isMultipleSelectable, isServerSideMode, mustSort, serverOptionsComputed, showIndex, sortBy, sortType, multiSort, updateServerOptionsSort, emits); const { rowsItemsComputed, rowsPerPageRef, updateRowsPerPage } = useRows(isServerSideMode, rowsItems, serverOptions, rowsPerPage); const { totalItems, selectItemsComputed, totalItemsLength, toggleSelectAll, toggleSelectItem } = useTotalItems(clientSortOptions, filterOptions, isServerSideMode, items, itemsSelected, searchField, searchValue, serverItemsLength, multiSort, emits); const { currentPaginationNumber, maxPaginationNumber, isLastPage, isFirstPage, nextPage, prevPage, updatePage, updateCurrentPaginationNumber } = usePagination(currentPage, isServerSideMode, loading, totalItemsLength, rowsPerPageRef, serverOptions, updateServerOptionsPage); const { currentPageFirstIndex, currentPageLastIndex, multipleSelectStatus, pageItems } = usePageItems(currentPaginationNumber, isMultipleSelectable, isServerSideMode, items, rowsPerPageRef, selectItemsComputed, showIndex, totalItems, totalItemsLength); const prevPageEndIndex = computed(() => { if (currentPaginationNumber.value === 0) return 0; return (currentPaginationNumber.value - 1) * rowsPerPageRef.value; }); const { expandingItemIndexList, updateExpandingItemIndexList, clearExpandingItemIndexList } = useExpandableRow(pageItems, prevPageEndIndex, emits); const { fixedHeaders, lastFixedColumn, fixedColumnsInfos } = useFixedColumn(headersForRender); const { clickRow } = useClickRow(clickEventType, isMultipleSelectable, showIndex, emits); const contextMenuRow = (item, $event) => { if (preventContextMenuRow.value) $event.preventDefault(); emits("contextmenuRow", item, $event); }; const getColStyle = (header) => { var _a; const width = (_a = header.width) != null ? _a : fixedHeaders.value.length ? 100 : null; if (width) return `width: ${width}px; min-width: ${width}px;`; return void 0; }; const getFixedDistance = (column, type = "th") => { if (!fixedHeaders.value.length) return void 0; const columInfo = fixedColumnsInfos.value.find((info) => info.value === column); if (columInfo) { return `left: ${columInfo.distance}px;z-index: ${type === "th" ? 3 : 1};position: sticky;`; } return void 0; }; watch(loading, (newVal, oldVal) => { if (serverOptionsComputed.value) { if (newVal === false && oldVal === true) { updateCurrentPaginationNumber(serverOptionsComputed.value.page); clearExpandingItemIndexList(); } } }); watch(rowsPerPageRef, (value) => { if (!isServerSideMode.value) { updatePage(1); } else { updateServerOptionsRowsPerPage(value); } }); watch([searchValue, filterOptions], () => { if (!isServerSideMode.value) { updatePage(1); } }); watch([currentPaginationNumber, clientSortOptions, searchField, searchValue, filterOptions], () => { clearExpandingItemIndexList(); }, { deep: true }); watch(pageItems, (value) => { emits("updatePageItems", value); }, { deep: true }); watch(totalItems, (value) => { emits("updateTotalItems", value); }, { deep: true }); expose({ currentPageFirstIndex, currentPageLastIndex, clientItemsLength: totalItemsLength, maxPaginationNumber, currentPaginationNumber, isLastPage, isFirstPage, nextPage, prevPage, updatePage, rowsPerPageOptions: rowsItemsComputed, rowsPerPageActiveOption: rowsPerPageRef, updateRowsPerPageActiveOption: updateRowsPerPage }); return (_ctx, _cache) =