gantt-lib 0.72.1 → 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.mjs CHANGED
@@ -4151,6 +4151,26 @@ var CopyIcon = () => /* @__PURE__ */ jsxs9(
4151
4151
  ]
4152
4152
  }
4153
4153
  );
4154
+ var UngroupIcon = () => /* @__PURE__ */ jsxs9(
4155
+ "svg",
4156
+ {
4157
+ xmlns: "http://www.w3.org/2000/svg",
4158
+ width: "16",
4159
+ height: "16",
4160
+ viewBox: "0 0 24 24",
4161
+ fill: "none",
4162
+ stroke: "currentColor",
4163
+ strokeWidth: "2",
4164
+ strokeLinecap: "round",
4165
+ strokeLinejoin: "round",
4166
+ children: [
4167
+ /* @__PURE__ */ jsx12("path", { d: "M3 12h10" }),
4168
+ /* @__PURE__ */ jsx12("path", { d: "m6 9-3 3 3 3" }),
4169
+ /* @__PURE__ */ jsx12("path", { d: "M13 6h8" }),
4170
+ /* @__PURE__ */ jsx12("path", { d: "M13 18h8" })
4171
+ ]
4172
+ }
4173
+ );
4154
4174
  var TASK_COLOR_PALETTE = [
4155
4175
  // { label: "Палисандр", value: "#A61E4D" },
4156
4176
  // { label: "Киноварь", value: "#E8590C" },
@@ -4583,6 +4603,7 @@ var TaskListRow = React9.memo(
4583
4603
  onToggleCollapse,
4584
4604
  onPromoteTask,
4585
4605
  onDemoteTask,
4606
+ onUngroupTask,
4586
4607
  onDuplicateTask,
4587
4608
  canDemoteTask = true,
4588
4609
  isLastChild = true,
@@ -4594,7 +4615,8 @@ var TaskListRow = React9.memo(
4594
4615
  businessDays,
4595
4616
  isFilterMatch = false,
4596
4617
  isFilterHideMode = false,
4597
- resolvedColumns
4618
+ resolvedColumns,
4619
+ taskListMenuCommands = []
4598
4620
  }) => {
4599
4621
  const [editingColumnId, setEditingColumnId] = useState4(null);
4600
4622
  const editingName = editingColumnId === "name";
@@ -4628,6 +4650,7 @@ var TaskListRow = React9.memo(
4628
4650
  [task.id, allTasks]
4629
4651
  );
4630
4652
  const isChild = task.parentId !== void 0;
4653
+ const isMilestoneRow = normalizedTask.type === "milestone";
4631
4654
  const weekendPredicate = useMemo7(
4632
4655
  () => createCustomDayPredicate({ customDays, isWeekend: isWeekend3 }),
4633
4656
  [customDays, isWeekend3]
@@ -5150,6 +5173,38 @@ var TaskListRow = React9.memo(
5150
5173
  },
5151
5174
  [allTasks, isParent, onTasksChange, task]
5152
5175
  );
5176
+ const handleUngroup = useCallback4(
5177
+ (e) => {
5178
+ e.stopPropagation();
5179
+ setContextMenuOpen(false);
5180
+ onUngroupTask?.(task.id);
5181
+ },
5182
+ [onUngroupTask, task.id]
5183
+ );
5184
+ const visibleCustomMenuCommands = useMemo7(
5185
+ () => taskListMenuCommands.filter(
5186
+ (command) => {
5187
+ const scope = command.scope ?? "all";
5188
+ if (scope === "group" && !isParent) return false;
5189
+ if (scope === "linear" && (isParent || isMilestoneRow)) return false;
5190
+ if (scope === "milestone" && !isMilestoneRow) return false;
5191
+ return command.isVisible?.(task) ?? true;
5192
+ }
5193
+ ),
5194
+ [taskListMenuCommands, task, isParent, isMilestoneRow]
5195
+ );
5196
+ const hasContextMenu = visibleCustomMenuCommands.length > 0 || !!onDuplicateTask || !!onDelete || !!onTasksChange || isParent && !!onUngroupTask;
5197
+ const handleCustomMenuCommandClick = useCallback4(
5198
+ (command) => (e) => {
5199
+ e.stopPropagation();
5200
+ if (command.closeOnSelect !== false) {
5201
+ setContextMenuOpen(false);
5202
+ setColorMenuOpen(false);
5203
+ }
5204
+ command.onSelect(task);
5205
+ },
5206
+ [task]
5207
+ );
5153
5208
  const handleAddClick = useCallback4(
5154
5209
  (e) => {
5155
5210
  e.stopPropagation();
@@ -5576,7 +5631,7 @@ var TaskListRow = React9.memo(
5576
5631
  "aria-hidden": "true"
5577
5632
  }
5578
5633
  ),
5579
- !editingName && (onInsertAfter || onDelete || onPromoteTask || onDemoteTask || onDuplicateTask || onTasksChange) && /* @__PURE__ */ jsxs9("div", { className: "gantt-tl-name-actions", children: [
5634
+ !editingName && (onInsertAfter || onDelete || onPromoteTask || onDemoteTask || onUngroupTask || onDuplicateTask || onTasksChange || hasContextMenu) && /* @__PURE__ */ jsxs9("div", { className: "gantt-tl-name-actions", children: [
5580
5635
  onInsertAfter && /* @__PURE__ */ jsx12(
5581
5636
  "button",
5582
5637
  {
@@ -5622,7 +5677,7 @@ var TaskListRow = React9.memo(
5622
5677
  onDemote: onDemoteTask ? handleDemote : void 0
5623
5678
  }
5624
5679
  ),
5625
- (onDuplicateTask || onDelete || onTasksChange) && /* @__PURE__ */ jsxs9(Popover, { open: contextMenuOpen, onOpenChange: (open) => {
5680
+ hasContextMenu && /* @__PURE__ */ jsxs9(Popover, { open: contextMenuOpen, onOpenChange: (open) => {
5626
5681
  setContextMenuOpen(open);
5627
5682
  if (!open) setColorMenuOpen(false);
5628
5683
  }, children: [
@@ -5715,6 +5770,32 @@ var TaskListRow = React9.memo(
5715
5770
  ]
5716
5771
  }
5717
5772
  ),
5773
+ visibleCustomMenuCommands.map((command) => /* @__PURE__ */ jsxs9(
5774
+ "button",
5775
+ {
5776
+ type: "button",
5777
+ className: `gantt-tl-context-menu-item${command.danger ? " gantt-tl-context-menu-item-danger" : ""}`,
5778
+ onClick: handleCustomMenuCommandClick(command),
5779
+ disabled: command.isDisabled?.(task) ?? false,
5780
+ children: [
5781
+ command.icon,
5782
+ command.label
5783
+ ]
5784
+ },
5785
+ command.id
5786
+ )),
5787
+ isParent && onUngroupTask && /* @__PURE__ */ jsxs9(
5788
+ "button",
5789
+ {
5790
+ type: "button",
5791
+ className: "gantt-tl-context-menu-item",
5792
+ onClick: handleUngroup,
5793
+ children: [
5794
+ /* @__PURE__ */ jsx12(UngroupIcon, {}),
5795
+ "\u0420\u0430\u0437\u0433\u0440\u0443\u043F\u043F\u0438\u0440\u043E\u0432\u0430\u0442\u044C"
5796
+ ]
5797
+ }
5798
+ ),
5718
5799
  onDelete && /* @__PURE__ */ jsxs9(
5719
5800
  "button",
5720
5801
  {
@@ -6410,6 +6491,7 @@ var TaskList = ({
6410
6491
  onToggleCollapse: externalOnToggleCollapse,
6411
6492
  onPromoteTask,
6412
6493
  onDemoteTask,
6494
+ onUngroupTask,
6413
6495
  customDays,
6414
6496
  isWeekend: isWeekend3,
6415
6497
  businessDays,
@@ -6417,7 +6499,8 @@ var TaskList = ({
6417
6499
  filterMode = "highlight",
6418
6500
  filteredTaskIds = /* @__PURE__ */ new Set(),
6419
6501
  isFilterActive = false,
6420
- additionalColumns
6502
+ additionalColumns,
6503
+ taskListMenuCommands
6421
6504
  }) => {
6422
6505
  const [internalCollapsedParentIds, setInternalCollapsedParentIds] = useState6(/* @__PURE__ */ new Set());
6423
6506
  const collapsedParentIds = externalCollapsedParentIds ?? internalCollapsedParentIds;
@@ -7081,6 +7164,7 @@ var TaskList = ({
7081
7164
  onToggleCollapse: handleToggleCollapse,
7082
7165
  onPromoteTask,
7083
7166
  onDemoteTask: onDemoteTask ? handleDemoteWrapper : void 0,
7167
+ onUngroupTask,
7084
7168
  onDuplicateTask: onReorder ? handleDuplicateTask : void 0,
7085
7169
  canDemoteTask,
7086
7170
  isLastChild: lastChildIds.has(task.id),
@@ -7092,7 +7176,8 @@ var TaskList = ({
7092
7176
  businessDays,
7093
7177
  isFilterMatch: filterMode === "highlight" ? highlightedTaskIds.has(task.id) : false,
7094
7178
  isFilterHideMode: filterMode === "hide" && isFilterActive,
7095
- resolvedColumns
7179
+ resolvedColumns,
7180
+ taskListMenuCommands
7096
7181
  }
7097
7182
  ),
7098
7183
  pendingInsertDisplayTaskId === task.id && /* @__PURE__ */ jsx14(
@@ -7150,8 +7235,13 @@ var TaskList = ({
7150
7235
  };
7151
7236
 
7152
7237
  // src/components/GanttChart/print.ts
7153
- function getPrintDocumentTitle({ header, title, fileName }) {
7154
- return header?.projectName || title || header?.serviceName || fileName || "Gantt chart";
7238
+ function getPrintDocumentTitle({
7239
+ header,
7240
+ documentTitle,
7241
+ title,
7242
+ fileName
7243
+ }) {
7244
+ return documentTitle || fileName || title || header?.projectName || header?.serviceName || "Gantt chart";
7155
7245
  }
7156
7246
  function formatHeaderExportDate(exportDate) {
7157
7247
  if (!exportDate) return null;
@@ -7446,6 +7536,7 @@ async function printGanttChart({
7446
7536
  sourceContainer,
7447
7537
  printContent,
7448
7538
  header,
7539
+ documentTitle,
7449
7540
  title,
7450
7541
  fileName,
7451
7542
  orientation
@@ -7457,7 +7548,7 @@ async function printGanttChart({
7457
7548
  if (!printWindow || !printDocument) {
7458
7549
  throw new Error("Unable to create print frame");
7459
7550
  }
7460
- const printTitle = getPrintDocumentTitle({ header, title, fileName });
7551
+ const printTitle = getPrintDocumentTitle({ header, documentTitle, title, fileName });
7461
7552
  printDocument.open();
7462
7553
  printDocument.write('<!doctype html><html><head><meta charset="utf-8" /></head><body></body></html>');
7463
7554
  printDocument.close();
@@ -7506,6 +7597,7 @@ function GanttChartInner(props, ref) {
7506
7597
  onReorder,
7507
7598
  onPromoteTask,
7508
7599
  onDemoteTask,
7600
+ onUngroupTask,
7509
7601
  enableAddTask = true,
7510
7602
  viewMode = "day",
7511
7603
  customDays,
@@ -7518,7 +7610,8 @@ function GanttChartInner(props, ref) {
7518
7610
  highlightedTaskIds,
7519
7611
  disableTaskDrag = false,
7520
7612
  showChart = true,
7521
- additionalColumns
7613
+ additionalColumns,
7614
+ taskListMenuCommands
7522
7615
  } = props;
7523
7616
  const containerRef = useRef7(null);
7524
7617
  const scrollContainerRef = useRef7(null);
@@ -7825,6 +7918,7 @@ function GanttChartInner(props, ref) {
7825
7918
  }
7826
7919
  if (includeChart) {
7827
7920
  chartClone?.classList.remove("gantt-chart-hidden");
7921
+ if (chartClone) chartClone.style.display = "";
7828
7922
  } else {
7829
7923
  chartClone?.remove();
7830
7924
  }
@@ -7833,6 +7927,7 @@ function GanttChartInner(props, ref) {
7833
7927
  sourceContainer,
7834
7928
  printContent,
7835
7929
  header: options?.header,
7930
+ documentTitle: options?.documentTitle,
7836
7931
  title: options?.title,
7837
7932
  fileName: options?.fileName,
7838
7933
  orientation: options?.orientation
@@ -7932,6 +8027,33 @@ function GanttChartInner(props, ref) {
7932
8027
  };
7933
8028
  onTasksChange?.([updatedDemotedTask]);
7934
8029
  }, [tasks, onTasksChange, onDemoteTask]);
8030
+ const handleUngroupTask = useCallback6((taskId) => {
8031
+ if (onUngroupTask) {
8032
+ onUngroupTask(taskId);
8033
+ return;
8034
+ }
8035
+ const parentTask = tasks.find((task) => task.id === taskId);
8036
+ if (!parentTask) return;
8037
+ const hasDirectChildren = tasks.some((task) => task.parentId === taskId);
8038
+ if (!hasDirectChildren) return;
8039
+ const changedTasks = [];
8040
+ for (const task of tasks) {
8041
+ if (task.id === taskId) continue;
8042
+ const nextParentId = task.parentId === taskId ? parentTask.parentId : task.parentId;
8043
+ const nextDependencies = task.dependencies?.filter((dep) => dep.taskId !== taskId);
8044
+ if (nextParentId !== task.parentId || nextDependencies?.length !== task.dependencies?.length) {
8045
+ changedTasks.push({
8046
+ ...task,
8047
+ parentId: nextParentId,
8048
+ dependencies: nextDependencies
8049
+ });
8050
+ }
8051
+ }
8052
+ if (changedTasks.length > 0) {
8053
+ onTasksChange?.(changedTasks);
8054
+ }
8055
+ onDelete?.(taskId);
8056
+ }, [tasks, onTasksChange, onDelete, onUngroupTask]);
7935
8057
  const panStateRef = useRef7(null);
7936
8058
  const handlePanStart = useCallback6((e) => {
7937
8059
  if (e.button !== 0) return;
@@ -8010,6 +8132,7 @@ function GanttChartInner(props, ref) {
8010
8132
  onToggleCollapse: handleToggleCollapse,
8011
8133
  onPromoteTask: onPromoteTask ?? handlePromoteTask,
8012
8134
  onDemoteTask: onDemoteTask ?? handleDemoteTask,
8135
+ onUngroupTask: onUngroupTask ?? handleUngroupTask,
8013
8136
  highlightedTaskIds: taskListHighlightedTaskIds,
8014
8137
  customDays,
8015
8138
  isWeekend: isWeekend3,
@@ -8017,103 +8140,111 @@ function GanttChartInner(props, ref) {
8017
8140
  filterMode,
8018
8141
  filteredTaskIds: matchedTaskIds,
8019
8142
  isFilterActive: !!taskFilter,
8020
- additionalColumns
8143
+ additionalColumns,
8144
+ taskListMenuCommands
8021
8145
  }
8022
8146
  ),
8023
- /* @__PURE__ */ jsxs12("div", { className: showChart ? "gantt-chartSurface" : "gantt-chartSurface gantt-chart-hidden", style: { minWidth: `${gridWidth}px`, flex: 1 }, children: [
8024
- /* @__PURE__ */ jsx15("div", { className: "gantt-stickyHeader", style: { width: `${gridWidth}px` }, children: /* @__PURE__ */ jsx15(
8025
- TimeScaleHeader_default,
8026
- {
8027
- days: dateRange,
8028
- dayWidth,
8029
- headerHeight,
8030
- viewMode,
8031
- isCustomWeekend
8032
- }
8033
- ) }),
8034
- /* @__PURE__ */ jsxs12(
8035
- "div",
8036
- {
8037
- className: "gantt-taskArea",
8038
- style: {
8039
- position: "relative",
8040
- width: `${gridWidth}px`
8041
- },
8042
- children: [
8043
- /* @__PURE__ */ jsx15(
8044
- GridBackground_default,
8045
- {
8046
- dateRange,
8047
- dayWidth,
8048
- totalHeight: totalGridHeight,
8049
- viewMode,
8050
- isCustomWeekend
8051
- }
8052
- ),
8053
- todayInRange && /* @__PURE__ */ jsx15(TodayIndicator_default, { monthStart, dayWidth }),
8054
- /* @__PURE__ */ jsx15(
8055
- DependencyLines_default,
8056
- {
8057
- tasks: previewVisibleTasks,
8058
- allTasks: previewNormalizedTasks,
8059
- collapsedParentIds,
8060
- monthStart,
8061
- dayWidth,
8062
- rowHeight,
8063
- gridWidth,
8064
- dragOverrides: dependencyOverrides,
8065
- selectedDep: selectedChip,
8066
- businessDays,
8067
- weekendPredicate: isCustomWeekend
8068
- }
8069
- ),
8070
- dragGuideLines && /* @__PURE__ */ jsx15(
8071
- DragGuideLines_default,
8072
- {
8073
- isDragging: dragGuideLines.isDragging,
8074
- dragMode: dragGuideLines.dragMode,
8075
- left: dragGuideLines.left,
8076
- width: dragGuideLines.width,
8077
- totalHeight: totalGridHeight
8078
- }
8079
- ),
8080
- visibleTasks.map((task, index) => /* @__PURE__ */ jsx15(
8081
- TaskRow_default,
8082
- {
8083
- task,
8084
- monthStart,
8085
- dayWidth,
8086
- rowHeight,
8087
- onTasksChange: handleTaskChange,
8088
- onDragStateChange: (state) => {
8089
- if (state.isDragging) {
8090
- setDragGuideLines(state);
8091
- setDraggedTaskOverride({ taskId: task.id, left: state.left, width: state.width });
8092
- } else {
8093
- setDragGuideLines(null);
8094
- setDraggedTaskOverride(null);
8095
- }
8096
- },
8097
- rowIndex: index,
8098
- allTasks: normalizedTasks,
8099
- enableAutoSchedule: enableAutoSchedule ?? false,
8100
- disableConstraints: disableConstraints ?? false,
8101
- overridePosition: cascadeOverrides.get(task.id),
8102
- onCascadeProgress: handleCascadeProgress,
8103
- onCascade: handleCascade,
8104
- highlightExpiredTasks,
8105
- isFilterMatch: filterMode === "highlight" ? matchedTaskIds.has(task.id) : false,
8106
- businessDays,
8107
- customDays,
8108
- isWeekend: isWeekend3,
8109
- disableTaskDrag
8147
+ /* @__PURE__ */ jsxs12(
8148
+ "div",
8149
+ {
8150
+ className: showChart ? "gantt-chartSurface" : "gantt-chartSurface gantt-chart-hidden",
8151
+ style: { minWidth: `${gridWidth}px`, flex: 1, display: showChart ? void 0 : "none" },
8152
+ children: [
8153
+ /* @__PURE__ */ jsx15("div", { className: "gantt-stickyHeader", style: { width: `${gridWidth}px` }, children: /* @__PURE__ */ jsx15(
8154
+ TimeScaleHeader_default,
8155
+ {
8156
+ days: dateRange,
8157
+ dayWidth,
8158
+ headerHeight,
8159
+ viewMode,
8160
+ isCustomWeekend
8161
+ }
8162
+ ) }),
8163
+ /* @__PURE__ */ jsxs12(
8164
+ "div",
8165
+ {
8166
+ className: "gantt-taskArea",
8167
+ style: {
8168
+ position: "relative",
8169
+ width: `${gridWidth}px`
8110
8170
  },
8111
- task.id
8112
- ))
8113
- ]
8114
- }
8115
- )
8116
- ] })
8171
+ children: [
8172
+ /* @__PURE__ */ jsx15(
8173
+ GridBackground_default,
8174
+ {
8175
+ dateRange,
8176
+ dayWidth,
8177
+ totalHeight: totalGridHeight,
8178
+ viewMode,
8179
+ isCustomWeekend
8180
+ }
8181
+ ),
8182
+ todayInRange && /* @__PURE__ */ jsx15(TodayIndicator_default, { monthStart, dayWidth }),
8183
+ /* @__PURE__ */ jsx15(
8184
+ DependencyLines_default,
8185
+ {
8186
+ tasks: previewVisibleTasks,
8187
+ allTasks: previewNormalizedTasks,
8188
+ collapsedParentIds,
8189
+ monthStart,
8190
+ dayWidth,
8191
+ rowHeight,
8192
+ gridWidth,
8193
+ dragOverrides: dependencyOverrides,
8194
+ selectedDep: selectedChip,
8195
+ businessDays,
8196
+ weekendPredicate: isCustomWeekend
8197
+ }
8198
+ ),
8199
+ dragGuideLines && /* @__PURE__ */ jsx15(
8200
+ DragGuideLines_default,
8201
+ {
8202
+ isDragging: dragGuideLines.isDragging,
8203
+ dragMode: dragGuideLines.dragMode,
8204
+ left: dragGuideLines.left,
8205
+ width: dragGuideLines.width,
8206
+ totalHeight: totalGridHeight
8207
+ }
8208
+ ),
8209
+ visibleTasks.map((task, index) => /* @__PURE__ */ jsx15(
8210
+ TaskRow_default,
8211
+ {
8212
+ task,
8213
+ monthStart,
8214
+ dayWidth,
8215
+ rowHeight,
8216
+ onTasksChange: handleTaskChange,
8217
+ onDragStateChange: (state) => {
8218
+ if (state.isDragging) {
8219
+ setDragGuideLines(state);
8220
+ setDraggedTaskOverride({ taskId: task.id, left: state.left, width: state.width });
8221
+ } else {
8222
+ setDragGuideLines(null);
8223
+ setDraggedTaskOverride(null);
8224
+ }
8225
+ },
8226
+ rowIndex: index,
8227
+ allTasks: normalizedTasks,
8228
+ enableAutoSchedule: enableAutoSchedule ?? false,
8229
+ disableConstraints: disableConstraints ?? false,
8230
+ overridePosition: cascadeOverrides.get(task.id),
8231
+ onCascadeProgress: handleCascadeProgress,
8232
+ onCascade: handleCascade,
8233
+ highlightExpiredTasks,
8234
+ isFilterMatch: filterMode === "highlight" ? matchedTaskIds.has(task.id) : false,
8235
+ businessDays,
8236
+ customDays,
8237
+ isWeekend: isWeekend3,
8238
+ disableTaskDrag
8239
+ },
8240
+ task.id
8241
+ ))
8242
+ ]
8243
+ }
8244
+ )
8245
+ ]
8246
+ }
8247
+ )
8117
8248
  ] })
8118
8249
  }
8119
8250
  ) });