gantt-lib 0.144.1 → 0.145.1

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.js CHANGED
@@ -896,6 +896,29 @@ var ACTIVITY_LANES_PADDING = 2;
896
896
  var DAY_MS2 = 24 * 60 * 60 * 1e3;
897
897
  function packIntervals(intervals) {
898
898
  const sorted = [...intervals].sort((a, b) => a.start - b.start);
899
+ if (intervals.some((item) => item.laneGroup !== void 0)) {
900
+ const groups = /* @__PURE__ */ new Map();
901
+ for (const item of intervals) {
902
+ const key = item.laneGroup ?? item;
903
+ const group = groups.get(key) ?? [];
904
+ group.push(item);
905
+ groups.set(key, group);
906
+ }
907
+ const lanes = [];
908
+ const assigned = /* @__PURE__ */ new Map();
909
+ for (const group of groups.values()) {
910
+ const compatible = lanes.findIndex((lane) => group.every((item) => !lane.some((other) => item.start < other.end && other.start < item.end)));
911
+ const preferred = compatible < 0 ? lanes.length : compatible;
912
+ for (const item of [...group].sort((a, b) => a.start - b.start)) {
913
+ const free = (lane2) => !lanes[lane2]?.some((other) => item.start < other.end && other.start < item.end);
914
+ let lane = free(preferred) ? preferred : lanes.findIndex((_, index) => free(index));
915
+ if (lane < 0) lane = lanes.length;
916
+ (lanes[lane] ?? (lanes[lane] = [])).push(item);
917
+ assigned.set(item, lane);
918
+ }
919
+ }
920
+ return sorted.map((item) => ({ ...item, lane: assigned.get(item) }));
921
+ }
899
922
  const laneEnds = [];
900
923
  return sorted.map((item) => {
901
924
  let lane = 0;
@@ -914,6 +937,7 @@ function computeActivityLanes(activities, monthStart, dayWidth) {
914
937
  const bar = calculateTaskBar(parseUTCDate(activity.startDate), parseUTCDate(activity.endDate), monthStart, dayWidth);
915
938
  return {
916
939
  id: activity.id,
940
+ laneGroup: activity.laneGroup,
917
941
  name: activity.name,
918
942
  color: activity.color,
919
943
  lag: activity.lag,
@@ -7590,40 +7614,6 @@ var getEndDateFromDuration = (startDate, durationDays) => {
7590
7614
  const start = parseUTCDate(startDate);
7591
7615
  return new Date(start.getTime() + (durationDays - 1) * DAY_MS4).toISOString().split("T")[0];
7592
7616
  };
7593
- var TrashIcon = () => /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
7594
- "svg",
7595
- {
7596
- xmlns: "http://www.w3.org/2000/svg",
7597
- width: "12",
7598
- height: "12",
7599
- viewBox: "0 0 24 24",
7600
- fill: "none",
7601
- stroke: "currentColor",
7602
- strokeWidth: "2",
7603
- strokeLinecap: "round",
7604
- strokeLinejoin: "round",
7605
- children: [
7606
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("path", { d: "M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6" }),
7607
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("path", { d: "M3 6h18" }),
7608
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("path", { d: "M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2" })
7609
- ]
7610
- }
7611
- );
7612
- var PlusIcon = () => /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
7613
- "svg",
7614
- {
7615
- xmlns: "http://www.w3.org/2000/svg",
7616
- width: "14",
7617
- height: "14",
7618
- viewBox: "0 0 24 24",
7619
- fill: "none",
7620
- stroke: "currentColor",
7621
- strokeWidth: "2",
7622
- strokeLinecap: "round",
7623
- strokeLinejoin: "round",
7624
- children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("path", { d: "M12 5v14M5 12h14" })
7625
- }
7626
- );
7627
7617
  var DepEditIcon = () => /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
7628
7618
  "svg",
7629
7619
  {
@@ -7666,67 +7656,6 @@ var VerticalDotsIcon = () => /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
7666
7656
  ]
7667
7657
  }
7668
7658
  );
7669
- var CopyIcon = () => /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
7670
- "svg",
7671
- {
7672
- xmlns: "http://www.w3.org/2000/svg",
7673
- width: "16",
7674
- height: "16",
7675
- viewBox: "0 0 24 24",
7676
- fill: "none",
7677
- stroke: "currentColor",
7678
- strokeWidth: "2",
7679
- strokeLinecap: "round",
7680
- strokeLinejoin: "round",
7681
- children: [
7682
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("rect", { width: "14", height: "14", x: "8", y: "8", rx: "2", ry: "2" }),
7683
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("path", { d: "M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2" })
7684
- ]
7685
- }
7686
- );
7687
- var UngroupIcon = () => /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
7688
- "svg",
7689
- {
7690
- xmlns: "http://www.w3.org/2000/svg",
7691
- width: "16",
7692
- height: "16",
7693
- viewBox: "0 0 24 24",
7694
- fill: "none",
7695
- stroke: "currentColor",
7696
- strokeWidth: "2",
7697
- strokeLinecap: "round",
7698
- strokeLinejoin: "round",
7699
- children: [
7700
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("path", { d: "M3 12h10" }),
7701
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("path", { d: "m6 9-3 3 3 3" }),
7702
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("path", { d: "M13 6h8" }),
7703
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("path", { d: "M13 18h8" })
7704
- ]
7705
- }
7706
- );
7707
- var TASK_COLOR_PALETTE = [
7708
- // { label: "Палисандр", value: "#A61E4D" },
7709
- // { label: "Киноварь", value: "#E8590C" },
7710
- // { label: "Жёлт", value: "#eec45c" },
7711
- { label: "\u041A\u0438\u043D\u043E\u0432\u0430\u0440\u044C2", value: "#fe724e" },
7712
- // { label: "Оранжевый", value: "#F08C00" },
7713
- { label: "\u041E\u0440\u0430\u043D\u0436\u0435\u0432\u044B\u04392", value: "#ff991f" },
7714
- { label: "\u0417\u043E\u043B\u043E\u0442\u043E\u0439", value: "#e5c800" },
7715
- { label: "\u0411\u0438\u0440\u044E\u0437\u0430", value: "#58d8a3" },
7716
- { label: "\u041F\u0430\u043B\u0438\u0441\u0430\u043D\u0434\u0440", value: "#d64a7b" },
7717
- { label: "\u041F\u0435\u0441\u043E\u0447\u043D\u044B\u0439", value: "#997B10" },
7718
- { label: "\u0428\u0430\u0440\u0442\u0440\u0435\u0437", value: "#A3BE00" },
7719
- { label: "\u0413\u043E\u043B\u0443\u0431\u043E\u0439", value: "#03c7e6" },
7720
- { label: "\u0412\u0438\u043D\u043E\u0433\u0440\u0430\u04342", value: "#8678d9" },
7721
- { label: "\u0421\u0435\u0440\u044B\u04392", value: "#6b778c" },
7722
- { label: "\u041B\u0435\u0441\u043D\u043E\u0439", value: "#2B8A3E" }
7723
- // { label: "Лесной3", value: "#60b838" },
7724
- // { label: "Бирюза", value: "#0B7285" },
7725
- // { label: "Серый", value: "#495057" },
7726
- // { label: "Океан", value: "#5244ff" },
7727
- // { label: "Океан2", value: "#0626ba" },
7728
- // { label: "Виноград", value: "#AE3EC9" },
7729
- ];
7730
7659
  var ChevronRightIcon = () => /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
7731
7660
  "svg",
7732
7661
  {
@@ -7756,81 +7685,6 @@ function formatDependencyPrintLabel(dep, predecessorTaskNumber, lag) {
7756
7685
  const lagSuffix = effectiveLag === 0 ? "" : effectiveLag > 0 ? `+${effectiveLag}` : String(effectiveLag);
7757
7686
  return `[${predecessorTaskNumber ?? dep.taskId}]${LINK_TYPE_LABELS_RU2[dep.type]}${lagSuffix}`;
7758
7687
  }
7759
- var ArrowLeft = () => /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
7760
- "svg",
7761
- {
7762
- xmlns: "http://www.w3.org/2000/svg",
7763
- width: "16",
7764
- height: "16",
7765
- viewBox: "0 0 24 24",
7766
- fill: "none",
7767
- stroke: "currentColor",
7768
- strokeWidth: "2",
7769
- strokeLinecap: "round",
7770
- strokeLinejoin: "round",
7771
- children: [
7772
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("path", { d: "m12 19-7-7 7-7" }),
7773
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("path", { d: "M19 12H5" })
7774
- ]
7775
- }
7776
- );
7777
- var ArrowRight = () => /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
7778
- "svg",
7779
- {
7780
- xmlns: "http://www.w3.org/2000/svg",
7781
- width: "16",
7782
- height: "16",
7783
- viewBox: "0 0 24 24",
7784
- fill: "none",
7785
- stroke: "currentColor",
7786
- strokeWidth: "2",
7787
- strokeLinecap: "round",
7788
- strokeLinejoin: "round",
7789
- children: [
7790
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("path", { d: "M5 12h14" }),
7791
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("path", { d: "m12 5 7 7-7 7" })
7792
- ]
7793
- }
7794
- );
7795
- var HierarchyButton = ({
7796
- isChild,
7797
- rowIndex: _rowIndex,
7798
- canDemote,
7799
- onPromote,
7800
- onDemote
7801
- }) => {
7802
- const canPromote = isChild && onPromote;
7803
- const showDemote = canDemote && !!onDemote;
7804
- if (!canPromote && !showDemote) return null;
7805
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_jsx_runtime15.Fragment, { children: [
7806
- canPromote && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
7807
- "button",
7808
- {
7809
- type: "button",
7810
- className: "gantt-tl-name-action-btn gantt-tl-action-hierarchy",
7811
- onClick: (e) => {
7812
- e.stopPropagation();
7813
- onPromote(e);
7814
- },
7815
- title: "\u041F\u043E\u0432\u044B\u0441\u0438\u0442\u044C \u0443\u0440\u043E\u0432\u0435\u043D\u044C",
7816
- children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(ArrowLeft, {})
7817
- }
7818
- ),
7819
- showDemote && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
7820
- "button",
7821
- {
7822
- type: "button",
7823
- className: "gantt-tl-name-action-btn gantt-tl-action-hierarchy",
7824
- onClick: (e) => {
7825
- e.stopPropagation();
7826
- onDemote(e);
7827
- },
7828
- title: "\u041F\u043E\u043D\u0438\u0437\u0438\u0442\u044C \u0443\u0440\u043E\u0432\u0435\u043D\u044C",
7829
- children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(ArrowRight, {})
7830
- }
7831
- )
7832
- ] });
7833
- };
7834
7688
  var DepChip = ({
7835
7689
  lag,
7836
7690
  dep,
@@ -8167,7 +8021,7 @@ var areTaskListRowPropsEqual = (prevProps, nextProps) => {
8167
8021
  const nextPickingTask = nextProps.selectingPredecessorFor === nextTask.id;
8168
8022
  const prevAnyPicking = prevProps.selectingPredecessorFor != null;
8169
8023
  const nextAnyPicking = nextProps.selectingPredecessorFor != null;
8170
- return prevTaskUnchanged && prevProps.rowIndex === nextProps.rowIndex && prevProps.taskNumber === nextProps.taskNumber && prevProps.taskNumberMap === nextProps.taskNumberMap && prevProps.rowHeight === nextProps.rowHeight && prevIsSelected === nextIsSelected && prevProps.disableTaskNameEditing === nextProps.disableTaskNameEditing && prevProps.disableDependencyEditing === nextProps.disableDependencyEditing && prevProps.allTasks === nextProps.allTasks && prevProps.activeLinkType === nextProps.activeLinkType && prevProps.dependencyPickMode === nextProps.dependencyPickMode && prevPickingTask === nextPickingTask && prevAnyPicking === nextAnyPicking && resolveSelectedChipRole(prevProps) === resolveSelectedChipRole(nextProps) && prevIsEditingTask === nextIsEditingTask && prevProps.isDragging === nextProps.isDragging && prevProps.isDragOver === nextProps.isDragOver && prevProps.dragOverPlacement === nextProps.dragOverPlacement && prevProps.isNestedDropTarget === nextProps.isNestedDropTarget && prevProps.isDirectChildDropTarget === nextProps.isDirectChildDropTarget && prevCollapsed === nextCollapsed && prevProps.canDemoteTask === nextProps.canDemoteTask && prevProps.isLastChild === nextProps.isLastChild && prevProps.nestingDepth === nextProps.nestingDepth && prevProps.hasVisibleChildren === nextProps.hasVisibleChildren && prevProps.ancestorLineModes === nextProps.ancestorLineModes && prevProps.customDays === nextProps.customDays && prevProps.isWeekend === nextProps.isWeekend && prevProps.fillParentRow === nextProps.fillParentRow && prevProps.businessDays === nextProps.businessDays && prevProps.defaultTaskDurationDays === nextProps.defaultTaskDurationDays && prevProps.isFilterMatch === nextProps.isFilterMatch && prevProps.isFilterHideMode === nextProps.isFilterHideMode && prevProps.resolvedColumns === nextProps.resolvedColumns && prevProps.isTaskSelected === nextProps.isTaskSelected && resolveActiveCustomCellForRow(prevProps) === resolveActiveCustomCellForRow(nextProps) && prevProps.taskListMenuCommands === nextProps.taskListMenuCommands && prevProps.hideTaskListRowActions === nextProps.hideTaskListRowActions && prevProps.rowClassName === nextProps.rowClassName && prevProps.getTaskListNamePrefixIcon === nextProps.getTaskListNamePrefixIcon && prevProps.taskDateChangeMode === nextProps.taskDateChangeMode && prevProps.printDependencyLabels === nextProps.printDependencyLabels;
8024
+ return prevTaskUnchanged && prevProps.rowIndex === nextProps.rowIndex && prevProps.taskNumber === nextProps.taskNumber && prevProps.taskNumberMap === nextProps.taskNumberMap && prevProps.rowHeight === nextProps.rowHeight && prevIsSelected === nextIsSelected && prevProps.disableTaskNameEditing === nextProps.disableTaskNameEditing && prevProps.disableDependencyEditing === nextProps.disableDependencyEditing && prevProps.allTasks === nextProps.allTasks && prevProps.activeLinkType === nextProps.activeLinkType && prevProps.dependencyPickMode === nextProps.dependencyPickMode && prevPickingTask === nextPickingTask && prevAnyPicking === nextAnyPicking && resolveSelectedChipRole(prevProps) === resolveSelectedChipRole(nextProps) && prevIsEditingTask === nextIsEditingTask && prevProps.isDragging === nextProps.isDragging && prevProps.isDragOver === nextProps.isDragOver && prevProps.dragOverPlacement === nextProps.dragOverPlacement && prevProps.isNestedDropTarget === nextProps.isNestedDropTarget && prevProps.isDirectChildDropTarget === nextProps.isDirectChildDropTarget && prevCollapsed === nextCollapsed && prevProps.canDemoteTask === nextProps.canDemoteTask && prevProps.isLastChild === nextProps.isLastChild && prevProps.nestingDepth === nextProps.nestingDepth && prevProps.hasVisibleChildren === nextProps.hasVisibleChildren && prevProps.ancestorLineModes === nextProps.ancestorLineModes && prevProps.customDays === nextProps.customDays && prevProps.isWeekend === nextProps.isWeekend && prevProps.fillParentRow === nextProps.fillParentRow && prevProps.businessDays === nextProps.businessDays && prevProps.defaultTaskDurationDays === nextProps.defaultTaskDurationDays && prevProps.isFilterMatch === nextProps.isFilterMatch && prevProps.isFilterHideMode === nextProps.isFilterHideMode && prevProps.resolvedColumns === nextProps.resolvedColumns && prevProps.isTaskSelected === nextProps.isTaskSelected && resolveActiveCustomCellForRow(prevProps) === resolveActiveCustomCellForRow(nextProps) && prevProps.taskListMenuCommands === nextProps.taskListMenuCommands && prevProps.onInsertAfter === nextProps.onInsertAfter && prevProps.onPromoteTask === nextProps.onPromoteTask && prevProps.onDemoteTask === nextProps.onDemoteTask && prevProps.onDuplicateTask === nextProps.onDuplicateTask && prevProps.onDelete === nextProps.onDelete && prevProps.onUngroupTask === nextProps.onUngroupTask && prevProps.renderTaskListActions === nextProps.renderTaskListActions && prevProps.renderTaskListMenu === nextProps.renderTaskListMenu && prevProps.hideTaskListRowActions === nextProps.hideTaskListRowActions && prevProps.rowClassName === nextProps.rowClassName && prevProps.getTaskListNamePrefixIcon === nextProps.getTaskListNamePrefixIcon && prevProps.taskDateChangeMode === nextProps.taskDateChangeMode && prevProps.printDependencyLabels === nextProps.printDependencyLabels;
8171
8025
  };
8172
8026
  var TaskListRow = import_react12.default.memo(
8173
8027
  ({
@@ -8231,6 +8085,8 @@ var TaskListRow = import_react12.default.memo(
8231
8085
  activeCustomCell,
8232
8086
  onActiveCustomCellChange,
8233
8087
  taskListMenuCommands = [],
8088
+ renderTaskListActions,
8089
+ renderTaskListMenu,
8234
8090
  hideTaskListRowActions = false,
8235
8091
  rowClassName,
8236
8092
  compositeParentColor,
@@ -8283,7 +8139,6 @@ var TaskListRow = import_react12.default.memo(
8283
8139
  const progressInputRef = (0, import_react12.useRef)(null);
8284
8140
  const [overflowOpen, setOverflowOpen] = (0, import_react12.useState)(false);
8285
8141
  const [contextMenuOpen, setContextMenuOpen] = (0, import_react12.useState)(false);
8286
- const [colorMenuOpen, setColorMenuOpen] = (0, import_react12.useState)(false);
8287
8142
  const nameConfirmedRef = (0, import_react12.useRef)(false);
8288
8143
  const durationConfirmedRef = (0, import_react12.useRef)(false);
8289
8144
  const progressConfirmedRef = (0, import_react12.useRef)(false);
@@ -8800,47 +8655,6 @@ var TaskListRow = import_react12.default.memo(
8800
8655
  },
8801
8656
  [task.id, onToggleCollapse]
8802
8657
  );
8803
- const handlePromote = (0, import_react12.useCallback)(
8804
- (e) => {
8805
- e.stopPropagation();
8806
- onPromoteTask?.(task.id);
8807
- },
8808
- [task.id, onPromoteTask]
8809
- );
8810
- const handleDemote = (0, import_react12.useCallback)(
8811
- (e) => {
8812
- e.stopPropagation();
8813
- onDemoteTask?.(task.id, "");
8814
- },
8815
- [task.id, onDemoteTask]
8816
- );
8817
- const closeColorMenu = (0, import_react12.useCallback)(() => {
8818
- setColorMenuOpen(false);
8819
- }, []);
8820
- const handleApplyColor = (0, import_react12.useCallback)(
8821
- (color) => {
8822
- if (!onTasksChange) return;
8823
- const descendantIds = new Set(
8824
- isParent ? getAllDescendants(task.id, allTasks).map((descendant) => descendant.id) : []
8825
- );
8826
- const updatedTasks = [
8827
- { ...task, color },
8828
- ...allTasks.filter((candidate) => descendantIds.has(candidate.id)).map((candidate) => ({ ...candidate, color }))
8829
- ];
8830
- onTasksChange(updatedTasks);
8831
- closeColorMenu();
8832
- setContextMenuOpen(false);
8833
- },
8834
- [allTasks, closeColorMenu, isParent, onTasksChange, task]
8835
- );
8836
- const handleUngroup = (0, import_react12.useCallback)(
8837
- (e) => {
8838
- e.stopPropagation();
8839
- setContextMenuOpen(false);
8840
- onUngroupTask?.(task.id);
8841
- },
8842
- [onUngroupTask, task.id]
8843
- );
8844
8658
  const visibleCustomMenuCommands = (0, import_react12.useMemo)(
8845
8659
  () => taskListMenuCommands.filter(
8846
8660
  (command) => {
@@ -8853,18 +8667,50 @@ var TaskListRow = import_react12.default.memo(
8853
8667
  ),
8854
8668
  [taskListMenuCommands, task, isParent, isMilestoneRow]
8855
8669
  );
8856
- const hasContextMenu = !hideTaskListRowActions && (visibleCustomMenuCommands.length > 0 || !!onDuplicateTask || !!onDelete || !!onTasksChange || isParent && !!onUngroupTask);
8857
- const handleCustomMenuCommandClick = (0, import_react12.useCallback)(
8858
- (command) => (e) => {
8859
- e.stopPropagation();
8860
- if (command.closeOnSelect !== false) {
8861
- setContextMenuOpen(false);
8862
- closeColorMenu();
8670
+ const actionContext = {
8671
+ task,
8672
+ isParent,
8673
+ canPromote: isChild && !!onPromoteTask,
8674
+ canDemote: canDemoteTask && !!onDemoteTask,
8675
+ insertAfter: onInsertAfter ? () => {
8676
+ const range = buildDefaultTaskDateRange(getTodayISODate(), {
8677
+ businessDays,
8678
+ defaultTaskDurationDays,
8679
+ weekendPredicate
8680
+ });
8681
+ onInsertAfter(task.id, { id: crypto.randomUUID(), name: "\u041D\u043E\u0432\u0430\u044F \u0440\u0430\u0431\u043E\u0442\u0430", ...range, parentId: task.parentId });
8682
+ } : void 0,
8683
+ promote: isChild && onPromoteTask ? () => onPromoteTask(task.id) : void 0,
8684
+ demote: canDemoteTask && onDemoteTask ? () => onDemoteTask(task.id, "") : void 0,
8685
+ duplicate: onDuplicateTask ? () => onDuplicateTask(task.id) : void 0,
8686
+ delete: onDelete ? () => onDelete(task.id) : void 0,
8687
+ ungroup: isParent && onUngroupTask ? () => onUngroupTask(task.id) : void 0,
8688
+ closeMenu: () => setContextMenuOpen(false)
8689
+ };
8690
+ const commandContent = visibleCustomMenuCommands.length ? visibleCustomMenuCommands.map((command) => /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_react12.default.Fragment, { children: [
8691
+ command.divider === "top" && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("hr", { className: "gantt-tl-context-menu-divider" }),
8692
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
8693
+ "button",
8694
+ {
8695
+ type: "button",
8696
+ className: `gantt-tl-context-menu-item${command.danger ? " gantt-tl-context-menu-item-danger" : ""}`,
8697
+ disabled: command.isDisabled?.(task) ?? false,
8698
+ onClick: (event) => {
8699
+ event.stopPropagation();
8700
+ if (command.closeOnSelect !== false) actionContext.closeMenu();
8701
+ command.onSelect(task);
8702
+ },
8703
+ children: [
8704
+ command.icon,
8705
+ command.label
8706
+ ]
8863
8707
  }
8864
- command.onSelect(task);
8865
- },
8866
- [closeColorMenu, task]
8867
- );
8708
+ ),
8709
+ command.divider === "bottom" && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("hr", { className: "gantt-tl-context-menu-divider" })
8710
+ ] }, command.id)) : null;
8711
+ const menuContent = hideTaskListRowActions ? null : renderTaskListMenu ? renderTaskListMenu(actionContext, commandContent) : commandContent;
8712
+ const actionContent = hideTaskListRowActions ? null : renderTaskListActions?.(actionContext);
8713
+ const hasContextMenu = menuContent !== null && menuContent !== void 0 && menuContent !== false;
8868
8714
  const handleAddClick = (0, import_react12.useCallback)(
8869
8715
  (e) => {
8870
8716
  e.stopPropagation();
@@ -9339,197 +9185,25 @@ var TaskListRow = import_react12.default.memo(
9339
9185
  "aria-hidden": "true"
9340
9186
  }
9341
9187
  ),
9342
- !editingName && !hideTaskListRowActions && (onInsertAfter || onDelete || onPromoteTask || onDemoteTask || onUngroupTask || onDuplicateTask || onTasksChange || hasContextMenu) && /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: `gantt-tl-name-actions${contextMenuOpen ? " gantt-tl-name-actions-open" : ""}`, children: [
9343
- onInsertAfter && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
9344
- "button",
9345
- {
9346
- type: "button",
9347
- className: "gantt-tl-name-action-btn gantt-tl-action-insert",
9348
- onClick: (e) => {
9349
- e.stopPropagation();
9350
- const range = buildDefaultTaskDateRange(getTodayISODate(), {
9351
- businessDays,
9352
- defaultTaskDurationDays,
9353
- weekendPredicate
9354
- });
9355
- const newTask = {
9356
- id: crypto.randomUUID(),
9357
- name: "\u041D\u043E\u0432\u0430\u044F \u0440\u0430\u0431\u043E\u0442\u0430",
9358
- startDate: range.startDate,
9359
- endDate: range.endDate,
9360
- parentId: task.parentId
9361
- };
9362
- onInsertAfter(task.id, newTask);
9363
- },
9364
- "aria-label": "\u0412\u0441\u0442\u0430\u0432\u0438\u0442\u044C \u0440\u0430\u0431\u043E\u0442\u0443 \u043F\u043E\u0441\u043B\u0435 \u044D\u0442\u043E\u0439",
9365
- children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(PlusIcon, {})
9366
- }
9367
- ),
9368
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
9369
- HierarchyButton,
9370
- {
9371
- isChild,
9372
- rowIndex,
9373
- canDemote: canDemoteTask,
9374
- onPromote: onPromoteTask ? handlePromote : void 0,
9375
- onDemote: onDemoteTask ? handleDemote : void 0
9376
- }
9377
- ),
9378
- hasContextMenu && /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(Popover, { open: contextMenuOpen, onOpenChange: (open) => {
9379
- setContextMenuOpen(open);
9380
- if (!open) closeColorMenu();
9381
- }, children: [
9188
+ !editingName && !hideTaskListRowActions && (actionContent || hasContextMenu) ? /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: `gantt-tl-name-actions${contextMenuOpen ? " gantt-tl-name-actions-open" : ""}`, onClick: (event) => event.stopPropagation(), children: [
9189
+ actionContent,
9190
+ hasContextMenu ? /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(Popover, { open: contextMenuOpen, onOpenChange: setContextMenuOpen, children: [
9382
9191
  /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
9383
9192
  "button",
9384
9193
  {
9385
9194
  type: "button",
9386
9195
  className: "gantt-tl-name-action-btn gantt-tl-action-context",
9387
- onClick: (e) => {
9388
- e.stopPropagation();
9389
- setContextMenuOpen((v) => !v);
9196
+ onClick: (event) => {
9197
+ event.stopPropagation();
9198
+ setContextMenuOpen((value) => !value);
9390
9199
  },
9391
9200
  "aria-label": "\u0414\u043E\u043F\u043E\u043B\u043D\u0438\u0442\u0435\u043B\u044C\u043D\u043E",
9392
9201
  children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(VerticalDotsIcon, {})
9393
9202
  }
9394
9203
  ) }),
9395
- /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(PopoverContent, { className: "gantt-tl-context-menu", portal: true, align: "end", children: [
9396
- onTasksChange && /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
9397
- "div",
9398
- {
9399
- className: "gantt-tl-context-menu-section gantt-tl-context-submenu-wrap",
9400
- onMouseLeave: (e) => {
9401
- if (!e.currentTarget.contains(e.relatedTarget)) {
9402
- closeColorMenu();
9403
- }
9404
- },
9405
- onBlur: (e) => {
9406
- if (!e.currentTarget.contains(e.relatedTarget)) {
9407
- closeColorMenu();
9408
- }
9409
- },
9410
- children: [
9411
- /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
9412
- "button",
9413
- {
9414
- type: "button",
9415
- className: "gantt-tl-context-menu-item gantt-tl-context-menu-item-toggle",
9416
- onMouseEnter: () => setColorMenuOpen(true),
9417
- "aria-expanded": colorMenuOpen,
9418
- "aria-haspopup": "menu",
9419
- children: [
9420
- /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("span", { className: "gantt-tl-context-menu-item-main", children: [
9421
- task.color && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
9422
- "span",
9423
- {
9424
- className: "gantt-tl-color-swatch gantt-tl-color-swatch-inline",
9425
- style: { backgroundColor: task.color },
9426
- "aria-hidden": "true"
9427
- }
9428
- ),
9429
- "\u0426\u0432\u0435\u0442"
9430
- ] }),
9431
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(ChevronRightIcon, {})
9432
- ]
9433
- }
9434
- ),
9435
- colorMenuOpen && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: "gantt-tl-context-submenu", role: "menu", "aria-label": "\u0412\u044B\u0431\u043E\u0440 \u0446\u0432\u0435\u0442\u0430", children: /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "gantt-tl-color-grid", children: [
9436
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
9437
- "button",
9438
- {
9439
- type: "button",
9440
- className: `gantt-tl-color-swatch gantt-tl-color-swatch-clear${!task.color ? " is-selected" : ""}`,
9441
- onClick: (e) => {
9442
- e.stopPropagation();
9443
- handleApplyColor(void 0);
9444
- },
9445
- "aria-label": "\u0421\u0431\u0440\u043E\u0441\u0438\u0442\u044C \u0446\u0432\u0435\u0442",
9446
- title: "\u0421\u0431\u0440\u043E\u0441\u0438\u0442\u044C \u0446\u0432\u0435\u0442",
9447
- children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "gantt-tl-color-swatch-clear-line" })
9448
- }
9449
- ),
9450
- TASK_COLOR_PALETTE.map((paletteColor) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
9451
- "button",
9452
- {
9453
- type: "button",
9454
- className: `gantt-tl-color-swatch${task.color === paletteColor.value ? " is-selected" : ""}`,
9455
- style: { backgroundColor: paletteColor.value },
9456
- onClick: (e) => {
9457
- e.stopPropagation();
9458
- handleApplyColor(paletteColor.value);
9459
- },
9460
- "aria-label": `\u0412\u044B\u0431\u0440\u0430\u0442\u044C \u0446\u0432\u0435\u0442 ${paletteColor.label}`,
9461
- title: paletteColor.label
9462
- },
9463
- paletteColor.value
9464
- ))
9465
- ] }) })
9466
- ]
9467
- }
9468
- ),
9469
- onDuplicateTask && /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
9470
- "button",
9471
- {
9472
- type: "button",
9473
- className: "gantt-tl-context-menu-item",
9474
- onClick: (e) => {
9475
- e.stopPropagation();
9476
- setContextMenuOpen(false);
9477
- onDuplicateTask(task.id);
9478
- },
9479
- children: [
9480
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(CopyIcon, {}),
9481
- "\u0414\u0443\u0431\u043B\u0438\u0440\u043E\u0432\u0430\u0442\u044C"
9482
- ]
9483
- }
9484
- ),
9485
- visibleCustomMenuCommands.map((command) => /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_react12.default.Fragment, { children: [
9486
- command.divider === "top" && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("hr", { className: "gantt-tl-context-menu-divider" }),
9487
- /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
9488
- "button",
9489
- {
9490
- type: "button",
9491
- className: `gantt-tl-context-menu-item${command.danger ? " gantt-tl-context-menu-item-danger" : ""}`,
9492
- onClick: handleCustomMenuCommandClick(command),
9493
- disabled: command.isDisabled?.(task) ?? false,
9494
- children: [
9495
- command.icon,
9496
- command.label
9497
- ]
9498
- }
9499
- ),
9500
- command.divider === "bottom" && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("hr", { className: "gantt-tl-context-menu-divider" })
9501
- ] }, command.id)),
9502
- isParent && onUngroupTask && /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
9503
- "button",
9504
- {
9505
- type: "button",
9506
- className: "gantt-tl-context-menu-item",
9507
- onClick: handleUngroup,
9508
- children: [
9509
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(UngroupIcon, {}),
9510
- "\u0420\u0430\u0437\u0433\u0440\u0443\u043F\u043F\u0438\u0440\u043E\u0432\u0430\u0442\u044C"
9511
- ]
9512
- }
9513
- ),
9514
- onDelete && /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
9515
- "button",
9516
- {
9517
- type: "button",
9518
- className: "gantt-tl-context-menu-item gantt-tl-context-menu-item-danger",
9519
- onClick: (e) => {
9520
- e.stopPropagation();
9521
- setContextMenuOpen(false);
9522
- onDelete(task.id);
9523
- },
9524
- children: [
9525
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(TrashIcon, {}),
9526
- "\u0423\u0434\u0430\u043B\u0438\u0442\u044C \u0440\u0430\u0431\u043E\u0442\u0443"
9527
- ]
9528
- }
9529
- )
9530
- ] })
9531
- ] })
9532
- ] })
9204
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(PopoverContent, { className: "gantt-tl-context-menu", portal: true, align: "end", children: menuContent })
9205
+ ] }) : null
9206
+ ] }) : null
9533
9207
  ] });
9534
9208
  const startDateCell = /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
9535
9209
  "div",
@@ -10379,7 +10053,7 @@ var BUILT_IN_CSS_CLASSES = {
10379
10053
  duration: "gantt-tl-cell-duration",
10380
10054
  progress: "gantt-tl-cell-progress"
10381
10055
  };
10382
- function getAllDescendants2(parentId, tasks) {
10056
+ function getAllDescendants3(parentId, tasks) {
10383
10057
  const descendants = [];
10384
10058
  const visited = /* @__PURE__ */ new Set();
10385
10059
  function collectChildren(taskId) {
@@ -10397,7 +10071,7 @@ function getAllDescendants2(parentId, tasks) {
10397
10071
  function duplicateTaskSubtree(anchorTaskId, orderedTasks) {
10398
10072
  const anchorTask = orderedTasks.find((task) => task.id === anchorTaskId);
10399
10073
  if (!anchorTask) return orderedTasks;
10400
- const descendants = getAllDescendants2(anchorTaskId, orderedTasks);
10074
+ const descendants = getAllDescendants3(anchorTaskId, orderedTasks);
10401
10075
  const sourceIds = /* @__PURE__ */ new Set([anchorTaskId, ...descendants.map((task) => task.id)]);
10402
10076
  const sourceSubtree = orderedTasks.filter((task) => sourceIds.has(task.id));
10403
10077
  const cloneIdMap = new Map(sourceSubtree.map((task) => [task.id, crypto.randomUUID()]));
@@ -10506,7 +10180,7 @@ var TaskList = ({
10506
10180
  disableTaskDrag = false,
10507
10181
  disableTaskListReorder = false,
10508
10182
  editingTaskId: propEditingTaskId,
10509
- enableAddTask = true,
10183
+ enableAddTask = false,
10510
10184
  addTaskLabel = "\u0414\u043E\u0431\u0430\u0432\u0438\u0442\u044C \u0440\u0430\u0431\u043E\u0442\u0443",
10511
10185
  defaultTaskDurationDays = DEFAULT_TASK_DURATION_DAYS,
10512
10186
  collapsedParentIds: externalCollapsedParentIds,
@@ -10532,6 +10206,8 @@ var TaskList = ({
10532
10206
  taskListColumnWidths,
10533
10207
  onTaskListColumnWidthsChange,
10534
10208
  taskListMenuCommands,
10209
+ renderTaskListActions,
10210
+ renderTaskListMenu,
10535
10211
  hideTaskListRowActions = false,
10536
10212
  getTaskListRowClassName,
10537
10213
  getTaskListNamePrefixIcon,
@@ -10962,7 +10638,7 @@ var TaskList = ({
10962
10638
  }
10963
10639
  const draggedTask = orderedTasks.find((t) => t.id === draggedTaskId);
10964
10640
  if (!draggedTask) return true;
10965
- const descendants = getAllDescendants2(draggedTaskId, orderedTasks);
10641
+ const descendants = getAllDescendants3(draggedTaskId, orderedTasks);
10966
10642
  const descendantIds = new Set(descendants.map((d) => d.id));
10967
10643
  if (descendantIds.has(dropTarget.id)) {
10968
10644
  return false;
@@ -10979,7 +10655,7 @@ var TaskList = ({
10979
10655
  if (target.placement !== "before" || target.index <= 0 || target.index >= visibleTasks.length) {
10980
10656
  return target;
10981
10657
  }
10982
- const descendantIds = new Set(getAllDescendants2(movedTaskId, orderedTasks).map((task) => task.id));
10658
+ const descendantIds = new Set(getAllDescendants3(movedTaskId, orderedTasks).map((task) => task.id));
10983
10659
  const movedIds = /* @__PURE__ */ new Set([movedTaskId, ...descendantIds]);
10984
10660
  const targetTask = visibleTasks[target.index];
10985
10661
  if (targetTask?.id === movedTaskId) {
@@ -11102,7 +10778,7 @@ var TaskList = ({
11102
10778
  let subtree;
11103
10779
  let subtreeCount;
11104
10780
  if (hasChildren) {
11105
- const descendants = getAllDescendants2(moved.id, orderedTasks);
10781
+ const descendants = getAllDescendants3(moved.id, orderedTasks);
11106
10782
  subtree = [moved, ...descendants];
11107
10783
  subtreeCount = subtree.length;
11108
10784
  } else {
@@ -11120,7 +10796,7 @@ var TaskList = ({
11120
10796
  const handleBeforeFirstDragOver = (0, import_react15.useCallback)((e) => {
11121
10797
  const draggedTaskId = dragTaskIdRef.current;
11122
10798
  const firstTask = visibleTasks[0];
11123
- const descendantIds = draggedTaskId ? new Set(getAllDescendants2(draggedTaskId, orderedTasks).map((task) => task.id)) : /* @__PURE__ */ new Set();
10799
+ const descendantIds = draggedTaskId ? new Set(getAllDescendants3(draggedTaskId, orderedTasks).map((task) => task.id)) : /* @__PURE__ */ new Set();
11124
10800
  const isValidBeforeFirstDrop = !!draggedTaskId && !!firstTask && firstTask.id !== draggedTaskId && !descendantIds.has(firstTask.id) && isValidParentDrop(draggedTaskId, 0);
11125
10801
  setIsBeforeFirstDropZoneActive(isValidBeforeFirstDrop);
11126
10802
  handleDragOver(0, e, "before");
@@ -11658,7 +11334,7 @@ var TaskList = ({
11658
11334
  onScrollToTask,
11659
11335
  onDelete,
11660
11336
  onAdd,
11661
- onInsertAfter: handleStartInsertAfter,
11337
+ onInsertAfter: onInsertAfter ? handleStartInsertAfter : void 0,
11662
11338
  editingTaskId: propEditingTaskId,
11663
11339
  isDragging: !reorderDisabled && draggingIndex === index,
11664
11340
  isDragOver: !reorderDisabled && dragOverTarget?.index === index,
@@ -11693,6 +11369,8 @@ var TaskList = ({
11693
11369
  activeCustomCell,
11694
11370
  onActiveCustomCellChange: setActiveCustomCell,
11695
11371
  taskListMenuCommands,
11372
+ renderTaskListActions,
11373
+ renderTaskListMenu,
11696
11374
  hideTaskListRowActions,
11697
11375
  rowClassName: [
11698
11376
  task.parentId && compositeParentIds.has(task.parentId) ? "gantt-tl-row-composite-detail" : "",
@@ -15622,7 +15300,7 @@ function TaskGanttChartInner(props, ref) {
15622
15300
  onPromoteTask,
15623
15301
  onDemoteTask,
15624
15302
  onUngroupTask,
15625
- enableAddTask = true,
15303
+ enableAddTask = false,
15626
15304
  addTaskLabel = "\u0414\u043E\u0431\u0430\u0432\u0438\u0442\u044C \u0440\u0430\u0431\u043E\u0442\u0443",
15627
15305
  defaultTaskDurationDays,
15628
15306
  taskFilter,
@@ -15655,6 +15333,8 @@ function TaskGanttChartInner(props, ref) {
15655
15333
  taskListColumnWidths,
15656
15334
  onTaskListColumnWidthsChange,
15657
15335
  taskListMenuCommands,
15336
+ renderTaskListActions,
15337
+ renderTaskListMenu,
15658
15338
  hideTaskListRowActions = false,
15659
15339
  getTaskListRowClassName,
15660
15340
  getTaskListNamePrefixIcon,
@@ -16981,9 +16661,9 @@ function TaskGanttChartInner(props, ref) {
16981
16661
  ),
16982
16662
  selectedChip,
16983
16663
  onAdd,
16984
- onDelete: handleDelete,
16985
- onInsertAfter: handleInsertAfter,
16986
- onReorder: handleReorder,
16664
+ onDelete: onDelete ? handleDelete : void 0,
16665
+ onInsertAfter: onInsertAfter ? handleInsertAfter : void 0,
16666
+ onReorder: onReorder || onTasksChange ? handleReorder : void 0,
16987
16667
  disableTaskDrag: disableTaskDrag || disableTaskListReorder,
16988
16668
  editingTaskId,
16989
16669
  enableAddTask,
@@ -16991,9 +16671,9 @@ function TaskGanttChartInner(props, ref) {
16991
16671
  defaultTaskDurationDays,
16992
16672
  collapsedParentIds,
16993
16673
  onToggleCollapse: handleToggleCollapse,
16994
- onPromoteTask: onPromoteTask ?? handlePromoteTask,
16995
- onDemoteTask: onDemoteTask ?? handleDemoteTask,
16996
- onUngroupTask: onUngroupTask ?? handleUngroupTask,
16674
+ onPromoteTask: onPromoteTask ?? (onTasksChange ? handlePromoteTask : void 0),
16675
+ onDemoteTask: onDemoteTask ?? (onTasksChange ? handleDemoteTask : void 0),
16676
+ onUngroupTask: onUngroupTask ?? (onTasksChange ? handleUngroupTask : void 0),
16997
16677
  highlightedTaskIds: taskListHighlightedTaskIds,
16998
16678
  fillParentRows: shouldFillParentRowsInTaskList,
16999
16679
  enableTaskMultiSelect,
@@ -17012,6 +16692,8 @@ function TaskGanttChartInner(props, ref) {
17012
16692
  taskListColumnWidths,
17013
16693
  onTaskListColumnWidthsChange,
17014
16694
  taskListMenuCommands,
16695
+ renderTaskListActions,
16696
+ renderTaskListMenu,
17015
16697
  hideTaskListRowActions,
17016
16698
  getTaskListRowClassName,
17017
16699
  getTaskListNamePrefixIcon,