gantt-lib 0.88.2 → 0.90.0
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.mts +11 -3
- package/dist/index.d.ts +11 -3
- package/dist/index.js +49 -22
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +49 -22
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -467,7 +467,7 @@ interface GanttModeProps<TTask extends Task = Task> {
|
|
|
467
467
|
onPromoteTask?: (taskId: string) => void;
|
|
468
468
|
/** Callback when a task is demoted (parentId set). If not provided, default internal logic is used. */
|
|
469
469
|
onDemoteTask?: (taskId: string, newParentId: string) => void;
|
|
470
|
-
/** Callback when a parent task is ungrouped
|
|
470
|
+
/** Callback when a parent task is ungrouped while direct children move one level up and the parent remains. */
|
|
471
471
|
onUngroupTask?: (taskId: string) => void;
|
|
472
472
|
/** Enable add task button at bottom of task list (default: true) */
|
|
473
473
|
enableAddTask?: boolean;
|
|
@@ -543,13 +543,21 @@ interface ExportToPdfHeaderOptions {
|
|
|
543
543
|
/** Export date shown on the right; string is rendered as-is */
|
|
544
544
|
exportDate?: string | Date;
|
|
545
545
|
}
|
|
546
|
+
interface ScrollToRowOptions {
|
|
547
|
+
/** Keep built-in row selection styling after scroll (default: true) */
|
|
548
|
+
select?: boolean;
|
|
549
|
+
/** Browser scroll behavior for the vertical scroll action (default: 'smooth') */
|
|
550
|
+
behavior?: ScrollBehavior;
|
|
551
|
+
/** Automatically clear built-in row selection after N milliseconds */
|
|
552
|
+
clearSelectionAfterMs?: number;
|
|
553
|
+
}
|
|
546
554
|
/**
|
|
547
555
|
* Ref handle type for GanttChart — exposes imperative scroll methods.
|
|
548
556
|
*/
|
|
549
557
|
interface GanttChartHandle {
|
|
550
558
|
scrollToToday: () => void;
|
|
551
559
|
scrollToTask: (taskId: string) => void;
|
|
552
|
-
scrollToRow: (taskId: string) => void;
|
|
560
|
+
scrollToRow: (taskId: string, options?: ScrollToRowOptions) => void;
|
|
553
561
|
collapseAll: () => void;
|
|
554
562
|
expandAll: () => void;
|
|
555
563
|
exportToPdf: (options?: ExportToPdfOptions) => Promise<void>;
|
|
@@ -764,7 +772,7 @@ interface TaskListProps {
|
|
|
764
772
|
onPromoteTask?: (taskId: string) => void;
|
|
765
773
|
/** Callback when task is demoted (parentId set to previous task) */
|
|
766
774
|
onDemoteTask?: (taskId: string, newParentId: string) => void;
|
|
767
|
-
/** Callback when parent task is ungrouped
|
|
775
|
+
/** Callback when a parent task is ungrouped while direct children move one level up and the parent remains */
|
|
768
776
|
onUngroupTask?: (taskId: string) => void;
|
|
769
777
|
/** Custom day configurations for date picker */
|
|
770
778
|
customDays?: CustomDayConfig[];
|
package/dist/index.d.ts
CHANGED
|
@@ -467,7 +467,7 @@ interface GanttModeProps<TTask extends Task = Task> {
|
|
|
467
467
|
onPromoteTask?: (taskId: string) => void;
|
|
468
468
|
/** Callback when a task is demoted (parentId set). If not provided, default internal logic is used. */
|
|
469
469
|
onDemoteTask?: (taskId: string, newParentId: string) => void;
|
|
470
|
-
/** Callback when a parent task is ungrouped
|
|
470
|
+
/** Callback when a parent task is ungrouped while direct children move one level up and the parent remains. */
|
|
471
471
|
onUngroupTask?: (taskId: string) => void;
|
|
472
472
|
/** Enable add task button at bottom of task list (default: true) */
|
|
473
473
|
enableAddTask?: boolean;
|
|
@@ -543,13 +543,21 @@ interface ExportToPdfHeaderOptions {
|
|
|
543
543
|
/** Export date shown on the right; string is rendered as-is */
|
|
544
544
|
exportDate?: string | Date;
|
|
545
545
|
}
|
|
546
|
+
interface ScrollToRowOptions {
|
|
547
|
+
/** Keep built-in row selection styling after scroll (default: true) */
|
|
548
|
+
select?: boolean;
|
|
549
|
+
/** Browser scroll behavior for the vertical scroll action (default: 'smooth') */
|
|
550
|
+
behavior?: ScrollBehavior;
|
|
551
|
+
/** Automatically clear built-in row selection after N milliseconds */
|
|
552
|
+
clearSelectionAfterMs?: number;
|
|
553
|
+
}
|
|
546
554
|
/**
|
|
547
555
|
* Ref handle type for GanttChart — exposes imperative scroll methods.
|
|
548
556
|
*/
|
|
549
557
|
interface GanttChartHandle {
|
|
550
558
|
scrollToToday: () => void;
|
|
551
559
|
scrollToTask: (taskId: string) => void;
|
|
552
|
-
scrollToRow: (taskId: string) => void;
|
|
560
|
+
scrollToRow: (taskId: string, options?: ScrollToRowOptions) => void;
|
|
553
561
|
collapseAll: () => void;
|
|
554
562
|
expandAll: () => void;
|
|
555
563
|
exportToPdf: (options?: ExportToPdfOptions) => Promise<void>;
|
|
@@ -764,7 +772,7 @@ interface TaskListProps {
|
|
|
764
772
|
onPromoteTask?: (taskId: string) => void;
|
|
765
773
|
/** Callback when task is demoted (parentId set to previous task) */
|
|
766
774
|
onDemoteTask?: (taskId: string, newParentId: string) => void;
|
|
767
|
-
/** Callback when parent task is ungrouped
|
|
775
|
+
/** Callback when a parent task is ungrouped while direct children move one level up and the parent remains */
|
|
768
776
|
onUngroupTask?: (taskId: string) => void;
|
|
769
777
|
/** Custom day configurations for date picker */
|
|
770
778
|
customDays?: CustomDayConfig[];
|
package/dist/index.js
CHANGED
|
@@ -5142,10 +5142,13 @@ var TaskListRow = import_react10.default.memo(
|
|
|
5142
5142
|
}
|
|
5143
5143
|
const clampedValue = Math.max(0, Math.min(100, progressValue));
|
|
5144
5144
|
if ((clampedValue === 100 || clampedValue === 0) && isTaskParent(task.id, allTasks)) {
|
|
5145
|
-
const
|
|
5145
|
+
const descendants = getAllDescendants(task.id, allTasks);
|
|
5146
5146
|
const updatedTasks = [
|
|
5147
5147
|
{ ...task, progress: clampedValue },
|
|
5148
|
-
...
|
|
5148
|
+
...descendants.map((descendant) => ({
|
|
5149
|
+
...descendant,
|
|
5150
|
+
progress: clampedValue
|
|
5151
|
+
}))
|
|
5149
5152
|
];
|
|
5150
5153
|
onTasksChange?.(updatedTasks);
|
|
5151
5154
|
} else {
|
|
@@ -5168,11 +5171,11 @@ var TaskListRow = import_react10.default.memo(
|
|
|
5168
5171
|
progressConfirmedRef.current = true;
|
|
5169
5172
|
const clampedValue = Math.max(0, Math.min(100, progressValue));
|
|
5170
5173
|
if ((clampedValue === 100 || clampedValue === 0) && isTaskParent(task.id, allTasks)) {
|
|
5171
|
-
const
|
|
5174
|
+
const descendants = getAllDescendants(task.id, allTasks);
|
|
5172
5175
|
const updatedTasks = [
|
|
5173
5176
|
{ ...task, progress: clampedValue },
|
|
5174
|
-
...
|
|
5175
|
-
...
|
|
5177
|
+
...descendants.map((descendant) => ({
|
|
5178
|
+
...descendant,
|
|
5176
5179
|
progress: clampedValue
|
|
5177
5180
|
}))
|
|
5178
5181
|
];
|
|
@@ -5379,16 +5382,9 @@ var TaskListRow = import_react10.default.memo(
|
|
|
5379
5382
|
const handleApplyColor = (0, import_react10.useCallback)(
|
|
5380
5383
|
(color) => {
|
|
5381
5384
|
if (!onTasksChange) return;
|
|
5382
|
-
const descendantIds =
|
|
5383
|
-
|
|
5384
|
-
|
|
5385
|
-
while (stack.length > 0) {
|
|
5386
|
-
const current = stack.shift();
|
|
5387
|
-
if (!current || descendantIds.has(current.id)) continue;
|
|
5388
|
-
descendantIds.add(current.id);
|
|
5389
|
-
stack.push(...getChildren(current.id, allTasks));
|
|
5390
|
-
}
|
|
5391
|
-
}
|
|
5385
|
+
const descendantIds = new Set(
|
|
5386
|
+
isParent ? getAllDescendants(task.id, allTasks).map((descendant) => descendant.id) : []
|
|
5387
|
+
);
|
|
5392
5388
|
const updatedTasks = [
|
|
5393
5389
|
{ ...task, color },
|
|
5394
5390
|
...allTasks.filter((candidate) => descendantIds.has(candidate.id)).map((candidate) => ({ ...candidate, color }))
|
|
@@ -9622,6 +9618,7 @@ function TaskGanttChartInner(props, ref) {
|
|
|
9622
9618
|
const containerRef = (0, import_react15.useRef)(null);
|
|
9623
9619
|
const scrollContainerRef = (0, import_react15.useRef)(null);
|
|
9624
9620
|
const scrollContentRef = (0, import_react15.useRef)(null);
|
|
9621
|
+
const clearSelectedTaskTimeoutRef = (0, import_react15.useRef)(null);
|
|
9625
9622
|
const [selectedTaskId, setSelectedTaskId] = (0, import_react15.useState)(null);
|
|
9626
9623
|
const [taskListHasRightShadow, setTaskListHasRightShadow] = (0, import_react15.useState)(false);
|
|
9627
9624
|
const [selectedChip, setSelectedChip] = (0, import_react15.useState)(null);
|
|
@@ -9633,7 +9630,17 @@ function TaskGanttChartInner(props, ref) {
|
|
|
9633
9630
|
() => createCustomDayPredicate({ customDays, isWeekend: isWeekend3 }),
|
|
9634
9631
|
[customDays, isWeekend3]
|
|
9635
9632
|
);
|
|
9636
|
-
const
|
|
9633
|
+
const dateRangeTasks = (0, import_react15.useMemo)(() => {
|
|
9634
|
+
if (!showBaseline) {
|
|
9635
|
+
return normalizedTasks;
|
|
9636
|
+
}
|
|
9637
|
+
return normalizedTasks.map((task) => ({
|
|
9638
|
+
...task,
|
|
9639
|
+
startDate: task.baselineStartDate && parseUTCDate(task.baselineStartDate).getTime() < parseUTCDate(task.startDate).getTime() ? task.baselineStartDate : task.startDate,
|
|
9640
|
+
endDate: task.baselineEndDate && parseUTCDate(task.baselineEndDate).getTime() > parseUTCDate(task.endDate).getTime() ? task.baselineEndDate : task.endDate
|
|
9641
|
+
}));
|
|
9642
|
+
}, [normalizedTasks, showBaseline]);
|
|
9643
|
+
const dateRange = (0, import_react15.useMemo)(() => getMultiMonthDays(dateRangeTasks), [dateRangeTasks]);
|
|
9637
9644
|
const [validationResult, setValidationResult] = (0, import_react15.useState)(null);
|
|
9638
9645
|
const [cascadeOverrides, setCascadeOverrides] = (0, import_react15.useState)(/* @__PURE__ */ new Map());
|
|
9639
9646
|
const gridWidth = (0, import_react15.useMemo)(
|
|
@@ -9741,7 +9748,7 @@ function TaskGanttChartInner(props, ref) {
|
|
|
9741
9748
|
const scrollLeft = Math.round(taskOffset - dayWidth * 2);
|
|
9742
9749
|
container.scrollTo({ left: Math.max(0, scrollLeft), behavior: "smooth" });
|
|
9743
9750
|
}, [tasks, dateRange, dayWidth]);
|
|
9744
|
-
const scrollToRow = (0, import_react15.useCallback)((taskId) => {
|
|
9751
|
+
const scrollToRow = (0, import_react15.useCallback)((taskId, options = {}) => {
|
|
9745
9752
|
const container = scrollContainerRef.current;
|
|
9746
9753
|
if (!container) return;
|
|
9747
9754
|
const task = tasks.find((t) => t.id === taskId);
|
|
@@ -9750,8 +9757,25 @@ function TaskGanttChartInner(props, ref) {
|
|
|
9750
9757
|
if (rowIndex === -1) return;
|
|
9751
9758
|
const paddedRowIndex = Math.max(0, rowIndex - SCROLL_TO_ROW_CONTEXT_ROWS);
|
|
9752
9759
|
const scrollTop = Math.max(0, rowHeight * paddedRowIndex);
|
|
9753
|
-
|
|
9754
|
-
|
|
9760
|
+
const {
|
|
9761
|
+
select = true,
|
|
9762
|
+
behavior = "smooth",
|
|
9763
|
+
clearSelectionAfterMs
|
|
9764
|
+
} = options;
|
|
9765
|
+
if (clearSelectedTaskTimeoutRef.current !== null) {
|
|
9766
|
+
window.clearTimeout(clearSelectedTaskTimeoutRef.current);
|
|
9767
|
+
clearSelectedTaskTimeoutRef.current = null;
|
|
9768
|
+
}
|
|
9769
|
+
if (select) {
|
|
9770
|
+
setSelectedTaskId(taskId);
|
|
9771
|
+
if (typeof clearSelectionAfterMs === "number" && clearSelectionAfterMs >= 0) {
|
|
9772
|
+
clearSelectedTaskTimeoutRef.current = window.setTimeout(() => {
|
|
9773
|
+
setSelectedTaskId((current) => current === taskId ? null : current);
|
|
9774
|
+
clearSelectedTaskTimeoutRef.current = null;
|
|
9775
|
+
}, clearSelectionAfterMs);
|
|
9776
|
+
}
|
|
9777
|
+
}
|
|
9778
|
+
container.scrollTo({ top: scrollTop, behavior });
|
|
9755
9779
|
}, [tasks, visibleTasks, rowHeight]);
|
|
9756
9780
|
const [dragGuideLines, setDragGuideLines] = (0, import_react15.useState)(null);
|
|
9757
9781
|
const [draggedTaskOverride, setDraggedTaskOverride] = (0, import_react15.useState)(null);
|
|
@@ -9761,6 +9785,11 @@ function TaskGanttChartInner(props, ref) {
|
|
|
9761
9785
|
setValidationResult(result);
|
|
9762
9786
|
onValidateDependencies?.(result);
|
|
9763
9787
|
}, [tasks, onValidateDependencies]);
|
|
9788
|
+
(0, import_react15.useEffect)(() => () => {
|
|
9789
|
+
if (clearSelectedTaskTimeoutRef.current !== null) {
|
|
9790
|
+
window.clearTimeout(clearSelectedTaskTimeoutRef.current);
|
|
9791
|
+
}
|
|
9792
|
+
}, []);
|
|
9764
9793
|
const handleTaskChange = (0, import_react15.useCallback)((updatedTasks) => {
|
|
9765
9794
|
const updatedTask = updatedTasks[0];
|
|
9766
9795
|
if (!updatedTask) return;
|
|
@@ -10079,7 +10108,6 @@ function TaskGanttChartInner(props, ref) {
|
|
|
10079
10108
|
if (!hasDirectChildren) return;
|
|
10080
10109
|
const changedTasks = [];
|
|
10081
10110
|
for (const task of tasks) {
|
|
10082
|
-
if (task.id === taskId) continue;
|
|
10083
10111
|
const nextParentId = task.parentId === taskId ? parentTask.parentId : task.parentId;
|
|
10084
10112
|
const nextDependencies = task.dependencies?.filter((dep) => dep.taskId !== taskId);
|
|
10085
10113
|
if (nextParentId !== task.parentId || nextDependencies?.length !== task.dependencies?.length) {
|
|
@@ -10093,8 +10121,7 @@ function TaskGanttChartInner(props, ref) {
|
|
|
10093
10121
|
if (changedTasks.length > 0) {
|
|
10094
10122
|
onTasksChange?.(changedTasks);
|
|
10095
10123
|
}
|
|
10096
|
-
|
|
10097
|
-
}, [tasks, onTasksChange, onDelete, onUngroupTask]);
|
|
10124
|
+
}, [tasks, onTasksChange, onUngroupTask]);
|
|
10098
10125
|
const panStateRef = (0, import_react15.useRef)(null);
|
|
10099
10126
|
const handlePanStart = (0, import_react15.useCallback)((e) => {
|
|
10100
10127
|
if (e.button !== 0) return;
|