UNPKG

@progress/kendo-react-grid

Version:

React Data Grid (Table) provides 100+ ready-to-use data grid features. KendoReact Grid package

466 lines (465 loc) 14.6 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 re } from "./GridStackedCell.mjs"; import { GridStackedDetailToggle as we } from "./GridStackedDetailToggle.mjs"; import { GridEditCellEditor as ve } from "../cells/editcell/GridEditCellEditor.mjs"; import { GridContext as De } from "../utils/GridContext.mjs"; import { tableKeyboardNavigationTools as g, editReducer as X, EDIT_ACTION as z, handleStackedKeyboardNavigation as Ce } from "@progress/kendo-react-data-tools"; import { useGridState as Se } from "../GridState.mjs"; const Re = (o) => /* @__PURE__ */ n.createElement("div", { style: { display: "contents" } }, o.children), Ne = (o) => { if (o != null && o.cols && typeof o.cols != "number") return o.cols.map((s) => typeof s == "number" ? `${s}px` : typeof s == "string" ? s : s && typeof s == "object" && s.width !== void 0 ? typeof s.width == "number" ? `${s.width}px` : s.width : "1fr").join(" "); }, Fe = (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", Pe = (o, s) => { 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 (s != null && s.stackedData && C(s.stackedData)) return s.stackedData; if ((u = o.cells) != null && u.data && C(o.cells.data)) return o.cells.data; if (s != null && s.data && C(s.data)) return s.data; }, ge = (o, s) => { if (!o || !s) return; const I = o.split("."); let u = s; for (const f of I) { if (u == null) return; u = u[f]; } return u; }, Ke = (o) => { const { dataItem: s, columns: I, stackedLayoutSettings: u, dataIndex: f, isAltRow: Y, isSelected: x, isInEdit: w, editMode: k, cells: q, idPrefix: L, className: J, style: V, ariaRowIndex: ce, absoluteRowIndex: S, groupLevel: Q = 0, preparedCells: K, showDetailToggle: ie, isDetailExpanded: ue, detailExpandField: fe, isPinned: Z } = o, t = n.useContext(De), [A, , y] = Se(), j = n.useMemo( () => Ne(u), [u] ), M = n.useMemo(() => Fe(u), [u]), [H, 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 ? g.getStackedCellFocusableElements(l) : [])[0]; if (c) { c.focus(); return; } const a = g.getStackedCellFocusableElements(e); a[0] && a[0].focus(); }, 0)); }, [w, k]), n.useEffect(() => { const e = (r) => { const c = N.current; setTimeout(() => { const a = document.activeElement; c && !c.contains(a) && 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] ), ee = n.useCallback((e, l) => { if (!e.field) return null; const r = ge(e.field, l); return r == null ? null : String(r); }, []), de = 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", "k-pinned-source": Z }), [J, Y, x, w, k, Z] ), te = n.useMemo( () => typeof (u == null ? void 0 : u.cols) == "number" && M > 1, [u == null ? void 0 : u.cols, M] ), pe = n.useMemo( () => W("k-grid-stack-row", { [`k-grid-cols-${M}`]: te }), [M, te] ), me = n.useMemo( () => j ? { gridTemplateColumns: j, ...V } : V || {}, [j, V] ), le = n.useCallback( (e) => { if (!(y != null && y.onEditChange) || !(t != null && t.dataItemKey) || !e) return; const l = s[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 } }), a = { 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: a, target: null }); }, [s, t == null ? void 0 : t.dataItemKey, y, A.edit] ), se = n.useCallback( (e, l) => { if (!(y != null && y.onEditChange) || !(t != null && t.dataItemKey) || !e) return; const r = s[t.dataItemKey]; if (r === void 0) return; const c = D.findIndex(($) => $.field === e); if (c === -1) return; const a = c + l; if (a < 0 || a >= D.length) return; const d = D[a].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 } }), P = { 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: P, target: null }); }, [s, t == null ? void 0 : t.dataItemKey, y, A.edit, D] ), Ee = n.useCallback( (e, l) => { var ne; const r = I.indexOf(e), c = K == null ? void 0 : K[r], a = c == null ? void 0 : c.props.cellProps, d = Pe(e, q), p = (ne = S != null ? S : f) != null ? ne : 0, F = L ? `${L}-${p}-${l}` : void 0, m = a ? a.isInEdit : w && e.editable !== !1, B = W("k-grid-stack-cell", e.className, { "k-grid-stack-edit-cell ": m }), P = (i) => { var E; if (m) { if (i.stopPropagation(), k === "inline" && (v.current = l), k === "incell") { const b = i.currentTarget, T = g.getStackedCellFocusableElements(b)[0], _ = document.activeElement; T && _ !== T && !T.contains(_) && T.focus(); } return; } (E = t == null ? void 0 : t.cellClick) == null || E.call(t, i, s, 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) { P(i); return; } Ce({ event: i, cellElement: b, onEscape: () => R(!1), onExitEdit: () => le(e.field), onTabToNextCell: (T) => se(e.field, T), isInEdit: m, editMode: k }); }, ae = (i) => { if (i && m && k === "incell") { const b = g.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 oe = g.getStackedCellFocusableElements(i)[0]; oe && (oe.focus(), v.current = l, G.current.set(l, !0)); } } }, Te = { className: B, "data-grid-col-index": l, id: F, style: void 0, tabIndex: H ? 0 : -1, onClick: P, onKeyDown: $, onFocus: () => { v.current = l; }, ref: ae }; let U = ee(e, s); if (m) { const i = a || { dataItem: s, 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(Re, null, /* @__PURE__ */ n.createElement(ve, { cellProps: i })); } if (d && C(d)) { const i = { dataItem: s, field: e.field, title: e.title, rowType: "data", dataIndex: f, columnIndex: l, isInEdit: m, format: e.format, className: e.className, columnType: e.columnType, stackedCellProps: Te, children: U }; return /* @__PURE__ */ n.createElement(d, { key: e.id || e.field || l, ...i }); } return /* @__PURE__ */ n.createElement( re, { key: e.id || e.field || l, header: e.title, className: e.className, isInEdit: m, columnIndex: l, id: F, onClick: P, onKeyDown: $, cellRef: ae }, U ); }, [ I, K, q, L, w, k, s, f, S, H, t, ee, R, le, se ] ), be = 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]), ke = n.useCallback( (e) => { var l, r; (l = t == null ? void 0 : t.rowClick) == null || l.call(t, e, s), f !== void 0 && ((r = t == null ? void 0 : t.selectionChange) == null || r.call(t, { event: e, dataItem: s, dataIndex: f, columnIndex: 0 })); }, [t, s, f] ), ye = n.useCallback( (e) => { var l; (l = t == null ? void 0 : t.rowDblClick) == null || l.call(t, e, s); }, [t, s] ), Ie = 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: s, dataIndex: f, columnIndex: 0 })); const a = r.querySelector(".k-grid-stack-cell"); a && a.focus(); } }, [t, s, f] ), he = n.useCallback( (e) => { var c; const l = e.target, r = e.currentTarget; if (l === r) { if (e.key === "Tab") { const a = r.closest("tr"); if (e.shiftKey) { const d = a == null ? void 0 : a.previousElementSibling; if (d) { const p = d.querySelector("td.k-table-td[tabindex]"); if (p) { e.preventDefault(), p.focus(); return; } } } else { const d = a == null ? void 0 : a.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 a = r.closest("tr"), d = e.key === "ArrowUp" ? a == null ? void 0 : a.previousElementSibling : a == null ? void 0 : a.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: s, dataIndex: f, columnIndex: 0 })), R(!0); const a = r.querySelector(".k-grid-stack-cell"); a && (a.hasAttribute("tabindex") || a.setAttribute("tabindex", "0"), a.focus()); } } }, [R, t, s, f] ); return /* @__PURE__ */ n.createElement( "tr", { className: de, "data-grid-row-index": S, "aria-rowindex": ce, onClick: ke, onDoubleClick: ye, onKeyDown: Ie }, be, /* @__PURE__ */ n.createElement("td", { ref: N, className: "k-table-td", colSpan: 1, tabIndex: 0, onKeyDown: he }, /* @__PURE__ */ n.createElement("div", { className: pe, style: me }, D.map((e, l) => Ee(e, l)), ie && /* @__PURE__ */ n.createElement(re, { columnIndex: D.length }, /* @__PURE__ */ n.createElement( we, { dataItem: s, dataIndex: f, expanded: !!ue, field: fe } )))) ); }; Ke.displayName = "KendoReactGridStackedRow"; export { Ke as GridStackedRow };