@progress/kendo-react-gantt
Version:
React Gantt enables the display of self-referencing tabular data with many features. KendoReact Gantt package
374 lines (373 loc) • 11.6 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 a from "react";
import n from "prop-types";
import { getTaskModelFields as Te, getDependencyModelFields as Ee, expandedChildren as xe } from "./utils/index.mjs";
import { useInternationalization as Fe } from "@progress/kendo-react-intl";
import { GanttContext as Ve } from "./context/GanttContext.mjs";
import { GanttWeekView as v, ganttWeekViewDefaultProps as Ie } from "./views/GanttWeekView.mjs";
import { GanttDayView as He, ganttDayViewDefaultProps as ze } from "./views/GanttDayView.mjs";
import { GanttMonthView as Ae, ganttMonthViewDefaultProps as Ge } from "./views/GanttMonthView.mjs";
import { GanttYearView as Ne, ganttYearViewDefaultProps as Pe } from "./views/GanttYearView.mjs";
import { flatData as Ke } from "@progress/kendo-react-treelist";
import { validatePackage as We, getter as h, useIsomorphicLayoutEffect as Le, classNames as Be, WatermarkOverlay as Oe } from "@progress/kendo-react-common";
import { useControlledState as Ye } from "./hooks/useControlledState.mjs";
import { ViewSelectorList as je } from "./components/toolbar/view-selector/ViewSelectorList.mjs";
import { ViewSelector as Ue } from "./components/toolbar/view-selector/ViewSelector.mjs";
import { Toolbar as _e } from "./components/toolbar/Toolbar.mjs";
import { ToolbarSpacer as qe } from "@progress/kendo-react-buttons";
import { DEFAULT_DATE as I } from "./constants/index.mjs";
import { packageMetadata as Je } from "./package-metadata.mjs";
import { AddButton as Qe } from "./components/toolbar/AddButton.mjs";
const H = a.forwardRef((e, z) => {
const A = !We(Je, { component: "Gantt" }), {
columns: G = R.columns,
taskData: M = R.taskData,
dependencyData: N = R.dependencyData,
style: P,
className: K,
noRecords: W,
timezone: S,
rowHeight: L = R.rowHeight,
resizable: B,
reorderable: O,
sortable: Y,
sort: j,
filter: U,
columnMenuFilter: _,
columnMenu: q,
navigatable: J,
toolbar: T,
row: Q,
selectable: X
} = e, d = /* @__PURE__ */ new Map();
d.set(He, ze), d.set(Ae, Ge), d.set(v, Ie), d.set(Ne, Pe);
const Z = Fe(), { fields: o } = a.useMemo(
() => Te(e.taskModelFields),
[e.taskModelFields]
), { fields: $ } = a.useMemo(
() => Ee(e.dependencyModelFields),
[e.dependencyModelFields]
), E = a.useCallback(
xe(o.isExpanded, o.children),
[o.isExpanded, o.children]
), w = a.useRef(null), c = a.useRef(null), i = a.useRef(null), m = a.useRef(null), C = a.useRef(null), p = a.useCallback(
(t) => {
const r = h(o.start)(t), u = h(o.end)(t), D = h(o.isSelected)(t);
(!c.current || r < c.current) && (c.current = r), (!i.current || u > i.current) && (i.current = u), D && (m.current = t);
},
[o.start, o.end]
), g = a.useMemo(() => (c.current = null, i.current = null, m.current = null, Ke(M, E, p)), [M, E]);
(!c.current || !i.current) && (c.current = new Date(I), i.current = new Date(I));
const f = a.Children.toArray(e.children || []).map(
(t) => {
var r;
return a.isValidElement(t) ? a.cloneElement(t, { ...d.get(t.type), ...(r = t.props) != null ? r : {} }) : t;
}
), ee = a.cloneElement(/* @__PURE__ */ a.createElement(v, null), d.get(v)), x = f.length ? f[0] : ee, [F, ne] = Ye(
e.defaultView || x.props.name,
e.view,
e.onViewChange
), s = f.find((t) => t.props.name === F) || x, te = typeof s.props.dateRange == "function" ? s.props.dateRange.call(void 0, {
intl: Z,
tasksStart: c.current,
tasksEnd: i.current,
timezone: S
}) : s.props.dateRange, b = a.useRef(null), [ae, le] = a.useState(0);
Le(() => {
b.current && le(b.current.element.offsetHeight);
}, []);
const oe = a.useCallback((t) => {
w.current && w.current.scrollIntoView(t);
}, []), V = a.useRef(null), l = a.useRef(null);
a.useImperativeHandle(l, () => ({ props: e, element: V.current, scrollIntoView: oe })), a.useImperativeHandle(z, () => l.current);
const re = a.useCallback(
(t) => {
e.onDataStateChange && e.onDataStateChange.call(void 0, {
...t,
target: l.current
});
},
[e.onDataStateChange]
), ce = a.useCallback(
(t) => {
e.onSortChange && e.onSortChange.call(void 0, { ...t, target: l.current });
},
[e.onSortChange]
), ie = a.useCallback(
(t) => {
e.onKeyDown && e.onKeyDown.call(void 0, { ...t, target: l.current });
},
[e.onKeyDown]
), se = a.useCallback(
(t) => {
e.onSelectionChange && e.onSelectionChange.call(void 0, {
...t,
target: l.current
});
},
[e.onSelectionChange]
), de = a.useCallback(
(t) => {
e.onHeaderSelectionChange && e.onHeaderSelectionChange.call(void 0, {
...t,
target: l.current
});
},
[e.onHeaderSelectionChange]
), ue = a.useCallback(
(t) => {
e.onFilterChange && e.onFilterChange.call(void 0, { ...t, target: l.current });
},
[e.onFilterChange]
), Ce = a.useCallback(
(t) => {
e.onColumnMenuFilterChange && e.onColumnMenuFilterChange.call(void 0, {
...t,
target: l.current
});
},
[e.onColumnMenuFilterChange]
), me = a.useCallback(
(t) => {
e.onExpandChange && e.onExpandChange.call(void 0, { ...t, target: l.current });
},
[e.onExpandChange]
), ge = a.useCallback(
(t) => {
e.onAddClick && e.onAddClick.call(void 0, {
...t,
target: l.current,
selectedDataItem: m.current,
slotStart: C.current && new Date(C.current.start.getTime()),
slotEnd: C.current && new Date(C.current.end.getTime())
});
},
[e.onAddClick]
), fe = a.useCallback(
(t) => {
e.onColumnResize && e.onColumnResize.call(void 0, {
...t,
target: l.current
});
},
[e.onColumnResize]
), ke = a.useCallback(
(t) => {
e.onColumnReorder && e.onColumnReorder.call(void 0, {
...t,
target: l.current
});
},
[e.onColumnReorder]
), he = a.useCallback(
(t) => {
e.onRowClick && e.onRowClick.call(void 0, { ...t, target: l.current });
},
[e.onRowClick]
), Re = a.useCallback(
(t) => {
e.onRowDoubleClick && e.onRowDoubleClick.call(void 0, {
...t,
target: l.current
});
},
[e.onRowClick]
), we = a.useCallback(
(t) => {
e.onRowContextMenu && e.onRowContextMenu.call(void 0, {
...t,
target: l.current
});
},
[e.onRowClick]
), be = a.useCallback(
(t) => {
e.onTaskClick && e.onTaskClick.call(void 0, { ...t, target: l.current });
},
[e.onTaskClick]
), De = a.useCallback(
(t) => {
e.onTaskDoubleClick && e.onTaskDoubleClick.call(void 0, {
...t,
target: l.current
});
},
[e.onTaskDoubleClick]
), ye = a.useCallback(
(t) => {
e.onTaskContextMenu && e.onTaskContextMenu.call(void 0, {
...t,
target: l.current
});
},
[e.onTaskContextMenu]
), ve = a.useCallback(
(t) => {
e.onTaskRemoveClick && e.onTaskRemoveClick.call(void 0, {
...t,
target: l.current
});
},
[e.onTaskRemoveClick]
), Me = a.useCallback(
(t) => {
if (e.onDependencyCreate) {
let r, u;
const D = h(o.id);
for (let y = 0; y < g.length; y++) {
const Se = g[y], k = D(Se.dataItem);
if (String(k) === t.fromId && (r = k), String(k) === t.toId && (u = k), r && u)
break;
}
e.onDependencyCreate.call(void 0, {
fromId: r,
toId: u,
target: l.current,
type: t.type
});
}
},
[e.onDependencyCreate, o, g]
);
return /* @__PURE__ */ a.createElement(
Ve,
{
dateRange: te,
taskData: g,
dependencyData: N,
taskModelFields: o,
dependencyModelFields: $,
views: f,
activeView: [F, ne],
rowHeight: L,
toolbarHeight: ae,
props: {
columns: G,
noRecords: W,
timezone: S,
resizable: B,
reorderable: O,
sortable: Y,
sort: j,
filter: U,
columnMenuFilter: _,
columnMenu: q,
navigatable: J,
row: Q,
selectable: X
},
events: {
onDataStateChange: re,
onSortChange: ce,
onFilterChange: ue,
onColumnMenuFilterChange: Ce,
onExpandChange: me,
onRowClick: he,
onRowDoubleClick: Re,
onRowContextMenu: we,
onColumnResize: fe,
onColumnReorder: ke,
onDependencyCreate: e.onDependencyCreate && Me,
onKeyDown: ie,
onSelectionChange: se,
onHeaderSelectionChange: de
},
taskEvents: {
onTaskClick: be,
onTaskDoubleClick: De,
onTaskContextMenu: ye,
onTaskRemoveClick: e.onTaskRemoveClick && ve
}
},
/* @__PURE__ */ a.createElement("div", { ref: V, role: "application", style: P, className: Be("k-gantt", K) }, /* @__PURE__ */ a.createElement(_e, { ref: b }, T && T.addTaskButton ? /* @__PURE__ */ a.createElement(Qe, { selectedTask: m.current, onClick: ge }) : null, /* @__PURE__ */ a.createElement(qe, null), /* @__PURE__ */ a.createElement(Ue, null, /* @__PURE__ */ a.createElement(je, null))), s && /* @__PURE__ */ a.createElement(
s.type,
{
key: s.props.name,
ref: w,
...s.props,
firstSlotRangeRef: C
}
), A && /* @__PURE__ */ a.createElement(Oe, null))
);
}), R = {
taskData: [],
dependencyData: [],
columns: [],
rowHeight: 40
};
H.propTypes = {
taskData: n.array,
taskModelFields: n.shape({
id: n.string,
start: n.string,
end: n.string,
title: n.string,
percentComplete: n.string,
parentId: n.string,
isRollup: n.string,
isExpanded: n.string,
children: n.string,
isInEdit: n.string
}),
dependencyData: n.array,
dependencyModelFields: n.shape({
id: n.string,
fromId: n.string,
toId: n.string,
type: n.string
}),
columns: n.arrayOf(
n.shape({
width: n.number,
cell: n.any,
editCell: n.any,
headerCell: n.any,
filter: n.any,
children: n.any,
field: n.string,
title: n.string,
sortable: n.any,
expandable: n.bool,
headerSelectionValue: n.bool,
format: n.string,
headerClassName: n.string,
className: n.string,
resizable: n.bool,
reorderable: n.bool,
minResizableWidth: n.number,
orderIndex: n.number,
columnMenu: n.any
})
),
sort: n.array,
filter: n.array,
columnMenuFilter: n.array,
columnMenu: n.any,
style: n.object,
className: n.string,
children: n.any,
timezone: n.string,
defaultView: n.string,
view: n.string,
rowHeight: n.number,
navigatable: n.bool,
onViewChange: n.func,
onDataStateChange: n.func,
onSortChange: n.func,
onFilterChange: n.func,
onExpandChange: n.func,
onRowClick: n.func,
onColumnResize: n.func,
onColumnReorder: n.func
};
H.displayName = "KendoReactGantt";
export {
H as Gantt,
R as ganttDefaultProps
};