UNPKG

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