gantt-lib 0.90.0 → 0.91.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 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-CQI1GCao.mjs';
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-CQI1GCao.mjs';
2
+ import { T as Task$1, R as ResourceTimelineItem, V as ValidationResult, a as TaskDateChangeMode, b as ResourcePlannerChartProps, c as ResourceTimelineResource } from './index-CKJZfeDv.mjs';
3
+ export { D as DAY_MS, d as DependencyError, G as GanttChartMode, e as GanttDateRange, f as GridConfig, g as GridLine, L as LinkType, M as MonthSpan, h as ResourceTimelineMove, i as ResourceTimelineResourceMenuCommand, j as TaskBarGeometry, W as WeekendBlock, k as alignToWorkingDay, l as areTasksHierarchicallyRelated, m as buildAdjacencyList, n as buildTaskRangeFromEnd, o as buildTaskRangeFromStart, p as calculateSuccessorDate, q as cascadeByLinks, r as clampTaskRangeForIncomingFS, s as computeLagFromDates, t as computeParentDates, u as computeParentProgress, v as detectCycles, w as findParentId, x as getAllDependencyEdges, y as getAllDescendants, z as getBusinessDayOffset, A as getChildren, B as getDependencyLag, C as getSuccessorChain, E as getTaskDuration, F as getTransitiveCascadeChain, H as isAncestorTask, I as isTaskParent, J as moveTaskRange, K as moveTaskWithCascade, N as normalizeDependencyLag, O as normalizePredecessorDates, P as normalizeTaskDependencyLags, Q as normalizeUTCDate, S as parseDateOnly, U as recalculateIncomingLags, X as recalculateProjectSchedule, Y as recalculateTaskFromDependencies, Z as reflowTasksOnModeSwitch, _ as removeDependenciesBetweenTasks, $ as resizeTaskWithCascade, a0 as shiftBusinessDayOffset, a1 as universalCascade, a2 as validateDependencies } from './index-CKJZfeDv.mjs';
4
4
  import * as react_jsx_runtime from 'react/jsx-runtime';
5
5
  import * as RadixPopover from '@radix-ui/react-popover';
6
6
 
@@ -511,6 +511,10 @@ interface GanttModeProps<TTask extends Task = Task> {
511
511
  hiddenTaskListColumns?: readonly TaskListColumnId[];
512
512
  /** Additional commands rendered in the TaskList row three-dots menu */
513
513
  taskListMenuCommands?: TaskListMenuCommand<TTask>[];
514
+ /** How task-list date pickers apply start/end edits (default: preserve-duration) */
515
+ taskDateChangeMode?: TaskDateChangeMode;
516
+ /** Controlled callback for task-list date picker mode changes */
517
+ onTaskDateChangeModeChange?: (mode: TaskDateChangeMode) => void;
514
518
  }
515
519
  type GanttChartProps<TTask extends Task = Task, TItem extends ResourceTimelineItem = ResourceTimelineItem> = GanttModeProps<TTask> | ResourcePlannerChartProps<TItem>;
516
520
  interface ExportToPdfOptions {
@@ -800,6 +804,10 @@ interface TaskListProps {
800
804
  hiddenTaskListColumns?: readonly TaskListColumnId[];
801
805
  /** Additional commands rendered in each row three-dots menu */
802
806
  taskListMenuCommands?: TaskListMenuCommand<Task>[];
807
+ /** How task-list date pickers apply start/end edits */
808
+ taskDateChangeMode?: TaskDateChangeMode;
809
+ /** Controlled callback for task-list date picker mode changes */
810
+ onTaskDateChangeModeChange?: (mode: TaskDateChangeMode) => void;
803
811
  }
804
812
  /**
805
813
  * TaskList component - displays tasks in a table format as an overlay
@@ -898,6 +906,8 @@ interface DatePickerProps {
898
906
  isWeekend?: (date: Date) => boolean;
899
907
  /** Whether to use business days for +1/+7 buttons (default: true) */
900
908
  businessDays?: boolean;
909
+ /** Optional footer content rendered below the calendar popup */
910
+ footer?: React$1.ReactNode;
901
911
  }
902
912
  /**
903
913
  * DatePicker component — shows formatted date as a button, opens calendar popup on click.
@@ -1295,4 +1305,4 @@ interface VisibleReorderPosition {
1295
1305
  */
1296
1306
  declare function getVisibleReorderPosition(orderedTasks: TaskLike[], visibleTasks: TaskLike[], movedTaskId: string, originVisibleIndex: number, dropVisibleIndex: number): VisibleReorderPosition | null;
1297
1307
 
1298
- export { type BuiltInTaskListColumnId, Button, type ButtonProps, Calendar, type CalendarProps, type CustomDayConfig, type CustomDayPredicateConfig, DatePicker, type DatePickerProps, DragGuideLines, type ExportToPdfHeaderOptions, type ExportToPdfOptions, GanttChart, type GanttChartHandle, type GanttChartProps, type GanttModeProps, GridBackground, Input, type InputProps, type MonthBlock, Popover, PopoverContent, type PopoverContentProps, type PopoverProps, PopoverTrigger, ResourcePlannerChartProps, ResourceTimelineChart, type ResourceTimelineConflictRange, ResourceTimelineItem, type ResourceTimelineLayoutDiagnostic, type ResourceTimelineLayoutItem, type ResourceTimelineLayoutOptions, type ResourceTimelineLayoutResult, type ResourceTimelineLayoutRow, ResourceTimelineResource, type Task, type TaskDependency, TaskList, type TaskListColumn, type TaskListColumnContext, type TaskListColumnId, type TaskListMenuCommand, type TaskListProps, type TaskPredicate, TaskRow, TimeScaleHeader, TodayIndicator, ValidationResult, type VisibleReorderPosition, type WeekBlock, type WeekSpan, type WithoutDepsOptions, type YearSpan, addBusinessDays, and, calculateBezierPath, calculateDependencyPath, calculateGridLines, calculateGridWidth, calculateMilestoneConnectionBounds, calculateMilestoneGeometry, calculateMonthGridLines, calculateOrthogonalPath, calculateTaskBar, calculateWeekGridLines, calculateWeekendBlocks, clampDateRangeForIncomingFS, createCustomDayPredicate, createDateKey, detectEdgeZone, expired, flattenHierarchy, formatDateLabel, formatDateRangeLabel, getBusinessDaysCount, getCursorForPosition, getDayOffset, getMonthBlocks, getMonthDays, getMonthSpans, getMultiMonthDays, getVisibleReorderPosition, getWeekBlocks, getWeekSpans, getYearSpans, inDateRange, isTaskExpired, isToday, isWeekend, layoutResourceTimelineItems, nameContains, normalizeHierarchyTasks, normalizeTaskDates, not, or, parseUTCDate, pixelsToDate, progressInRange, resolveDateRangeFromPixels, resolveTaskHorizontalGeometry, subtractBusinessDays, useTaskDrag, withoutDeps };
1308
+ export { type BuiltInTaskListColumnId, Button, type ButtonProps, Calendar, type CalendarProps, type CustomDayConfig, type CustomDayPredicateConfig, DatePicker, type DatePickerProps, DragGuideLines, type ExportToPdfHeaderOptions, type ExportToPdfOptions, GanttChart, type GanttChartHandle, type GanttChartProps, type GanttModeProps, GridBackground, Input, type InputProps, type MonthBlock, Popover, PopoverContent, type PopoverContentProps, type PopoverProps, PopoverTrigger, ResourcePlannerChartProps, ResourceTimelineChart, type ResourceTimelineConflictRange, ResourceTimelineItem, type ResourceTimelineLayoutDiagnostic, type ResourceTimelineLayoutItem, type ResourceTimelineLayoutOptions, type ResourceTimelineLayoutResult, type ResourceTimelineLayoutRow, ResourceTimelineResource, type Task, TaskDateChangeMode, type TaskDependency, TaskList, type TaskListColumn, type TaskListColumnContext, type TaskListColumnId, type TaskListMenuCommand, type TaskListProps, type TaskPredicate, TaskRow, TimeScaleHeader, TodayIndicator, ValidationResult, type VisibleReorderPosition, type WeekBlock, type WeekSpan, type WithoutDepsOptions, type YearSpan, addBusinessDays, and, calculateBezierPath, calculateDependencyPath, calculateGridLines, calculateGridWidth, calculateMilestoneConnectionBounds, calculateMilestoneGeometry, calculateMonthGridLines, calculateOrthogonalPath, calculateTaskBar, calculateWeekGridLines, calculateWeekendBlocks, clampDateRangeForIncomingFS, createCustomDayPredicate, createDateKey, detectEdgeZone, expired, flattenHierarchy, formatDateLabel, formatDateRangeLabel, getBusinessDaysCount, getCursorForPosition, getDayOffset, getMonthBlocks, getMonthDays, getMonthSpans, getMultiMonthDays, getVisibleReorderPosition, getWeekBlocks, getWeekSpans, getYearSpans, inDateRange, isTaskExpired, isToday, isWeekend, layoutResourceTimelineItems, nameContains, normalizeHierarchyTasks, normalizeTaskDates, not, or, parseUTCDate, pixelsToDate, progressInRange, resolveDateRangeFromPixels, resolveTaskHorizontalGeometry, subtractBusinessDays, useTaskDrag, withoutDeps };
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-CQI1GCao.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-CQI1GCao.js';
2
+ import { T as Task$1, R as ResourceTimelineItem, V as ValidationResult, a as TaskDateChangeMode, b as ResourcePlannerChartProps, c as ResourceTimelineResource } from './index-CKJZfeDv.js';
3
+ export { D as DAY_MS, d as DependencyError, G as GanttChartMode, e as GanttDateRange, f as GridConfig, g as GridLine, L as LinkType, M as MonthSpan, h as ResourceTimelineMove, i as ResourceTimelineResourceMenuCommand, j as TaskBarGeometry, W as WeekendBlock, k as alignToWorkingDay, l as areTasksHierarchicallyRelated, m as buildAdjacencyList, n as buildTaskRangeFromEnd, o as buildTaskRangeFromStart, p as calculateSuccessorDate, q as cascadeByLinks, r as clampTaskRangeForIncomingFS, s as computeLagFromDates, t as computeParentDates, u as computeParentProgress, v as detectCycles, w as findParentId, x as getAllDependencyEdges, y as getAllDescendants, z as getBusinessDayOffset, A as getChildren, B as getDependencyLag, C as getSuccessorChain, E as getTaskDuration, F as getTransitiveCascadeChain, H as isAncestorTask, I as isTaskParent, J as moveTaskRange, K as moveTaskWithCascade, N as normalizeDependencyLag, O as normalizePredecessorDates, P as normalizeTaskDependencyLags, Q as normalizeUTCDate, S as parseDateOnly, U as recalculateIncomingLags, X as recalculateProjectSchedule, Y as recalculateTaskFromDependencies, Z as reflowTasksOnModeSwitch, _ as removeDependenciesBetweenTasks, $ as resizeTaskWithCascade, a0 as shiftBusinessDayOffset, a1 as universalCascade, a2 as validateDependencies } from './index-CKJZfeDv.js';
4
4
  import * as react_jsx_runtime from 'react/jsx-runtime';
5
5
  import * as RadixPopover from '@radix-ui/react-popover';
6
6
 
@@ -511,6 +511,10 @@ interface GanttModeProps<TTask extends Task = Task> {
511
511
  hiddenTaskListColumns?: readonly TaskListColumnId[];
512
512
  /** Additional commands rendered in the TaskList row three-dots menu */
513
513
  taskListMenuCommands?: TaskListMenuCommand<TTask>[];
514
+ /** How task-list date pickers apply start/end edits (default: preserve-duration) */
515
+ taskDateChangeMode?: TaskDateChangeMode;
516
+ /** Controlled callback for task-list date picker mode changes */
517
+ onTaskDateChangeModeChange?: (mode: TaskDateChangeMode) => void;
514
518
  }
515
519
  type GanttChartProps<TTask extends Task = Task, TItem extends ResourceTimelineItem = ResourceTimelineItem> = GanttModeProps<TTask> | ResourcePlannerChartProps<TItem>;
516
520
  interface ExportToPdfOptions {
@@ -800,6 +804,10 @@ interface TaskListProps {
800
804
  hiddenTaskListColumns?: readonly TaskListColumnId[];
801
805
  /** Additional commands rendered in each row three-dots menu */
802
806
  taskListMenuCommands?: TaskListMenuCommand<Task>[];
807
+ /** How task-list date pickers apply start/end edits */
808
+ taskDateChangeMode?: TaskDateChangeMode;
809
+ /** Controlled callback for task-list date picker mode changes */
810
+ onTaskDateChangeModeChange?: (mode: TaskDateChangeMode) => void;
803
811
  }
804
812
  /**
805
813
  * TaskList component - displays tasks in a table format as an overlay
@@ -898,6 +906,8 @@ interface DatePickerProps {
898
906
  isWeekend?: (date: Date) => boolean;
899
907
  /** Whether to use business days for +1/+7 buttons (default: true) */
900
908
  businessDays?: boolean;
909
+ /** Optional footer content rendered below the calendar popup */
910
+ footer?: React$1.ReactNode;
901
911
  }
902
912
  /**
903
913
  * DatePicker component — shows formatted date as a button, opens calendar popup on click.
@@ -1295,4 +1305,4 @@ interface VisibleReorderPosition {
1295
1305
  */
1296
1306
  declare function getVisibleReorderPosition(orderedTasks: TaskLike[], visibleTasks: TaskLike[], movedTaskId: string, originVisibleIndex: number, dropVisibleIndex: number): VisibleReorderPosition | null;
1297
1307
 
1298
- export { type BuiltInTaskListColumnId, Button, type ButtonProps, Calendar, type CalendarProps, type CustomDayConfig, type CustomDayPredicateConfig, DatePicker, type DatePickerProps, DragGuideLines, type ExportToPdfHeaderOptions, type ExportToPdfOptions, GanttChart, type GanttChartHandle, type GanttChartProps, type GanttModeProps, GridBackground, Input, type InputProps, type MonthBlock, Popover, PopoverContent, type PopoverContentProps, type PopoverProps, PopoverTrigger, ResourcePlannerChartProps, ResourceTimelineChart, type ResourceTimelineConflictRange, ResourceTimelineItem, type ResourceTimelineLayoutDiagnostic, type ResourceTimelineLayoutItem, type ResourceTimelineLayoutOptions, type ResourceTimelineLayoutResult, type ResourceTimelineLayoutRow, ResourceTimelineResource, type Task, type TaskDependency, TaskList, type TaskListColumn, type TaskListColumnContext, type TaskListColumnId, type TaskListMenuCommand, type TaskListProps, type TaskPredicate, TaskRow, TimeScaleHeader, TodayIndicator, ValidationResult, type VisibleReorderPosition, type WeekBlock, type WeekSpan, type WithoutDepsOptions, type YearSpan, addBusinessDays, and, calculateBezierPath, calculateDependencyPath, calculateGridLines, calculateGridWidth, calculateMilestoneConnectionBounds, calculateMilestoneGeometry, calculateMonthGridLines, calculateOrthogonalPath, calculateTaskBar, calculateWeekGridLines, calculateWeekendBlocks, clampDateRangeForIncomingFS, createCustomDayPredicate, createDateKey, detectEdgeZone, expired, flattenHierarchy, formatDateLabel, formatDateRangeLabel, getBusinessDaysCount, getCursorForPosition, getDayOffset, getMonthBlocks, getMonthDays, getMonthSpans, getMultiMonthDays, getVisibleReorderPosition, getWeekBlocks, getWeekSpans, getYearSpans, inDateRange, isTaskExpired, isToday, isWeekend, layoutResourceTimelineItems, nameContains, normalizeHierarchyTasks, normalizeTaskDates, not, or, parseUTCDate, pixelsToDate, progressInRange, resolveDateRangeFromPixels, resolveTaskHorizontalGeometry, subtractBusinessDays, useTaskDrag, withoutDeps };
1308
+ export { type BuiltInTaskListColumnId, Button, type ButtonProps, Calendar, type CalendarProps, type CustomDayConfig, type CustomDayPredicateConfig, DatePicker, type DatePickerProps, DragGuideLines, type ExportToPdfHeaderOptions, type ExportToPdfOptions, GanttChart, type GanttChartHandle, type GanttChartProps, type GanttModeProps, GridBackground, Input, type InputProps, type MonthBlock, Popover, PopoverContent, type PopoverContentProps, type PopoverProps, PopoverTrigger, ResourcePlannerChartProps, ResourceTimelineChart, type ResourceTimelineConflictRange, ResourceTimelineItem, type ResourceTimelineLayoutDiagnostic, type ResourceTimelineLayoutItem, type ResourceTimelineLayoutOptions, type ResourceTimelineLayoutResult, type ResourceTimelineLayoutRow, ResourceTimelineResource, type Task, TaskDateChangeMode, type TaskDependency, TaskList, type TaskListColumn, type TaskListColumnContext, type TaskListColumnId, type TaskListMenuCommand, type TaskListProps, type TaskPredicate, TaskRow, TimeScaleHeader, TodayIndicator, ValidationResult, type VisibleReorderPosition, type WeekBlock, type WeekSpan, type WithoutDepsOptions, type YearSpan, addBusinessDays, and, calculateBezierPath, calculateDependencyPath, calculateGridLines, calculateGridWidth, calculateMilestoneConnectionBounds, calculateMilestoneGeometry, calculateMonthGridLines, calculateOrthogonalPath, calculateTaskBar, calculateWeekGridLines, calculateWeekendBlocks, clampDateRangeForIncomingFS, createCustomDayPredicate, createDateKey, detectEdgeZone, expired, flattenHierarchy, formatDateLabel, formatDateRangeLabel, getBusinessDaysCount, getCursorForPosition, getDayOffset, getMonthBlocks, getMonthDays, getMonthSpans, getMultiMonthDays, getVisibleReorderPosition, getWeekBlocks, getWeekSpans, getYearSpans, inDateRange, isTaskExpired, isToday, isWeekend, layoutResourceTimelineItems, nameContains, normalizeHierarchyTasks, normalizeTaskDates, not, or, parseUTCDate, pixelsToDate, progressInRange, resolveDateRangeFromPixels, resolveTaskHorizontalGeometry, subtractBusinessDays, useTaskDrag, withoutDeps };
package/dist/index.js CHANGED
@@ -3922,7 +3922,8 @@ var DatePicker = ({
3922
3922
  className,
3923
3923
  disabled = false,
3924
3924
  isWeekend: isWeekend3,
3925
- businessDays = true
3925
+ businessDays = true,
3926
+ footer
3926
3927
  }) => {
3927
3928
  const [open, setOpen] = (0, import_react9.useState)(false);
3928
3929
  const [inputValue, setInputValue] = (0, import_react9.useState)("");
@@ -4200,7 +4201,8 @@ var DatePicker = ({
4200
4201
  initialDate: activeDate,
4201
4202
  isWeekend: isWeekend3
4202
4203
  }
4203
- )
4204
+ ),
4205
+ footer ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "gantt-datepicker-footer", children: footer }) : null
4204
4206
  ]
4205
4207
  }
4206
4208
  )
@@ -4842,7 +4844,9 @@ var TaskListRow = import_react10.default.memo(
4842
4844
  resolvedColumns,
4843
4845
  isTaskSelected = false,
4844
4846
  onTaskSelectionChange,
4845
- taskListMenuCommands = []
4847
+ taskListMenuCommands = [],
4848
+ taskDateChangeMode = "preserve-duration",
4849
+ onTaskDateChangeModeChange
4846
4850
  }) => {
4847
4851
  const [editingColumnId, setEditingColumnId] = (0, import_react10.useState)(null);
4848
4852
  const editingName = editingColumnId === "name";
@@ -5245,24 +5249,22 @@ var TaskListRow = import_react10.default.memo(
5245
5249
  emitMilestoneDateChange(newDateISO);
5246
5250
  return;
5247
5251
  }
5248
- let nextEndISO;
5249
5252
  const normalizedInputStart = businessDays ? alignToWorkingDay(/* @__PURE__ */ new Date(`${newDateISO}T00:00:00.000Z`), 1, weekendPredicate) : /* @__PURE__ */ new Date(`${newDateISO}T00:00:00.000Z`);
5250
- if (businessDays) {
5251
- const duration = getDuration(task.startDate, task.endDate);
5252
- nextEndISO = buildTaskRangeFromStart(
5253
+ const { startDate: normalizedStart, endDate: normalizedEnd } = taskDateChangeMode === "free" ? normalizeTaskDates(
5254
+ normalizedInputStart,
5255
+ normalizedInputStart.getTime() > parseUTCDate(task.endDate).getTime() ? normalizedInputStart : parseUTCDate(task.endDate)
5256
+ ) : normalizeTaskDates(
5257
+ normalizedInputStart,
5258
+ businessDays ? buildTaskRangeFromStart(
5253
5259
  normalizedInputStart,
5254
- duration,
5260
+ getDuration(task.startDate, task.endDate),
5255
5261
  true,
5256
5262
  weekendPredicate,
5257
5263
  1
5258
- ).end.toISOString().split("T")[0];
5259
- } else {
5260
- const origStart = parseUTCDate(task.startDate);
5261
- const origEnd = parseUTCDate(task.endDate);
5262
- const durationMs = origEnd.getTime() - origStart.getTime();
5263
- nextEndISO = new Date(normalizedInputStart.getTime() + durationMs).toISOString().split("T")[0];
5264
- }
5265
- const { startDate: normalizedStart, endDate: normalizedEnd } = normalizeTaskDates(normalizedInputStart, nextEndISO);
5264
+ ).end.toISOString().split("T")[0] : new Date(
5265
+ normalizedInputStart.getTime() + (parseUTCDate(task.endDate).getTime() - parseUTCDate(task.startDate).getTime())
5266
+ ).toISOString().split("T")[0]
5267
+ );
5266
5268
  const clampedRange = clampTaskRangeForIncomingFS(
5267
5269
  task,
5268
5270
  /* @__PURE__ */ new Date(`${normalizedStart}T00:00:00.000Z`),
@@ -5291,7 +5293,7 @@ var TaskListRow = import_react10.default.memo(
5291
5293
  }
5292
5294
  ]);
5293
5295
  },
5294
- [task, onTasksChange, businessDays, getDuration, getEndDate, allTasks, weekendPredicate, isMilestone, emitMilestoneDateChange]
5296
+ [task, onTasksChange, businessDays, getDuration, allTasks, weekendPredicate, isMilestone, emitMilestoneDateChange, taskDateChangeMode]
5295
5297
  );
5296
5298
  const handleEndDateChange = (0, import_react10.useCallback)(
5297
5299
  (newDateISO) => {
@@ -5300,24 +5302,22 @@ var TaskListRow = import_react10.default.memo(
5300
5302
  emitMilestoneDateChange(newDateISO);
5301
5303
  return;
5302
5304
  }
5303
- let nextStartISO;
5304
5305
  const normalizedInputEnd = businessDays ? alignToWorkingDay(/* @__PURE__ */ new Date(`${newDateISO}T00:00:00.000Z`), -1, weekendPredicate) : /* @__PURE__ */ new Date(`${newDateISO}T00:00:00.000Z`);
5305
- if (businessDays) {
5306
- const duration = getDuration(task.startDate, task.endDate);
5307
- nextStartISO = buildTaskRangeFromEnd(
5306
+ const { startDate: normalizedStart, endDate: normalizedEnd } = taskDateChangeMode === "free" ? normalizeTaskDates(
5307
+ normalizedInputEnd.getTime() < parseUTCDate(task.startDate).getTime() ? normalizedInputEnd : parseUTCDate(task.startDate),
5308
+ normalizedInputEnd
5309
+ ) : normalizeTaskDates(
5310
+ businessDays ? buildTaskRangeFromEnd(
5308
5311
  normalizedInputEnd,
5309
- duration,
5312
+ getDuration(task.startDate, task.endDate),
5310
5313
  true,
5311
5314
  weekendPredicate,
5312
5315
  -1
5313
- ).start.toISOString().split("T")[0];
5314
- } else {
5315
- const origStart = parseUTCDate(task.startDate);
5316
- const origEnd = parseUTCDate(task.endDate);
5317
- const durationMs = origEnd.getTime() - origStart.getTime();
5318
- nextStartISO = new Date(normalizedInputEnd.getTime() - durationMs).toISOString().split("T")[0];
5319
- }
5320
- const { startDate: normalizedStart, endDate: normalizedEnd } = normalizeTaskDates(nextStartISO, normalizedInputEnd);
5316
+ ).start.toISOString().split("T")[0] : new Date(
5317
+ normalizedInputEnd.getTime() - (parseUTCDate(task.endDate).getTime() - parseUTCDate(task.startDate).getTime())
5318
+ ).toISOString().split("T")[0],
5319
+ normalizedInputEnd
5320
+ );
5321
5321
  const clampedRange = clampTaskRangeForIncomingFS(
5322
5322
  task,
5323
5323
  /* @__PURE__ */ new Date(`${normalizedStart}T00:00:00.000Z`),
@@ -5346,8 +5346,19 @@ var TaskListRow = import_react10.default.memo(
5346
5346
  }
5347
5347
  ]);
5348
5348
  },
5349
- [task, onTasksChange, businessDays, getDuration, weekendPredicate, allTasks, isMilestone, emitMilestoneDateChange]
5349
+ [task, onTasksChange, businessDays, getDuration, weekendPredicate, allTasks, isMilestone, emitMilestoneDateChange, taskDateChangeMode]
5350
5350
  );
5351
+ const datePickerFooter = onTaskDateChangeModeChange ? /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("label", { className: "gantt-datepicker-mode-checkbox", children: [
5352
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
5353
+ "input",
5354
+ {
5355
+ type: "checkbox",
5356
+ checked: taskDateChangeMode === "preserve-duration",
5357
+ onChange: (event) => onTaskDateChangeModeChange(event.target.checked ? "preserve-duration" : "free")
5358
+ }
5359
+ ),
5360
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { children: "\u0421\u043E\u0445\u0440\u0430\u043D\u044F\u0442\u044C \u0434\u043B\u0438\u0442\u0435\u043B\u044C\u043D\u043E\u0441\u0442\u044C" })
5361
+ ] }) : null;
5351
5362
  const handleRowClickInternal = (0, import_react10.useCallback)(() => {
5352
5363
  onRowClick?.(task.id);
5353
5364
  }, [task.id, onRowClick]);
@@ -6046,7 +6057,8 @@ var TaskListRow = import_react10.default.memo(
6046
6057
  portal: true,
6047
6058
  disabled: task.locked,
6048
6059
  isWeekend: weekendPredicate,
6049
- businessDays
6060
+ businessDays,
6061
+ footer: datePickerFooter
6050
6062
  }
6051
6063
  )
6052
6064
  }
@@ -6065,7 +6077,8 @@ var TaskListRow = import_react10.default.memo(
6065
6077
  portal: true,
6066
6078
  disabled: task.locked,
6067
6079
  isWeekend: weekendPredicate,
6068
- businessDays
6080
+ businessDays,
6081
+ footer: datePickerFooter
6069
6082
  }
6070
6083
  )
6071
6084
  }
@@ -6745,7 +6758,9 @@ var TaskList = ({
6745
6758
  isFilterActive = false,
6746
6759
  additionalColumns,
6747
6760
  hiddenTaskListColumns,
6748
- taskListMenuCommands
6761
+ taskListMenuCommands,
6762
+ taskDateChangeMode = "preserve-duration",
6763
+ onTaskDateChangeModeChange
6749
6764
  }) => {
6750
6765
  const [internalSelectedTaskIds, setInternalSelectedTaskIds] = (0, import_react12.useState)(/* @__PURE__ */ new Set());
6751
6766
  const effectiveSelectedTaskIds = selectedTaskIds ?? internalSelectedTaskIds;
@@ -7481,7 +7496,9 @@ var TaskList = ({
7481
7496
  resolvedColumns,
7482
7497
  isTaskSelected: effectiveSelectedTaskIds.has(task.id),
7483
7498
  onTaskSelectionChange: handleToggleTaskSelection,
7484
- taskListMenuCommands
7499
+ taskListMenuCommands,
7500
+ taskDateChangeMode,
7501
+ onTaskDateChangeModeChange
7485
7502
  }
7486
7503
  ),
7487
7504
  pendingInsertDisplayTaskId === task.id && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
@@ -9613,7 +9630,9 @@ function TaskGanttChartInner(props, ref) {
9613
9630
  showChart = true,
9614
9631
  additionalColumns,
9615
9632
  hiddenTaskListColumns,
9616
- taskListMenuCommands
9633
+ taskListMenuCommands,
9634
+ taskDateChangeMode: externalTaskDateChangeMode,
9635
+ onTaskDateChangeModeChange: externalOnTaskDateChangeModeChange
9617
9636
  } = props;
9618
9637
  const containerRef = (0, import_react15.useRef)(null);
9619
9638
  const scrollContainerRef = (0, import_react15.useRef)(null);
@@ -9621,10 +9640,13 @@ function TaskGanttChartInner(props, ref) {
9621
9640
  const clearSelectedTaskTimeoutRef = (0, import_react15.useRef)(null);
9622
9641
  const [selectedTaskId, setSelectedTaskId] = (0, import_react15.useState)(null);
9623
9642
  const [taskListHasRightShadow, setTaskListHasRightShadow] = (0, import_react15.useState)(false);
9643
+ const [internalTaskDateChangeMode, setInternalTaskDateChangeMode] = (0, import_react15.useState)("preserve-duration");
9624
9644
  const [selectedChip, setSelectedChip] = (0, import_react15.useState)(null);
9625
9645
  const [internalCollapsedParentIds, setInternalCollapsedParentIds] = (0, import_react15.useState)(/* @__PURE__ */ new Set());
9626
9646
  const collapsedParentIds = externalCollapsedParentIds ?? internalCollapsedParentIds;
9627
9647
  const [editingTaskId, setEditingTaskId] = (0, import_react15.useState)(null);
9648
+ const taskDateChangeMode = externalTaskDateChangeMode ?? internalTaskDateChangeMode;
9649
+ const handleTaskDateChangeMode = externalOnTaskDateChangeModeChange ?? setInternalTaskDateChangeMode;
9628
9650
  const normalizedTasks = (0, import_react15.useMemo)(() => normalizeHierarchyTasks(tasks), [tasks]);
9629
9651
  const isCustomWeekend = (0, import_react15.useMemo)(
9630
9652
  () => createCustomDayPredicate({ customDays, isWeekend: isWeekend3 }),
@@ -10221,7 +10243,9 @@ function TaskGanttChartInner(props, ref) {
10221
10243
  isFilterActive: !!taskFilter,
10222
10244
  additionalColumns,
10223
10245
  hiddenTaskListColumns,
10224
- taskListMenuCommands
10246
+ taskListMenuCommands,
10247
+ taskDateChangeMode,
10248
+ onTaskDateChangeModeChange: handleTaskDateChangeMode
10225
10249
  }
10226
10250
  ),
10227
10251
  /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(