gantt-lib 0.2.0 → 0.3.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.mjs CHANGED
@@ -1092,29 +1092,51 @@ var useTaskDrag = (options) => {
1092
1092
  // src/components/TaskRow/TaskRow.tsx
1093
1093
  import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
1094
1094
  var arePropsEqual = (prevProps, nextProps) => {
1095
- 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.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.allTasks === nextProps.allTasks && prevProps.disableConstraints === nextProps.disableConstraints && prevProps.task.locked === nextProps.task.locked && prevProps.task.divider === nextProps.task.divider;
1095
+ 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.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.allTasks === nextProps.allTasks && prevProps.disableConstraints === nextProps.disableConstraints && prevProps.task.locked === nextProps.task.locked && prevProps.task.divider === nextProps.task.divider && prevProps.highlightExpiredTasks === nextProps.highlightExpiredTasks;
1096
1096
  };
1097
1097
  var TaskRow = React2.memo(
1098
- ({ task, monthStart, dayWidth, rowHeight, onChange, onDragStateChange, rowIndex, allTasks, enableAutoSchedule, disableConstraints, overridePosition, onCascadeProgress, onCascade, divider }) => {
1098
+ ({ task, monthStart, dayWidth, rowHeight, onChange, onDragStateChange, rowIndex, allTasks, enableAutoSchedule, disableConstraints, overridePosition, onCascadeProgress, onCascade, divider, highlightExpiredTasks }) => {
1099
1099
  const { divider: taskDivider } = task;
1100
1100
  const taskStartDate = useMemo2(() => parseUTCDate(task.startDate), [task.startDate]);
1101
1101
  const taskEndDate = useMemo2(() => parseUTCDate(task.endDate), [task.endDate]);
1102
+ const isExpired = useMemo2(() => {
1103
+ if (!highlightExpiredTasks) return false;
1104
+ const now = /* @__PURE__ */ new Date();
1105
+ const today = new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate()));
1106
+ const tomorrow = new Date(Date.UTC(today.getUTCFullYear(), today.getUTCMonth(), today.getUTCDate() + 1));
1107
+ const taskStart = parseUTCDate(task.startDate);
1108
+ const taskEnd = parseUTCDate(task.endDate);
1109
+ const actualProgress = task.progress ?? 0;
1110
+ if (actualProgress >= 100) {
1111
+ return false;
1112
+ }
1113
+ const msPerDay = 1e3 * 60 * 60 * 24;
1114
+ const taskDuration = taskEnd.getTime() - taskStart.getTime() + msPerDay;
1115
+ const isTaskEndingTodayOrTomorrow = today.getUTCFullYear() === taskEnd.getUTCFullYear() && today.getUTCMonth() === taskEnd.getUTCMonth() && today.getUTCDate() === taskEnd.getUTCDate() || tomorrow.getUTCFullYear() === taskEnd.getUTCFullYear() && tomorrow.getUTCMonth() === taskEnd.getUTCMonth() && tomorrow.getUTCDate() === taskEnd.getUTCDate();
1116
+ const elapsedCutoff = isTaskEndingTodayOrTomorrow ? new Date(today.getTime() - msPerDay) : today;
1117
+ const daysFromStart = elapsedCutoff.getTime() - taskStart.getTime();
1118
+ const todayPosition = Math.min(100, Math.max(0, daysFromStart / taskDuration * 100));
1119
+ return actualProgress < todayPosition;
1120
+ }, [task.startDate, task.endDate, task.progress, highlightExpiredTasks]);
1102
1121
  const { left, width } = useMemo2(
1103
1122
  () => calculateTaskBar(taskStartDate, taskEndDate, monthStart, dayWidth),
1104
1123
  [taskStartDate, taskEndDate, monthStart, dayWidth]
1105
1124
  );
1106
- const barColor = task.color || "var(--gantt-task-bar-default-color)";
1125
+ const barColor = isExpired ? "var(--gantt-expired-color)" : task.color || "var(--gantt-task-bar-default-color)";
1107
1126
  const progressWidth = useMemo2(() => {
1108
1127
  if (task.progress === void 0 || task.progress <= 0) return 0;
1109
1128
  return Math.min(100, Math.max(0, Math.round(task.progress)));
1110
1129
  }, [task.progress]);
1111
1130
  const progressColor = useMemo2(() => {
1131
+ if (isExpired) {
1132
+ return "color-mix(in srgb, var(--gantt-expired-color) 40%, black)";
1133
+ }
1112
1134
  if (progressWidth === 100) {
1113
1135
  return task.accepted ? "var(--gantt-progress-accepted, #22c55e)" : "var(--gantt-progress-completed, #fbbf24)";
1114
1136
  }
1115
1137
  const baseColor = task.color || "var(--gantt-task-bar-default-color)";
1116
1138
  return `color-mix(in srgb, ${baseColor} 40%, black)`;
1117
- }, [progressWidth, task.accepted, task.color]);
1139
+ }, [isExpired, progressWidth, task.accepted, task.color]);
1118
1140
  const handleDragEnd = (result) => {
1119
1141
  const updatedTask = {
1120
1142
  ...task,
@@ -1604,7 +1626,8 @@ var PopoverContent = ({
1604
1626
  align = "start",
1605
1627
  side = "bottom",
1606
1628
  portal = true,
1607
- collisionPadding = 8
1629
+ collisionPadding = 8,
1630
+ onInteractOutside
1608
1631
  }) => {
1609
1632
  const content = /* @__PURE__ */ jsx7(
1610
1633
  RadixPopover.Content,
@@ -1614,6 +1637,7 @@ var PopoverContent = ({
1614
1637
  side,
1615
1638
  collisionPadding,
1616
1639
  sideOffset: 4,
1640
+ onInteractOutside,
1617
1641
  children
1618
1642
  }
1619
1643
  );
@@ -1938,10 +1962,9 @@ var DepChip = ({
1938
1962
  const depPrefix = formatDepDescription(dep.type, lag);
1939
1963
  const depName = predecessorName ?? dep.taskId;
1940
1964
  return /* @__PURE__ */ jsxs9(Popover, { open: isSelected, onOpenChange: (open) => {
1941
- if (!open) onChipSelectClear();
1942
1965
  }, children: [
1943
- /* @__PURE__ */ jsxs9("span", { className: "gantt-tl-dep-chip-wrapper", children: [
1944
- /* @__PURE__ */ jsx12(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsx12(
1966
+ /* @__PURE__ */ jsx12(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxs9("span", { className: "gantt-tl-dep-chip-wrapper", children: [
1967
+ /* @__PURE__ */ jsx12(
1945
1968
  "span",
1946
1969
  {
1947
1970
  className: `gantt-tl-dep-chip${isSelected ? " gantt-tl-dep-chip-selected" : ""}`,
@@ -1951,7 +1974,7 @@ var DepChip = ({
1951
1974
  lag != null && lag !== 0 ? lag > 0 ? `+${lag}` : `${lag}` : ""
1952
1975
  ] })
1953
1976
  }
1954
- ) }),
1977
+ ),
1955
1978
  !disableDependencyEditing && /* @__PURE__ */ jsx12(
1956
1979
  "button",
1957
1980
  {
@@ -1962,11 +1985,28 @@ var DepChip = ({
1962
1985
  children: /* @__PURE__ */ jsx12(TrashIcon, {})
1963
1986
  }
1964
1987
  )
1965
- ] }),
1966
- /* @__PURE__ */ jsxs9(PopoverContent, { portal: true, side: "bottom", align: "start", className: "gantt-tl-dep-info-popover", children: [
1967
- /* @__PURE__ */ jsx12("span", { className: "gantt-tl-dep-info-prefix", children: depPrefix }),
1968
- /* @__PURE__ */ jsx12("span", { className: "gantt-tl-dep-info-name", children: depName })
1969
- ] })
1988
+ ] }) }),
1989
+ /* @__PURE__ */ jsxs9(
1990
+ PopoverContent,
1991
+ {
1992
+ portal: true,
1993
+ side: "bottom",
1994
+ align: "start",
1995
+ className: "gantt-tl-dep-info-popover",
1996
+ onInteractOutside: (event) => {
1997
+ const target = event.target;
1998
+ if (target?.closest?.(".gantt-tl-dep-chip") || target?.closest?.(".gantt-tl-dep-delete-label") || target?.closest?.(".gantt-tl-dep-chip-trash")) {
1999
+ event.preventDefault();
2000
+ } else {
2001
+ onChipSelectClear();
2002
+ }
2003
+ },
2004
+ children: [
2005
+ /* @__PURE__ */ jsx12("span", { className: "gantt-tl-dep-info-prefix", children: depPrefix }),
2006
+ /* @__PURE__ */ jsx12("span", { className: "gantt-tl-dep-info-name", children: depName })
2007
+ ]
2008
+ }
2009
+ )
1970
2010
  ] });
1971
2011
  };
1972
2012
  var toISODate = (value) => {
@@ -2462,7 +2502,8 @@ var GanttChart = forwardRef(({
2462
2502
  showTaskList = false,
2463
2503
  taskListWidth = 520,
2464
2504
  disableTaskNameEditing = false,
2465
- disableDependencyEditing = false
2505
+ disableDependencyEditing = false,
2506
+ highlightExpiredTasks = false
2466
2507
  }, ref) => {
2467
2508
  const scrollContainerRef = useRef5(null);
2468
2509
  const [selectedTaskId, setSelectedTaskId] = useState6(null);
@@ -2734,7 +2775,8 @@ var GanttChart = forwardRef(({
2734
2775
  disableConstraints: disableConstraints ?? false,
2735
2776
  overridePosition: cascadeOverrides.get(task.id),
2736
2777
  onCascadeProgress: handleCascadeProgress,
2737
- onCascade: handleCascade
2778
+ onCascade: handleCascade,
2779
+ highlightExpiredTasks
2738
2780
  },
2739
2781
  task.id
2740
2782
  ))