@progress/kendo-react-gantt
Version:
React Gantt enables the display of self-referencing tabular data with many features. KendoReact Gantt package
249 lines (248 loc) • 8.79 kB
JavaScript
/**
* @license
*-------------------------------------------------------------------------------------------
* Copyright © 2025 Progress Software Corporation. All rights reserved.
* Licensed under commercial license. See LICENSE.md in the package root for more information
*-------------------------------------------------------------------------------------------
*/
import * as e from "react";
import { useGanttPropsContext as Ae, useGanttEventsContext as Ne, useGanttRowHeightContext as Xe, useGanttToolbarHeightContext as Ye, useGanttTaskModelFieldsContext as Pe, useGanttDependencyModelFieldsContext as We, useGanttTaskDataContext as _e, useGanttDependencyDataContext as ze } from "../context/GanttContext.mjs";
import { GanttViewContext as Ve } from "../context/GanttViewContext.mjs";
import { GanttTask as ve } from "./GanttTask.mjs";
import { useDictionaryStore as Oe } from "../hooks/useDictionaryStore.mjs";
import { GanttDependency as $e } from "./GanttDependency.mjs";
import { getTimelineHeader as Ke, getTimelineContent as Be, getTimelineWidth as Ue } from "../utils/index.mjs";
import { readColumns as je, mapColumns as qe } from "@progress/kendo-react-data-tools";
import { DEFAULT_COLUMN_WIDTH as Je, DEPENDENCY_DRAG_HANDLE as S, TASK_ID_ATT as A } from "../constants/index.mjs";
import { GanttTreeList as Qe } from "./GanttTreelist.mjs";
import { useId as N, getter as Ze } from "@progress/kendo-react-common";
const et = e.forwardRef((X, Y) => {
const { slotLevels: E, slotWidth: P, timelineHeaderCell: W } = X, {
columns: k,
noRecords: _,
resizable: z,
reorderable: V,
sortable: v,
sort: O,
filter: $,
columnMenuFilter: K,
columnMenu: B,
navigatable: U,
row: j,
selectable: q
} = Ae(), {
onDataStateChange: J,
onSortChange: Q,
onFilterChange: Z,
onColumnMenuFilterChange: ee,
onExpandChange: te,
onRowClick: ne,
onRowDoubleClick: re,
onRowContextMenu: oe,
onColumnResize: b,
onColumnReorder: se,
onDependencyCreate: m,
onKeyDown: le,
onSelectionChange: ce,
onHeaderSelectionChange: ae
} = Ne(), ie = Xe(), ue = Ye(), i = Pe(), fe = We(), y = _e(), de = ze(), x = e.useRef(null), I = e.useRef(null), u = e.useRef(null), p = e.useRef(null), L = e.useRef(0), F = e.useRef(N()), me = e.useRef(N()), c = e.useRef(null), G = e.useRef(null), pe = e.useCallback((t) => {
u.current && u.current.scrollIntoView(t);
}, []);
e.useImperativeHandle(G, () => ({ scrollIntoView: pe })), e.useImperativeHandle(Y, () => G.current);
const C = e.useRef(0), g = e.useRef(0), R = e.useRef(0), h = e.useRef(0), f = e.useRef(null), T = e.useRef(null), [d, w] = e.useState(null), Ce = Ke(E, x, W), ge = Be(E, I), D = Ue(E, P), { extendedColumns: Re, columnsWidth: he, columnsMap: De } = e.useMemo(() => {
const t = je(
[
...k,
{
title: "",
sortable: !1,
resizable: !1,
reorderable: !1,
width: D,
headerCell: () => Ce,
cell: ve,
orderIndex: Number.MAX_SAFE_INTEGER,
navigatable: !1
}
],
{ prevId: 0, idPrefix: F.current }
);
let r = 0;
return t.forEach((n, o, l) => {
const s = o + 1 === l.length, a = n.children.length === 0;
s ? n.isAccessible = !1 : (n.locked = !0, a && (n.width = n.width || Je)), a && (r += parseFloat(String(n.width)));
}), {
extendedColumns: t,
columnsWidth: r,
columnsMap: qe(t)
};
}, [k, D]), [Ee, be] = Oe(), H = e.useCallback(
() => x.current && x.current.parentElement,
[]
), M = () => {
const t = H(), r = I.current, n = u.current && u.current.tbodyElement;
if (!t || !r || !n)
return;
const o = n.offsetTop, l = t.offsetLeft, s = D;
r.style.top = o + "px", r.style.left = l + "px", r.style.width = s + "px", r.style.height = n.offsetHeight + "px";
}, ye = () => {
const t = H();
t && (L.current = t.offsetLeft);
};
e.useEffect(M), e.useEffect(ye);
const xe = e.useCallback(
(t) => {
if (!p.current)
return;
const r = t.columns.slice(0, t.columns.length - 1);
if (t.end)
p.current.style.left = "0px";
else {
const n = H();
if (!n)
return;
p.current.style.left = n.offsetLeft - L.current + "px", M();
}
b({
...t,
columns: r
});
},
[b]
), Te = e.useCallback(
(t) => {
const r = t.columns.slice(0, t.columns.length - 1);
se({
...t,
columns: r
});
},
[b]
), we = e.useCallback((t) => {
const n = (c.current && c.current.ownerDocument ? c.current.ownerDocument : document).elementFromPoint(t.clientX, t.clientY), o = c.current;
if (!n || !n.parentElement || !o)
return;
const l = o.parentElement, s = o.firstElementChild;
if (!l || !s)
return;
const a = n.getAttribute(S);
if (a) {
const Ie = o.offsetTop, Le = o.offsetLeft, Fe = l.offsetTop, Ge = l.offsetLeft, Me = s.scrollTop, Se = s.scrollLeft;
R.current = Le + Ge, h.current = Ie + Fe, C.current = t.clientX - R.current + Se, g.current = t.clientY - h.current + Me, f.current = n.parentElement.getAttribute(A), T.current = a;
}
}, []), He = e.useCallback((t) => {
const r = c.current;
if (!r)
return;
const n = r.firstElementChild;
if (!n)
return;
const o = n.scrollTop, l = n.scrollLeft, s = t.clientX - R.current + l, a = t.clientY - h.current + o;
Math.abs(C.current - s) < 10 && Math.abs(g.current - a) < 10 || w({
startX: C.current,
startY: g.current,
endX: s,
endY: a
});
}, []), ke = e.useCallback(
(t) => {
const n = (c.current && c.current.ownerDocument ? c.current.ownerDocument : document).elementFromPoint(t.clientX, t.clientY);
if (!n || !n.parentElement)
return;
const o = n.parentElement.getAttribute(A), l = n.getAttribute(S);
if (l && o !== f.current && m) {
let s;
T.current === "start" ? s = l === "start" ? 3 : 2 : s = l === "start" ? 1 : 0, m({
fromId: f.current,
toId: o,
type: s
});
}
C.current = 0, g.current = 0, R.current = 0, h.current = 0, f.current = null, T.current = null, w(null);
},
[m, w]
);
return /* @__PURE__ */ e.createElement(
Ve,
{
tasksStore: [Ee, be],
timelineWidth: D,
dependencyDrag: {
isEnabled: !!m,
draggedId: f.current,
onDependencyHandlePress: we,
onDependencyHandleDrag: He,
onDependencyHandleRelease: ke
}
},
/* @__PURE__ */ e.createElement("div", { className: "k-gantt-content", ref: c, style: { height: `calc(100% - ${ue}px)` } }, /* @__PURE__ */ e.createElement(
Qe,
{
treelistId: me.current,
ref: u,
extendedColumns: Re,
columnsMap: De,
dataItemKey: i.id,
data: y,
idPrefix: F.current,
navigatable: U,
expandField: i.isExpanded,
subItemsField: i.children,
editField: i.isInEdit,
selectedField: i.isSelected,
onDataStateChange: J,
onSortChange: Q,
onFilterChange: Z,
onExpandChange: te,
onRowClick: ne,
onRowDoubleClick: re,
onRowContextMenu: oe,
onColumnResize: xe,
onColumnReorder: Te,
onColumnMenuFilterChange: ee,
onKeyDown: le,
onSelectionChange: ce,
onHeaderSelectionChange: ae,
tableProps: {
style: { width: he },
className: "k-table k-table-md k-table-layout-fixed"
},
noRecords: _,
rowHeight: ie,
resizable: z,
reorderable: V,
sortable: v,
sort: O,
filter: $,
columnMenuFilter: K,
columnMenu: B,
row: j,
selectable: q,
afterContent: /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(
"svg",
{
className: "k-gantt-dependencies-svg",
ref: p,
style: { left: 0, top: 0 }
},
de.map((t) => /* @__PURE__ */ e.createElement(
$e,
{
key: Ze(fe.id)(t),
dependency: t
}
))
), /* @__PURE__ */ e.createElement("svg", { className: "k-gantt-dependencies-svg", style: { left: 0, top: 0, zIndex: 3 } }, d && /* @__PURE__ */ e.createElement(
"polyline",
{
points: `${d.startX},${d.startY} ${d.endX},${d.endY}`
}
)), y && y.length ? ge : null)
}
))
);
});
et.displayName = "KendoReactGanttBaseView";
export {
et as BaseView
};