UNPKG

@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
/** * @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 };