gantt-lib 0.129.0 → 0.131.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.
@@ -14,6 +14,8 @@ type GanttScheduleIntent = {
14
14
  taskId: string;
15
15
  duration: number;
16
16
  anchor: 'start' | 'end';
17
+ /** Explicit target type for milestone <-> task transitions from the duration editor. */
18
+ taskType?: 'task' | 'milestone';
17
19
  };
18
20
  type GanttChartMode = 'gantt' | 'table-matrix' | 'plan-fact' | 'resource-planner';
19
21
  type TaskDateChangeMode = 'preserve-duration' | 'free';
@@ -14,6 +14,8 @@ type GanttScheduleIntent = {
14
14
  taskId: string;
15
15
  duration: number;
16
16
  anchor: 'start' | 'end';
17
+ /** Explicit target type for milestone <-> task transitions from the duration editor. */
18
+ taskType?: 'task' | 'milestone';
17
19
  };
18
20
  type GanttChartMode = 'gantt' | 'table-matrix' | 'plan-fact' | 'resource-planner';
19
21
  type TaskDateChangeMode = 'preserve-duration' | 'free';
package/dist/index.d.mts CHANGED
@@ -1,6 +1,6 @@
1
1
  import React$1, { ReactNode } from 'react';
2
- import { T as Task$1, R as ResourceTimelineItem, G as GanttScheduleIntent, V as ValidationResult, a as TimelineMarker, b as TaskDateChangeMode, S as ScaleTaskSubtreeResult, c as ResourcePlannerChartProps, d as ResourceTimelineResource } from './index-CIFbOgGc.mjs';
3
- export { B as BuiltInResourceTableColumnId, C as CriticalPathOptions, D as DAY_MS, e as DependencyError, f as GanttChartMode, g as GanttDateRange, h as GridConfig, i as GridLine, L as LinkType, M as MonthSpan, j as ResourceTableColumnId, k as ResourceTableColumnWidthMap, l as ResourceTimelineMove, m as ResourceTimelineResourceMenuCommand, n as ScaleTaskSubtreeAnchor, o as ScaleTaskSubtreeErrorCode, p as ScaleTaskSubtreeExternalPolicy, q as ScaleTaskSubtreeOptions, r as ScaleTaskSubtreeWarning, s as TaskBarGeometry, W as WeekendBlock, t as alignToWorkingDay, u as areTasksHierarchicallyRelated, v as buildAdjacencyList, w as buildTaskRangeFromEnd, x as buildTaskRangeFromStart, y as calculateSuccessorDate, z as cascadeByLinks, A as clampTaskRangeForIncomingFS, E as computeCriticalPath, F as computeLagFromDates, H as computeParentDates, I as computeParentProgress, J as detectCycles, K as extendCriticalIdsToParents, N as findParentId, O as getAllDependencyEdges, P as getAllDescendants, Q as getBusinessDayOffset, U as getChildren, X as getDependencyLag, Y as getSuccessorChain, Z as getTaskDuration, _ as getTransitiveCascadeChain, $ as isAncestorTask, a0 as isTaskParent, a1 as moveTaskRange, a2 as moveTaskWithCascade, a3 as normalizeDependencyLag, a4 as normalizePredecessorDates, a5 as normalizeTaskDependencyLags, a6 as normalizeUTCDate, a7 as parseDateOnly, a8 as recalculateIncomingLags, a9 as recalculateProjectSchedule, aa as recalculateTaskFromDependencies, ab as reflowTasksOnModeSwitch, ac as removeDependenciesBetweenTasks, ad as resizeTaskWithCascade, ae as scaleTaskSubtreeDuration, af as shiftBusinessDayOffset, ag as universalCascade, ah as validateDependencies } from './index-CIFbOgGc.mjs';
2
+ import { T as Task$1, R as ResourceTimelineItem, G as GanttScheduleIntent, V as ValidationResult, a as TimelineMarker, b as TaskDateChangeMode, S as ScaleTaskSubtreeResult, c as ResourcePlannerChartProps, d as ResourceTimelineResource } from './index-CZ_2i1CO.mjs';
3
+ export { B as BuiltInResourceTableColumnId, C as CriticalPathOptions, D as DAY_MS, e as DependencyError, f as GanttChartMode, g as GanttDateRange, h as GridConfig, i as GridLine, L as LinkType, M as MonthSpan, j as ResourceTableColumnId, k as ResourceTableColumnWidthMap, l as ResourceTimelineMove, m as ResourceTimelineResourceMenuCommand, n as ScaleTaskSubtreeAnchor, o as ScaleTaskSubtreeErrorCode, p as ScaleTaskSubtreeExternalPolicy, q as ScaleTaskSubtreeOptions, r as ScaleTaskSubtreeWarning, s as TaskBarGeometry, W as WeekendBlock, t as alignToWorkingDay, u as areTasksHierarchicallyRelated, v as buildAdjacencyList, w as buildTaskRangeFromEnd, x as buildTaskRangeFromStart, y as calculateSuccessorDate, z as cascadeByLinks, A as clampTaskRangeForIncomingFS, E as computeCriticalPath, F as computeLagFromDates, H as computeParentDates, I as computeParentProgress, J as detectCycles, K as extendCriticalIdsToParents, N as findParentId, O as getAllDependencyEdges, P as getAllDescendants, Q as getBusinessDayOffset, U as getChildren, X as getDependencyLag, Y as getSuccessorChain, Z as getTaskDuration, _ as getTransitiveCascadeChain, $ as isAncestorTask, a0 as isTaskParent, a1 as moveTaskRange, a2 as moveTaskWithCascade, a3 as normalizeDependencyLag, a4 as normalizePredecessorDates, a5 as normalizeTaskDependencyLags, a6 as normalizeUTCDate, a7 as parseDateOnly, a8 as recalculateIncomingLags, a9 as recalculateProjectSchedule, aa as recalculateTaskFromDependencies, ab as reflowTasksOnModeSwitch, ac as removeDependenciesBetweenTasks, ad as resizeTaskWithCascade, ae as scaleTaskSubtreeDuration, af as shiftBusinessDayOffset, ag as universalCascade, ah as validateDependencies } from './index-CZ_2i1CO.mjs';
4
4
  import * as react_jsx_runtime from 'react/jsx-runtime';
5
5
  import * as RadixPopover from '@radix-ui/react-popover';
6
6
 
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, G as GanttScheduleIntent, V as ValidationResult, a as TimelineMarker, b as TaskDateChangeMode, S as ScaleTaskSubtreeResult, c as ResourcePlannerChartProps, d as ResourceTimelineResource } from './index-CIFbOgGc.js';
3
- export { B as BuiltInResourceTableColumnId, C as CriticalPathOptions, D as DAY_MS, e as DependencyError, f as GanttChartMode, g as GanttDateRange, h as GridConfig, i as GridLine, L as LinkType, M as MonthSpan, j as ResourceTableColumnId, k as ResourceTableColumnWidthMap, l as ResourceTimelineMove, m as ResourceTimelineResourceMenuCommand, n as ScaleTaskSubtreeAnchor, o as ScaleTaskSubtreeErrorCode, p as ScaleTaskSubtreeExternalPolicy, q as ScaleTaskSubtreeOptions, r as ScaleTaskSubtreeWarning, s as TaskBarGeometry, W as WeekendBlock, t as alignToWorkingDay, u as areTasksHierarchicallyRelated, v as buildAdjacencyList, w as buildTaskRangeFromEnd, x as buildTaskRangeFromStart, y as calculateSuccessorDate, z as cascadeByLinks, A as clampTaskRangeForIncomingFS, E as computeCriticalPath, F as computeLagFromDates, H as computeParentDates, I as computeParentProgress, J as detectCycles, K as extendCriticalIdsToParents, N as findParentId, O as getAllDependencyEdges, P as getAllDescendants, Q as getBusinessDayOffset, U as getChildren, X as getDependencyLag, Y as getSuccessorChain, Z as getTaskDuration, _ as getTransitiveCascadeChain, $ as isAncestorTask, a0 as isTaskParent, a1 as moveTaskRange, a2 as moveTaskWithCascade, a3 as normalizeDependencyLag, a4 as normalizePredecessorDates, a5 as normalizeTaskDependencyLags, a6 as normalizeUTCDate, a7 as parseDateOnly, a8 as recalculateIncomingLags, a9 as recalculateProjectSchedule, aa as recalculateTaskFromDependencies, ab as reflowTasksOnModeSwitch, ac as removeDependenciesBetweenTasks, ad as resizeTaskWithCascade, ae as scaleTaskSubtreeDuration, af as shiftBusinessDayOffset, ag as universalCascade, ah as validateDependencies } from './index-CIFbOgGc.js';
2
+ import { T as Task$1, R as ResourceTimelineItem, G as GanttScheduleIntent, V as ValidationResult, a as TimelineMarker, b as TaskDateChangeMode, S as ScaleTaskSubtreeResult, c as ResourcePlannerChartProps, d as ResourceTimelineResource } from './index-CZ_2i1CO.js';
3
+ export { B as BuiltInResourceTableColumnId, C as CriticalPathOptions, D as DAY_MS, e as DependencyError, f as GanttChartMode, g as GanttDateRange, h as GridConfig, i as GridLine, L as LinkType, M as MonthSpan, j as ResourceTableColumnId, k as ResourceTableColumnWidthMap, l as ResourceTimelineMove, m as ResourceTimelineResourceMenuCommand, n as ScaleTaskSubtreeAnchor, o as ScaleTaskSubtreeErrorCode, p as ScaleTaskSubtreeExternalPolicy, q as ScaleTaskSubtreeOptions, r as ScaleTaskSubtreeWarning, s as TaskBarGeometry, W as WeekendBlock, t as alignToWorkingDay, u as areTasksHierarchicallyRelated, v as buildAdjacencyList, w as buildTaskRangeFromEnd, x as buildTaskRangeFromStart, y as calculateSuccessorDate, z as cascadeByLinks, A as clampTaskRangeForIncomingFS, E as computeCriticalPath, F as computeLagFromDates, H as computeParentDates, I as computeParentProgress, J as detectCycles, K as extendCriticalIdsToParents, N as findParentId, O as getAllDependencyEdges, P as getAllDescendants, Q as getBusinessDayOffset, U as getChildren, X as getDependencyLag, Y as getSuccessorChain, Z as getTaskDuration, _ as getTransitiveCascadeChain, $ as isAncestorTask, a0 as isTaskParent, a1 as moveTaskRange, a2 as moveTaskWithCascade, a3 as normalizeDependencyLag, a4 as normalizePredecessorDates, a5 as normalizeTaskDependencyLags, a6 as normalizeUTCDate, a7 as parseDateOnly, a8 as recalculateIncomingLags, a9 as recalculateProjectSchedule, aa as recalculateTaskFromDependencies, ab as reflowTasksOnModeSwitch, ac as removeDependenciesBetweenTasks, ad as resizeTaskWithCascade, ae as scaleTaskSubtreeDuration, af as shiftBusinessDayOffset, ag as universalCascade, ah as validateDependencies } from './index-CZ_2i1CO.js';
4
4
  import * as react_jsx_runtime from 'react/jsx-runtime';
5
5
  import * as RadixPopover from '@radix-ui/react-popover';
6
6
 
package/dist/index.js CHANGED
@@ -1189,7 +1189,7 @@ function universalCascade(movedTask, newStart, newEnd, allTasks, businessDays =
1189
1189
  }
1190
1190
  }
1191
1191
  const parentId = currentOriginal.parentId;
1192
- if (parentId) {
1192
+ if (parentId && parentId !== movedTask.id) {
1193
1193
  const parent = taskById.get(parentId);
1194
1194
  if (parent && !parent.locked) {
1195
1195
  const siblings = childrenByParentId.get(parentId) ?? [];
@@ -3729,6 +3729,30 @@ function cancelDrag() {
3729
3729
  function snapToGrid(pixels, dayWidth) {
3730
3730
  return Math.round(pixels / dayWidth) * dayWidth;
3731
3731
  }
3732
+ function resolveDragRangeForInteraction(activeDrag, task, mode, left, width) {
3733
+ const proposedRange = resolveDateRangeFromPixels(
3734
+ mode,
3735
+ left,
3736
+ width,
3737
+ activeDrag.monthStart,
3738
+ activeDrag.dayWidth,
3739
+ task,
3740
+ activeDrag.businessDays,
3741
+ activeDrag.weekendPredicate
3742
+ );
3743
+ if (activeDrag.scheduleIntentMode) {
3744
+ return proposedRange;
3745
+ }
3746
+ return clampDateRangeForIncomingFS(
3747
+ task,
3748
+ proposedRange,
3749
+ activeDrag.allTasks,
3750
+ mode,
3751
+ activeDrag.businessDays,
3752
+ activeDrag.weekendPredicate,
3753
+ activeDrag.cascadeContext?.taskById
3754
+ );
3755
+ }
3732
3756
  function handleGlobalMouseMove(e) {
3733
3757
  if (!globalActiveDrag || globalRafId !== null) {
3734
3758
  return;
@@ -3761,45 +3785,13 @@ function handleGlobalMouseMove(e) {
3761
3785
  break;
3762
3786
  }
3763
3787
  if (activeDrag.businessDays && activeDrag.weekendPredicate && draggedTask) {
3764
- const previewRange = clampDateRangeForIncomingFS(
3765
- draggedTask,
3766
- resolveDateRangeFromPixels(
3767
- mode,
3768
- newLeft,
3769
- newWidth,
3770
- activeDrag.monthStart,
3771
- dayWidth,
3772
- draggedTask,
3773
- true,
3774
- activeDrag.weekendPredicate
3775
- ),
3776
- allTasks,
3777
- mode,
3778
- true,
3779
- activeDrag.weekendPredicate,
3780
- activeDrag.cascadeContext?.taskById
3781
- );
3788
+ const previewRange = resolveDragRangeForInteraction(activeDrag, draggedTask, mode, newLeft, newWidth);
3782
3789
  const alignedStartDay = getDayOffsetFromMonthStart(previewRange.start, activeDrag.monthStart);
3783
3790
  const alignedEndDay = getDayOffsetFromMonthStart(previewRange.end, activeDrag.monthStart);
3784
3791
  newLeft = Math.round(alignedStartDay * dayWidth);
3785
3792
  newWidth = Math.round((alignedEndDay - alignedStartDay + 1) * dayWidth);
3786
3793
  } else if (draggedTask) {
3787
- const previewRange = clampDateRangeForIncomingFS(
3788
- draggedTask,
3789
- resolveDateRangeFromPixels(
3790
- mode,
3791
- newLeft,
3792
- newWidth,
3793
- activeDrag.monthStart,
3794
- dayWidth,
3795
- draggedTask
3796
- ),
3797
- allTasks,
3798
- mode,
3799
- activeDrag.businessDays,
3800
- activeDrag.weekendPredicate,
3801
- activeDrag.cascadeContext?.taskById
3802
- );
3794
+ const previewRange = resolveDragRangeForInteraction(activeDrag, draggedTask, mode, newLeft, newWidth);
3803
3795
  const alignedStartDay = getDayOffsetFromMonthStart(previewRange.start, activeDrag.monthStart);
3804
3796
  const alignedEndDay = getDayOffsetFromMonthStart(previewRange.end, activeDrag.monthStart);
3805
3797
  newLeft = Math.round(alignedStartDay * dayWidth);
@@ -3811,24 +3803,7 @@ function handleGlobalMouseMove(e) {
3811
3803
  const isParentResizePreview = draggedTask && (mode === "resize-left" || mode === "resize-right") && isTaskParent(activeDrag.taskId, allTasks);
3812
3804
  if (isParentResizePreview && activeDrag.onCascadeProgress) {
3813
3805
  const { dayWidth: dw, monthStart: mStart } = activeDrag;
3814
- const previewRange = clampDateRangeForIncomingFS(
3815
- draggedTask,
3816
- resolveDateRangeFromPixels(
3817
- mode,
3818
- newLeft,
3819
- newWidth,
3820
- mStart,
3821
- dw,
3822
- draggedTask,
3823
- activeDrag.businessDays,
3824
- activeDrag.weekendPredicate
3825
- ),
3826
- allTasks,
3827
- mode,
3828
- activeDrag.businessDays,
3829
- activeDrag.weekendPredicate,
3830
- activeDrag.cascadeContext?.taskById
3831
- );
3806
+ const previewRange = resolveDragRangeForInteraction(activeDrag, draggedTask, mode, newLeft, newWidth);
3832
3807
  const anchor = mode === "resize-left" ? "end" : "start";
3833
3808
  const parentRange = computeParentDates(activeDrag.taskId, allTasks);
3834
3809
  const targetDuration = Math.max(1, getTaskDuration(
@@ -4075,23 +4050,15 @@ var useTaskDrag = (options) => {
4075
4050
  isOwnerRef.current = false;
4076
4051
  const currentTaskRaw = allTasks.find((t) => t.id === taskId);
4077
4052
  const currentTask = currentTaskRaw ? normalizeTaskDatesForType(currentTaskRaw) : void 0;
4078
- const finalRange = currentTask ? clampDateRangeForIncomingFS(
4079
- currentTask,
4080
- resolveDateRangeFromPixels(
4081
- finalMode,
4082
- finalLeft,
4083
- finalWidth,
4084
- monthStart,
4085
- dayWidth,
4086
- currentTask,
4087
- businessDays,
4088
- weekendPredicate
4089
- ),
4090
- allTasks,
4053
+ const proposedFinalRange = currentTask ? resolveDateRangeFromPixels(
4091
4054
  finalMode,
4055
+ finalLeft,
4056
+ finalWidth,
4057
+ monthStart,
4058
+ dayWidth,
4059
+ currentTask,
4092
4060
  businessDays,
4093
- weekendPredicate,
4094
- cascadeContext?.taskById
4061
+ weekendPredicate
4095
4062
  ) : (() => {
4096
4063
  const dayOffset = Math.round(finalLeft / dayWidth);
4097
4064
  const durationDays = Math.round(finalWidth / dayWidth) - 1;
@@ -4108,6 +4075,15 @@ var useTaskDrag = (options) => {
4108
4075
  ))
4109
4076
  };
4110
4077
  })();
4078
+ const finalRange = currentTask && !onScheduleIntent ? clampDateRangeForIncomingFS(
4079
+ currentTask,
4080
+ proposedFinalRange,
4081
+ allTasks,
4082
+ finalMode,
4083
+ businessDays,
4084
+ weekendPredicate,
4085
+ cascadeContext?.taskById
4086
+ ) : proposedFinalRange;
4111
4087
  const newStartDate = finalRange.start;
4112
4088
  const newEndDate = currentTask && isMilestoneTask(currentTask) ? finalRange.start : finalRange.end;
4113
4089
  setIsDragging(false);
@@ -4172,7 +4148,7 @@ var useTaskDrag = (options) => {
4172
4148
  }
4173
4149
  }
4174
4150
  const isParentResize = currentTask && (finalMode === "resize-left" || finalMode === "resize-right") ? isTaskParent(taskId, allTasks) : false;
4175
- if (!disableConstraints && onCascade && allTasks.length > 0 && !isParentResize) {
4151
+ if (!disableConstraints && onCascade && !onScheduleIntent && allTasks.length > 0 && !isParentResize) {
4176
4152
  const draggedTaskData = currentTask;
4177
4153
  const movedTask = {
4178
4154
  ...draggedTaskData ?? { id: taskId, name: "", startDate: "", endDate: "" },
@@ -4323,7 +4299,8 @@ var useTaskDrag = (options) => {
4323
4299
  onCascadeProgress,
4324
4300
  businessDays,
4325
4301
  weekendPredicate,
4326
- cascadeContext: shouldBuildCascadeContext ? createCascadeContext(allTasks) : void 0
4302
+ cascadeContext: shouldBuildCascadeContext ? createCascadeContext(allTasks) : void 0,
4303
+ scheduleIntentMode: Boolean(onScheduleIntent)
4327
4304
  };
4328
4305
  }, [edgeZoneWidth, currentLeft, currentWidth, dayWidth, monthStart, taskId, onDragStateChange, handleProgress, handleComplete, handleCancel, allTasks, disableConstraints, onCascadeProgress, onCascade, effectiveLocked, viewMode]);
4329
4306
  const handleMouseDown = (0, import_react2.useCallback)((e) => {
@@ -14519,7 +14496,8 @@ function TaskGanttChartInner(props, ref) {
14519
14496
  type: "change_duration",
14520
14497
  taskId: updatedTask.id,
14521
14498
  duration: targetDuration,
14522
- anchor: durationEdit?.anchor ?? anchor
14499
+ anchor: durationEdit?.anchor ?? anchor,
14500
+ ...durationEdit ? { taskType: updatedTask.type ?? "task" } : {}
14523
14501
  });
14524
14502
  const scaleResult = scaleTaskSubtreeDuration(updatedTask.id, targetDuration, tasks, {
14525
14503
  anchor,
@@ -14559,7 +14537,8 @@ function TaskGanttChartInner(props, ref) {
14559
14537
  type: "change_duration",
14560
14538
  taskId: updatedTask.id,
14561
14539
  duration: durationEdit.duration,
14562
- anchor: durationEdit.anchor
14540
+ anchor: durationEdit.anchor,
14541
+ taskType: updatedTask.type ?? "task"
14563
14542
  });
14564
14543
  } else {
14565
14544
  onTasksChange?.(cascadedTasks);