gantt-lib 0.123.0 → 0.124.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/core/scheduling/index.d.mts +1 -1
- package/dist/core/scheduling/index.d.ts +1 -1
- package/dist/core/scheduling/index.js +157 -0
- package/dist/core/scheduling/index.js.map +1 -1
- package/dist/core/scheduling/index.mjs +155 -0
- package/dist/core/scheduling/index.mjs.map +1 -1
- package/dist/{index-OZVb2o_D.d.mts → index-DD3YvhvA.d.mts} +38 -1
- package/dist/{index-OZVb2o_D.d.ts → index-DD3YvhvA.d.ts} +38 -1
- package/dist/index.css.map +1 -1
- package/dist/index.d.mts +6 -2
- package/dist/index.d.ts +6 -2
- package/dist/index.js +217 -18
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +215 -18
- package/dist/index.mjs.map +1 -1
- package/dist/styles.css +32 -0
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -550,6 +550,159 @@ function calculateSuccessorDate(predecessorStart, predecessorEnd, linkType, lag
|
|
|
550
550
|
return shiftBusinessDayOffset(anchorDate, offset, weekendPredicate);
|
|
551
551
|
}
|
|
552
552
|
|
|
553
|
+
// src/core/scheduling/criticalPath.ts
|
|
554
|
+
function computeCriticalPath(tasks, options = {}) {
|
|
555
|
+
const { businessDays = false, weekendPredicate } = options;
|
|
556
|
+
const taskById = new Map(tasks.map((task) => [task.id, task]));
|
|
557
|
+
const childIds = /* @__PURE__ */ new Set();
|
|
558
|
+
for (const task of tasks) {
|
|
559
|
+
if (task.parentId) childIds.add(task.parentId);
|
|
560
|
+
}
|
|
561
|
+
const leafTasks = tasks.filter((task) => !childIds.has(task.id));
|
|
562
|
+
const leafIds = new Set(leafTasks.map((task) => task.id));
|
|
563
|
+
const leafIdsByAncestor = /* @__PURE__ */ new Map();
|
|
564
|
+
for (const leaf of leafTasks) {
|
|
565
|
+
let ancestor = leaf.parentId;
|
|
566
|
+
while (ancestor) {
|
|
567
|
+
const set = leafIdsByAncestor.get(ancestor) ?? /* @__PURE__ */ new Set();
|
|
568
|
+
set.add(leaf.id);
|
|
569
|
+
leafIdsByAncestor.set(ancestor, set);
|
|
570
|
+
ancestor = taskById.get(ancestor)?.parentId;
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
const durationOf = (task) => getTaskDuration(task.startDate, task.endDate, businessDays, weekendPredicate);
|
|
574
|
+
const projectStartDate = leafTasks.reduce((earliest, task) => {
|
|
575
|
+
const taskStart = parseDateOnly(task.startDate);
|
|
576
|
+
return taskStart.getTime() < earliest.getTime() ? taskStart : earliest;
|
|
577
|
+
}, parseDateOnly(leafTasks[0]?.startDate ?? /* @__PURE__ */ new Date()));
|
|
578
|
+
const offsetFromProjectStart = (date) => {
|
|
579
|
+
const targetDate = parseDateOnly(date);
|
|
580
|
+
if (businessDays && weekendPredicate) {
|
|
581
|
+
return getBusinessDayOffset(projectStartDate, targetDate, weekendPredicate);
|
|
582
|
+
}
|
|
583
|
+
return Math.round((targetDate.getTime() - projectStartDate.getTime()) / DAY_MS);
|
|
584
|
+
};
|
|
585
|
+
const scheduledStart = /* @__PURE__ */ new Map();
|
|
586
|
+
for (const leaf of leafTasks) {
|
|
587
|
+
scheduledStart.set(leaf.id, offsetFromProjectStart(leaf.startDate));
|
|
588
|
+
}
|
|
589
|
+
const succByPred = /* @__PURE__ */ new Map();
|
|
590
|
+
const predBySucc = /* @__PURE__ */ new Map();
|
|
591
|
+
const seenEdges = /* @__PURE__ */ new Set();
|
|
592
|
+
const addEdge = (predecessorId, succId, lag, type) => {
|
|
593
|
+
const edgeKey = `${predecessorId}|${succId}|${type}`;
|
|
594
|
+
if (seenEdges.has(edgeKey)) return;
|
|
595
|
+
seenEdges.add(edgeKey);
|
|
596
|
+
const outEdges = succByPred.get(predecessorId) ?? [];
|
|
597
|
+
outEdges.push({ succId, lag, type });
|
|
598
|
+
succByPred.set(predecessorId, outEdges);
|
|
599
|
+
const inEdges = predBySucc.get(succId) ?? [];
|
|
600
|
+
inEdges.push({ predId: predecessorId, lag, type });
|
|
601
|
+
predBySucc.set(succId, inEdges);
|
|
602
|
+
};
|
|
603
|
+
for (const succ of leafTasks) {
|
|
604
|
+
for (const dep of succ.dependencies ?? []) {
|
|
605
|
+
const lag = getDependencyLag(dep);
|
|
606
|
+
if (leafIds.has(dep.taskId)) {
|
|
607
|
+
addEdge(dep.taskId, succ.id, lag, dep.type);
|
|
608
|
+
continue;
|
|
609
|
+
}
|
|
610
|
+
const descendants = leafIdsByAncestor.get(dep.taskId);
|
|
611
|
+
if (!descendants || descendants.size === 0) continue;
|
|
612
|
+
for (const leafId of descendants) {
|
|
613
|
+
if (leafId === succ.id) continue;
|
|
614
|
+
addEdge(leafId, succ.id, lag, dep.type);
|
|
615
|
+
}
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
const indegree = /* @__PURE__ */ new Map();
|
|
619
|
+
for (const leaf of leafTasks) indegree.set(leaf.id, 0);
|
|
620
|
+
for (const edges of succByPred.values()) {
|
|
621
|
+
for (const { succId } of edges) {
|
|
622
|
+
indegree.set(succId, (indegree.get(succId) ?? 0) + 1);
|
|
623
|
+
}
|
|
624
|
+
}
|
|
625
|
+
const order = [];
|
|
626
|
+
const enqueued = /* @__PURE__ */ new Set();
|
|
627
|
+
const queue = leafTasks.filter((leaf) => (indegree.get(leaf.id) ?? 0) === 0).map((leaf) => leaf.id);
|
|
628
|
+
for (const id of queue) enqueued.add(id);
|
|
629
|
+
while (queue.length > 0) {
|
|
630
|
+
const current = queue.shift();
|
|
631
|
+
order.push(current);
|
|
632
|
+
for (const { succId } of succByPred.get(current) ?? []) {
|
|
633
|
+
const next = (indegree.get(succId) ?? 0) - 1;
|
|
634
|
+
indegree.set(succId, next);
|
|
635
|
+
if (next === 0 && !enqueued.has(succId)) {
|
|
636
|
+
enqueued.add(succId);
|
|
637
|
+
queue.push(succId);
|
|
638
|
+
}
|
|
639
|
+
}
|
|
640
|
+
}
|
|
641
|
+
const projectFinish = Math.max(
|
|
642
|
+
0,
|
|
643
|
+
...leafTasks.map((leaf) => (scheduledStart.get(leaf.id) ?? 0) + durationOf(leaf))
|
|
644
|
+
);
|
|
645
|
+
const LF = /* @__PURE__ */ new Map();
|
|
646
|
+
const LS = /* @__PURE__ */ new Map();
|
|
647
|
+
for (const leaf of leafTasks) LF.set(leaf.id, projectFinish);
|
|
648
|
+
for (let i = order.length - 1; i >= 0; i--) {
|
|
649
|
+
const id = order[i];
|
|
650
|
+
const task = taskById.get(id);
|
|
651
|
+
const durPred = durationOf(task);
|
|
652
|
+
const outEdges = succByPred.get(id) ?? [];
|
|
653
|
+
let lf = projectFinish;
|
|
654
|
+
if (outEdges.length > 0) {
|
|
655
|
+
const candidates = outEdges.map(({ succId, lag, type }) => {
|
|
656
|
+
const succLs = LS.get(succId) ?? projectFinish;
|
|
657
|
+
const durSucc = durationOf(taskById.get(succId));
|
|
658
|
+
switch (type) {
|
|
659
|
+
case "FS":
|
|
660
|
+
return succLs - lag;
|
|
661
|
+
case "SS":
|
|
662
|
+
return succLs - lag + durPred;
|
|
663
|
+
case "FF":
|
|
664
|
+
return succLs + durSucc - lag;
|
|
665
|
+
case "SF":
|
|
666
|
+
return succLs + durSucc - lag + durPred;
|
|
667
|
+
default:
|
|
668
|
+
return projectFinish;
|
|
669
|
+
}
|
|
670
|
+
});
|
|
671
|
+
lf = Math.min(projectFinish, ...candidates);
|
|
672
|
+
}
|
|
673
|
+
LF.set(id, lf);
|
|
674
|
+
LS.set(id, lf - durPred);
|
|
675
|
+
}
|
|
676
|
+
const critical = /* @__PURE__ */ new Set();
|
|
677
|
+
const ordered = new Set(order);
|
|
678
|
+
for (const leaf of leafTasks) {
|
|
679
|
+
if (!ordered.has(leaf.id)) continue;
|
|
680
|
+
const hasGraphEdge = (succByPred.get(leaf.id)?.length ?? 0) > 0 || (predBySucc.get(leaf.id)?.length ?? 0) > 0;
|
|
681
|
+
if (!hasGraphEdge && (leaf.dependencies?.length ?? 0) > 0) continue;
|
|
682
|
+
const es = scheduledStart.get(leaf.id) ?? 0;
|
|
683
|
+
const ls = LS.get(leaf.id) ?? 0;
|
|
684
|
+
if (ls - es <= 0) critical.add(leaf.id);
|
|
685
|
+
}
|
|
686
|
+
return critical;
|
|
687
|
+
}
|
|
688
|
+
function extendCriticalIdsToParents(criticalLeafIds, tasks) {
|
|
689
|
+
const result = new Set(criticalLeafIds);
|
|
690
|
+
const parentByChild = /* @__PURE__ */ new Map();
|
|
691
|
+
for (const task of tasks) {
|
|
692
|
+
if (task.parentId) parentByChild.set(task.id, task.parentId);
|
|
693
|
+
}
|
|
694
|
+
const stack = Array.from(criticalLeafIds);
|
|
695
|
+
while (stack.length > 0) {
|
|
696
|
+
const id = stack.pop();
|
|
697
|
+
const parentId = parentByChild.get(id);
|
|
698
|
+
if (parentId && !result.has(parentId)) {
|
|
699
|
+
result.add(parentId);
|
|
700
|
+
stack.push(parentId);
|
|
701
|
+
}
|
|
702
|
+
}
|
|
703
|
+
return result;
|
|
704
|
+
}
|
|
705
|
+
|
|
553
706
|
// src/core/scheduling/commands.ts
|
|
554
707
|
function buildTaskRangeFromStart(startDate, duration, businessDays = false, weekendPredicate, snapDirection = 1) {
|
|
555
708
|
const normalizedStart = businessDays && weekendPredicate ? alignToWorkingDay(startDate, snapDirection, weekendPredicate) : normalizeUTCDate(startDate);
|
|
@@ -2412,8 +2565,7 @@ function handleGlobalMouseMove(e) {
|
|
|
2412
2565
|
activeDrag.weekendPredicate,
|
|
2413
2566
|
activeDrag.cascadeContext
|
|
2414
2567
|
);
|
|
2415
|
-
const
|
|
2416
|
-
const previewTasks = hasTasksWithIncomingDependencies ? (() => {
|
|
2568
|
+
const previewTasks = (() => {
|
|
2417
2569
|
const mergedPreviewTaskById = new Map(activeDrag.cascadeContext?.taskById);
|
|
2418
2570
|
for (const task of cascadeResult) {
|
|
2419
2571
|
mergedPreviewTaskById.set(task.id, task);
|
|
@@ -2434,7 +2586,7 @@ function handleGlobalMouseMove(e) {
|
|
|
2434
2586
|
) : task.dependencies
|
|
2435
2587
|
};
|
|
2436
2588
|
});
|
|
2437
|
-
})()
|
|
2589
|
+
})();
|
|
2438
2590
|
const overrides = /* @__PURE__ */ new Map();
|
|
2439
2591
|
overrides.set(dragId, { left: newLeft, width: newWidth });
|
|
2440
2592
|
for (const task of cascadeResult) {
|
|
@@ -2837,10 +2989,10 @@ var useTaskDrag = (options) => {
|
|
|
2837
2989
|
// src/components/TaskRow/TaskRow.tsx
|
|
2838
2990
|
import { Fragment, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
2839
2991
|
var arePropsEqual = (prevProps, nextProps) => {
|
|
2840
|
-
return prevProps.task.id === nextProps.task.id && prevProps.task.name === nextProps.task.name && prevProps.task.startDate === nextProps.task.startDate && prevProps.task.endDate === nextProps.task.endDate && prevProps.task.baselineStartDate === nextProps.task.baselineStartDate && prevProps.task.baselineEndDate === nextProps.task.baselineEndDate && prevProps.task.type === nextProps.task.type && prevProps.task.color === nextProps.task.color && prevProps.task.progress === nextProps.task.progress && prevProps.task.accepted === nextProps.task.accepted && prevProps.monthStart.getTime() === nextProps.monthStart.getTime() && prevProps.dayWidth === nextProps.dayWidth && prevProps.rowHeight === nextProps.rowHeight && prevProps.overridePosition?.left === nextProps.overridePosition?.left && prevProps.overridePosition?.width === nextProps.overridePosition?.width && prevProps.previewPositionStore === nextProps.previewPositionStore && prevProps.allTasks === nextProps.allTasks && prevProps.disableConstraints === nextProps.disableConstraints && prevProps.task.locked === nextProps.task.locked && prevProps.task.synced === nextProps.task.synced && prevProps.task.divider === nextProps.task.divider && prevProps.highlightExpiredTasks === nextProps.highlightExpiredTasks && prevProps.showBaseline === nextProps.showBaseline && prevProps.isFilterMatch === nextProps.isFilterMatch && prevProps.businessDays === nextProps.businessDays && prevProps.customDays === nextProps.customDays && prevProps.isWeekend === nextProps.isWeekend && prevProps.disableTaskDrag === nextProps.disableTaskDrag && prevProps.disableDependencyEditing === nextProps.disableDependencyEditing && prevProps.isDependencyDragActive === nextProps.isDependencyDragActive && prevProps.viewMode === nextProps.viewMode;
|
|
2992
|
+
return prevProps.task.id === nextProps.task.id && prevProps.task.name === nextProps.task.name && prevProps.task.startDate === nextProps.task.startDate && prevProps.task.endDate === nextProps.task.endDate && prevProps.task.baselineStartDate === nextProps.task.baselineStartDate && prevProps.task.baselineEndDate === nextProps.task.baselineEndDate && prevProps.task.type === nextProps.task.type && prevProps.task.color === nextProps.task.color && prevProps.task.progress === nextProps.task.progress && prevProps.task.accepted === nextProps.task.accepted && prevProps.monthStart.getTime() === nextProps.monthStart.getTime() && prevProps.dayWidth === nextProps.dayWidth && prevProps.rowHeight === nextProps.rowHeight && prevProps.overridePosition?.left === nextProps.overridePosition?.left && prevProps.overridePosition?.width === nextProps.overridePosition?.width && prevProps.previewPositionStore === nextProps.previewPositionStore && prevProps.allTasks === nextProps.allTasks && prevProps.disableConstraints === nextProps.disableConstraints && prevProps.task.locked === nextProps.task.locked && prevProps.task.synced === nextProps.task.synced && prevProps.task.divider === nextProps.task.divider && prevProps.highlightExpiredTasks === nextProps.highlightExpiredTasks && prevProps.isCritical === nextProps.isCritical && prevProps.showBaseline === nextProps.showBaseline && prevProps.isFilterMatch === nextProps.isFilterMatch && prevProps.businessDays === nextProps.businessDays && prevProps.customDays === nextProps.customDays && prevProps.isWeekend === nextProps.isWeekend && prevProps.disableTaskDrag === nextProps.disableTaskDrag && prevProps.disableDependencyEditing === nextProps.disableDependencyEditing && prevProps.isDependencyDragActive === nextProps.isDependencyDragActive && prevProps.viewMode === nextProps.viewMode;
|
|
2841
2993
|
};
|
|
2842
2994
|
var TaskRow = React2.memo(
|
|
2843
|
-
({ task, monthStart, dayWidth, rowHeight, onTasksChange, onDragStateChange, rowIndex, allTasks, enableAutoSchedule, disableConstraints, overridePosition, previewPositionStore, onCascadeProgress, onCascade, divider, highlightExpiredTasks, showBaseline = false, isFilterMatch = false, businessDays, customDays, isWeekend: isWeekend3, disableTaskDrag = false, disableDependencyEditing = false, onDependencyPortPointerDown, isDependencyDragActive = false, viewMode = "day" }) => {
|
|
2995
|
+
({ task, monthStart, dayWidth, rowHeight, onTasksChange, onDragStateChange, rowIndex, allTasks, enableAutoSchedule, disableConstraints, overridePosition, previewPositionStore, onCascadeProgress, onCascade, divider, highlightExpiredTasks, isCritical = false, showBaseline = false, isFilterMatch = false, businessDays, customDays, isWeekend: isWeekend3, disableTaskDrag = false, disableDependencyEditing = false, onDependencyPortPointerDown, isDependencyDragActive = false, viewMode = "day" }) => {
|
|
2844
2996
|
const defaultParentBarColor = "#782FC4";
|
|
2845
2997
|
const { divider: taskDivider } = task;
|
|
2846
2998
|
const normalizedTask = useMemo2(() => normalizeTaskDatesForType(task), [task]);
|
|
@@ -3030,7 +3182,7 @@ var TaskRow = React2.memo(
|
|
|
3030
3182
|
"div",
|
|
3031
3183
|
{
|
|
3032
3184
|
"data-taskbar": true,
|
|
3033
|
-
className: `gantt-tr-taskBar ${isDragging ? "gantt-tr-dragging" : ""} ${task.locked ? "gantt-tr-locked" : ""} ${task.synced === false ? "gantt-tr-unsynced" : ""} ${isParent ? "gantt-tr-parentBar" : ""} ${milestone ? "gantt-tr-milestone" : ""}`,
|
|
3185
|
+
className: `gantt-tr-taskBar ${isDragging ? "gantt-tr-dragging" : ""} ${task.locked ? "gantt-tr-locked" : ""} ${task.synced === false ? "gantt-tr-unsynced" : ""} ${isParent ? "gantt-tr-parentBar" : ""} ${milestone ? "gantt-tr-milestone" : ""} ${isCritical ? "gantt-tr-critical" : ""}`,
|
|
3034
3186
|
style: {
|
|
3035
3187
|
left: `${visualLeft}px`,
|
|
3036
3188
|
...barStyle,
|
|
@@ -3445,6 +3597,7 @@ var DependencyLines = React6.memo(({
|
|
|
3445
3597
|
rowIndexByTaskId,
|
|
3446
3598
|
dragOverrides,
|
|
3447
3599
|
selectedDep,
|
|
3600
|
+
criticalTaskIds,
|
|
3448
3601
|
businessDays = true,
|
|
3449
3602
|
weekendPredicate,
|
|
3450
3603
|
onDependencyClick
|
|
@@ -3583,6 +3736,9 @@ var DependencyLines = React6.memo(({
|
|
|
3583
3736
|
const to = { x: finalToX, y: toY };
|
|
3584
3737
|
const path = calculateDependencyPath(from, to, arrivesFromRight);
|
|
3585
3738
|
const hasCycle = cycleInfo.has(edge.predecessorId) || cycleInfo.has(edge.successorId);
|
|
3739
|
+
const isCritical = Boolean(
|
|
3740
|
+
criticalTaskIds?.has(edge.predecessorId) && criticalTaskIds.has(edge.successorId)
|
|
3741
|
+
);
|
|
3586
3742
|
lines2.push({
|
|
3587
3743
|
id: `${edge.predecessorId}-${edge.successorId}-${edge.type}`,
|
|
3588
3744
|
predecessorId: edge.predecessorId,
|
|
@@ -3595,12 +3751,13 @@ var DependencyLines = React6.memo(({
|
|
|
3595
3751
|
toX: finalToX,
|
|
3596
3752
|
fromY,
|
|
3597
3753
|
reverseOrder,
|
|
3598
|
-
isVirtual
|
|
3754
|
+
isVirtual,
|
|
3755
|
+
isCritical
|
|
3599
3756
|
});
|
|
3600
3757
|
}
|
|
3601
3758
|
}
|
|
3602
3759
|
return lines2;
|
|
3603
|
-
}, [tasks, allTasks, taskPositions, taskIndices, cycleInfo, collapsedParentIds]);
|
|
3760
|
+
}, [tasks, allTasks, taskPositions, taskIndices, cycleInfo, collapsedParentIds, criticalTaskIds]);
|
|
3604
3761
|
const svgHeight = totalHeight ?? tasks.length * rowHeight;
|
|
3605
3762
|
return /* @__PURE__ */ jsxs5(
|
|
3606
3763
|
"svg",
|
|
@@ -3687,20 +3844,41 @@ var DependencyLines = React6.memo(({
|
|
|
3687
3844
|
}
|
|
3688
3845
|
)
|
|
3689
3846
|
}
|
|
3847
|
+
),
|
|
3848
|
+
/* @__PURE__ */ jsx7(
|
|
3849
|
+
"marker",
|
|
3850
|
+
{
|
|
3851
|
+
id: "arrowhead-critical",
|
|
3852
|
+
markerWidth: "8",
|
|
3853
|
+
markerHeight: "6",
|
|
3854
|
+
markerUnits: "userSpaceOnUse",
|
|
3855
|
+
refX: "7",
|
|
3856
|
+
refY: "3",
|
|
3857
|
+
orient: "auto",
|
|
3858
|
+
children: /* @__PURE__ */ jsx7(
|
|
3859
|
+
"polygon",
|
|
3860
|
+
{
|
|
3861
|
+
points: "0 0, 8 3, 0 6",
|
|
3862
|
+
fill: "var(--gantt-critical-path-color, #dc2626)"
|
|
3863
|
+
}
|
|
3864
|
+
)
|
|
3865
|
+
}
|
|
3690
3866
|
)
|
|
3691
3867
|
] }),
|
|
3692
|
-
lines.map(({ id, predecessorId, successorId, linkType, path, hasCycle, lag, fromX, toX, fromY, reverseOrder, isVirtual }) => {
|
|
3868
|
+
lines.map(({ id, predecessorId, successorId, linkType, path, hasCycle, lag, fromX, toX, fromY, reverseOrder, isVirtual, isCritical }) => {
|
|
3693
3869
|
const isHovered = hoveredLineId === id;
|
|
3694
3870
|
const isSelected = selectedDep != null && id === `${selectedDep.predecessorId}-${selectedDep.successorId}-${selectedDep.linkType}`;
|
|
3695
3871
|
let pathClassName = "gantt-dependency-path";
|
|
3696
3872
|
if (isSelected) pathClassName += " gantt-dependency-selected";
|
|
3697
3873
|
else if (hasCycle) pathClassName += " gantt-dependency-cycle";
|
|
3874
|
+
else if (isCritical) pathClassName += " gantt-dependency-critical";
|
|
3698
3875
|
if (isVirtual && !isSelected) pathClassName += " gantt-dependency-virtual";
|
|
3699
3876
|
let markerEnd;
|
|
3700
3877
|
if (isSelected) markerEnd = "url(#arrowhead-selected)";
|
|
3701
3878
|
else if (hasCycle) markerEnd = "url(#arrowhead-cycle)";
|
|
3879
|
+
else if (isCritical) markerEnd = "url(#arrowhead-critical)";
|
|
3702
3880
|
else markerEnd = "url(#arrowhead)";
|
|
3703
|
-
const lagColor = isSelected ? "#ef4444" : hasCycle ? "var(--gantt-dependency-cycle-color, #ef4444)" : "var(--gantt-dependency-line-color, #666666)";
|
|
3881
|
+
const lagColor = isSelected ? "#ef4444" : hasCycle ? "var(--gantt-dependency-cycle-color, #ef4444)" : isCritical ? "var(--gantt-critical-path-color, #dc2626)" : "var(--gantt-dependency-line-color, #666666)";
|
|
3704
3882
|
return /* @__PURE__ */ jsxs5(React6.Fragment, { children: [
|
|
3705
3883
|
/* @__PURE__ */ jsxs5(
|
|
3706
3884
|
"g",
|
|
@@ -12432,6 +12610,7 @@ function TaskGanttChartInner(props, ref) {
|
|
|
12432
12610
|
onTaskDateChangeModeChange: externalOnTaskDateChangeModeChange
|
|
12433
12611
|
} = props;
|
|
12434
12612
|
const dayWidth = !isTableMatrixMode ? props.dayWidth ?? 40 : 40;
|
|
12613
|
+
const criticalPathMode = !isTableMatrixMode && !isPlanFactMode ? props.criticalPathMode : void 0;
|
|
12435
12614
|
const viewMode = !isTableMatrixMode && !isPlanFactMode ? props.viewMode ?? "day" : "day";
|
|
12436
12615
|
const customDays = !isTableMatrixMode ? props.customDays : void 0;
|
|
12437
12616
|
const isWeekend3 = !isTableMatrixMode ? props.isWeekend : void 0;
|
|
@@ -12631,10 +12810,23 @@ function TaskGanttChartInner(props, ref) {
|
|
|
12631
12810
|
[resolvedRowContentLines, rowHeight]
|
|
12632
12811
|
);
|
|
12633
12812
|
const normalizedTasks = useMemo13(() => normalizeHierarchyTasks(tasks), [tasks]);
|
|
12813
|
+
const [previewTasksById, setPreviewTasksById] = useState12(/* @__PURE__ */ new Map());
|
|
12814
|
+
const previewNormalizedTasks = useMemo13(() => {
|
|
12815
|
+
if (previewTasksById.size === 0) return normalizedTasks;
|
|
12816
|
+
return normalizedTasks.map((task) => previewTasksById.get(task.id) ?? task);
|
|
12817
|
+
}, [normalizedTasks, previewTasksById]);
|
|
12634
12818
|
const isCustomWeekend = useMemo13(
|
|
12635
12819
|
() => createCustomDayPredicate({ customDays, isWeekend: isWeekend3 }),
|
|
12636
12820
|
[customDays, isWeekend3]
|
|
12637
12821
|
);
|
|
12822
|
+
const criticalTaskIds = useMemo13(() => {
|
|
12823
|
+
if (!criticalPathMode) return /* @__PURE__ */ new Set();
|
|
12824
|
+
const leafCritical = computeCriticalPath(previewNormalizedTasks, {
|
|
12825
|
+
businessDays,
|
|
12826
|
+
weekendPredicate: isCustomWeekend
|
|
12827
|
+
});
|
|
12828
|
+
return extendCriticalIdsToParents(leafCritical, previewNormalizedTasks);
|
|
12829
|
+
}, [criticalPathMode, previewNormalizedTasks, businessDays, isCustomWeekend]);
|
|
12638
12830
|
const dateRangeTasks = useMemo13(() => {
|
|
12639
12831
|
if (isPlanFactMode) {
|
|
12640
12832
|
return getPlanFactRangeTasks(normalizedTasks);
|
|
@@ -12679,8 +12871,11 @@ function TaskGanttChartInner(props, ref) {
|
|
|
12679
12871
|
if (filterMode === "hide" && taskFilter) {
|
|
12680
12872
|
tasks2 = tasks2.filter(taskFilter);
|
|
12681
12873
|
}
|
|
12874
|
+
if (criticalPathMode === "hide") {
|
|
12875
|
+
tasks2 = tasks2.filter((task) => criticalTaskIds.has(task.id));
|
|
12876
|
+
}
|
|
12682
12877
|
return tasks2;
|
|
12683
|
-
}, [normalizedTasks, collapsedParentIds, filterMode, taskFilter]);
|
|
12878
|
+
}, [normalizedTasks, collapsedParentIds, filterMode, taskFilter, criticalPathMode, criticalTaskIds]);
|
|
12684
12879
|
const matchedTaskIds = useMemo13(() => {
|
|
12685
12880
|
if (!taskFilter) return /* @__PURE__ */ new Set();
|
|
12686
12881
|
return new Set(visibleTasks.filter(taskFilter).map((task) => task.id));
|
|
@@ -12873,7 +13068,6 @@ function TaskGanttChartInner(props, ref) {
|
|
|
12873
13068
|
}, [effectiveRowHeight, tasks, visibleTasks]);
|
|
12874
13069
|
const [dragGuideLines, setDragGuideLines] = useState12(null);
|
|
12875
13070
|
const [draggedTaskOverride, setDraggedTaskOverride] = useState12(null);
|
|
12876
|
-
const [previewTasksById, setPreviewTasksById] = useState12(/* @__PURE__ */ new Map());
|
|
12877
13071
|
useEffect10(() => {
|
|
12878
13072
|
const result = validateDependencies(tasks);
|
|
12879
13073
|
setValidationResult(result);
|
|
@@ -13001,14 +13195,10 @@ function TaskGanttChartInner(props, ref) {
|
|
|
13001
13195
|
}
|
|
13002
13196
|
setCascadeOverrides((current) => arePositionMapsEqual(current, renderedOverrides) ? current : renderedOverrides);
|
|
13003
13197
|
setPreviewTasksById((current) => {
|
|
13004
|
-
const next = previewTasks.length > 0 ? new Map(previewTasks.
|
|
13198
|
+
const next = previewTasks.length > 0 ? new Map(previewTasks.map((task) => [task.id, task])) : /* @__PURE__ */ new Map();
|
|
13005
13199
|
return arePreviewTaskMapsEqual(current, next) ? current : next;
|
|
13006
13200
|
});
|
|
13007
13201
|
}, [previewPositionStore]);
|
|
13008
|
-
const previewNormalizedTasks = useMemo13(() => {
|
|
13009
|
-
if (previewTasksById.size === 0) return normalizedTasks;
|
|
13010
|
-
return normalizedTasks.map((task) => previewTasksById.get(task.id) ?? task);
|
|
13011
|
-
}, [normalizedTasks, previewTasksById]);
|
|
13012
13202
|
const previewVisibleTasks = useMemo13(() => {
|
|
13013
13203
|
if (previewTasksById.size === 0) return visibleTasks;
|
|
13014
13204
|
return visibleTasks.map((task) => previewTasksById.get(task.id) ?? task);
|
|
@@ -13608,7 +13798,8 @@ function TaskGanttChartInner(props, ref) {
|
|
|
13608
13798
|
selectedDep: selectedChip,
|
|
13609
13799
|
businessDays,
|
|
13610
13800
|
weekendPredicate: isCustomWeekend,
|
|
13611
|
-
onDependencyClick: handleDependencyLineClick
|
|
13801
|
+
onDependencyClick: handleDependencyLineClick,
|
|
13802
|
+
criticalTaskIds: criticalPathMode ? criticalTaskIds : void 0
|
|
13612
13803
|
}
|
|
13613
13804
|
),
|
|
13614
13805
|
dependencyLineMenu && /* @__PURE__ */ jsxs16(
|
|
@@ -13678,6 +13869,9 @@ function TaskGanttChartInner(props, ref) {
|
|
|
13678
13869
|
} else {
|
|
13679
13870
|
setDragGuideLines((current) => current === null ? current : null);
|
|
13680
13871
|
setDraggedTaskOverride((current) => current === null ? current : null);
|
|
13872
|
+
previewPositionStore.clear();
|
|
13873
|
+
setCascadeOverrides((current) => current.size === 0 ? current : /* @__PURE__ */ new Map());
|
|
13874
|
+
setPreviewTasksById((current) => current.size === 0 ? current : /* @__PURE__ */ new Map());
|
|
13681
13875
|
}
|
|
13682
13876
|
},
|
|
13683
13877
|
rowIndex: index,
|
|
@@ -13690,6 +13884,7 @@ function TaskGanttChartInner(props, ref) {
|
|
|
13690
13884
|
highlightExpiredTasks,
|
|
13691
13885
|
showBaseline,
|
|
13692
13886
|
isFilterMatch: filterMode === "highlight" ? matchedTaskIds.has(task.id) : false,
|
|
13887
|
+
isCritical: criticalTaskIds.has(task.id),
|
|
13693
13888
|
businessDays,
|
|
13694
13889
|
customDays,
|
|
13695
13890
|
isWeekend: isWeekend3,
|
|
@@ -13811,6 +14006,7 @@ export {
|
|
|
13811
14006
|
cascadeByLinks,
|
|
13812
14007
|
clampDateRangeForIncomingFS,
|
|
13813
14008
|
clampTaskRangeForIncomingFS,
|
|
14009
|
+
computeCriticalPath,
|
|
13814
14010
|
computeLagFromDates,
|
|
13815
14011
|
computeParentDates,
|
|
13816
14012
|
computeParentProgress,
|
|
@@ -13819,6 +14015,7 @@ export {
|
|
|
13819
14015
|
detectCycles,
|
|
13820
14016
|
detectEdgeZone,
|
|
13821
14017
|
expired,
|
|
14018
|
+
extendCriticalIdsToParents,
|
|
13822
14019
|
findParentId,
|
|
13823
14020
|
flattenHierarchy,
|
|
13824
14021
|
formatDateLabel,
|