@progress/kendo-react-grid
Version:
React Data Grid (Table) provides 100+ ready-to-use data grid features. KendoReact Grid package
464 lines (463 loc) • 14.5 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
*-------------------------------------------------------------------------------------------
*/
"use client";
import * as n from "react";
import { classNames as W } from "@progress/kendo-react-common";
import { GridStackedCell as oe } from "./GridStackedCell.mjs";
import { GridStackedDetailToggle as Te } from "./GridStackedDetailToggle.mjs";
import { GridEditCellEditor as we } from "../cells/editcell/GridEditCellEditor.mjs";
import { GridContext as ve } from "../utils/GridContext.mjs";
import { tableKeyboardNavigationTools as P, editReducer as X, EDIT_ACTION as z, handleStackedKeyboardNavigation as De } from "@progress/kendo-react-data-tools";
import { useGridState as Ce } from "../GridState.mjs";
const Se = (o) => /* @__PURE__ */ n.createElement("div", { style: { display: "contents" } }, o.children), Re = (o) => {
if (o != null && o.cols && typeof o.cols != "number")
return o.cols.map((a) => typeof a == "number" ? `${a}px` : typeof a == "string" ? a : a && typeof a == "object" && a.width !== void 0 ? typeof a.width == "number" ? `${a.width}px` : a.width : "1fr").join(" ");
}, Ne = (o) => o != null && o.cols ? typeof o.cols == "number" ? o.cols : o.cols.length : 1, C = (o) => typeof o == "function" || typeof o == "object" && o !== null && typeof o.$$typeof == "symbol", Fe = (o, a) => {
var I, u;
if (o.cell && C(o.cell))
return o.cell;
if ((I = o.cells) != null && I.stackedData && C(o.cells.stackedData))
return o.cells.stackedData;
if (a != null && a.stackedData && C(a.stackedData))
return a.stackedData;
if ((u = o.cells) != null && u.data && C(o.cells.data))
return o.cells.data;
if (a != null && a.data && C(a.data))
return a.data;
}, ge = (o, a) => {
if (!o || !a)
return;
const I = o.split(".");
let u = a;
for (const f of I) {
if (u == null)
return;
u = u[f];
}
return u;
}, Pe = (o) => {
const {
dataItem: a,
columns: I,
stackedLayoutSettings: u,
dataIndex: f,
isAltRow: Y,
isSelected: x,
isInEdit: w,
editMode: k,
cells: q,
idPrefix: L,
className: J,
style: V,
ariaRowIndex: re,
absoluteRowIndex: S,
groupLevel: Q = 0,
preparedCells: K,
showDetailToggle: ce,
isDetailExpanded: ie,
detailExpandField: ue
} = o, t = n.useContext(ve), [A, , y] = Ce(), j = n.useMemo(
() => Re(u),
[u]
), M = n.useMemo(() => Ne(u), [u]), [Z, R] = n.useState(!1), N = n.useRef(null), v = n.useRef(null), G = n.useRef(/* @__PURE__ */ new Map()), O = n.useRef(!1);
n.useLayoutEffect(() => {
if (!w || k !== "inline") {
O.current = !1, G.current.clear();
return;
}
O.current || (O.current = !0, v.current = 0, setTimeout(() => {
const e = N.current;
if (!e || e.contains(document.activeElement))
return;
const l = e.querySelector('[data-grid-col-index="0"]'), c = (l ? P.getStackedCellFocusableElements(l) : [])[0];
if (c) {
c.focus();
return;
}
const s = P.getStackedCellFocusableElements(e);
s[0] && s[0].focus();
}, 0));
}, [w, k]), n.useEffect(() => {
const e = (r) => {
const c = N.current;
setTimeout(() => {
const s = document.activeElement;
c && !c.contains(s) && R(!1);
}, 0);
}, l = N.current;
if (l)
return l.addEventListener("focusout", e), () => {
l.removeEventListener("focusout", e);
};
}, []);
const D = n.useMemo(
() => I.filter((e) => {
const l = !!e._type, r = e.isAccessible === !1;
return !e.hidden && !l && !r && (e.columnType === "data" || e.columnType === void 0);
}),
[I]
), H = n.useCallback((e, l) => {
if (!e.field)
return null;
const r = ge(e.field, l);
return r == null ? null : String(r);
}, []), fe = n.useMemo(
() => W("k-table-row", "k-master-row", J, {
"k-table-alt-row": Y,
"k-selected": x,
"k-grid-edit-row": w && k === "inline"
}),
[J, Y, x, w, k]
), ee = n.useMemo(
() => typeof (u == null ? void 0 : u.cols) == "number" && M > 1,
[u == null ? void 0 : u.cols, M]
), de = n.useMemo(
() => W("k-grid-stack-row", {
[`k-grid-cols-${M}`]: ee
}),
[M, ee]
), pe = n.useMemo(
() => j ? { gridTemplateColumns: j, ...V } : V || {},
[j, V]
), te = n.useCallback(
(e) => {
if (!(y != null && y.onEditChange) || !(t != null && t.dataItemKey) || !e)
return;
const l = a[t.dataItemKey];
if (l === void 0)
return;
const r = A.edit || {}, c = X(r, {
type: z.EXIT_FIELD_EDIT,
payload: { id: String(l), field: e }
}), s = {
nativeEvent: {},
currentTarget: null,
target: null,
bubbles: !1,
cancelable: !1,
defaultPrevented: !1,
eventPhase: 0,
isTrusted: !1,
timeStamp: Date.now(),
type: "editchange",
preventDefault: () => {
},
stopPropagation: () => {
},
persist: () => {
},
isDefaultPrevented: () => !1,
isPropagationStopped: () => !1
};
y.onEditChange({
edit: c,
nativeEvent: {},
syntheticEvent: s,
target: null
});
},
[a, t == null ? void 0 : t.dataItemKey, y, A.edit]
), le = n.useCallback(
(e, l) => {
if (!(y != null && y.onEditChange) || !(t != null && t.dataItemKey) || !e)
return;
const r = a[t.dataItemKey];
if (r === void 0)
return;
const c = D.findIndex(($) => $.field === e);
if (c === -1)
return;
const s = c + l;
if (s < 0 || s >= D.length)
return;
const d = D[s].field;
if (!d)
return;
const p = A.edit || {}, F = String(r), m = X(p, {
type: z.EXIT_FIELD_EDIT,
payload: { id: F, field: e }
}), B = X(m, {
type: z.ENTER_FIELD_EDIT,
payload: { id: F, field: d }
}), g = {
nativeEvent: {},
currentTarget: null,
target: null,
bubbles: !1,
cancelable: !1,
defaultPrevented: !1,
eventPhase: 0,
isTrusted: !1,
timeStamp: Date.now(),
type: "editchange",
preventDefault: () => {
},
stopPropagation: () => {
},
persist: () => {
},
isDefaultPrevented: () => !1,
isPropagationStopped: () => !1
};
y.onEditChange({
edit: B,
nativeEvent: {},
syntheticEvent: g,
target: null
});
},
[a, t == null ? void 0 : t.dataItemKey, y, A.edit, D]
), me = n.useCallback(
(e, l) => {
var se;
const r = I.indexOf(e), c = K == null ? void 0 : K[r], s = c == null ? void 0 : c.props.cellProps, d = Fe(e, q), p = (se = S != null ? S : f) != null ? se : 0, F = L ? `${L}-${p}-${l}` : void 0, m = s ? s.isInEdit : w && e.editable !== !1, B = W("k-grid-stack-cell", e.className, {
"k-grid-stack-edit-cell ": m
}), g = (i) => {
var E;
if (m) {
if (i.stopPropagation(), k === "inline" && (v.current = l), k === "incell") {
const b = i.currentTarget, T = P.getStackedCellFocusableElements(b)[0], _ = document.activeElement;
T && _ !== T && !T.contains(_) && T.focus();
}
return;
}
(E = t == null ? void 0 : t.cellClick) == null || E.call(t, i, a, e.field);
}, $ = (i) => {
const E = i.target, b = i.currentTarget;
if (i.key === "Tab" && E !== b)
return;
if (i.key === "Enter" && E === b && !m && e.editable !== !1) {
g(i);
return;
}
De({
event: i,
cellElement: b,
onEscape: () => R(!1),
onExitEdit: () => te(e.field),
onTabToNextCell: (T) => le(e.field, T),
isInEdit: m,
editMode: k
});
}, ae = (i) => {
if (i && m && k === "incell") {
const b = P.getStackedCellFocusableElements(i)[0], h = document.activeElement;
if (!b || !h || b === h || b.contains(h))
return;
b.focus();
} else if (i && m && k === "inline") {
const E = document.activeElement;
if (E == null ? void 0 : E.closest(".k-animation-container, .k-popup, .k-list-container"))
return;
if (i.contains(E)) {
v.current = l, G.current.set(l, !0);
return;
}
const h = N.current;
if (h != null && h.contains(E))
return;
const T = G.current.size === 0, _ = l === 0;
if (v.current === l || _ && T) {
const ne = P.getStackedCellFocusableElements(i)[0];
ne && (ne.focus(), v.current = l, G.current.set(l, !0));
}
}
}, he = {
className: B,
"data-grid-col-index": l,
id: F,
style: void 0,
tabIndex: Z ? 0 : -1,
onClick: g,
onKeyDown: $,
onFocus: () => {
v.current = l;
},
ref: ae
};
let U = H(e, a);
if (m) {
const i = s || {
dataItem: a,
field: e.field,
dataIndex: f,
columnIndex: l,
rowType: "data",
isInEdit: m,
format: e.format,
className: e.className,
editor: e.editor,
cells: q
};
U = /* @__PURE__ */ n.createElement(Se, null, /* @__PURE__ */ n.createElement(we, { cellProps: i }));
}
if (d && C(d)) {
const i = {
dataItem: a,
field: e.field,
title: e.title,
rowType: "data",
dataIndex: f,
columnIndex: l,
isInEdit: m,
format: e.format,
className: e.className,
columnType: e.columnType,
stackedCellProps: he,
children: U
};
return /* @__PURE__ */ n.createElement(d, { key: e.id || e.field || l, ...i });
}
return /* @__PURE__ */ n.createElement(
oe,
{
key: e.id || e.field || l,
header: e.title,
className: e.className,
isInEdit: m,
columnIndex: l,
id: F,
onClick: g,
onKeyDown: $,
cellRef: ae
},
U
);
},
[
I,
K,
q,
L,
w,
k,
a,
f,
S,
Z,
t,
H,
R,
te,
le
]
), Ee = n.useMemo(() => {
const e = [];
for (let l = 0; l < Q; l++)
e.push(/* @__PURE__ */ n.createElement("td", { key: `group-cell-${l}`, className: "k-table-group-td k-group-cell k-table-td" }));
return e;
}, [Q]), be = n.useCallback(
(e) => {
var l, r;
(l = t == null ? void 0 : t.rowClick) == null || l.call(t, e, a), f !== void 0 && ((r = t == null ? void 0 : t.selectionChange) == null || r.call(t, {
event: e,
dataItem: a,
dataIndex: f,
columnIndex: 0
}));
},
[t, a, f]
), ke = n.useCallback(
(e) => {
var l;
(l = t == null ? void 0 : t.rowDblClick) == null || l.call(t, e, a);
},
[t, a]
), ye = n.useCallback(
(e) => {
var c;
const l = e.target, r = e.currentTarget;
if (l === r && e.key === "Enter") {
e.preventDefault(), f !== void 0 && ((c = t == null ? void 0 : t.selectionChange) == null || c.call(t, {
event: e,
dataItem: a,
dataIndex: f,
columnIndex: 0
}));
const s = r.querySelector(".k-grid-stack-cell");
s && s.focus();
}
},
[t, a, f]
), Ie = n.useCallback(
(e) => {
var c;
const l = e.target, r = e.currentTarget;
if (l === r) {
if (e.key === "Tab") {
const s = r.closest("tr");
if (e.shiftKey) {
const d = s == null ? void 0 : s.previousElementSibling;
if (d) {
const p = d.querySelector("td.k-table-td[tabindex]");
if (p) {
e.preventDefault(), p.focus();
return;
}
}
} else {
const d = s == null ? void 0 : s.nextElementSibling;
if (d) {
const p = d.querySelector("td.k-table-td[tabindex]");
if (p) {
e.preventDefault(), p.focus();
return;
}
}
}
return;
}
if (e.key === "ArrowUp" || e.key === "ArrowDown") {
e.preventDefault();
const s = r.closest("tr"), d = e.key === "ArrowUp" ? s == null ? void 0 : s.previousElementSibling : s == null ? void 0 : s.nextElementSibling;
if (!d)
return;
const p = d.querySelector("td.k-table-td[tabindex]");
p && (p.focus(), p.scrollIntoView && p.scrollIntoView({ block: "nearest" }));
return;
}
if (e.key === "Enter") {
e.preventDefault(), e.stopPropagation(), f !== void 0 && ((c = t == null ? void 0 : t.selectionChange) == null || c.call(t, {
event: e,
dataItem: a,
dataIndex: f,
columnIndex: 0
})), R(!0);
const s = r.querySelector(".k-grid-stack-cell");
s && (s.hasAttribute("tabindex") || s.setAttribute("tabindex", "0"), s.focus());
}
}
},
[R, t, a, f]
);
return /* @__PURE__ */ n.createElement(
"tr",
{
className: fe,
"data-grid-row-index": S,
"aria-rowindex": re,
onClick: be,
onDoubleClick: ke,
onKeyDown: ye
},
Ee,
/* @__PURE__ */ n.createElement("td", { ref: N, className: "k-table-td", colSpan: 1, tabIndex: 0, onKeyDown: Ie }, /* @__PURE__ */ n.createElement("div", { className: de, style: pe }, D.map((e, l) => me(e, l)), ce && /* @__PURE__ */ n.createElement(oe, { columnIndex: D.length }, /* @__PURE__ */ n.createElement(
Te,
{
dataItem: a,
dataIndex: f,
expanded: !!ie,
field: ue
}
))))
);
};
Pe.displayName = "KendoReactGridStackedRow";
export {
Pe as GridStackedRow
};