@progress/kendo-vue-grid
Version:
320 lines (319 loc) • 11.8 kB
JavaScript
/**
* @license
*-------------------------------------------------------------------------------------------
* Copyright © 2026 Progress Software Corporation. All rights reserved.
* Licensed under commercial license. See LICENSE.md in the package root for more information
*-------------------------------------------------------------------------------------------
*/
import { defineComponent as W, createVNode as r, isVNode as J, h as Q } from "vue";
import { normalize as X } from "../interfaces/GridSortSettings.mjs";
import { ColumnResizer as Y } from "../drag/ColumnResizer.mjs";
import { ColumnDraggable as Z } from "../drag/ColumnDraggable.mjs";
import { GridHeaderCell as ee } from "./GridHeaderCell.mjs";
import { ColumnMenu as te } from "../columnMenu/ColumnMenu.mjs";
import { noop as ne, templateRendering as le, getListeners as re, Keys as z, hasListener as oe, getTemplate as se, Icon as ie } from "@progress/kendo-vue-common";
import { HeaderThElement as ae } from "@progress/kendo-vue-data-tools";
import { resolveCells as ce } from "../utils/main.mjs";
import { sortableColumnAriaLabel as A, messages as H, sortableColumnAscendingAriaLabel as j, sortableColumnDescendingAriaLabel as w } from "../messages/main.mjs";
import { provideLocalizationService as de } from "@progress/kendo-vue-intl";
import { sortAscSmallIcon as ue, sortDescSmallIcon as pe } from "@progress/kendo-svg-icons";
import { getVirtualHeaderCellsToRender as he } from "../utils/virtualColumns.mjs";
function b(t) {
return typeof t == "function" || Object.prototype.toString.call(t) === "[object Object]" && !J(t);
}
const M = {
none: "none",
asc: "ascending",
desc: "descending"
}, fe = {
true: {
asc: "desc",
desc: "",
"": "asc"
},
false: {
asc: "desc",
desc: "asc",
"": "asc"
}
}, ze = /* @__PURE__ */ W({
name: "KendoHeaderRow",
props: {
grid: Object,
cellRender: [String, Function, Object],
cells: Object,
groupable: [Boolean, Object],
reorderable: Boolean,
sortable: [Boolean, Object],
sort: {
type: Array
},
filter: Object,
filterable: Boolean,
filterOperators: Object,
filterChange: Function,
filterRow: Object,
columns: Array,
cellsToRender: Array,
columnVirtualization: Boolean,
columnsMap: Array,
columnResize: Object,
columnMenu: [Boolean, String, Function, Object],
columnMenuAnimate: {
type: [Boolean, Object],
default: function() {
return !0;
}
},
columnMenuIcon: Object,
isRtl: Boolean,
isColCountDefined: Boolean,
headerSelectionValue: [Boolean, Array],
// columnsInitial prop:
// Needed for hidden column scenarios. By this value we can define correct aria-colindex attribute
columnsInitial: Array,
onSortChange: Function,
onFilterChange: Function,
onSelectionchange: Function,
onPressHandler: Function,
onDragHandler: Function,
onReleaseHandler: Function
},
inject: {
onNavFocus: {
default: ne
},
kendoLocalizationService: {
default: null
},
gridContext: {
default: null
}
},
data() {
return {
columnMenuOpened: {}
};
},
created() {
this.serviceIndex = 0, this.index = -1, this._element = null, this.cellClick = this.cellClick.bind(this);
},
methods: {
pressHandler(t, n) {
this.$emit("pressHandler", t, n);
},
dragHandler(t, n) {
this.$emit("dragHandler", t, n);
},
releaseHandler(t) {
this.$emit("releaseHandler", t);
},
selectionChangeHandler(t) {
this.$emit("selectionchange", t);
},
cellClick(t, n) {
if (t.preventDefault(), !oe.call(this, "sortChange"))
return;
const {
allowUnsort: o,
mode: i
} = X(this.$props.sortable || !1, n.sortable || !1), a = (this.$props.sort || []).filter((s) => s.field === n.field)[0], d = fe[o][a && a.dir || ""], u = i === "single" ? [] : (this.$props.sort || []).filter((s) => s.field !== n.field);
d !== "" && n.field && u.push({
field: n.field,
dir: d
}), this.sortChangeHandler(u, {
event: t,
field: n.field
});
},
sortChangeHandler(t, n) {
this.$emit("sortChange", t, n);
},
filterChangeHandler(t, n) {
this.$emit("filterChange", t, n);
},
cellClass(t, n, o) {
const i = n ? " " + n : "";
let a = "k-header" + (o ? " k-grid-header-sticky" : "") + i;
return this.$props.sort && this.$props.sort.filter((d) => d.field === t).length > 0 && (a += " k-sorted"), a;
},
cellKeyDown(t, n) {
t.defaultPrevented || (t.keyCode === z.enter && this.cellClick(t, n), t.altKey && t.keyCode === z.down && n.field && (t.preventDefault(), this.columnMenuOpened = {
[n.field]: !0
}));
},
getTemplate(t) {
return le.call(this.$props.grid, t, re.call(this.$props.grid));
},
columnMenuClose() {
this.onNavFocus({}), this.columnMenuOpened = {};
},
triggerContextMenu(t, n) {
var o, i;
(i = (o = this.gridContext) == null ? void 0 : o.onContextMenu) == null || i.call(o, t, void 0, n.field);
}
},
computed: {
element() {
return this._element;
},
theadClasses() {
return {
"k-table-thead": !0
};
}
},
render() {
const t = de(this), n = t.toLanguageString(A, H[A]), o = t.toLanguageString(j, H[j]), i = t.toLanguageString(w, H[w]);
this.serviceIndex = 0, this.index = -1;
const a = this.$props.columnVirtualization, d = function(u, s) {
const c = he({
cellsToRender: this.$props.cellsToRender || [],
columns: this.$props.columns,
rowIndex: s,
enableVirtualization: a,
columnsMap: this.$props.columnsMap
}), y = a;
let $ = y && c.columnsToRender ? c.columnsToRender : u;
const D = y ? c.colSpans : [];
return !$ || $.length === 0 ? [] : $.map(function(F, V) {
var x, I, L;
const e = this.$props.columns[F], m = this.$props.sortable && e.sortable, k = this.$props.sort ? this.$props.sort.findIndex((l) => l.field === e.field) : -1, S = k >= 0 && this.$props.sort[k].dir || "none", h = function(l) {
if (!this.$props.sort)
return null;
const C = l >= 0 ? this.$props.sort[l].dir : "";
return l >= 0 && [r("span", {
key: 1,
class: "k-sort-icon"
}, [r(ie, {
name: "sort-" + C + "-small",
icon: C === "asc" ? ue : pe
}, null)]), this.$props.sort.length > 1 && r("span", {
key: 2,
class: "k-sort-icon"
}, [r("span", {
class: "k-sort-order"
}, [l + 1])])];
}.call(this, k), p = e.columnMenu || e.columnMenu === !1 ? e.columnMenu : this.$props.columnMenu, v = e.menuIcon || this.$props.columnMenuIcon, T = (e.kFirst ? "k-first " : "") + this.cellClass(e.field, e.headerClassName, e.locked) + (p ? " k-filterable" : ""), B = !p || typeof p == "boolean" ? !!p : this.getTemplate(p), K = c.skipOffset ? {
borderLeftWidth: "1px"
} : void 0, P = e.locked && (e.left !== void 0 || e.right !== void 0) ? this.$props.isRtl ? {
left: e.right + "px",
right: e.left + "px"
} : {
left: e.left + "px",
right: e.right + "px"
} : K, N = M[S] === "none" ? n : M[S] === "ascending" ? o : i;
let f = e.isAccessible ? {
ariaSort: M[S],
ariaLabel: N,
role: "columnheader",
ariaColumnIndex: this.$props.isColCountDefined ? this.$props.columnsInitial.findIndex((l) => l.field === e.field) + 1 : void 0,
ariaSelected: !1,
ariaHaspopup: p ? "menu" : this.$props.filterable && e.filterable ? "dialog" : void 0
} : {
role: "columnheader"
};
const _ = e.declarationIndex >= 0 ? ++this.index : --this.serviceIndex, q = e.columnMenuOpened !== void 0 ? e.columnMenuOpened : this.columnMenuOpened[e.field], E = (x = D[V]) != null ? x : e.headerColSpan, R = ce(this.$props.cells, e.cells), O = {
ariaSort: m ? f.ariaSort : void 0,
ariaLabel: m ? f.ariaLabel : void 0,
role: f.role,
ariaColumnIndex: f.ariaColumnIndex,
ariaSelected: f.ariaSelected,
ariaHaspopup: f.ariaHaspopup,
key: _,
colSpan: E,
rowSpan: e.rowSpan,
class: T,
style: P,
columnId: e.id,
navigatable: e.navigatable,
onKeydown: (l) => this.cellKeyDown(l, e),
onContextmenu: (l) => this.triggerContextMenu(l, e)
}, g = [e.children.length === 0 && p && r(te, {
key: 0,
column: {
field: e.field,
filter: e.filter
},
opened: q,
animate: this.$props.columnMenuAnimate,
sortable: m,
sort: this.$props.sort,
onClose: this.columnMenuClose,
onSortchange: this.sortChangeHandler,
filter: this.$props.filter,
filterable: this.$props.filterable && e.filterable,
filterOperators: this.$props.filterOperators,
onFilterchange: this.filterChangeHandler,
render: B,
columnMenuIcon: v
}, null), e.defaultHeaderCell && r("span", {
class: "k-cell-inner"
}, [r(e.defaultHeaderCell, {
key: 1,
field: e.field,
sortable: m,
onHeadercellclick: (l) => this.cellClick(l, e),
onSelectionchange: this.selectionChangeHandler,
selectionValue: (I = e.headerSelectionValue) != null ? I : this.$props.headerSelectionValue,
title: e.title,
render: (e.headerCell || this.$props.cellRender) && this.getTemplate(e.headerCell || this.$props.cellRender)
}, b(h) ? h : {
default: () => [h]
})]) || r("span", {
class: "k-cell-inner"
}, [r(ee, {
key: 1,
field: e.field,
sortable: m,
onHeadercellclick: (l) => this.cellClick(l, e),
selectionValue: (L = e.headerSelectionValue) != null ? L : this.$props.headerSelectionValue,
title: e.title,
render: (e.headerCell || this.$props.cellRender) && this.getTemplate(e.headerCell || this.$props.cellRender)
}, b(h) ? h : {
default: () => [h]
})]), this.$props.columnResize && this.$props.columnResize.resizable && e.resizable && r(Y, {
key: 2,
onResize: (l, C, U) => this.$props.columnResize && this.$props.columnResize.dragHandler(l, e, C, U)
}, null)], G = r(ae, O, b(g) ? g : {
default: () => [g]
});
return se.call(this, {
h: Q,
template: R == null ? void 0 : R.headerCell,
defaultRendering: G,
additionalProps: {
field: e.field,
thProps: O
},
additionalListeners: {
contextmenu: (l) => this.triggerContextMenu(l, e)
},
defaultSlots: g
});
}, this);
};
return r("thead", {
role: "rowgroup",
class: this.theadClasses,
"data-keyboardnavheader": !0
}, [this.$props.columnsMap.map(function(u, s) {
let c;
return (this.$props.groupable || this.$props.reorderable) && r(Z, {
key: s,
onPressHandler: this.pressHandler,
onDragHandler: this.dragHandler,
onReleaseHandler: this.releaseHandler
}, b(c = d.call(this, u, s)) ? c : {
default: () => [c]
}) || r("tr", {
class: "k-table-row",
role: "row",
"aria-rowindex": s + 1
}, [d.call(this, u, s)]);
}, this), this.$props.filterRow]);
}
});
export {
ze as HeaderRow
};