gantt-task-react-powern
Version:
Interactive Gantt Chart for React with TypeScript.
1,456 lines (1,304 loc) • 176 kB
JavaScript
import React, { useMemo, useRef, useState, useEffect } from 'react';
import { useVirtualizer } from '@tanstack/react-virtual';
function _extends() {
_extends = Object.assign || function (target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i];
for (var key in source) {
if (Object.prototype.hasOwnProperty.call(source, key)) {
target[key] = source[key];
}
}
}
return target;
};
return _extends.apply(this, arguments);
}
function _objectDestructuringEmpty(obj) {
if (obj == null) throw new TypeError("Cannot destructure undefined");
}
function _unsupportedIterableToArray(o, minLen) {
if (!o) return;
if (typeof o === "string") return _arrayLikeToArray(o, minLen);
var n = Object.prototype.toString.call(o).slice(8, -1);
if (n === "Object" && o.constructor) n = o.constructor.name;
if (n === "Map" || n === "Set") return Array.from(o);
if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen);
}
function _arrayLikeToArray(arr, len) {
if (len == null || len > arr.length) len = arr.length;
for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i];
return arr2;
}
function _createForOfIteratorHelperLoose(o, allowArrayLike) {
var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"];
if (it) return (it = it.call(o)).next.bind(it);
if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") {
if (it) o = it;
var i = 0;
return function () {
if (i >= o.length) return {
done: true
};
return {
done: false,
value: o[i++]
};
};
}
throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
}
var ViewMode;
(function (ViewMode) {
ViewMode["Hour"] = "Hour";
ViewMode["QuarterDay"] = "Quarter Day";
ViewMode["HalfDay"] = "Half Day";
ViewMode["Day"] = "Day";
ViewMode["Week"] = "Week";
ViewMode["Month"] = "Month";
ViewMode["Quarter"] = "Quarter";
ViewMode["Year"] = "Year";
})(ViewMode || (ViewMode = {}));
var _VIEW_MODE_DEFAULT_VI, _VIEW_MODE_MAX_VISIBL;
var intlDTCache = {};
var getCachedDateTimeFormat = function getCachedDateTimeFormat(locString, opts) {
if (opts === void 0) {
opts = {};
}
var key = JSON.stringify([locString, opts]);
var dtf = intlDTCache[key];
if (!dtf) {
dtf = new Intl.DateTimeFormat(locString, opts);
intlDTCache[key] = dtf;
}
return dtf;
};
var addToDate = function addToDate(date, quantity, scale) {
var newDate = new Date(date.getFullYear() + (scale === "year" ? quantity : 0), date.getMonth() + (scale === "month" ? quantity : 0), date.getDate() + (scale === "day" ? quantity : 0), date.getHours() + (scale === "hour" ? quantity : 0), date.getMinutes() + (scale === "minute" ? quantity : 0), date.getSeconds() + (scale === "second" ? quantity : 0), date.getMilliseconds() + (scale === "millisecond" ? quantity : 0));
return newDate;
};
var startOfDate = function startOfDate(date, scale) {
var scores = ["millisecond", "second", "minute", "hour", "day", "month", "quarter", "year"];
var shouldReset = function shouldReset(_scale) {
var maxScore = scores.indexOf(scale);
return scores.indexOf(_scale) <= maxScore;
};
var newDate = new Date(date.getFullYear(), shouldReset("year") ? 0 : date.getMonth(), shouldReset("month") ? 1 : date.getDate(), shouldReset("day") ? 0 : date.getHours(), shouldReset("hour") ? 0 : date.getMinutes(), shouldReset("minute") ? 0 : date.getSeconds(), shouldReset("second") ? 0 : date.getMilliseconds());
return newDate;
};
var getFiscalQuarterStartDate = function getFiscalQuarterStartDate(date, quarterStart) {
var month = date.getMonth();
var offset = (month - quarterStart + 12) % 12;
var qStartMonth = (quarterStart + Math.floor(offset / 3) * 3) % 12;
var year = date.getFullYear();
if (qStartMonth > month) year -= 1;
return new Date(year, qStartMonth, 1);
};
var VIEW_MODE_DEFAULT_VISIBLE_COUNT = (_VIEW_MODE_DEFAULT_VI = {}, _VIEW_MODE_DEFAULT_VI[ViewMode.Day] = 14, _VIEW_MODE_DEFAULT_VI[ViewMode.Week] = 6, _VIEW_MODE_DEFAULT_VI[ViewMode.Month] = 6, _VIEW_MODE_DEFAULT_VI[ViewMode.Quarter] = 4, _VIEW_MODE_DEFAULT_VI);
var VIEW_MODE_MAX_VISIBLE_COUNT = (_VIEW_MODE_MAX_VISIBL = {}, _VIEW_MODE_MAX_VISIBL[ViewMode.Day] = 30, _VIEW_MODE_MAX_VISIBL[ViewMode.Week] = 13, _VIEW_MODE_MAX_VISIBL[ViewMode.Month] = 12, _VIEW_MODE_MAX_VISIBL[ViewMode.Quarter] = 8, _VIEW_MODE_MAX_VISIBL);
var ganttDateRange = function ganttDateRange(tasks, viewMode, preStepsCount, quarterStart) {
var _tasks$, _tasks$2, _tasks$3, _tasks$4;
if (quarterStart === void 0) {
quarterStart = 0;
}
var newStartDate = ((_tasks$ = tasks[0]) === null || _tasks$ === void 0 ? void 0 : _tasks$.start.getTime()) !== 0 ? ((_tasks$2 = tasks[0]) === null || _tasks$2 === void 0 ? void 0 : _tasks$2.start) || new Date() : new Date();
var newEndDate = ((_tasks$3 = tasks[0]) === null || _tasks$3 === void 0 ? void 0 : _tasks$3.end.getTime()) !== 0 ? ((_tasks$4 = tasks[0]) === null || _tasks$4 === void 0 ? void 0 : _tasks$4.end) || new Date() : new Date();
for (var _iterator = _createForOfIteratorHelperLoose(tasks), _step; !(_step = _iterator()).done;) {
var task = _step.value;
if (task.start && task.start.getTime() !== 0 && task.start < newStartDate) {
newStartDate = task.start;
}
if (task.end && task.end.getTime() !== 0 && task.end > newEndDate) {
newEndDate = task.end;
}
if (task.actualStart && task.actualStart.getTime() !== 0 && task.actualStart < newStartDate) {
newStartDate = task.actualStart;
}
if (task.actualEnd && task.actualEnd.getTime() !== 0 && task.actualEnd > newEndDate) {
newEndDate = task.actualEnd;
}
}
switch (viewMode) {
case ViewMode.Year:
newStartDate = addToDate(newStartDate, -1, "year");
newStartDate = startOfDate(newStartDate, "year");
newEndDate = addToDate(newEndDate, 1, "year");
newEndDate = startOfDate(newEndDate, "year");
break;
case ViewMode.Quarter:
{
newStartDate = addToDate(newStartDate, -1 * preStepsCount, "year");
newStartDate = getFiscalQuarterStartDate(newStartDate, quarterStart);
newEndDate = addToDate(newEndDate, 1, "year");
var endQStart = getFiscalQuarterStartDate(newEndDate, quarterStart);
newEndDate = endQStart < newEndDate ? addToDate(endQStart, 3, "month") : endQStart;
break;
}
case ViewMode.Month:
newStartDate = addToDate(newStartDate, -1 * preStepsCount, "month");
newStartDate = startOfDate(newStartDate, "month");
newEndDate = addToDate(newEndDate, 1, "year");
newEndDate = startOfDate(newEndDate, "year");
break;
case ViewMode.Week:
newStartDate = startOfDate(newStartDate, "day");
newStartDate = addToDate(getMonday(newStartDate), -7 * preStepsCount, "day");
newEndDate = startOfDate(newEndDate, "day");
newEndDate = addToDate(newEndDate, 1.5, "month");
break;
case ViewMode.Day:
newStartDate = startOfDate(newStartDate, "day");
newStartDate = addToDate(newStartDate, -1 * preStepsCount, "day");
newEndDate = startOfDate(newEndDate, "day");
newEndDate = addToDate(newEndDate, 19, "day");
break;
case ViewMode.QuarterDay:
newStartDate = startOfDate(newStartDate, "day");
newStartDate = addToDate(newStartDate, -1 * preStepsCount, "day");
newEndDate = startOfDate(newEndDate, "day");
newEndDate = addToDate(newEndDate, 66, "hour");
break;
case ViewMode.HalfDay:
newStartDate = startOfDate(newStartDate, "day");
newStartDate = addToDate(newStartDate, -1 * preStepsCount, "day");
newEndDate = startOfDate(newEndDate, "day");
newEndDate = addToDate(newEndDate, 108, "hour");
break;
case ViewMode.Hour:
newStartDate = startOfDate(newStartDate, "hour");
newStartDate = addToDate(newStartDate, -1 * preStepsCount, "hour");
newEndDate = startOfDate(newEndDate, "day");
newEndDate = addToDate(newEndDate, 1, "day");
break;
}
return [newStartDate, newEndDate];
};
var seedDates = function seedDates(startDate, endDate, viewMode) {
var currentDate = new Date(startDate);
var dates = [currentDate];
while (currentDate < endDate) {
switch (viewMode) {
case ViewMode.Year:
currentDate = addToDate(currentDate, 1, "year");
break;
case ViewMode.Quarter:
currentDate = addToDate(currentDate, 3, "month");
break;
case ViewMode.Month:
currentDate = addToDate(currentDate, 1, "month");
break;
case ViewMode.Week:
currentDate = addToDate(currentDate, 7, "day");
break;
case ViewMode.Day:
currentDate = addToDate(currentDate, 1, "day");
break;
case ViewMode.HalfDay:
currentDate = addToDate(currentDate, 12, "hour");
break;
case ViewMode.QuarterDay:
currentDate = addToDate(currentDate, 6, "hour");
break;
case ViewMode.Hour:
currentDate = addToDate(currentDate, 1, "hour");
break;
}
dates.push(currentDate);
}
return dates;
};
var getLocalDayOfWeek = function getLocalDayOfWeek(date, locale, format) {
var bottomValue = getCachedDateTimeFormat(locale, {
weekday: format
}).format(date);
bottomValue = bottomValue.replace(bottomValue[0], bottomValue[0].toLocaleUpperCase());
return bottomValue;
};
var getMonday = function getMonday(date) {
var day = date.getDay();
var diff = date.getDate() - day + (day === 0 ? -6 : 1);
return new Date(date.setDate(diff));
};
var styles = {"ganttTable":"_3_ygE","ganttTable_Header":"_1nBOt","ganttTable_HeaderSeparator":"_2eZzQ","ganttTable_HeaderItem":"_WuQ0f"};
var TaskListHeaderDefault = function TaskListHeaderDefault(_ref) {
var headerHeight = _ref.headerHeight,
fontFamily = _ref.fontFamily,
fontSize = _ref.fontSize,
rowWidth = _ref.rowWidth,
scheduleType = _ref.scheduleType,
allSelected = _ref.allSelected,
onSelectAll = _ref.onSelectAll;
return React.createElement("div", {
className: styles.ganttTable,
style: {
fontFamily: fontFamily,
fontSize: fontSize
}
}, React.createElement("div", {
className: styles.ganttTable_Header,
style: {
height: headerHeight - 2
}
}, onSelectAll && React.createElement("div", null, React.createElement("div", {
className: styles.ganttTable_HeaderItem,
style: {
minWidth: parseInt(rowWidth) * 0.3,
maxWidth: parseInt(rowWidth) * 0.3
}
}, React.createElement("input", {
type: "checkbox",
checked: allSelected,
onChange: function onChange(e) {
return onSelectAll(e.target.checked);
}
}))), React.createElement("div", {
className: styles.ganttTable_HeaderItem,
style: {
minWidth: parseInt(rowWidth) * 0.8,
maxWidth: parseInt(rowWidth) * 0.8
}
}, "ID"), React.createElement("div", {
className: styles.ganttTable_HeaderSeparator,
style: {
height: headerHeight * 0.5,
marginTop: headerHeight * 0.2
}
}), React.createElement("div", {
className: styles.ganttTable_HeaderItem,
style: {
minWidth: parseInt(rowWidth) * 0.8,
maxWidth: parseInt(rowWidth) * 0.8
}
}, "WBS Code / Activity ID"), React.createElement("div", {
className: styles.ganttTable_HeaderSeparator,
style: {
height: headerHeight * 0.5,
marginTop: headerHeight * 0.2
}
}), React.createElement("div", {
className: styles.ganttTable_HeaderItem,
style: {
minWidth: parseInt(rowWidth) * 1.8,
maxWidth: parseInt(rowWidth) * 1.8
}
}, "Task"), React.createElement("div", {
className: styles.ganttTable_HeaderSeparator,
style: {
height: headerHeight * 0.5,
marginTop: headerHeight * 0.2
}
}), React.createElement("div", {
className: styles.ganttTable_HeaderItem,
style: {
minWidth: parseInt(rowWidth) * 0.6
},
title: "Planned Start"
}, "Planned Start"), React.createElement("div", {
className: styles.ganttTable_HeaderSeparator,
style: {
height: headerHeight * 0.5,
marginTop: headerHeight * 0.25
}
}), React.createElement("div", {
className: styles.ganttTable_HeaderItem,
style: {
minWidth: parseInt(rowWidth) * 0.6
},
title: "Planned End"
}, "Planned End"), scheduleType === "lookAhead" && React.createElement("div", {
className: styles.ganttTable_HeaderItem,
style: {
minWidth: parseInt(rowWidth) * 0.6
},
title: "Planned Start"
}, "Actual Start"), scheduleType === "lookAhead" && React.createElement("div", {
className: styles.ganttTable_HeaderSeparator,
style: {
height: headerHeight * 0.5,
marginTop: headerHeight * 0.25
}
}), scheduleType === "lookAhead" && React.createElement("div", {
className: styles.ganttTable_HeaderItem,
style: {
minWidth: parseInt(rowWidth) * 0.6
},
title: "Planned End"
}, "Actual End"), scheduleType === "main" && React.createElement(React.Fragment, null, React.createElement("div", {
className: styles.ganttTable_HeaderSeparator,
style: {
height: headerHeight * 0.5,
marginTop: headerHeight * 0.25
}
}), React.createElement("div", {
className: styles.ganttTable_HeaderItem,
style: {
minWidth: parseInt(rowWidth) * 0.6,
maxWidth: parseInt(rowWidth) * 0.6
},
title: "% Complete"
}, "% Complete"), React.createElement("div", {
className: styles.ganttTable_HeaderSeparator,
style: {
height: headerHeight * 0.5,
marginTop: headerHeight * 0.25
}
}), React.createElement("div", {
className: styles.ganttTable_HeaderItem,
style: {
minWidth: parseInt(rowWidth) * 0.6,
maxWidth: parseInt(rowWidth) * 0.6
},
title: "Planned Duration"
}, "Planned Duration"), React.createElement("div", {
className: styles.ganttTable_HeaderSeparator,
style: {
height: headerHeight * 0.5,
marginTop: headerHeight * 0.25
}
}), React.createElement("div", {
className: styles.ganttTable_HeaderItem,
style: {
minWidth: parseInt(rowWidth) * 0.7,
maxWidth: parseInt(rowWidth) * 0.7
},
title: "Remaining Duration"
}, "Remaining Duration"), React.createElement("div", {
className: styles.ganttTable_HeaderSeparator,
style: {
height: headerHeight * 0.5,
marginTop: headerHeight * 0.25
}
}), React.createElement("div", {
className: styles.ganttTable_HeaderItem,
style: {
minWidth: parseInt(rowWidth) * 0.6,
maxWidth: parseInt(rowWidth) * 0.6
},
title: "Actual Duration"
}, "Actual Duration"), React.createElement("div", {
className: styles.ganttTable_HeaderSeparator,
style: {
height: headerHeight * 0.5,
marginTop: headerHeight * 0.25
}
}), React.createElement("div", {
className: styles.ganttTable_HeaderItem,
style: {
minWidth: parseInt(rowWidth) * 0.8,
maxWidth: parseInt(rowWidth) * 0.8
},
title: "Duration Type"
}, "Duration Type"))));
};
var styles$1 = {"taskListWrapper":"_3ZbQT","taskListTableRow":"_34SS0","taskListLookAheadRow":"_GzvG4","taskListMilestoneRow":"_3Ykml","taskListCell":"_3lLk3","taskListNameWrapper":"_nI1Xw","taskListExpander":"_2QjE6","taskListExpanderPlaceholder":"_1fnLB","taskListEmptyExpander":"_2TfEi","taskListText":"_2ZvXU"};
var localeDateStringCache = {};
var toLocaleDateStringFactory = function toLocaleDateStringFactory(locale) {
return function (date, dateTimeOptions) {
if (!date || date.getTime() === 0) return "";
var key = date.toString();
var lds = localeDateStringCache[key];
if (!lds) {
lds = date.toLocaleDateString(locale, dateTimeOptions);
localeDateStringCache[key] = lds;
}
return lds;
};
};
var dateTimeOptions = {
year: "numeric",
month: "numeric",
day: "numeric"
};
var TaskListTableDefault = function TaskListTableDefault(_ref) {
var rowHeight = _ref.rowHeight,
rowWidth = _ref.rowWidth,
tasks = _ref.tasks,
scheduleType = _ref.scheduleType,
leafTasks = _ref.leafTasks,
fontFamily = _ref.fontFamily,
fontSize = _ref.fontSize,
locale = _ref.locale,
onExpanderClick = _ref.onExpanderClick,
_ref$selectedTasks = _ref.selectedTasks,
selectedTasks = _ref$selectedTasks === void 0 ? [] : _ref$selectedTasks,
onTaskSelect = _ref.onTaskSelect,
_ref$taskLabelRendere = _ref.taskLabelRenderer,
taskLabelRenderer = _ref$taskLabelRendere === void 0 ? function (t) {
return " " + t.name;
} : _ref$taskLabelRendere,
virtualItems = _ref.virtualItems;
var toLocaleDateString = useMemo(function () {
return toLocaleDateStringFactory(locale);
}, [locale]);
var leafTaskIds = useMemo(function () {
return new Set(leafTasks.map(function (t) {
return t.id;
}));
}, [leafTasks]);
var hasSelectedAncestor = function hasSelectedAncestor(taskId, selectedSet, allTasks) {
var task = allTasks.find(function (t) {
return t.id === taskId;
});
if (!task) return false;
var parentWbs = getParentWbs(task.id);
if (!parentWbs) return false;
if (selectedSet.has(parentWbs)) return true;
return hasSelectedAncestor(parentWbs, selectedSet, allTasks);
};
var itemsToRender = virtualItems || tasks.map(function (_, index) {
return {
index: index,
start: index * rowHeight,
size: rowHeight,
key: index,
end: (index + 1) * rowHeight,
lane: 0,
measureElement: function measureElement() {}
};
});
return React.createElement("div", {
className: styles$1.taskListWrapper,
style: {
fontFamily: fontFamily,
fontSize: fontSize
}
}, itemsToRender.map(function (vi) {
var t = tasks[vi.index];
var expanderSymbol = "";
if (!(leafTaskIds.has(t.id) || t.type === "milestone")) {
if (t.hideChildren === false) {
expanderSymbol = "▼";
} else if (t.hideChildren === true) {
expanderSymbol = "►";
}
}
var isSelected = selectedTasks.includes(t.id);
var isAncestorSelected = hasSelectedAncestor(t.id, new Set(selectedTasks), tasks);
return React.createElement("div", {
key: "" + vi.key,
"data-index": vi.index,
style: {
position: "absolute",
top: 0,
left: 0,
width: "100%",
height: vi.size + "px",
transform: "translateY(" + vi.start + "px)"
}
}, React.createElement("div", {
className: t.type === "milestone" ? styles$1.taskListMilestoneRow : scheduleType === "lookAhead" ? styles$1.taskListLookAheadRow : styles$1.taskListTableRow,
style: {
height: rowHeight
},
key: t.id + "row"
}, onTaskSelect && React.createElement("div", {
className: styles$1.taskListCell,
style: {
minWidth: parseInt(rowWidth) * 0.3,
maxWidth: parseInt(rowWidth) * 0.3
}
}, React.createElement("div", {
className: styles$1.taskListText,
style: {
display: "flex",
justifyContent: "center",
alignItems: "center",
height: "100%",
paddingLeft: "0",
paddingRight: "0"
}
}, React.createElement("input", {
type: "checkbox",
checked: isSelected,
disabled: isAncestorSelected,
onChange: function onChange(e) {
return onTaskSelect(t.id, e.target.checked);
}
}))), React.createElement("div", {
className: styles$1.taskListCell,
style: {
minWidth: parseInt(rowWidth) * 0.8,
maxWidth: parseInt(rowWidth) * 0.8
},
title: t.id
}, React.createElement("div", {
className: styles$1.taskListNameWrapper,
style: {
paddingLeft: t.depth * 4 + "px"
}
}, !(leafTaskIds.has(t.id) || t.type === "milestone") ? React.createElement("div", {
className: styles$1.taskListExpander,
onClick: function onClick() {
return onExpanderClick(t);
}
}, expanderSymbol) : React.createElement("div", {
className: styles$1.taskListExpanderPlaceholder
}), React.createElement("div", {
className: styles$1.taskListText
}, t.id, " ", t.actualEnd.getTime() > 0 && t.actualEnd.getTime() < Date.now() ? React.createElement("span", {
title: "Task Complete",
style: {
color: "limegreen",
fontSize: "16px"
}
}, "\u2714") : ""))), React.createElement("div", {
className: styles$1.taskListCell,
style: {
minWidth: parseInt(rowWidth) * 0.8,
maxWidth: parseInt(rowWidth) * 0.8
},
title: t.optionalId ? t.optionalId : ""
}, t.optionalId), React.createElement("div", {
className: styles$1.taskListCell,
style: {
minWidth: parseInt(rowWidth) * 1.8,
maxWidth: parseInt(rowWidth) * 1.8
},
title: t.name
}, React.createElement("div", {
className: styles$1.taskListText
}, taskLabelRenderer(t))), React.createElement("div", {
className: styles$1.taskListCell,
style: {
minWidth: parseInt(rowWidth) * 0.6,
maxWidth: parseInt(rowWidth) * 0.6
}
}, React.createElement("div", {
className: styles$1.taskListText
}, "\xA0", toLocaleDateString(t.start, dateTimeOptions))), React.createElement("div", {
className: styles$1.taskListCell,
style: {
minWidth: parseInt(rowWidth) * 0.6,
maxWidth: parseInt(rowWidth) * 0.6
}
}, React.createElement("div", {
className: styles$1.taskListText
}, "\xA0", toLocaleDateString(t.end, dateTimeOptions))), scheduleType === "lookAhead" && React.createElement("div", {
className: styles$1.taskListCell,
style: {
minWidth: parseInt(rowWidth) * 0.6,
maxWidth: parseInt(rowWidth) * 0.6
}
}, React.createElement("div", {
className: styles$1.taskListText
}, "\xA0", toLocaleDateString(t.actualStart, dateTimeOptions))), scheduleType === "lookAhead" && React.createElement("div", {
className: styles$1.taskListCell,
style: {
minWidth: parseInt(rowWidth) * 0.6,
maxWidth: parseInt(rowWidth) * 0.6
}
}, React.createElement("div", {
className: styles$1.taskListText
}, "\xA0", toLocaleDateString(t.actualEnd, dateTimeOptions))), scheduleType === "main" && function () {
var _t$progress, _t$durationType;
var percentComplete = t.percentComplete != null ? t.percentComplete : (_t$progress = t.progress) != null ? _t$progress : 0;
var plannedDuration = t.plannedDuration != null ? t.plannedDuration : null;
var remainingDuration = plannedDuration != null ? Math.round(plannedDuration - plannedDuration * (percentComplete / 100)) : null;
var actualDuration = function () {
if (!t.actualStart || t.actualStart.getTime() === 0) return null;
var endRef = t.actualEnd && t.actualEnd.getTime() > 0 ? t.actualEnd : new Date();
return Math.ceil((endRef.getTime() - t.actualStart.getTime()) / (1000 * 60 * 60 * 24));
}();
return React.createElement(React.Fragment, null, React.createElement("div", {
className: styles$1.taskListCell,
style: {
minWidth: parseInt(rowWidth) * 0.6,
maxWidth: parseInt(rowWidth) * 0.6
}
}, React.createElement("div", {
className: styles$1.taskListText
}, "\xA0", percentComplete != null ? percentComplete + "%" : "")), React.createElement("div", {
className: styles$1.taskListCell,
style: {
minWidth: parseInt(rowWidth) * 0.6,
maxWidth: parseInt(rowWidth) * 0.6
}
}, React.createElement("div", {
className: styles$1.taskListText
}, "\xA0", plannedDuration != null ? plannedDuration : "")), React.createElement("div", {
className: styles$1.taskListCell,
style: {
minWidth: parseInt(rowWidth) * 0.7,
maxWidth: parseInt(rowWidth) * 0.7
}
}, React.createElement("div", {
className: styles$1.taskListText
}, "\xA0", remainingDuration != null ? remainingDuration : "")), React.createElement("div", {
className: styles$1.taskListCell,
style: {
minWidth: parseInt(rowWidth) * 0.6,
maxWidth: parseInt(rowWidth) * 0.6
}
}, React.createElement("div", {
className: styles$1.taskListText
}, "\xA0", actualDuration != null ? actualDuration : "")), React.createElement("div", {
className: styles$1.taskListCell,
style: {
minWidth: parseInt(rowWidth) * 0.8,
maxWidth: parseInt(rowWidth) * 0.8
}
}, React.createElement("div", {
className: styles$1.taskListText
}, "\xA0", (_t$durationType = t.durationType) != null ? _t$durationType : "Activity Calendar")));
}()));
}));
};
var styles$2 = {"tooltipDefaultContainer":"_3T42e","tooltipDefaultContainerParagraph":"_29NTg","tooltipDetailsContainer":"_25P-K","tooltipDetailsContainerHidden":"_3gVAq"};
var Tooltip = function Tooltip(_ref) {
var task = _ref.task,
type = _ref.type,
rowHeight = _ref.rowHeight,
rtl = _ref.rtl,
svgContainerHeight = _ref.svgContainerHeight,
svgContainerWidth = _ref.svgContainerWidth,
scrollX = _ref.scrollX,
scrollY = _ref.scrollY,
arrowIndent = _ref.arrowIndent,
fontSize = _ref.fontSize,
fontFamily = _ref.fontFamily,
headerHeight = _ref.headerHeight,
taskListWidth = _ref.taskListWidth,
TooltipContent = _ref.TooltipContent,
isDragging = _ref.isDragging;
var tooltipRef = useRef(null);
var _useState = useState(0),
relatedY = _useState[0],
setRelatedY = _useState[1];
var _useState2 = useState(0),
relatedX = _useState2[0],
setRelatedX = _useState2[1];
useEffect(function () {
if (tooltipRef.current) {
var tooltipHeight = tooltipRef.current.offsetHeight * 1.1;
var tooltipWidth = tooltipRef.current.offsetWidth * 1.1;
var newRelatedY = task.index * rowHeight - scrollY + headerHeight;
var newRelatedX;
if (isDragging) {
newRelatedX = taskListWidth + svgContainerWidth - tooltipWidth - 10;
newRelatedY = headerHeight + 5;
setRelatedY(newRelatedY);
setRelatedX(newRelatedX);
return;
}
if (rtl) {
newRelatedX = task.x1 - arrowIndent * 1.5 - tooltipWidth - scrollX;
if (newRelatedX < 0) {
newRelatedX = task.x2 + arrowIndent * 1.5 - scrollX;
}
var tooltipLeftmostPoint = tooltipWidth + newRelatedX;
if (tooltipLeftmostPoint > svgContainerWidth) {
newRelatedX = svgContainerWidth - tooltipWidth;
newRelatedY += rowHeight;
}
} else {
newRelatedX = type == "planned" ? task.x2 + arrowIndent * 1.5 + taskListWidth - scrollX : task.actualx2 + arrowIndent * 1.5 + taskListWidth - scrollX;
var _tooltipLeftmostPoint = tooltipWidth + newRelatedX;
var fullChartWidth = taskListWidth + svgContainerWidth;
if (_tooltipLeftmostPoint > fullChartWidth) {
newRelatedX = type == "planned" ? task.x1 + taskListWidth - arrowIndent * 1.5 - scrollX - tooltipWidth : task.actualx1 + taskListWidth - arrowIndent * 1.5 - scrollX - tooltipWidth;
}
if (newRelatedX < taskListWidth) {
newRelatedX = svgContainerWidth + taskListWidth - tooltipWidth;
newRelatedY += rowHeight;
}
}
var tooltipLowerPoint = tooltipHeight + newRelatedY - scrollY;
if (tooltipLowerPoint > svgContainerHeight - scrollY) {
newRelatedY = svgContainerHeight - tooltipHeight;
}
setRelatedY(newRelatedY);
setRelatedX(newRelatedX);
}
}, [tooltipRef, task, arrowIndent, scrollX, scrollY, headerHeight, taskListWidth, rowHeight, svgContainerHeight, svgContainerWidth, rtl, isDragging]);
return React.createElement("div", {
ref: tooltipRef,
className: relatedX ? styles$2.tooltipDetailsContainer : styles$2.tooltipDetailsContainerHidden,
style: {
left: relatedX,
top: relatedY
}
}, React.createElement(TooltipContent, {
task: task,
fontSize: fontSize,
fontFamily: fontFamily,
type: type
}));
};
var StandardTooltipContent = function StandardTooltipContent(_ref2) {
var _task$plannedDuration, _task$actualDuration;
var task = _ref2.task,
fontSize = _ref2.fontSize,
fontFamily = _ref2.fontFamily,
type = _ref2.type;
var style = {
fontSize: fontSize,
fontFamily: fontFamily
};
var computedPlannedDuration = task.start && task.end && task.end.getTime() - task.start.getTime() > 0 ? Math.max(1, Math.round((task.end.getTime() - task.start.getTime()) / (1000 * 60 * 60 * 24))) : (_task$plannedDuration = task.plannedDuration) != null ? _task$plannedDuration : 0;
var computedActualDuration = task.actualStart && task.actualEnd && task.actualEnd.getTime() - task.actualStart.getTime() > 0 ? Math.max(1, Math.round((task.actualEnd.getTime() - task.actualStart.getTime()) / (1000 * 60 * 60 * 24))) : (_task$actualDuration = task.actualDuration) != null ? _task$actualDuration : 0;
if (type == "planned") return React.createElement("div", {
className: styles$2.tooltipDefaultContainer,
style: style
}, React.createElement("b", {
style: {
fontSize: fontSize + 6
}
}, task.name + ": Planned dates: "), React.createElement("b", null, task.start.getMonth() + 1 + "/" + task.start.getDate() + "/" + task.start.getFullYear() + " - " + (task.end.getMonth() + 1) + "/" + task.end.getDate() + "/" + task.end.getFullYear()), task.end.getTime() - task.start.getTime() !== 0 && React.createElement("p", {
className: styles$2.tooltipDefaultContainerParagraph
}, "Duration: " + computedPlannedDuration + " day(s)"), React.createElement("p", {
className: styles$2.tooltipDefaultContainerParagraph
}, !!task.progress && "Progress: " + task.progress + " %"));else return React.createElement("div", {
className: styles$2.tooltipDefaultContainer,
style: style
}, React.createElement("b", {
style: {
fontSize: fontSize + 6
}
}, task.name + ": Actual dates: "), React.createElement("b", null, task.actualStart.getMonth() + 1 + "/" + task.actualStart.getDate() + "/" + task.actualStart.getFullYear() + " - " + (task.actualEnd.getMonth() + 1) + "/" + task.actualEnd.getDate() + "/" + task.actualEnd.getFullYear()), task.actualEnd.getTime() - task.actualStart.getTime() !== 0 && React.createElement("p", {
className: styles$2.tooltipDefaultContainerParagraph
}, "Duration: " + computedActualDuration + " day(s)"), React.createElement("p", {
className: styles$2.tooltipDefaultContainerParagraph
}, !!task.progress && "Progress: " + task.progress + " %"));
};
var styles$3 = {"scroll":"_1eT-t"};
var VerticalScroll = function VerticalScroll(_ref) {
var scroll = _ref.scroll,
ganttHeight = _ref.ganttHeight,
ganttFullHeight = _ref.ganttFullHeight,
headerHeight = _ref.headerHeight,
rtl = _ref.rtl,
onScroll = _ref.onScroll;
var scrollRef = useRef(null);
useEffect(function () {
if (scrollRef.current) {
scrollRef.current.scrollTop = scroll;
}
}, [scroll]);
return React.createElement("div", {
style: {
height: ganttHeight,
marginTop: headerHeight,
marginLeft: rtl ? "" : "-1rem",
marginRight: "1rem"
},
className: styles$3.scroll,
onScroll: onScroll,
ref: scrollRef
}, React.createElement("div", {
style: {
height: ganttFullHeight,
width: 1
}
}));
};
var styles$4 = {"hideScrollbar":"_38emS"};
var TaskList = function TaskList(_ref) {
var headerHeight = _ref.headerHeight,
fontFamily = _ref.fontFamily,
fontSize = _ref.fontSize,
rowWidth = _ref.rowWidth,
rowHeight = _ref.rowHeight,
scrollY = _ref.scrollY,
tasks = _ref.tasks,
scheduleType = _ref.scheduleType,
leafTasks = _ref.leafTasks,
selectedTask = _ref.selectedTask,
setSelectedTask = _ref.setSelectedTask,
onExpanderClick = _ref.onExpanderClick,
locale = _ref.locale,
ganttHeight = _ref.ganttHeight,
taskListRef = _ref.taskListRef,
horizontalContainerClass = _ref.horizontalContainerClass,
TaskListHeader = _ref.TaskListHeader,
TaskListTable = _ref.TaskListTable,
taskLabelRenderer = _ref.taskLabelRenderer,
onMultiSelect = _ref.onMultiSelect,
containerWidth = _ref.containerWidth,
innerScrollRef = _ref.innerScrollRef,
externalHorizontalContainerRef = _ref.horizontalContainerRef;
var internalHorizontalContainerRef = useRef(null);
var horizontalContainerRef = externalHorizontalContainerRef != null ? externalHorizontalContainerRef : internalHorizontalContainerRef;
var headerScrollRef = useRef(null);
useEffect(function () {
var rowsEl = horizontalContainerRef.current;
if (!rowsEl) return;
var onScroll = function onScroll() {
if (headerScrollRef.current) {
headerScrollRef.current.scrollLeft = rowsEl.scrollLeft;
}
};
rowsEl.addEventListener("scroll", onScroll);
return function () {
return rowsEl.removeEventListener("scroll", onScroll);
};
}, [horizontalContainerRef]);
var _useState = useState([]),
selectedTasks = _useState[0],
setSelectedTasks = _useState[1];
var _useState2 = useState([]),
pendingTaskSelect = _useState2[0],
setPendingTaskSelect = _useState2[1];
var prevSelectedTasksRef = useRef([]);
var expandedTasks = useRef([]);
var virtualizer = useVirtualizer({
count: tasks.length,
getScrollElement: function getScrollElement() {
return horizontalContainerRef.current;
},
estimateSize: function estimateSize() {
return rowHeight;
},
overscan: 10
});
useEffect(function () {
if (horizontalContainerRef.current) {
horizontalContainerRef.current.scrollTop = scrollY;
}
}, [scrollY]);
useEffect(function () {
if (onMultiSelect && JSON.stringify(prevSelectedTasksRef.current) !== JSON.stringify(selectedTasks)) {
var selectedTaskObjects = tasks.filter(function (task) {
return selectedTasks.includes(task.id);
});
prevSelectedTasksRef.current = [].concat(selectedTasks);
onMultiSelect(selectedTaskObjects);
}
}, [selectedTasks, tasks, onMultiSelect]);
useEffect(function () {
if (pendingTaskSelect.length === 0) return;
var newSelected = new Set(selectedTasks);
pendingTaskSelect.forEach(function (_ref2) {
var taskId = _ref2.taskId,
selected = _ref2.selected;
if (selected) {
recursiveOpen(taskId, tasks);
var descendants = getDescendants(taskId, tasks);
newSelected.add(taskId);
descendants.forEach(function (d) {
return newSelected.add(d);
});
} else {
var _descendants = getDescendants(taskId, tasks);
newSelected["delete"](taskId);
_descendants.forEach(function (d) {
return newSelected["delete"](d);
});
}
});
setSelectedTasks(Array.from(newSelected));
setPendingTaskSelect([]);
}, [pendingTaskSelect]);
useEffect(function () {
expandedTasks.current = expandedTasks.current.filter(function (id) {
var t = tasks.find(function (task) {
return task.id === id;
});
return t && !t.hideChildren;
});
if (selectedTasks.length === 0) return;
var newSelected = new Set();
selectedTasks.forEach(function (taskId) {
if (tasks.find(function (t) {
return t.id === taskId;
})) {
recursiveOpen(taskId, tasks);
newSelected.add(taskId);
var descendants = getDescendants(taskId, tasks);
descendants.forEach(function (d) {
return newSelected.add(d);
});
}
});
var newSelectedArray = Array.from(newSelected);
if (JSON.stringify(newSelectedArray) !== JSON.stringify(selectedTasks)) {
setSelectedTasks(newSelectedArray);
}
}, [tasks.length]);
var getDescendants = function getDescendants(taskId, allTasks) {
var task = allTasks.find(function (t) {
return t.id === taskId;
});
if (!task) return [];
var children = allTasks.filter(function (t) {
return getParentWbs(t.id) === taskId;
});
return children.flatMap(function (child) {
return [child.id].concat(getDescendants(child.id, allTasks));
});
};
var recursiveOpen = function recursiveOpen(taskId, allTasks) {
var task = allTasks.find(function (t) {
return t.id === taskId;
});
if (!task) return;
if (!expandedTasks.current.includes(taskId) && task.hideChildren) {
onExpanderClick(task);
expandedTasks.current = [].concat(expandedTasks.current, [taskId]);
}
var children = allTasks.filter(function (t) {
return getParentWbs(t.id) === taskId;
});
children.forEach(function (c) {
return recursiveOpen(c.id, allTasks);
});
};
var handleTaskSelect = function handleTaskSelect(taskId, selected) {
setPendingTaskSelect(function (prev) {
return [].concat(prev, [{
taskId: taskId,
selected: selected
}]);
});
};
var handleSelectAll = function handleSelectAll(selected) {
if (selected) {
var topLevelTasks = tasks.filter(function (task) {
return !getParentWbs(task.id);
});
setPendingTaskSelect(topLevelTasks.map(function (task) {
return {
taskId: task.id,
selected: true
};
}));
} else {
setSelectedTasks([]);
setPendingTaskSelect([]);
}
};
var headerProps = {
headerHeight: headerHeight,
fontFamily: fontFamily,
fontSize: fontSize,
rowWidth: rowWidth,
scheduleType: scheduleType,
allSelected: tasks.length > 0 && selectedTasks.length === tasks.length,
onSelectAll: onMultiSelect ? handleSelectAll : undefined
};
var selectedTaskId = selectedTask ? selectedTask.id : "";
var tableProps = {
rowHeight: rowHeight,
rowWidth: rowWidth,
fontFamily: fontFamily,
fontSize: fontSize,
tasks: tasks,
leafTasks: leafTasks,
scheduleType: scheduleType,
locale: locale,
selectedTaskId: selectedTaskId,
setSelectedTask: setSelectedTask,
onExpanderClick: onExpanderClick,
selectedTasks: onMultiSelect ? selectedTasks : undefined,
onTaskSelect: onMultiSelect ? handleTaskSelect : undefined,
taskLabelRenderer: taskLabelRenderer,
virtualItems: virtualizer.getVirtualItems()
};
return React.createElement("div", {
ref: taskListRef,
style: containerWidth != null ? {
width: containerWidth,
overflow: "hidden",
flexShrink: 0
} : {}
}, React.createElement("div", {
ref: innerScrollRef,
className: styles$4.hideScrollbar,
style: {
overflowX: "hidden"
}
}, React.createElement("div", {
ref: headerScrollRef,
style: {
overflow: "hidden"
}
}, React.createElement(TaskListHeader, Object.assign({}, headerProps))), React.createElement("div", {
ref: horizontalContainerRef,
className: horizontalContainerClass,
style: ganttHeight ? {
height: ganttHeight
} : {}
}, React.createElement("div", {
style: {
height: virtualizer.getTotalSize() + "px",
width: "100%",
position: "relative"
}
}, React.createElement(TaskListTable, Object.assign({}, tableProps))))));
};
function parseTimeToMinutes(t) {
var parts = t.split(":").map(Number);
return parts[0] * 60 + parts[1] + (parts[2] ? parts[2] / 60 : 0);
}
function toDateString(date) {
var y = date.getFullYear();
var m = String(date.getMonth() + 1).padStart(2, "0");
var d = String(date.getDate()).padStart(2, "0");
return y + "-" + m + "-" + d;
}
function isHoliday(date, cal) {
if (cal.holidays && cal.holidays.length > 0) {
return cal.holidays.includes(toDateString(date));
} else {
return false;
}
}
function isOffDay(date, cal) {
if (cal.off_days && cal.off_days.length > 0) {
return cal.off_days.includes(date.getDay()) || isHoliday(date, cal);
} else {
return false;
}
}
function getShiftsForDay(date, cal) {
if (isOffDay(date, cal) || !cal.shifts) return [];
return cal.shifts.map(function (_ref) {
var s = _ref[0],
e = _ref[1];
return {
start: parseTimeToMinutes(s),
end: parseTimeToMinutes(e)
};
});
}
function getWorkingIntervals(start, end, cal) {
if (start >= end) return [];
var intervals = [];
var cursor = new Date(start);
cursor.setHours(0, 0, 0, 0);
while (cursor <= end) {
var shifts = getShiftsForDay(cursor, cal);
for (var _iterator = _createForOfIteratorHelperLoose(shifts), _step; !(_step = _iterator()).done;) {
var shift = _step.value;
var shiftStart = new Date(cursor);
shiftStart.setHours(Math.floor(shift.start / 60), Math.floor(shift.start % 60), Math.round(shift.start % 1 * 60), 0);
var shiftEnd = new Date(cursor);
shiftEnd.setHours(Math.floor(shift.end / 60), Math.floor(shift.end % 60), Math.round(shift.end % 1 * 60), 0);
var intervalStart = shiftStart < start ? start : shiftStart;
var intervalEnd = shiftEnd > end ? end : shiftEnd;
if (intervalStart < intervalEnd) {
intervals.push({
start: intervalStart,
end: intervalEnd
});
}
}
cursor.setDate(cursor.getDate() + 1);
}
return intervals;
}
function snapToWorkingTime(date, cal, direction) {
var MAX_DAYS = 60;
var result = new Date(date);
for (var attempt = 0; attempt < MAX_DAYS * 24 * 60; attempt++) {
var dayStart = new Date(result);
dayStart.setHours(0, 0, 0, 0);
var shifts = getShiftsForDay(dayStart, cal);
if (shifts.length > 0) {
if (direction === "forward") {
var currentMins = result.getHours() * 60 + result.getMinutes() + result.getSeconds() / 60;
for (var _iterator2 = _createForOfIteratorHelperLoose(shifts), _step2; !(_step2 = _iterator2()).done;) {
var shift = _step2.value;
if (currentMins <= shift.end) {
if (currentMins < shift.start) {
result.setHours(Math.floor(shift.start / 60), Math.round(shift.start % 60), 0, 0);
}
return result;
}
}
result.setDate(result.getDate() + 1);
result.setHours(0, 0, 0, 0);
} else {
var _currentMins = result.getHours() * 60 + result.getMinutes() + result.getSeconds() / 60;
for (var i = shifts.length - 1; i >= 0; i--) {
if (_currentMins >= shifts[i].start) {
if (_currentMins > shifts[i].end) {
result.setHours(Math.floor(shifts[i].end / 60), Math.round(shifts[i].end % 60), 0, 0);
}
return result;
}
}
result.setDate(result.getDate() - 1);
result.setHours(23, 59, 59, 0);
}
} else {
if (direction === "forward") {
result.setDate(result.getDate() + 1);
result.setHours(0, 0, 0, 0);
} else {
result.setDate(result.getDate() - 1);
result.setHours(23, 59, 59, 0);
}
}
}
return date;
}
function getQuarterNumber(date, quarterStart) {
var month = date.getMonth();
var offset = (month - quarterStart + 12) % 12;
return Math.floor(offset / 3) + 1;
}
var styles$5 = {"gridRow":"_2dZTy","gridRowLookAhead":"_2RRca","gridRowLine":"_3rUKi","gridTick":"_RuwuK","gridTickDashed":"_Zh9jh","darkerGridRow":"_2M-tt"};
var GridBody = function GridBody(_ref) {
var _projectCalendar$week;
var tasks = _ref.tasks,
scheduleType = _ref.scheduleType,
dates = _ref.dates,
rowHeight = _ref.rowHeight,
svgWidth = _ref.svgWidth,
columnWidth = _ref.columnWidth,
todayColor = _ref.todayColor,
weekendColor = _ref.weekendColor,
rtl = _ref.rtl,
_ref$virtualItems = _ref.virtualItems,
virtualItems = _ref$virtualItems === void 0 ? [] : _ref$virtualItems,
visibleStartY = _ref.visibleStartY,
visibleEndY = _ref.visibleEndY,
projectCalendar = _ref.projectCalendar,
viewMode = _ref.viewMode;
var visibleHeight = visibleEndY - visibleStartY;
var now = new Date();
var items = virtualItems.length > 0 ? virtualItems : tasks.map(function (_, i) {
return {
index: i,
start: i * rowHeight,
end: (i + 1) * rowHeight,
size: rowHeight,
key: i
};
});
var isDayOff = function isDayOff(date) {
if (projectCalendar) return isOffDay(date, projectCalendar);
var d = date.getDay();
return d === 0 || d === 6;
};
var isTodayColumn = function isTodayColumn(i) {
var date = dates[i];
var next = dates[i + 1];
if (next && date <= now && next > now) return true;
if (!next && date <= now) {
var step = date.getTime() - dates[i - 1].getTime();
var end = addToDate(date, step, "millisecond");
return end > now;
}
return false;
};
var todayRects = [];
var offDayRects = [];
var weekStartDay = (_projectCalendar$week = projectCalendar === null || projectCalendar === void 0 ? void 0 : projectCalendar.week_start) != null ? _projectCalendar$week : 1;
for (var i = 0, x = 0; i < dates.length; i++, x += columnWidth) {
if (isTodayColumn(i)) {
todayRects.push(React.createElement("rect", {
key: "today-" + i,
x: rtl ? x + columnWidth : x,
y: visibleStartY,
width: columnWidth,
height: visibleHeight,
fill: todayColor
}));
}
if (viewMode !== ViewMode.Month && viewMode !== ViewMode.Quarter) {
var _dates;
var pEnd = (_dates = dates[i + 1]) != null ? _dates : addToDate(dates[i], 1, "day");
var periodMs = pEnd.getTime() - dates[i].getTime();
if (periodMs > 0) {
var cursor = new Date(dates[i]);
cursor.setHours(0, 0, 0, 0);
while (cursor.getTime() < pEnd.getTime()) {
if (isDayOff(cursor)) {
var ds = cursor.getTime() - dates[i].getTime();
var de = ds + 86400000;
var startFrac = Math.max(0, ds) / periodMs;
var endFrac = Math.min(periodMs, de) / periodMs;
var rw = (endFrac - startFrac) * columnWidth;
if (rw > 0.5) {
offDayRects.push(React.createElement("rect", {
key: "offday-" + i + "-" + cursor.getTime(),
x: x + startFrac * columnWidth,
y: visibleStartY,
width: rw,
height: visibleHeight,
fill: weekendColor
}));
}
}
cursor.setDate(cursor.getDate() + 1);
}
}
}
}
var isDayView = viewMode === ViewMode.Day;
var tickLines = dates.map(function (date, i) {
var tickClass = styles$5.gridTick;
if (isDayView) {
tickClass = date.getDay() === weekStartDay ? styles$5.gridTick : styles$5.gridTickDashed;
}
return React.createElement("line", {
key: "tick-" + i,
x1: i * columnWidth,
y1: visibleStartY,
x2: i * columnWidth,
y2: visibleEndY,
className: tickClass
});
});
var rowBackgrounds = [];
var rowLines = [];
var rowOverlays = [];
rowLines.push(React.createElement("line", {
key: "top-line",
x1: 0,
y1: visibleStartY,
x2: svgWidth,
y2: visibleStartY,
className: styles$5.gridRowLine
}));
var showPerRowOffDays = viewMode !== ViewMode.Month && viewMode !== ViewMode.Quarter;
for (var _iterator = _createForOfIteratorHelperLoose(items), _step; !(_step = _iterator()).done;) {
var vi = _step.value;
var task = tasks[vi.index];
if (!task) break;
var y = vi.start;
var isMilestone = task.type === "milestone";
var rowClass = isMilestone ? styles$5.darkerGridRow : scheduleType === "lookAhead" ? styles$5.gridRowLookAhead : styles$5.gridRow;
rowBackgrounds.push(React.createElement("rect", {
key: "bg-" + vi.key,
x: 0,
y: y,
width: svgWidth,
height: rowHeight,
className: rowClass
}));
rowLines.push(React.createElement("line", {
key: "line-" + vi.key,
x1: 0,
y1: y + rowHeight,
x2: svgWidth,
y2: y + rowHeight,
className: styles$5.gridRowLine
}));
if (showPerRowOffDays) {
var rowEven = vi.index % 2 === 1;
var rowFill = isMilestone ? "#e6e4e4" : scheduleType === "lookAhead" ? "#fff" : rowEven ? "#f5f5f5" : "#fff";
rowOverlays.push(React.createElement("rect", {
key: "row-clean-" + vi.key,
x: 0,
y: y,
width: svgWidth,
height: rowHeight,
fill: rowFill
}));
var cal = task.calendar;
if (cal) {
for (var _i = 0, _x = 0; _i < dates.length; _i++, _x += columnWidth) {
var _dates2;
var _pEnd = (_dates2 = dates[_i + 1]) != null ? _dates2 : addToDate(dates[_i], 1, "day");
var _periodMs = _pEnd.getTime() - dates[_i].getTime();
if (_periodMs <= 0) continue;
var _cursor = new Date(dates[_i]);
_cursor.setHours(0, 0, 0, 0);
while (_cursor.getTime() < _pEnd.getTime()) {
if (isOffDay(_cursor, cal)) {
var _ds = _cursor.getTime() - dates[_i].getTime();
var _de = _ds + 86400000;
var _startFrac = Math.max(0, _ds) / _periodMs;
var _endFrac = Math.min(_periodMs, _de) / _periodMs;