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