gantt-lib 0.72.2 → 0.73.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
@@ -385,6 +385,26 @@ interface TaskDependency {
385
385
  /** Lag in days */
386
386
  lag: number;
387
387
  }
388
+ interface TaskListMenuCommand<TTask extends Task = Task> {
389
+ /** Stable command id for React keys and consumer bookkeeping */
390
+ id: string;
391
+ /** Visible label in the three-dots menu */
392
+ label: string;
393
+ /** Optional icon rendered before the label */
394
+ icon?: React$1.ReactNode;
395
+ /** Command handler receives the current task row */
396
+ onSelect: (row: TTask) => void;
397
+ /** Optional per-row visibility predicate */
398
+ isVisible?: (row: TTask) => boolean;
399
+ /** Optional per-row disabled predicate */
400
+ isDisabled?: (row: TTask) => boolean;
401
+ /** Scope of the command in the hierarchy: all rows, parent/group rows, regular linear rows, or milestones */
402
+ scope?: 'all' | 'group' | 'linear' | 'milestone';
403
+ /** Marks the command with danger styling */
404
+ danger?: boolean;
405
+ /** Close the menu after click (default: true) */
406
+ closeOnSelect?: boolean;
407
+ }
388
408
  interface GanttChartProps<TTask extends Task = Task> {
389
409
  /** Array of tasks to display */
390
410
  tasks: TTask[];
@@ -428,6 +448,8 @@ interface GanttChartProps<TTask extends Task = Task> {
428
448
  onPromoteTask?: (taskId: string) => void;
429
449
  /** Callback when a task is demoted (parentId set). If not provided, default internal logic is used. */
430
450
  onDemoteTask?: (taskId: string, newParentId: string) => void;
451
+ /** Callback when a parent task is ungrouped (removed while direct children move one level up). */
452
+ onUngroupTask?: (taskId: string) => void;
431
453
  /** Enable add task button at bottom of task list (default: true) */
432
454
  enableAddTask?: boolean;
433
455
  /** View mode: 'day' renders one column per day, 'week' renders one column per 7 days, 'month' renders one column per month (default: 'day') */
@@ -458,6 +480,8 @@ interface GanttChartProps<TTask extends Task = Task> {
458
480
  showChart?: boolean;
459
481
  /** Additional custom columns to render in the TaskList after built-in columns */
460
482
  additionalColumns?: TaskListColumn<TTask>[];
483
+ /** Additional commands rendered in the TaskList row three-dots menu */
484
+ taskListMenuCommands?: TaskListMenuCommand<TTask>[];
461
485
  }
462
486
  interface ExportToPdfOptions {
463
487
  /** Structured header displayed above the exported chart */
@@ -696,6 +720,8 @@ interface TaskListProps {
696
720
  onPromoteTask?: (taskId: string) => void;
697
721
  /** Callback when task is demoted (parentId set to previous task) */
698
722
  onDemoteTask?: (taskId: string, newParentId: string) => void;
723
+ /** Callback when parent task is ungrouped (removed while direct children move one level up) */
724
+ onUngroupTask?: (taskId: string) => void;
699
725
  /** Custom day configurations for date picker */
700
726
  customDays?: CustomDayConfig[];
701
727
  /** Optional base weekend predicate for date picker */
@@ -712,6 +738,8 @@ interface TaskListProps {
712
738
  isFilterActive?: boolean;
713
739
  /** Additional columns to display after built-in columns */
714
740
  additionalColumns?: TaskListColumn<any>[];
741
+ /** Additional commands rendered in each row three-dots menu */
742
+ taskListMenuCommands?: TaskListMenuCommand<Task>[];
715
743
  }
716
744
  /**
717
745
  * TaskList component - displays tasks in a table format as an overlay
@@ -1155,4 +1183,4 @@ interface VisibleReorderPosition {
1155
1183
  */
1156
1184
  declare function getVisibleReorderPosition(orderedTasks: TaskLike[], visibleTasks: TaskLike[], movedTaskId: string, originVisibleIndex: number, dropVisibleIndex: number): VisibleReorderPosition | null;
1157
1185
 
1158
- 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, GridBackground, Input, type InputProps, type MonthBlock, Popover, PopoverContent, type PopoverContentProps, type PopoverProps, PopoverTrigger, type Task, type TaskDependency, TaskList, type TaskListColumn, type TaskListColumnContext, type TaskListProps, type TaskPredicate, TaskRow, TimeScaleHeader, TodayIndicator, ValidationResult, type VisibleReorderPosition, type WeekBlock, type WeekSpan, 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, nameContains, normalizeHierarchyTasks, normalizeTaskDates, not, or, parseUTCDate, pixelsToDate, progressInRange, resolveDateRangeFromPixels, resolveTaskHorizontalGeometry, subtractBusinessDays, useTaskDrag, withoutDeps };
1186
+ 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, GridBackground, Input, type InputProps, type MonthBlock, Popover, PopoverContent, type PopoverContentProps, type PopoverProps, PopoverTrigger, type Task, type TaskDependency, TaskList, type TaskListColumn, type TaskListColumnContext, type TaskListMenuCommand, type TaskListProps, type TaskPredicate, TaskRow, TimeScaleHeader, TodayIndicator, ValidationResult, type VisibleReorderPosition, type WeekBlock, type WeekSpan, 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, nameContains, normalizeHierarchyTasks, normalizeTaskDates, not, or, parseUTCDate, pixelsToDate, progressInRange, resolveDateRangeFromPixels, resolveTaskHorizontalGeometry, subtractBusinessDays, useTaskDrag, withoutDeps };
package/dist/index.d.ts CHANGED
@@ -385,6 +385,26 @@ interface TaskDependency {
385
385
  /** Lag in days */
386
386
  lag: number;
387
387
  }
388
+ interface TaskListMenuCommand<TTask extends Task = Task> {
389
+ /** Stable command id for React keys and consumer bookkeeping */
390
+ id: string;
391
+ /** Visible label in the three-dots menu */
392
+ label: string;
393
+ /** Optional icon rendered before the label */
394
+ icon?: React$1.ReactNode;
395
+ /** Command handler receives the current task row */
396
+ onSelect: (row: TTask) => void;
397
+ /** Optional per-row visibility predicate */
398
+ isVisible?: (row: TTask) => boolean;
399
+ /** Optional per-row disabled predicate */
400
+ isDisabled?: (row: TTask) => boolean;
401
+ /** Scope of the command in the hierarchy: all rows, parent/group rows, regular linear rows, or milestones */
402
+ scope?: 'all' | 'group' | 'linear' | 'milestone';
403
+ /** Marks the command with danger styling */
404
+ danger?: boolean;
405
+ /** Close the menu after click (default: true) */
406
+ closeOnSelect?: boolean;
407
+ }
388
408
  interface GanttChartProps<TTask extends Task = Task> {
389
409
  /** Array of tasks to display */
390
410
  tasks: TTask[];
@@ -428,6 +448,8 @@ interface GanttChartProps<TTask extends Task = Task> {
428
448
  onPromoteTask?: (taskId: string) => void;
429
449
  /** Callback when a task is demoted (parentId set). If not provided, default internal logic is used. */
430
450
  onDemoteTask?: (taskId: string, newParentId: string) => void;
451
+ /** Callback when a parent task is ungrouped (removed while direct children move one level up). */
452
+ onUngroupTask?: (taskId: string) => void;
431
453
  /** Enable add task button at bottom of task list (default: true) */
432
454
  enableAddTask?: boolean;
433
455
  /** View mode: 'day' renders one column per day, 'week' renders one column per 7 days, 'month' renders one column per month (default: 'day') */
@@ -458,6 +480,8 @@ interface GanttChartProps<TTask extends Task = Task> {
458
480
  showChart?: boolean;
459
481
  /** Additional custom columns to render in the TaskList after built-in columns */
460
482
  additionalColumns?: TaskListColumn<TTask>[];
483
+ /** Additional commands rendered in the TaskList row three-dots menu */
484
+ taskListMenuCommands?: TaskListMenuCommand<TTask>[];
461
485
  }
462
486
  interface ExportToPdfOptions {
463
487
  /** Structured header displayed above the exported chart */
@@ -696,6 +720,8 @@ interface TaskListProps {
696
720
  onPromoteTask?: (taskId: string) => void;
697
721
  /** Callback when task is demoted (parentId set to previous task) */
698
722
  onDemoteTask?: (taskId: string, newParentId: string) => void;
723
+ /** Callback when parent task is ungrouped (removed while direct children move one level up) */
724
+ onUngroupTask?: (taskId: string) => void;
699
725
  /** Custom day configurations for date picker */
700
726
  customDays?: CustomDayConfig[];
701
727
  /** Optional base weekend predicate for date picker */
@@ -712,6 +738,8 @@ interface TaskListProps {
712
738
  isFilterActive?: boolean;
713
739
  /** Additional columns to display after built-in columns */
714
740
  additionalColumns?: TaskListColumn<any>[];
741
+ /** Additional commands rendered in each row three-dots menu */
742
+ taskListMenuCommands?: TaskListMenuCommand<Task>[];
715
743
  }
716
744
  /**
717
745
  * TaskList component - displays tasks in a table format as an overlay
@@ -1155,4 +1183,4 @@ interface VisibleReorderPosition {
1155
1183
  */
1156
1184
  declare function getVisibleReorderPosition(orderedTasks: TaskLike[], visibleTasks: TaskLike[], movedTaskId: string, originVisibleIndex: number, dropVisibleIndex: number): VisibleReorderPosition | null;
1157
1185
 
1158
- 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, GridBackground, Input, type InputProps, type MonthBlock, Popover, PopoverContent, type PopoverContentProps, type PopoverProps, PopoverTrigger, type Task, type TaskDependency, TaskList, type TaskListColumn, type TaskListColumnContext, type TaskListProps, type TaskPredicate, TaskRow, TimeScaleHeader, TodayIndicator, ValidationResult, type VisibleReorderPosition, type WeekBlock, type WeekSpan, 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, nameContains, normalizeHierarchyTasks, normalizeTaskDates, not, or, parseUTCDate, pixelsToDate, progressInRange, resolveDateRangeFromPixels, resolveTaskHorizontalGeometry, subtractBusinessDays, useTaskDrag, withoutDeps };
1186
+ 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, GridBackground, Input, type InputProps, type MonthBlock, Popover, PopoverContent, type PopoverContentProps, type PopoverProps, PopoverTrigger, type Task, type TaskDependency, TaskList, type TaskListColumn, type TaskListColumnContext, type TaskListMenuCommand, type TaskListProps, type TaskPredicate, TaskRow, TimeScaleHeader, TodayIndicator, ValidationResult, type VisibleReorderPosition, type WeekBlock, type WeekSpan, 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, nameContains, normalizeHierarchyTasks, normalizeTaskDates, not, or, parseUTCDate, pixelsToDate, progressInRange, resolveDateRangeFromPixels, resolveTaskHorizontalGeometry, subtractBusinessDays, useTaskDrag, withoutDeps };
package/dist/index.js CHANGED
@@ -4246,6 +4246,26 @@ var CopyIcon = () => /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
4246
4246
  ]
4247
4247
  }
4248
4248
  );
4249
+ var UngroupIcon = () => /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
4250
+ "svg",
4251
+ {
4252
+ xmlns: "http://www.w3.org/2000/svg",
4253
+ width: "16",
4254
+ height: "16",
4255
+ viewBox: "0 0 24 24",
4256
+ fill: "none",
4257
+ stroke: "currentColor",
4258
+ strokeWidth: "2",
4259
+ strokeLinecap: "round",
4260
+ strokeLinejoin: "round",
4261
+ children: [
4262
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("path", { d: "M3 12h10" }),
4263
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("path", { d: "m6 9-3 3 3 3" }),
4264
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("path", { d: "M13 6h8" }),
4265
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("path", { d: "M13 18h8" })
4266
+ ]
4267
+ }
4268
+ );
4249
4269
  var TASK_COLOR_PALETTE = [
4250
4270
  // { label: "Палисандр", value: "#A61E4D" },
4251
4271
  // { label: "Киноварь", value: "#E8590C" },
@@ -4678,6 +4698,7 @@ var TaskListRow = import_react10.default.memo(
4678
4698
  onToggleCollapse,
4679
4699
  onPromoteTask,
4680
4700
  onDemoteTask,
4701
+ onUngroupTask,
4681
4702
  onDuplicateTask,
4682
4703
  canDemoteTask = true,
4683
4704
  isLastChild = true,
@@ -4689,7 +4710,8 @@ var TaskListRow = import_react10.default.memo(
4689
4710
  businessDays,
4690
4711
  isFilterMatch = false,
4691
4712
  isFilterHideMode = false,
4692
- resolvedColumns
4713
+ resolvedColumns,
4714
+ taskListMenuCommands = []
4693
4715
  }) => {
4694
4716
  const [editingColumnId, setEditingColumnId] = (0, import_react10.useState)(null);
4695
4717
  const editingName = editingColumnId === "name";
@@ -4723,6 +4745,7 @@ var TaskListRow = import_react10.default.memo(
4723
4745
  [task.id, allTasks]
4724
4746
  );
4725
4747
  const isChild = task.parentId !== void 0;
4748
+ const isMilestoneRow = normalizedTask.type === "milestone";
4726
4749
  const weekendPredicate = (0, import_react10.useMemo)(
4727
4750
  () => createCustomDayPredicate({ customDays, isWeekend: isWeekend3 }),
4728
4751
  [customDays, isWeekend3]
@@ -5245,6 +5268,38 @@ var TaskListRow = import_react10.default.memo(
5245
5268
  },
5246
5269
  [allTasks, isParent, onTasksChange, task]
5247
5270
  );
5271
+ const handleUngroup = (0, import_react10.useCallback)(
5272
+ (e) => {
5273
+ e.stopPropagation();
5274
+ setContextMenuOpen(false);
5275
+ onUngroupTask?.(task.id);
5276
+ },
5277
+ [onUngroupTask, task.id]
5278
+ );
5279
+ const visibleCustomMenuCommands = (0, import_react10.useMemo)(
5280
+ () => taskListMenuCommands.filter(
5281
+ (command) => {
5282
+ const scope = command.scope ?? "all";
5283
+ if (scope === "group" && !isParent) return false;
5284
+ if (scope === "linear" && (isParent || isMilestoneRow)) return false;
5285
+ if (scope === "milestone" && !isMilestoneRow) return false;
5286
+ return command.isVisible?.(task) ?? true;
5287
+ }
5288
+ ),
5289
+ [taskListMenuCommands, task, isParent, isMilestoneRow]
5290
+ );
5291
+ const hasContextMenu = visibleCustomMenuCommands.length > 0 || !!onDuplicateTask || !!onDelete || !!onTasksChange || isParent && !!onUngroupTask;
5292
+ const handleCustomMenuCommandClick = (0, import_react10.useCallback)(
5293
+ (command) => (e) => {
5294
+ e.stopPropagation();
5295
+ if (command.closeOnSelect !== false) {
5296
+ setContextMenuOpen(false);
5297
+ setColorMenuOpen(false);
5298
+ }
5299
+ command.onSelect(task);
5300
+ },
5301
+ [task]
5302
+ );
5248
5303
  const handleAddClick = (0, import_react10.useCallback)(
5249
5304
  (e) => {
5250
5305
  e.stopPropagation();
@@ -5671,7 +5726,7 @@ var TaskListRow = import_react10.default.memo(
5671
5726
  "aria-hidden": "true"
5672
5727
  }
5673
5728
  ),
5674
- !editingName && (onInsertAfter || onDelete || onPromoteTask || onDemoteTask || onDuplicateTask || onTasksChange) && /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "gantt-tl-name-actions", children: [
5729
+ !editingName && (onInsertAfter || onDelete || onPromoteTask || onDemoteTask || onUngroupTask || onDuplicateTask || onTasksChange || hasContextMenu) && /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "gantt-tl-name-actions", children: [
5675
5730
  onInsertAfter && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
5676
5731
  "button",
5677
5732
  {
@@ -5717,7 +5772,7 @@ var TaskListRow = import_react10.default.memo(
5717
5772
  onDemote: onDemoteTask ? handleDemote : void 0
5718
5773
  }
5719
5774
  ),
5720
- (onDuplicateTask || onDelete || onTasksChange) && /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(Popover, { open: contextMenuOpen, onOpenChange: (open) => {
5775
+ hasContextMenu && /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(Popover, { open: contextMenuOpen, onOpenChange: (open) => {
5721
5776
  setContextMenuOpen(open);
5722
5777
  if (!open) setColorMenuOpen(false);
5723
5778
  }, children: [
@@ -5810,6 +5865,32 @@ var TaskListRow = import_react10.default.memo(
5810
5865
  ]
5811
5866
  }
5812
5867
  ),
5868
+ visibleCustomMenuCommands.map((command) => /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
5869
+ "button",
5870
+ {
5871
+ type: "button",
5872
+ className: `gantt-tl-context-menu-item${command.danger ? " gantt-tl-context-menu-item-danger" : ""}`,
5873
+ onClick: handleCustomMenuCommandClick(command),
5874
+ disabled: command.isDisabled?.(task) ?? false,
5875
+ children: [
5876
+ command.icon,
5877
+ command.label
5878
+ ]
5879
+ },
5880
+ command.id
5881
+ )),
5882
+ isParent && onUngroupTask && /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
5883
+ "button",
5884
+ {
5885
+ type: "button",
5886
+ className: "gantt-tl-context-menu-item",
5887
+ onClick: handleUngroup,
5888
+ children: [
5889
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(UngroupIcon, {}),
5890
+ "\u0420\u0430\u0437\u0433\u0440\u0443\u043F\u043F\u0438\u0440\u043E\u0432\u0430\u0442\u044C"
5891
+ ]
5892
+ }
5893
+ ),
5813
5894
  onDelete && /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
5814
5895
  "button",
5815
5896
  {
@@ -6505,6 +6586,7 @@ var TaskList = ({
6505
6586
  onToggleCollapse: externalOnToggleCollapse,
6506
6587
  onPromoteTask,
6507
6588
  onDemoteTask,
6589
+ onUngroupTask,
6508
6590
  customDays,
6509
6591
  isWeekend: isWeekend3,
6510
6592
  businessDays,
@@ -6512,7 +6594,8 @@ var TaskList = ({
6512
6594
  filterMode = "highlight",
6513
6595
  filteredTaskIds = /* @__PURE__ */ new Set(),
6514
6596
  isFilterActive = false,
6515
- additionalColumns
6597
+ additionalColumns,
6598
+ taskListMenuCommands
6516
6599
  }) => {
6517
6600
  const [internalCollapsedParentIds, setInternalCollapsedParentIds] = (0, import_react12.useState)(/* @__PURE__ */ new Set());
6518
6601
  const collapsedParentIds = externalCollapsedParentIds ?? internalCollapsedParentIds;
@@ -7176,6 +7259,7 @@ var TaskList = ({
7176
7259
  onToggleCollapse: handleToggleCollapse,
7177
7260
  onPromoteTask,
7178
7261
  onDemoteTask: onDemoteTask ? handleDemoteWrapper : void 0,
7262
+ onUngroupTask,
7179
7263
  onDuplicateTask: onReorder ? handleDuplicateTask : void 0,
7180
7264
  canDemoteTask,
7181
7265
  isLastChild: lastChildIds.has(task.id),
@@ -7187,7 +7271,8 @@ var TaskList = ({
7187
7271
  businessDays,
7188
7272
  isFilterMatch: filterMode === "highlight" ? highlightedTaskIds.has(task.id) : false,
7189
7273
  isFilterHideMode: filterMode === "hide" && isFilterActive,
7190
- resolvedColumns
7274
+ resolvedColumns,
7275
+ taskListMenuCommands
7191
7276
  }
7192
7277
  ),
7193
7278
  pendingInsertDisplayTaskId === task.id && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
@@ -7607,6 +7692,7 @@ function GanttChartInner(props, ref) {
7607
7692
  onReorder,
7608
7693
  onPromoteTask,
7609
7694
  onDemoteTask,
7695
+ onUngroupTask,
7610
7696
  enableAddTask = true,
7611
7697
  viewMode = "day",
7612
7698
  customDays,
@@ -7619,7 +7705,8 @@ function GanttChartInner(props, ref) {
7619
7705
  highlightedTaskIds,
7620
7706
  disableTaskDrag = false,
7621
7707
  showChart = true,
7622
- additionalColumns
7708
+ additionalColumns,
7709
+ taskListMenuCommands
7623
7710
  } = props;
7624
7711
  const containerRef = (0, import_react13.useRef)(null);
7625
7712
  const scrollContainerRef = (0, import_react13.useRef)(null);
@@ -8035,6 +8122,33 @@ function GanttChartInner(props, ref) {
8035
8122
  };
8036
8123
  onTasksChange?.([updatedDemotedTask]);
8037
8124
  }, [tasks, onTasksChange, onDemoteTask]);
8125
+ const handleUngroupTask = (0, import_react13.useCallback)((taskId) => {
8126
+ if (onUngroupTask) {
8127
+ onUngroupTask(taskId);
8128
+ return;
8129
+ }
8130
+ const parentTask = tasks.find((task) => task.id === taskId);
8131
+ if (!parentTask) return;
8132
+ const hasDirectChildren = tasks.some((task) => task.parentId === taskId);
8133
+ if (!hasDirectChildren) return;
8134
+ const changedTasks = [];
8135
+ for (const task of tasks) {
8136
+ if (task.id === taskId) continue;
8137
+ const nextParentId = task.parentId === taskId ? parentTask.parentId : task.parentId;
8138
+ const nextDependencies = task.dependencies?.filter((dep) => dep.taskId !== taskId);
8139
+ if (nextParentId !== task.parentId || nextDependencies?.length !== task.dependencies?.length) {
8140
+ changedTasks.push({
8141
+ ...task,
8142
+ parentId: nextParentId,
8143
+ dependencies: nextDependencies
8144
+ });
8145
+ }
8146
+ }
8147
+ if (changedTasks.length > 0) {
8148
+ onTasksChange?.(changedTasks);
8149
+ }
8150
+ onDelete?.(taskId);
8151
+ }, [tasks, onTasksChange, onDelete, onUngroupTask]);
8038
8152
  const panStateRef = (0, import_react13.useRef)(null);
8039
8153
  const handlePanStart = (0, import_react13.useCallback)((e) => {
8040
8154
  if (e.button !== 0) return;
@@ -8113,6 +8227,7 @@ function GanttChartInner(props, ref) {
8113
8227
  onToggleCollapse: handleToggleCollapse,
8114
8228
  onPromoteTask: onPromoteTask ?? handlePromoteTask,
8115
8229
  onDemoteTask: onDemoteTask ?? handleDemoteTask,
8230
+ onUngroupTask: onUngroupTask ?? handleUngroupTask,
8116
8231
  highlightedTaskIds: taskListHighlightedTaskIds,
8117
8232
  customDays,
8118
8233
  isWeekend: isWeekend3,
@@ -8120,7 +8235,8 @@ function GanttChartInner(props, ref) {
8120
8235
  filterMode,
8121
8236
  filteredTaskIds: matchedTaskIds,
8122
8237
  isFilterActive: !!taskFilter,
8123
- additionalColumns
8238
+ additionalColumns,
8239
+ taskListMenuCommands
8124
8240
  }
8125
8241
  ),
8126
8242
  /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(