@oruga-ui/oruga-next
Version:
UI components for Vue.js and CSS framework agnostic
1,175 lines • 65.1 kB
JavaScript
/*! Oruga v0.11.0 | MIT License | github.com/oruga-ui/oruga */
import { defineComponent, ref, computed, watch, createElementBlock, openBlock, normalizeClass, createVNode, withCtx, withDirectives, createCommentVNode, toDisplayString, vShow, Fragment, renderList, getCurrentInstance, unref, createTextVNode, mergeModels, useModel, createElementVNode, renderSlot, createBlock, mergeProps, useSlots, useTemplateRef, toValue, onMounted, nextTick, normalizeStyle, withKeys, withModifiers, toHandlerKey, TransitionGroup, toRaw, triggerRef } from "vue";
import { _ as _sfc_main$9 } from "./Checkbox.vue_vue_type_script_setup_true_lang-DeZ-dnZw.mjs";
import { _ as _sfc_main$7 } from "./Icon.vue_vue_type_script_setup_true_lang-C6IfOTXx.mjs";
import { _ as _sfc_main$a } from "./Input.vue_vue_type_script_setup_true_lang-BmEqNFiY.mjs";
import { _ as _sfc_main$b } from "./Loading.vue_vue_type_script_setup_true_lang-kC76qSMD.mjs";
import { O as OSlotComponent } from "./SlotComponent-CxyqJoRq.mjs";
import { _ as _sfc_main$6 } from "./Button.vue_vue_type_script_setup_true_lang-D_43seT-.mjs";
import { _ as _sfc_main$5 } from "./Select.vue_vue_type_script_setup_true_lang-DGfUwi7l.mjs";
import { _ as _sfc_main$4 } from "./Field.vue_vue_type_script_setup_true_lang-Dhoormb8.mjs";
import { d as defineClasses, g as getActiveClasses } from "./defineClasses-CWB9NuS-.mjs";
import { a as useProviderChild, u as useProviderParent } from "./useParentProvider-26MPTCZ6.mjs";
import { toCssDimension, getValueByPath, sortBy, getPropertyValue, isDefined, escapeRegExpChars, removeDiacriticsFromString } from "./helpers.mjs";
import { _ as _sfc_main$8 } from "./Pagination.vue_vue_type_script_setup_true_lang-C5hIVCp1.mjs";
import { g as getDefault, b as registerComponent } from "./config-Dl7tu_Ly.mjs";
import { u as useMatchMedia } from "./useMatchMedia-Go6cZv_b.mjs";
import { u as useDebounce } from "./useDebounce-CVLytXgm.mjs";
import { a as isOptionViable, f as filterOptionsItems } from "./useOptions-eabMIWNM.mjs";
import { u as useSequentialId } from "./useSequentialId-BpzOPIdj.mjs";
const _hoisted_1$2 = ["value"];
const _sfc_main$3 = /* @__PURE__ */ defineComponent({
...{
isOruga: true,
name: "OTableMobileSort",
configField: "table"
},
__name: "TableMobileSort",
props: {
currentSortColumn: {
type: Object,
default: void 0
},
columns: {
type: Array,
default: void 0
},
placeholder: { type: String, default: void 0 },
iconPack: { type: String, default: void 0 },
sortIcon: { type: String, default: "arrow-up" },
sortIconSize: { type: String, default: "small" },
isAsc: { type: Boolean, default: false },
mobileSortClasses: { type: Array, required: true }
},
emits: ["sort"],
setup(__props, { emit: __emit }) {
var _a;
const props = __props;
const emits = __emit;
const mobileSort = ref((_a = props.currentSortColumn) == null ? void 0 : _a.identifier);
const showPlaceholder = computed(
() => !props.columns || props.columns.every((column) => column.identifier !== mobileSort.value)
);
const sortableColumns = computed(
() => props.columns ? props.columns.filter((c) => c.sortable) : []
);
const isCurrentSort = computed(
() => {
var _a2;
return ((_a2 = props.currentSortColumn) == null ? void 0 : _a2.identifier) === mobileSort.value;
}
);
watch(mobileSort, (value) => {
var _a2;
if (((_a2 = props.currentSortColumn) == null ? void 0 : _a2.identifier) === value) return;
sort(new Event("sort"));
});
watch(
() => props.currentSortColumn,
(column) => {
mobileSort.value = column == null ? void 0 : column.identifier;
}
);
function sort(event) {
const column = sortableColumns.value.find(
(column2) => column2.identifier === mobileSort.value
);
if (!column) return;
emits("sort", column, event);
}
return (_ctx, _cache) => {
return openBlock(), createElementBlock("div", {
class: normalizeClass(__props.mobileSortClasses)
}, [
createVNode(_sfc_main$4, { addons: "" }, {
default: withCtx(() => [
createVNode(_sfc_main$5, {
modelValue: mobileSort.value,
"onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => mobileSort.value = $event),
expanded: ""
}, {
default: withCtx(() => [
__props.placeholder ? withDirectives((openBlock(), createElementBlock("option", {
key: 0,
value: {},
selected: "",
disabled: "",
hidden: ""
}, toDisplayString(__props.placeholder), 513)), [
[vShow, showPlaceholder.value]
]) : createCommentVNode("", true),
(openBlock(true), createElementBlock(Fragment, null, renderList(sortableColumns.value, (column, index2) => {
return openBlock(), createElementBlock("option", {
key: column.field || index2,
value: column.identifier
}, toDisplayString(column.label), 9, _hoisted_1$2);
}), 128))
]),
_: 1
}, 8, ["modelValue"]),
createVNode(_sfc_main$6, {
onClick: _cache[1] || (_cache[1] = ($event) => sort($event))
}, {
default: withCtx(() => [
withDirectives(createVNode(_sfc_main$7, {
icon: __props.sortIcon,
pack: __props.iconPack,
size: __props.sortIconSize,
rotation: !__props.isAsc ? 180 : 0
}, null, 8, ["icon", "pack", "size", "rotation"]), [
[vShow, isCurrentSort.value]
])
]),
_: 1
})
]),
_: 1
})
], 2);
};
}
});
const _hoisted_1$1 = ["data-id"];
const _sfc_main$2 = /* @__PURE__ */ defineComponent({
...{
isOruga: true,
name: "OTableColumn",
configField: "table"
},
__name: "TableColumn",
props: {
label: { default: void 0 },
field: { default: void 0 },
formatter: { type: Function, default: void 0 },
subheading: { default: void 0 },
width: { default: void 0 },
numeric: { type: Boolean, default: false },
position: { default: void 0 },
searchable: { type: Boolean, default: false },
sortable: { type: Boolean, default: false },
hidden: { type: Boolean, default: false },
sticky: { type: Boolean, default: false },
headerSelectable: { type: Boolean, default: false },
customSort: { type: Function, default: void 0 },
customSearch: { type: Function, default: void 0 },
thAttrs: { default: void 0 },
tdAttrs: { default: void 0 }
},
setup(__props) {
const props = __props;
const style = computed(() => ({
width: toCssDimension(props.width)
}));
const isHeaderUnselectable = computed(
() => !props.headerSelectable && props.sortable
);
const vm = getCurrentInstance();
const providedData = computed(() => ({
...props,
$el: vm.proxy,
$slots: vm.slots,
style: style.value,
thClasses: thClasses.value,
tdClasses: tdClasses.value
}));
const { parent, item } = useProviderChild({ data: providedData });
const thClasses = defineClasses(
[
"thCurrentSortClass",
"o-table__th-current-sort",
null,
computed(() => {
var _a;
return (_a = parent.value) == null ? void 0 : _a.isColumnSorted(item.value);
})
],
[
"thSortableClass",
"o-table__th--sortable",
null,
computed(() => props.sortable)
],
[
"thUnselectableClass",
"o-table__th--unselectable",
null,
isHeaderUnselectable
],
[
"thPositionClass",
"o-table__th--",
computed(() => props.position),
computed(() => !!props.position)
],
[
"thStickyClass",
"o-table__th--sticky",
null,
computed(() => props.sticky)
]
);
const tdClasses = defineClasses(
[
"tdPositionClass",
"o-table__td--",
computed(() => props.position),
computed(() => !!props.position)
],
[
"tdStickyClass",
"o-table__td--sticky",
null,
computed(() => props.sticky)
]
);
return (_ctx, _cache) => {
return openBlock(), createElementBlock("span", {
"data-oruga": "table-column",
"data-id": `table-${unref(item).identifier}`
}, [
createTextVNode(toDisplayString(_ctx.label) + " ", 1),
createCommentVNode("", true)
], 8, _hoisted_1$1);
};
}
});
const _sfc_main$1 = /* @__PURE__ */ defineComponent({
...{
isOruga: true,
name: "OTablePagination",
configField: "table",
inheritAttrs: false
},
__name: "TablePagination",
props: /* @__PURE__ */ mergeModels({
current: { type: Number, default: void 0 },
paginated: { type: Boolean, default: false },
rootClass: {
type: [String, Array, Object],
default: void 0
}
}, {
"current": {},
"currentModifiers": {}
}),
emits: /* @__PURE__ */ mergeModels(["update:current", "change"], ["update:current"]),
setup(__props, { emit: __emit }) {
const emits = __emit;
const currentPage = useModel(__props, "current");
function pageChanged(page) {
const newPage = page > 0 ? page : 1;
currentPage.value = newPage;
emits("change", newPage);
}
return (_ctx, _cache) => {
return openBlock(), createElementBlock("div", {
class: normalizeClass(__props.rootClass)
}, [
createElementVNode("div", null, [
renderSlot(_ctx.$slots, "default")
]),
createElementVNode("div", null, [
__props.paginated ? (openBlock(), createBlock(_sfc_main$8, mergeProps({ key: 0 }, _ctx.$attrs, {
current: currentPage.value,
onChange: pageChanged
}), null, 16, ["current"])) : createCommentVNode("", true)
])
], 2);
};
}
});
const _hoisted_1 = {
ref: "slotsWrapper",
style: { "display": "none" }
};
const _hoisted_2 = ["tabindex", "aria-rowcount", "aria-colcount"];
const _hoisted_3 = { key: 0 };
const _hoisted_4 = { key: 1 };
const _hoisted_5 = { "aria-rowindex": 1 };
const _hoisted_6 = ["aria-colindex"];
const _hoisted_7 = ["draggable", "aria-sort", "aria-colindex", "onClick", "onDragstart", "onDragend", "onDrop", "onDragover", "onDragleave"];
const _hoisted_8 = { key: 1 };
const _hoisted_9 = ["aria-hidden"];
const _hoisted_10 = ["aria-colindex"];
const _hoisted_11 = {
key: 0,
"aria-rowindex": 2
};
const _hoisted_12 = { key: 1 };
const _hoisted_13 = { key: 2 };
const _hoisted_14 = ["aria-rowindex"];
const _hoisted_15 = { key: 1 };
const _hoisted_16 = { key: 1 };
const _hoisted_17 = { key: 2 };
const _hoisted_18 = ["draggable", "aria-rowindex", "onClick", "onDblclick", "onMouseenter", "onMouseleave", "onContextmenu", "onDragstart", "onDragend", "onDrop", "onDragover", "onDragleave"];
const _hoisted_19 = ["colspan"];
const _hoisted_20 = ["colspan"];
const _hoisted_21 = { key: 2 };
const _hoisted_22 = ["colspan"];
const _sfc_main = /* @__PURE__ */ defineComponent({
...{
isOruga: true,
name: "OTable",
configField: "table",
inheritAttrs: false
},
__name: "Table",
props: /* @__PURE__ */ mergeModels({
override: { type: Boolean, default: void 0 },
data: { default: void 0 },
columns: { default: void 0 },
rowKey: { default: () => getDefault("table.rowKey") },
rowClass: { type: Function, default: getDefault("table.rowClass", () => "") },
thAttrs: { type: Function, default: void 0 },
tdAttrs: { type: Function, default: void 0 },
customCompare: { type: Function, default: void 0 },
bordered: { type: Boolean, default: () => getDefault("table.bordered", false) },
striped: { type: Boolean, default: () => getDefault("table.striped", false) },
narrowed: { type: Boolean, default: () => getDefault("table.narrowed", false) },
hoverable: { type: Boolean, default: () => getDefault("table.hoverable", false) },
selected: { default: void 0 },
selectable: { type: Boolean, default: () => getDefault("table.selectable", false) },
isRowSelectable: { type: Function, default: () => true },
showHeader: { type: Boolean, default: () => getDefault("table.showHeader", true) },
draggable: { type: Boolean, default: false },
draggableColumn: { type: Boolean, default: false },
scrollable: { type: Boolean, default: void 0 },
stickyHeader: { type: Boolean, default: false },
height: { default: void 0 },
checkable: { type: Boolean, default: false },
checkableHeader: { type: Boolean, default: true },
stickyCheckbox: { type: Boolean, default: false },
checkedRows: { default: () => [] },
checkboxPosition: { default: () => getDefault("table.checkboxPosition", "left") },
checkboxVariant: { default: () => getDefault("table.checkboxVariant") },
isRowChecked: { type: Function, default: void 0 },
isRowCheckable: { type: Function, default: getDefault("table.isRowCheckable", () => true) },
backendSorting: { type: Boolean, default: () => getDefault("table.backendSorting", false) },
defaultSort: { default: () => getDefault("table.defaultSort") },
defaultSortDirection: { default: () => getDefault("table.defaultSortDirection", "asc") },
sortIcon: { default: () => getDefault("table.sortIcon", "arrow-up") },
sortIconSize: { default: () => getDefault("table.sortIconSize", "small") },
iconPack: { default: () => getDefault("table.iconPack") },
detailed: { type: Boolean, default: false },
detailedRows: { default: () => [] },
isDetailedVisible: { type: Function, default: getDefault("table.isDetailedVisible", () => true) },
showDetailIcon: { type: Boolean, default: () => getDefault("table.showDetailIcon", true) },
detailIcon: { default: () => getDefault("table.detailIcon", "chevron-right") },
customDetailRow: { type: Boolean, default: false },
detailTransition: { default: () => getDefault("table.detailTransition", "slide") },
paginated: { type: Boolean, default: () => getDefault("table.paginated", false) },
backendPagination: { type: Boolean, default: false },
total: { default: 0 },
currentPage: { default: 1 },
perPage: { default: () => getDefault("table.perPage", 20) },
paginationPosition: { default: () => getDefault("table.paginationPosition", "bottom") },
paginationSize: { default: () => getDefault("table.paginationSize", "small") },
paginationRounded: { type: Boolean, default: () => getDefault("table.paginationRounded", false) },
paginationSimple: { type: Boolean, default: () => getDefault("table.paginationSimple", false) },
paginationRangeBefore: { default: void 0 },
paginationRangeAfter: { default: void 0 },
paginationOrder: { default: () => getDefault("table.paginationOrder") },
backendFiltering: { type: Boolean, default: () => getDefault("table.backendFiltering", false) },
filtersIcon: { default: () => getDefault("table.filterIcon") },
filtersPlaceholder: { default: () => getDefault("table.filterPlaceholder") },
filtersEvent: { default: "" },
filterDebounce: { default: () => getDefault("table.filterDebounce", 300) },
emptyLabel: { default: () => getDefault("table.emptyLabel") },
emptyIcon: { default: () => getDefault("table.emptyIcon") },
emptyIconSize: { default: () => getDefault("table.emptyIconSize") },
loading: { type: Boolean, default: false },
loadingIcon: { default: () => getDefault("table.loadingIcon", "loading") },
loadingLabel: { default: () => getDefault("table.loadingLabel") },
mobileBreakpoint: { default: () => getDefault("table.mobileBreakpoint") },
mobileCards: { type: Boolean, default: () => getDefault("table.mobileCards", true) },
mobileSortPlaceholder: { default: () => getDefault("table.mobileSortPlaceholder") },
ariaNextLabel: { default: () => getDefault("table.ariaNextLabel") },
ariaPreviousLabel: { default: () => getDefault("table.ariaPreviousLabel") },
ariaPageLabel: { default: () => getDefault("table.ariaPageLabel") },
ariaCurrentLabel: { default: () => getDefault("table.ariaCurrentLabel") },
rootClass: {},
mobileClass: {},
mobileSortClass: {},
wrapperClass: {},
stickyHeaderClass: {},
scrollableClass: {},
tableClass: {},
borderedClass: {},
stripedClass: {},
narrowedClass: {},
hoverableClass: {},
emptyClass: {},
thClass: {},
thPositionClass: {},
thCheckboxClass: {},
thStickyClass: {},
thDetailedClass: {},
thSortableClass: {},
thSortIconClass: {},
thCurrentSortClass: {},
thUnselectableClass: {},
thSubheadingClass: {},
trSelectedClass: {},
trCheckedClass: {},
trDetailedClass: {},
trEmptyClass: {},
tdClass: {},
tdPositionClass: {},
tdStickyClass: {},
tdCheckboxClass: {},
tdDetailedChevronClass: {},
paginationWrapperClass: {},
footerClass: {},
loadingClasses: {}
}, {
"currentPage": { default: 1 },
"currentPageModifiers": {},
"selected": { default: void 0 },
"selectedModifiers": {},
"checkedRows": {
default: []
},
"checkedRowsModifiers": {},
"detailedRows": {
default: []
},
"detailedRowsModifiers": {}
}),
emits: /* @__PURE__ */ mergeModels(["update:currentPage", "page-change", "update:selected", "select", "check", "check-all", "update:checkedRows", "sort", "filters-change", "filters-event", "update:detailedRows", "details-open", "details-close", "click", "dblclick", "contextmenu", "mouseenter", "mouseleave", "cell-click", "dragstart", "dragend", "drop", "dragleave", "dragover", "columndragstart", "columndragend", "columndrop", "columndragleave", "columndragover"], ["update:currentPage", "update:selected", "update:checkedRows", "update:detailedRows"]),
setup(__props, { expose: __expose, emit: __emit }) {
const props = __props;
const emits = __emit;
const slots = useSlots();
const { isMobile } = useMatchMedia(props.mobileBreakpoint);
const isMobileActive = computed(() => props.mobileCards && isMobile.value);
const slotsRef = useTemplateRef("slotsWrapper");
const provideData = computed(() => ({
isColumnSorted
}));
const { childItems } = useProviderParent({
rootRef: slotsRef,
data: provideData
});
const tableColumns = computed(() => {
if (!childItems.value.length) return [];
return childItems.value.map((columnItem) => {
const column = toValue(columnItem.data);
let thAttrsData = typeof props.thAttrs === "function" ? props.thAttrs(column) : {};
thAttrsData = Object.assign(thAttrsData, column.thAttrs);
const tdAttrsData = (props.data ?? []).map((data) => {
const tdAttrs = typeof props.tdAttrs === "function" ? props.tdAttrs(data, column) : {};
return Object.assign(tdAttrs, column.tdAttrs);
});
return {
...column,
value: column,
index: columnItem.index,
identifier: columnItem.identifier,
thAttrsData,
tdAttrsData
};
});
});
const columnCount = computed(() => {
let i = tableColumns.value.length;
if (showDetailRowIcon.value) i++;
if (props.checkable) i++;
return i;
});
const ariaColIndexStart = computed(() => {
let i = 1;
if (showDetailRowIcon.value) i++;
if (props.checkable && props.checkboxPosition === "left") i++;
return i;
});
const hasSubheadings = computed(() => {
if (slots.subheading) return true;
return tableColumns.value.some((column) => !!column.subheading);
});
const isScrollable = computed(() => {
if (props.scrollable) return true;
return tableColumns.value.some((column) => column.sticky);
});
const tableCurrentPage = useModel(__props, "currentPage");
watch(
[
tableCurrentPage,
() => props.perPage,
() => props.data,
() => props.paginated
],
() => filterTableRows()
);
const { nextSequence } = useSequentialId();
const tableRows = computed(() => {
if (!props.data) return [];
return props.data.map((value, idx) => ({
label: "row " + idx,
// row display label
value: toValue(value),
// normalizes wrapped ref values
index: idx,
// row index
key: (
// if no key is given and data is object, create unique row id for each row
String(getValueByPath(value, props.rowKey) || nextSequence())
)
}));
});
const availableRows = computed(
() => tableRows.value.filter(isOptionViable)
);
function filterTableRows() {
const currentPage = tableCurrentPage.value;
const perPage = Number(props.perPage);
const pageStart = (currentPage - 1) * perPage;
const pageEnd = pageStart + perPage;
filterOptionsItems(tableRows, (row, idx) => {
if (props.paginated && !props.backendPagination) {
if (tableRows.value.length > perPage && (idx < pageStart || idx >= pageEnd))
return true;
}
if (!props.backendFiltering)
return !isRowFiltered(row.value);
return false;
});
}
const tableTotal = computed(
() => props.backendPagination ? props.total : tableRows.value.length
);
const rowCount = computed(() => {
return tableTotal.value + ariaRowIndexStart.value;
});
const ariaRowIndexStart = computed(() => {
let i = 1;
if (hasSearchableColumns.value) i++;
if (hasSubheadings.value) i++;
return i;
});
function hasCustomFooterSlot() {
if (!slots.footer) return false;
const footer = slots.footer({
columnCount: columnCount.value,
rowCount: rowCount.value
});
if (footer.length > 1) return true;
const tag = footer[0]["type"];
return tag === "th" || tag === "td";
}
function getColumnValue(row, column) {
return getPropertyValue(row, column.field, column.formatter);
}
function isRowEqual(sourceRow, targetRow) {
const el1 = toRaw(toValue(sourceRow));
const el2 = toRaw(toValue(targetRow));
if (!isDefined(targetRow)) return false;
if (typeof props.customCompare === "function")
return props.customCompare(el1, el2);
if (props.rowKey)
return getPropertyValue(el1, props.rowKey) == getPropertyValue(el2, props.rowKey);
return el1 == el2;
}
const tableSelectedRow = useModel(__props, "selected");
function onArrowPressed(delta, event) {
if (!availableRows.value.length) return;
let index2 = availableRows.value.findIndex(
(row2) => isRowEqual(row2.value, tableSelectedRow.value)
) + delta;
index2 = index2 > availableRows.value.length - 1 ? availableRows.value.length - 1 : index2;
index2 = index2 < 0 ? 0 : index2;
const row = availableRows.value[index2];
if (!props.isRowSelectable(row.value)) {
let newIndex;
if (delta > 0) {
for (let i = index2; i < availableRows.value.length && newIndex === void 0; i++) {
if (props.isRowSelectable(availableRows.value[i].value))
newIndex = i;
}
} else {
for (let i = index2; i >= 0 && newIndex === void 0; i--) {
if (props.isRowSelectable(availableRows.value[i].value))
newIndex = i;
}
}
if (newIndex != void 0 && newIndex >= 0)
selectRow(availableRows.value[newIndex], event);
} else {
selectRow(row, event);
}
}
function selectRow(row, event) {
emits("click", row.value, row.index, event);
if (!props.selectable) return;
if (isRowEqual(tableSelectedRow, row.value)) return;
if (!props.isRowSelectable(row.value)) return;
tableSelectedRow.value = row.value;
emits("select", row.value, tableSelectedRow.value);
}
const filters = ref({});
const hasSearchableColumns = computed(
() => tableColumns.value.some((column) => column.searchable)
);
let debouncedFilter;
watch(
() => props.filterDebounce,
(debounce) => debouncedFilter = useDebounce(handleFiltersChange, debounce || 0),
{ immediate: true }
);
watch(filters, (value) => debouncedFilter(value), { deep: true });
function handleFiltersChange(value) {
emits("filters-change", value);
if (!props.backendFiltering) {
filterTableRows();
triggerRef(tableRows);
}
}
function onFiltersEvent(event) {
emits("filters-event", props.filtersEvent, filters.value, event);
}
function isRowFiltered(row) {
if (!Object.values(filters.value).filter(Boolean).length) return true;
return Object.entries(filters.value).some(([key, filter]) => {
if (!filter) return false;
const column = tableColumns.value.find((c) => c.field === key);
if (typeof (column == null ? void 0 : column.customSearch) === "function")
return column.customSearch(row, filter);
const value = typeof row === "object" && !!row ? getValueByPath(row, key) : row;
if (value == null) return false;
if (Number.isInteger(value)) return value === Number(filter);
const re = new RegExp(escapeRegExpChars(filter), "i");
if (Array.isArray(value))
return value.some(
(val) => re.test(removeDiacriticsFromString(val)) || re.test(val)
);
if (typeof value !== "string") return !!value;
return re.test(removeDiacriticsFromString(value)) || re.test(value);
});
}
const currentSortColumn = ref();
const isAsc = ref(true);
const hasSortableColumns = computed(
() => tableColumns.value.some((column) => column.sortable)
);
function isColumnSorted(column) {
var _a;
return ((_a = currentSortColumn.value) == null ? void 0 : _a.identifier) === column.identifier;
}
onMounted(() => nextTick(() => initSort()));
function initSort() {
if (!tableColumns.value.length || currentSortColumn.value) return;
if (!props.defaultSort) return;
let sortField = "";
let sortDirection = props.defaultSortDirection;
if (Array.isArray(props.defaultSort)) {
sortField = props.defaultSort[0];
if (props.defaultSort[1]) sortDirection = props.defaultSort[1];
} else {
sortField = props.defaultSort;
}
sortByField(sortField, sortDirection);
}
function sortByField(field, direction) {
const sortColumn = tableColumns.value.find(
(column) => column.field === field
);
if (sortColumn) {
isAsc.value = direction.toLowerCase() === "asc";
sort(sortColumn);
}
}
function sort(column, updateDirection = false, event) {
if (!(column == null ? void 0 : column.sortable)) return;
if (updateDirection)
isAsc.value = isColumnSorted(column) ? !isAsc.value : props.defaultSortDirection.toLowerCase() === "asc";
if (currentSortColumn.value)
emits(
"sort",
column,
isAsc.value ? "asc" : "desc",
event || new Event("sort")
);
currentSortColumn.value = column;
if (!props.backendSorting) {
sortByColumn(tableRows.value);
filterTableRows();
}
}
function sortByColumn(rows) {
const column = currentSortColumn.value;
if (!column) return rows;
return sortBy(
rows,
(column == null ? void 0 : column.field) ? "value." + column.field : "",
(column == null ? void 0 : column.customSort) ? (a, b, asc) => column.customSort(a.value, b.value, asc) : void 0,
isAsc.value,
true
);
}
const tableCheckedRows = useModel(__props, "checkedRows");
const isAllChecked = computed(() => {
const validVisibleData = availableRows.value.filter(
(row) => props.isRowCheckable(row.value)
);
if (validVisibleData.length === 0) return false;
return validVisibleData.every(
(currentVisibleRow) => isChecked(currentVisibleRow)
);
});
const isAllUncheckable = computed(
() => !availableRows.value.some((row) => props.isRowCheckable(row.value))
);
function isChecked(row) {
if (typeof props.isRowChecked === "function")
return props.isRowChecked(row.value);
else return tableCheckedRows.value.some((r) => isRowEqual(r, row.value));
}
function addCheckedRow(row) {
tableCheckedRows.value = [...tableCheckedRows.value, row.value];
}
function removeCheckedRow(row) {
const idx = tableCheckedRows.value.findIndex(
(r) => isRowEqual(r, row.value)
);
if (idx >= 0)
tableCheckedRows.value = tableCheckedRows.value.toSpliced(idx, 1);
}
function checkAll() {
if (isAllChecked.value)
tableCheckedRows.value = [];
else {
tableCheckedRows.value = availableRows.value.filter((row) => props.isRowCheckable(row.value)).map((row) => row.value);
}
nextTick(() => emits("check-all", tableCheckedRows.value));
}
function checkRow(row) {
if (!props.isRowCheckable(row.value)) return;
if (isChecked(row)) removeCheckedRow(row);
else addCheckedRow(row);
nextTick(() => emits("check", tableCheckedRows.value, row.value));
}
const visibleDetailedRows = useModel(__props, "detailedRows");
const showDetailRowIcon = computed(
() => props.detailed && props.showDetailIcon
);
function toggleDetails(row) {
if (isDetailRowVisible(row)) {
closeDetailRow(row);
emits("details-close", row.value);
} else {
openDetailRow(row);
emits("details-open", row.value);
}
}
function openDetailRow(row) {
visibleDetailedRows.value = [...visibleDetailedRows.value, row.value];
}
function closeDetailRow(row) {
const idx = visibleDetailedRows.value.findIndex(
(r) => isRowEqual(r, row.value)
);
if (idx >= 0)
visibleDetailedRows.value = visibleDetailedRows.value.toSpliced(idx, 1);
}
function isDetailRowVisible(row) {
return props.detailed && visibleDetailedRows.value.some((r) => isRowEqual(r, row.value));
}
const isDraggingRow = ref(false);
const isDraggingColumn = ref(false);
const canDragRow = computed(() => props.draggable && !isDraggingColumn.value);
const canDragColumn = computed(
() => props.draggableColumn && !isDraggingRow.value
);
function handleDragStart(row, event) {
if (!props.draggable) return;
emits("dragstart", row.value, row.index, event);
}
function handleDragEnd(row, event) {
if (!props.draggable) return;
emits("dragend", row.value, row.index, event);
}
function handleDrop(row, event) {
if (!props.draggable) return;
emits("drop", row.value, row.index, event);
}
function handleDragOver(row, event) {
if (!props.draggable) return;
emits("dragover", row.value, row.index, event);
}
function handleDragLeave(row, event) {
if (!props.draggable) return;
emits("dragleave", row.value, row.index, event);
}
function handleColumnDragStart(column, event) {
if (!canDragColumn.value) return;
isDraggingColumn.value = true;
emits("columndragstart", column.value, column.index, event);
}
function handleColumnDragEnd(column, event) {
if (!canDragColumn.value) return;
isDraggingColumn.value = false;
emits("columndragend", column.value, column.index, event);
}
function handleColumnDrop(column, event) {
if (!canDragColumn.value) return;
emits("columndrop", column.value, column.index, event);
}
function handleColumnDragOver(column, event) {
if (!canDragColumn.value) return;
emits("columndragover", column.value, column.index, event);
}
function handleColumnDragLeave(column, event) {
if (!canDragColumn.value) return;
emits("columndragleave", column.value, column.index, event);
}
const rootClasses = defineClasses(
["rootClass", "o-table__root"],
["mobileClass", "o-table__root--mobile", null, isMobileActive]
);
const tableWrapperClasses = defineClasses(
["wrapperClass", "o-table__wrapper"],
[
"stickyHeaderClass",
"o-table__wrapper--sticky-header",
null,
computed(() => props.stickyHeader)
],
["scrollableClass", "o-table__wrapper--scrollable", null, isScrollable],
["mobileClass", "o-table__wrapper--mobile", null, isMobileActive]
);
const tableWrapperStyle = computed(() => ({
height: toCssDimension(props.height)
}));
const tableClasses = defineClasses(
["tableClass", "o-table"],
[
"borderedClass",
"o-table--bordered",
null,
computed(() => props.bordered)
],
["stripedClass", "o-table--striped", null, computed(() => props.striped)],
[
"narrowedClass",
"o-table--narrowed",
null,
computed(() => props.narrowed)
],
[
"hoverableClass",
"o-table--hoverable",
null,
computed(
() => (props.hoverable || props.selectable) && !!availableRows.value.length
)
],
[
"emptyClass",
"o-table--empty",
null,
computed(() => !availableRows.value.length)
]
);
const thBaseClasses = defineClasses(["thClass", "o-table__th"]);
const thCheckboxClasses = defineClasses(
["thCheckboxClass", "o-table__th-checkbox"],
[
"thStickyClass",
"o-table__th--sticky",
null,
computed(() => props.stickyCheckbox)
]
);
const thDetailedClasses = defineClasses([
"thDetailedClass",
"o-table__th-detailed"
]);
const thSubheadingClasses = defineClasses([
"thSubheadingClass",
"o-table__th-subheading"
]);
const thSortIconClasses = defineClasses([
"thSortIconClass",
"o-table__th__sort-icon"
]);
const trSelectedClasses = defineClasses([
"trSelectedClass",
"o-table__tr--selected"
]);
const trCheckedClasses = defineClasses([
"trCheckedClass",
"o-table__tr--checked"
]);
const trEmptyClasses = defineClasses(["trEmptyClass", "o-table__tr-empty"]);
const trDetailedClasses = defineClasses([
"trDetailedClass",
"o-table__tr-detail"
]);
const tdBaseClasses = defineClasses(["tdClass", "o-table__td"]);
const tdCheckboxClasses = defineClasses(
["tdCheckboxClass", "o-table__td-checkbox"],
[
"thStickyClass",
"o-table__th--sticky",
null,
computed(() => props.stickyCheckbox)
]
);
const tdDetailedChevronClasses = defineClasses([
"tdDetailedChevronClass",
"o-table__td-chevron"
]);
const footerClasses = defineClasses(["footerClass", "o-table__footer"]);
const mobileSortClasses = defineClasses([
"mobileSortClass",
"o-table__mobile-sort"
]);
const paginationWrapperClasses = defineClasses([
"paginationWrapperClass",
"o-table__pagination"
]);
const paginationWrapperRootClasses = computed(
() => getActiveClasses(paginationWrapperClasses)
);
function rowClasses(row) {
const selectedClasses = isRowEqual(row.value, tableSelectedRow.value) ? trSelectedClasses.value : [];
const checkedClasses = isChecked(row) ? trCheckedClasses.value : [];
const rowClass = typeof props.rowClass === "function" ? props.rowClass(row.value, row.index) || "" : "";
return [...selectedClasses, ...checkedClasses, { [rowClass]: true }];
}
filterTableRows();
__expose({ rows: tableRows, sort: sortByField });
return (_ctx, _cache) => {
return openBlock(), createElementBlock("div", {
"data-oruga": "table",
class: normalizeClass(unref(rootClasses))
}, [
createElementVNode("div", _hoisted_1, [
renderSlot(_ctx.$slots, "default", {}, () => {
var _a;
return [
renderSlot(_ctx.$slots, "before"),
((_a = _ctx.columns) == null ? void 0 : _a.length) ? (openBlock(true), createElementBlock(Fragment, { key: 0 }, renderList(_ctx.columns, (column, idx) => {
return openBlock(), createBlock(_sfc_main$2, mergeProps({
key: column.field || idx,
ref_for: true
}, column), {
default: withCtx(({ row }) => [
createTextVNode(toDisplayString(getColumnValue(row, column)), 1)
]),
_: 2
}, 1040);
}), 128)) : createCommentVNode("", true),
renderSlot(_ctx.$slots, "after")
];
})
], 512),
isMobileActive.value && hasSortableColumns.value ? (openBlock(), createBlock(_sfc_main$3, {
key: 0,
"current-sort-column": currentSortColumn.value,
columns: tableColumns.value,
placeholder: _ctx.mobileSortPlaceholder,
"icon-pack": _ctx.iconPack,
"sort-icon": _ctx.sortIcon,
"sort-icon-size": _ctx.sortIconSize,
"is-asc": isAsc.value,
"mobile-sort-classes": unref(mobileSortClasses),
onSort: _cache[0] || (_cache[0] = (column, event) => sort(column, true, event))
}, null, 8, ["current-sort-column", "columns", "placeholder", "icon-pack", "sort-icon", "sort-icon-size", "is-asc", "mobile-sort-classes"])) : createCommentVNode("", true),
_ctx.paginated && (_ctx.paginationPosition === "top" || _ctx.paginationPosition === "both") ? renderSlot(_ctx.$slots, "pagination", {
key: 1,
current: tableCurrentPage.value,
perPage: _ctx.perPage,
total: tableTotal.value,
change: (page) => tableCurrentPage.value = page
}, () => [
createVNode(_sfc_main$1, {
current: tableCurrentPage.value,
"onUpdate:current": _cache[1] || (_cache[1] = ($event) => tableCurrentPage.value = $event),
paginated: _ctx.paginated,
"per-page": _ctx.perPage,
total: tableTotal.value,
rounded: _ctx.paginationRounded,
size: _ctx.paginationSize,
order: _ctx.paginationOrder,
simple: _ctx.paginationSimple,
"range-before": _ctx.paginationRangeBefore,
"range-after": _ctx.paginationRangeAfter,
"icon-pack": _ctx.iconPack,
"aria-next-label": _ctx.ariaNextLabel,
"aria-previous-label": _ctx.ariaPreviousLabel,
"aria-page-label": _ctx.ariaPageLabel,
"aria-current-label": _ctx.ariaCurrentLabel,
"root-class": paginationWrapperRootClasses.value,
onChange: _cache[2] || (_cache[2] = (page) => _ctx.$emit("page-change", page))
}, {
default: withCtx(() => [
renderSlot(_ctx.$slots, "top-left")
]),
_: 3
}, 8, ["current", "paginated", "per-page", "total", "rounded", "size", "order", "simple", "range-before", "range-after", "icon-pack", "aria-next-label", "aria-previous-label", "aria-page-label", "aria-current-label", "root-class"])
]) : createCommentVNode("", true),
createElementVNode("div", {
class: normalizeClass(unref(tableWrapperClasses)),
style: normalizeStyle(tableWrapperStyle.value)
}, [
tableColumns.value.length ? (openBlock(), createElementBlock("table", mergeProps({ key: 0 }, _ctx.$attrs, {
class: unref(tableClasses),
tabindex: _ctx.selectable || isScrollable.value ? 0 : void 0,
"aria-rowcount": rowCount.value,
"aria-colcount": columnCount.value,
onKeydown: [
_cache[3] || (_cache[3] = withKeys(withModifiers(($event) => onArrowPressed(-1, $event), ["prevent"]), ["up"])),
_cache[4] || (_cache[4] = withKeys(withModifiers(($event) => onArrowPressed(1, $event), ["prevent"]), ["down"])),
_cache[5] || (_cache[5] = withKeys(withModifiers(($event) => selectRow(availableRows.value[0], $event), ["prevent"]), ["home"])),
_cache[6] || (_cache[6] = withKeys(withModifiers(($event) => selectRow(availableRows.value[availableRows.value.length - 1], $event), ["prevent"]), ["end"]))
]
}), [
_ctx.$slots.caption ? (openBlock(), createElementBlock("caption", _hoisted_3, [
renderSlot(_ctx.$slots, "caption")
])) : createCommentVNode("", true),
_ctx.showHeader ? (openBlock(), createElementBlock("thead", _hoisted_4, [
renderSlot(_ctx.$slots, "preheader"),
createElementVNode("tr", _hoisted_5, [
showDetailRowIcon.value ? (openBlock(), createElementBlock("th", {
key: 0,
class: normalizeClass([...unref(thBaseClasses), ...unref(thDetailedClasses)]),
"aria-colindex": 1,
"aria-hidden": "true"
}, null, 2)) : createCommentVNode("", true),
_ctx.checkable && _ctx.checkboxPosition === "left" ? (openBlock(), createElementBlock("th", {
key: 1,
class: normalizeClass([...unref(thBaseClasses), ...unref(thCheckboxClasses)]),
"aria-colindex": showDetailRowIcon.value ? 2 : 1
}, [
_ctx.checkableHeader ? renderSlot(_ctx.$slots, "check-all", {
key: 0,
isAllChecked: isAllChecked.value,
isAllUncheckable: isAllUncheckable.value,
checkAll
}, () => [
createVNode(_sfc_main$9, {
"model-value": isAllChecked.value,
autocomplete: "off",
name: "row_check_all",
variant: _ctx.checkboxVariant,
disabled: isAllUncheckable.value,
"aria-label": "Check all",
"onUpdate:modelValue": checkAll
}, null, 8, ["model-value", "variant", "disabled"])
]) : createCommentVNode("", true)
], 10, _hoisted_6)) : createCommentVNode("", true),
(openBlock(true), createElementBlock(Fragment, null, renderList(tableColumns.value, (column) => {
var _a;
return openBlock(), createElementBlock(Fragment, {
key: column.identifier
}, [
!column.hidden ? (openBlock(), createElementBlock("th", mergeProps({
key: 0,
ref_for: true
}, column.thAttrsData, {
class: [...unref(thBaseClasses), ...column.thClasses],
style: isMobileActive.value ? {} : column.style,
draggable: canDragColumn.value,
"aria-sort": isColumnSorted(column) ? isAsc.value ? "ascending" : "descending" : void 0,
"aria-colindex": ariaColIndexStart.value + column.index,
onClick: withModifiers(($event) => sort(column, true, $event), ["stop"]),
onDragstart: ($event) => handleColumnDragStart(column, $event),
onDragend: ($event) => handleColumnDragEnd(column, $event),
onDrop: ($event) => handleColumnDrop(column, $event),
onDragover: ($event) => handleColumnDragOver(column, $event),
onDragleave: ($event) => handleColumnDragLeave(column, $event)
}), [
((_a = column.$slots) == null ? void 0 : _a.header) ? (openBlock(), createBlock(unref(OSlotComponent), {
key: 0,
component: column.$el,
name: "header",
tag: "span",
props: {
column: column.value,
index: column.index
}
}, null, 8, ["component", "props"])) : (openBlock(), createElementBlock("span", _hoisted_8, [
createTextVNode(toDisplayString(column.label) + " ", 1),
column.sortable ? withDirectives((openBlock(), createElementBlock("span", {
key: 0,
class: normalizeClass(unref(thSortIconClasses)),
"aria-hidden": !isColumnSorted(column)
}, [
createVNode(_sfc_main$7, {
icon: _ctx.sortIcon,
pack: _ctx.iconPack,
size: _ctx.sortIconSize,
rotation: !isAsc.value ? 180 : 0
}, null, 8, ["icon", "pack", "size", "rotation"])
], 10, _hoisted_9)), [
[vShow, isColumnSorted(column)]
]) : createCommentVNode("", true)
]))
], 16, _hoisted_7)) : createCommentVNode("", true)
], 64);
}), 128)),
_ctx.checkable && _ctx.checkboxPosition === "right" ? (openBlock(), createElementBlock("th", {
key: 2,
class: normalizeClass([...unref(thBaseClasses), ...unref(thCheckboxClasses)]),
"aria-colindex": ariaColIndexStart.value + tableColumns.value.length
}, [
_ctx.checkableHeader ? renderSlot(_ctx.$slots, "check-all", {
key: 0,
isAllChecked: isAllChecked.value,
isAllUncheckable: isAllUncheckable.value,
checkAll
}, () => [
createVNode(_sfc_main$9, {
"model-value": isAllChecked.value,
autocomplete: "off",
name: "row_check_all",
variant: _ctx.checkboxVariant,
disabled: isAllUncheckable.value,
"aria-label": "Check all",
"onUpdate:modelValue": checkAll
}, null, 8, ["model-value", "variant", "disabled"])
]) : createCommentVNode("", true)
], 10, _hoisted_10)) : createCommentVNode("", true)
]),
hasSearchableColumns.value ? (openBlock(), createElementBlock("tr", _hoisted_11, [
showDetailRowIcon.value ? (openBlock(), createElementBlock("th", {
key: 0,
class: normalizeClass([...unref(thBaseClasses), ...unref(thDetailedClasses)]),
"aria-hidden": "true"
}, null, 2)) : createCommentVNode("", true),
_ctx.checkable && _ctx.checkboxPosition === "left" ? (openBlock(), createElementBlock("th", _hoisted_12)) : createCommentVNode("", true),
(openBlock(true), createElementBlock(Fragment, null, renderList(tableColumns.value, (column) => {
var _a;
return openBlock(), createElementBlock(Fragment, {
key: column.identifier
}, [
!column.hidden ? (openBlock(), createElementBlock("th", mergeProps({
key: 0,
ref_for: true
}, column.thAttrsData, {
class: [...unref(thBaseClasses), ...column.thClasses],
style: isMobileActive.value ? {} : column.style
}), [
column.searchable ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [
((_a = column.$slots) == null ? void 0 : _a.searchable) ? (openBlock(), createBlock(unref(OSlotComponent), {
key: 0,
component: column.$el,
name: "searchable",
tag: "span",
props: {
column: column.value,
index: column.index,
filters: filters.value
}
}, null, 8, ["component", "props"])) : column.field ? (openBlock(), createBlock(_sfc_main$a, mergeProps({
key: 1,
modelValue: filters.value[column.field],
"onUpdate:modelValue": ($event) => filters.value[column.field] = $event,
name: `column_${column.field}_filter`,
type: column.numeric ? "number" : "search",
placeholder: _ctx.filtersPlaceholder,
icon: _ctx.filtersIcon,
pack: _ctx.iconPack,
size: "small",
"aria-label": `${column.label} search`
}, { [toHandlerKey(_ctx.filtersEvent)]: onFiltersEvent }), null, 16, ["modelValue", "onUpdate:modelValue", "name", "type", "placeholder", "icon", "pack", "ar