gantt-lib 0.84.0 → 0.85.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/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import React$1, { ReactNode } from 'react';
2
- import { T as Task$1, R as ResourceTimelineItem, V as ValidationResult, a as ResourcePlannerChartProps, b as ResourceTimelineResource } from './index-DGOZyXZt.js';
3
- export { D as DAY_MS, c as DependencyError, G as GanttChartMode, d as GanttDateRange, e as GridConfig, f as GridLine, L as LinkType, M as MonthSpan, g as ResourceTimelineMove, h as ResourceTimelineResourceMenuCommand, i as TaskBarGeometry, W as WeekendBlock, j as alignToWorkingDay, k as areTasksHierarchicallyRelated, l as buildAdjacencyList, m as buildTaskRangeFromEnd, n as buildTaskRangeFromStart, o as calculateSuccessorDate, p as cascadeByLinks, q as clampTaskRangeForIncomingFS, r as computeLagFromDates, s as computeParentDates, t as computeParentProgress, u as detectCycles, v as findParentId, w as getAllDependencyEdges, x as getAllDescendants, y as getBusinessDayOffset, z as getChildren, A as getDependencyLag, B as getSuccessorChain, C as getTaskDuration, E as getTransitiveCascadeChain, F as isAncestorTask, H as isTaskParent, I as moveTaskRange, J as moveTaskWithCascade, K as normalizeDependencyLag, N as normalizePredecessorDates, O as normalizeUTCDate, P as parseDateOnly, Q as recalculateIncomingLags, S as recalculateProjectSchedule, U as recalculateTaskFromDependencies, X as reflowTasksOnModeSwitch, Y as removeDependenciesBetweenTasks, Z as resizeTaskWithCascade, _ as shiftBusinessDayOffset, $ as universalCascade, a0 as validateDependencies } from './index-DGOZyXZt.js';
2
+ import { T as Task$1, R as ResourceTimelineItem, V as ValidationResult, a as ResourcePlannerChartProps, b as ResourceTimelineResource } from './index-BbdHmt1Q.js';
3
+ export { D as DAY_MS, c as DependencyError, G as GanttChartMode, d as GanttDateRange, e as GridConfig, f as GridLine, L as LinkType, M as MonthSpan, g as ResourceTimelineMove, h as ResourceTimelineResourceMenuCommand, i as TaskBarGeometry, W as WeekendBlock, j as alignToWorkingDay, k as areTasksHierarchicallyRelated, l as buildAdjacencyList, m as buildTaskRangeFromEnd, n as buildTaskRangeFromStart, o as calculateSuccessorDate, p as cascadeByLinks, q as clampTaskRangeForIncomingFS, r as computeLagFromDates, s as computeParentDates, t as computeParentProgress, u as detectCycles, v as findParentId, w as getAllDependencyEdges, x as getAllDescendants, y as getBusinessDayOffset, z as getChildren, A as getDependencyLag, B as getSuccessorChain, C as getTaskDuration, E as getTransitiveCascadeChain, F as isAncestorTask, H as isTaskParent, I as moveTaskRange, J as moveTaskWithCascade, K as normalizeDependencyLag, N as normalizePredecessorDates, O as normalizeTaskDependencyLags, P as normalizeUTCDate, Q as parseDateOnly, S as recalculateIncomingLags, U as recalculateProjectSchedule, X as recalculateTaskFromDependencies, Y as reflowTasksOnModeSwitch, Z as removeDependenciesBetweenTasks, _ as resizeTaskWithCascade, $ as shiftBusinessDayOffset, a0 as universalCascade, a1 as validateDependencies } from './index-BbdHmt1Q.js';
4
4
  import * as react_jsx_runtime from 'react/jsx-runtime';
5
5
  import * as RadixPopover from '@radix-ui/react-popover';
6
6
 
@@ -372,7 +372,7 @@ interface Task {
372
372
  * Optional array of task dependencies
373
373
  * - Each dependency references a predecessor task by ID
374
374
  * - Supports 4 link types: FS (finish-to-start), SS (start-to-start), FF (finish-to-finish), SF (start-to-finish)
375
- * - Lag is required (positive = delay, negative = overlap)
375
+ * - Lag is required (positive = delay; FS lag is clamped to zero)
376
376
  */
377
377
  dependencies?: TaskDependency[];
378
378
  /**
package/dist/index.js CHANGED
@@ -116,6 +116,7 @@ __export(index_exports, {
116
116
  normalizeHierarchyTasks: () => normalizeHierarchyTasks,
117
117
  normalizePredecessorDates: () => normalizePredecessorDates,
118
118
  normalizeTaskDates: () => normalizeTaskDates,
119
+ normalizeTaskDependencyLags: () => normalizeTaskDependencyLags,
119
120
  normalizeUTCDate: () => normalizeUTCDate,
120
121
  not: () => not,
121
122
  or: () => or,
@@ -586,17 +587,27 @@ function normalizePredecessorDates(predecessor, parseDateFn) {
586
587
  function getDependencyLag(dep) {
587
588
  return Number.isFinite(dep.lag) ? dep.lag : 0;
588
589
  }
590
+ function normalizeTaskDependencyLags(task) {
591
+ if (!task.dependencies?.length) {
592
+ return task;
593
+ }
594
+ let changed = false;
595
+ const dependencies = task.dependencies.map((dep) => {
596
+ const lag = getDependencyLag(dep);
597
+ const normalizedLag = dep.type === "FS" ? Math.max(0, lag) : lag;
598
+ if (normalizedLag === dep.lag) {
599
+ return dep;
600
+ }
601
+ changed = true;
602
+ return { ...dep, lag: normalizedLag };
603
+ });
604
+ return changed ? { ...task, dependencies } : task;
605
+ }
589
606
  function normalizeDependencyLag(linkType, lag, predecessorStart, predecessorEnd, businessDays = false, weekendPredicate) {
590
607
  if (linkType !== "FS") {
591
608
  return lag;
592
609
  }
593
- const predecessorDuration = getTaskDuration(
594
- predecessorStart,
595
- predecessorEnd,
596
- businessDays,
597
- weekendPredicate
598
- );
599
- return Math.max(-predecessorDuration, lag);
610
+ return Math.max(0, lag);
600
611
  }
601
612
  function computeLagFromDates(linkType, predStart, predEnd, succStart, succEnd, businessDays = false, weekendPredicate) {
602
613
  const pS = Date.UTC(predStart.getUTCFullYear(), predStart.getUTCMonth(), predStart.getUTCDate());
@@ -855,17 +866,11 @@ function clampTaskRangeForIncomingFS(task, proposedStart, proposedEnd, allTasks,
855
866
  continue;
856
867
  }
857
868
  const { predStart: predecessorStart, predEnd: predecessorEnd } = normalizePredecessorDates(predecessor, parseDateOnly);
858
- const predecessorDuration = getTaskDuration(
859
- predecessorStart,
860
- predecessorEnd,
861
- businessDays,
862
- weekendPredicate
863
- );
864
869
  const candidateMinStart = calculateSuccessorDate(
865
870
  predecessorStart,
866
871
  predecessorEnd,
867
872
  "FS",
868
- -predecessorDuration,
873
+ 0,
869
874
  businessDays,
870
875
  weekendPredicate
871
876
  );
@@ -976,11 +981,11 @@ function cascadeByLinks(movedTaskId, newStart, newEnd, allTasks, skipChildCascad
976
981
  const newChildEnd = new Date(origEnd.getTime() + parentEndDelta);
977
982
  visited.add(child.id);
978
983
  updatedDates.set(child.id, { start: newChildStart, end: newChildEnd });
979
- result.push({
984
+ result.push(normalizeTaskDependencyLags({
980
985
  ...child,
981
986
  startDate: newChildStart.toISOString().split("T")[0],
982
987
  endDate: newChildEnd.toISOString().split("T")[0]
983
- });
988
+ }));
984
989
  queue.push(child.id);
985
990
  }
986
991
  }
@@ -1016,11 +1021,11 @@ function cascadeByLinks(movedTaskId, newStart, newEnd, allTasks, skipChildCascad
1016
1021
  }
1017
1022
  visited.add(task.id);
1018
1023
  updatedDates.set(task.id, { start: newSuccStart, end: newSuccEnd });
1019
- result.push({
1024
+ result.push(normalizeTaskDependencyLags({
1020
1025
  ...task,
1021
1026
  startDate: newSuccStart.toISOString().split("T")[0],
1022
1027
  endDate: newSuccEnd.toISOString().split("T")[0]
1023
- });
1028
+ }));
1024
1029
  queue.push(task.id);
1025
1030
  break;
1026
1031
  }
@@ -1075,11 +1080,11 @@ function universalCascade(movedTask, newStart, newEnd, allTasks, businessDays =
1075
1080
  const updatedDates = /* @__PURE__ */ new Map();
1076
1081
  updatedDates.set(movedTask.id, { start: newStart, end: newEnd });
1077
1082
  const resultMap = /* @__PURE__ */ new Map();
1078
- resultMap.set(movedTask.id, {
1083
+ resultMap.set(movedTask.id, normalizeTaskDependencyLags({
1079
1084
  ...movedTask,
1080
1085
  startDate: newStart.toISOString().split("T")[0],
1081
1086
  endDate: newEnd.toISOString().split("T")[0]
1082
- });
1087
+ }));
1083
1088
  const queue = [[movedTask.id, "direct"]];
1084
1089
  const childShifted = /* @__PURE__ */ new Set();
1085
1090
  let iterations = 0;
@@ -1125,11 +1130,11 @@ function universalCascade(movedTask, newStart, newEnd, allTasks, businessDays =
1125
1130
  updatedDates.set(child.id, { start: childNewStart, end: childNewEnd });
1126
1131
  childShifted.add(child.id);
1127
1132
  queue.push([child.id, "child-delta"]);
1128
- resultMap.set(child.id, {
1133
+ resultMap.set(child.id, normalizeTaskDependencyLags({
1129
1134
  ...child,
1130
1135
  startDate: childNewStart.toISOString().split("T")[0],
1131
1136
  endDate: childNewEnd.toISOString().split("T")[0]
1132
- });
1137
+ }));
1133
1138
  }
1134
1139
  }
1135
1140
  const parentId = currentOriginal.parentId;
@@ -1147,11 +1152,11 @@ function universalCascade(movedTask, newStart, newEnd, allTasks, businessDays =
1147
1152
  if (!prev || prev.start.getTime() !== minStart.getTime() || prev.end.getTime() !== maxEnd.getTime()) {
1148
1153
  updatedDates.set(parentId, { start: minStart, end: maxEnd });
1149
1154
  queue.push([parentId, "parent-recalc"]);
1150
- resultMap.set(parentId, {
1155
+ resultMap.set(parentId, normalizeTaskDependencyLags({
1151
1156
  ...parent,
1152
1157
  startDate: minStart.toISOString().split("T")[0],
1153
1158
  endDate: maxEnd.toISOString().split("T")[0]
1154
- });
1159
+ }));
1155
1160
  }
1156
1161
  }
1157
1162
  }
@@ -1201,11 +1206,11 @@ function universalCascade(movedTask, newStart, newEnd, allTasks, businessDays =
1201
1206
  }
1202
1207
  updatedDates.set(task.id, { start: succNewStart, end: succNewEnd });
1203
1208
  queue.push([task.id, "dependency"]);
1204
- resultMap.set(task.id, {
1209
+ resultMap.set(task.id, normalizeTaskDependencyLags({
1205
1210
  ...task,
1206
1211
  startDate: succNewStart.toISOString().split("T")[0],
1207
1212
  endDate: succNewEnd.toISOString().split("T")[0]
1208
- });
1213
+ }));
1209
1214
  }
1210
1215
  }
1211
1216
  return Array.from(resultMap.values());
@@ -7908,6 +7913,13 @@ var ResourceTypeIcon = ({ type }) => {
7908
7913
  /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("path", { d: "M12 16h.01" })
7909
7914
  ] });
7910
7915
  };
7916
+ function isInactiveResourceStatus(status) {
7917
+ return status?.trim().toLocaleLowerCase() === "inactive";
7918
+ }
7919
+ var ResourceStatusLockIcon = () => /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("svg", { className: "gantt-resourceTimeline-resourceStatusIcon", width: "12", height: "12", viewBox: "0 0 24 24", "aria-hidden": "true", children: [
7920
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("rect", { x: "5", y: "11", width: "14", height: "10", rx: "2" }),
7921
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("path", { d: "M8 11V8a4 4 0 1 1 8 0v3" })
7922
+ ] });
7911
7923
  var ResourceHeader = ({
7912
7924
  resource,
7913
7925
  resourceId,
@@ -7937,6 +7949,7 @@ var ResourceHeader = ({
7937
7949
  const type = resource.type ?? "\u0414\u0440\u0443\u0433\u043E\u0435";
7938
7950
  const scope = resource.scope ?? "Project";
7939
7951
  const scopeLabel = RESOURCE_SCOPE_LABELS[scope] ?? scope;
7952
+ const isInactive = isInactiveResourceStatus(resource.status);
7940
7953
  const applyResourcePatch = (0, import_react14.useCallback)((patch) => {
7941
7954
  onResourceChange?.({ ...resource, ...patch });
7942
7955
  }, [onResourceChange, resource]);
@@ -7997,7 +8010,7 @@ var ResourceHeader = ({
7997
8010
  return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
7998
8011
  "div",
7999
8012
  {
8000
- className: `gantt-resourceTimeline-resourceHeader${menuOpen ? " gantt-resourceTimeline-resourceHeaderMenuOpen" : ""}`,
8013
+ className: `gantt-resourceTimeline-resourceHeader${menuOpen ? " gantt-resourceTimeline-resourceHeaderMenuOpen" : ""}${isInactive ? " gantt-resourceTimeline-resourceHeaderInactive" : ""}`,
8001
8014
  "data-resource-row-id": resourceId,
8002
8015
  style: {
8003
8016
  height: `${height}px`,
@@ -8064,7 +8077,18 @@ var ResourceHeader = ({
8064
8077
  onResourceNameClick?.(resourceId);
8065
8078
  },
8066
8079
  onDoubleClick: handleNameDoubleClick,
8067
- children: resource.name
8080
+ children: /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("span", { className: "gantt-resourceTimeline-resourceNameContent", children: [
8081
+ isInactive && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
8082
+ "span",
8083
+ {
8084
+ className: "gantt-resourceTimeline-resourceStatusMarker",
8085
+ "aria-label": `\u0420\u0435\u0441\u0443\u0440\u0441 ${resource.name} \u043D\u0435\u0430\u043A\u0442\u0438\u0432\u0435\u043D`,
8086
+ title: "\u041D\u0435\u0430\u043A\u0442\u0438\u0432\u0435\u043D",
8087
+ children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(ResourceStatusLockIcon, {})
8088
+ }
8089
+ ),
8090
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "gantt-resourceTimeline-resourceNameText", children: resource.name })
8091
+ ] })
8068
8092
  }
8069
8093
  )
8070
8094
  ] }),
@@ -10130,6 +10154,7 @@ var nameContains = (substring, caseSensitive = false) => (task) => {
10130
10154
  normalizeHierarchyTasks,
10131
10155
  normalizePredecessorDates,
10132
10156
  normalizeTaskDates,
10157
+ normalizeTaskDependencyLags,
10133
10158
  normalizeUTCDate,
10134
10159
  not,
10135
10160
  or,