gantt-lib 0.145.2 → 0.146.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.js CHANGED
@@ -7716,6 +7716,7 @@ var DepChip = ({
7716
7716
  weekendPredicate
7717
7717
  }) => {
7718
7718
  const [popoverOpen, setPopoverOpen] = (0, import_react12.useState)(false);
7719
+ const [typeMenuOpen, setTypeMenuOpen] = (0, import_react12.useState)(false);
7719
7720
  const lagAbs = Math.abs(lag ?? 0);
7720
7721
  const [inputAbs, setInputAbs] = (0, import_react12.useState)(lagAbs === 0 ? "" : String(lagAbs));
7721
7722
  (0, import_react12.useEffect)(() => {
@@ -7837,6 +7838,69 @@ var DepChip = ({
7837
7838
  const Icon = LINK_TYPE_ICONS[dep.type];
7838
7839
  const depName = predecessorName ?? dep.taskId;
7839
7840
  const effectiveLag = lag ?? 0;
7841
+ const handleTypeChange = (0, import_react12.useCallback)(
7842
+ (newType) => {
7843
+ if (newType === dep.type) return;
7844
+ if (!onTasksChange || !allTasks) return;
7845
+ if ((task.dependencies ?? []).some((d) => d.taskId === dep.taskId && d.type === newType)) return;
7846
+ const taskById = new Map(allTasks.map((t) => [t.id, t]));
7847
+ const predecessor = taskById.get(dep.taskId);
7848
+ if (!predecessor) return;
7849
+ const predStart = parseUTCDate(predecessor.startDate);
7850
+ const predEnd = predecessor.type === "milestone" ? predStart : parseUTCDate(predecessor.endDate);
7851
+ const origStart = parseUTCDate(task.startDate);
7852
+ const origEnd = parseUTCDate(task.endDate);
7853
+ const durationMs = origEnd.getTime() - origStart.getTime();
7854
+ const normalizedLag = normalizeDependencyLag(
7855
+ newType,
7856
+ effectiveLag,
7857
+ predStart,
7858
+ predEnd,
7859
+ businessDays,
7860
+ weekendPredicate,
7861
+ task.type
7862
+ );
7863
+ const constraintDate = calculateSuccessorDate(
7864
+ predStart,
7865
+ predEnd,
7866
+ newType,
7867
+ normalizedLag,
7868
+ businessDays,
7869
+ weekendPredicate,
7870
+ task.type
7871
+ );
7872
+ let newStart, newEnd;
7873
+ if (newType === "FS" || newType === "SS") {
7874
+ newStart = constraintDate;
7875
+ if (businessDays) {
7876
+ const businessDuration = getBusinessDaysCount(origStart, origEnd, weekendPredicate);
7877
+ newEnd = addBusinessDays(constraintDate, businessDuration, weekendPredicate);
7878
+ } else {
7879
+ newEnd = new Date(constraintDate.getTime() + durationMs);
7880
+ }
7881
+ } else {
7882
+ newEnd = constraintDate;
7883
+ if (businessDays) {
7884
+ const businessDuration = getBusinessDaysCount(origStart, origEnd, weekendPredicate);
7885
+ newStart = subtractBusinessDays(constraintDate, businessDuration, weekendPredicate);
7886
+ } else {
7887
+ newStart = new Date(constraintDate.getTime() - durationMs);
7888
+ }
7889
+ }
7890
+ onTasksChange([
7891
+ {
7892
+ ...task,
7893
+ startDate: newStart.toISOString().split("T")[0],
7894
+ endDate: newEnd.toISOString().split("T")[0],
7895
+ dependencies: (task.dependencies ?? []).map(
7896
+ (existingDep) => existingDep.taskId === dep.taskId && existingDep.type === dep.type ? { ...existingDep, type: newType, lag: normalizedLag } : existingDep
7897
+ )
7898
+ }
7899
+ ]);
7900
+ onChipSelect?.({ successorId: taskId, predecessorId: dep.taskId, linkType: newType });
7901
+ },
7902
+ [dep.type, dep.taskId, task, allTasks, onTasksChange, businessDays, weekendPredicate, effectiveLag, onChipSelect, taskId]
7903
+ );
7840
7904
  const actionVerb = dep.type === "FS" || dep.type === "SS" ? "\u043D\u0430\u0447\u0430\u0442\u044C" : "\u0437\u0430\u0432\u0435\u0440\u0448\u0438\u0442\u044C";
7841
7905
  const zeroPlaceholder = dep.type === "SF" ? "\u0447\u0451\u0442\u043A\u043E" : dep.type === "FF" ? "\u0432\u043C\u0435\u0441\u0442\u0435" : dep.type === "SS" ? "\u0432\u043C\u0435\u0441\u0442\u0435" : "\u0441\u0440\u0430\u0437\u0443";
7842
7906
  let afterWhat;
@@ -7968,27 +8032,71 @@ var DepChip = ({
7968
8032
  !disableDependencyEditing && /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_jsx_runtime15.Fragment, { children: [
7969
8033
  /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("hr", { className: "gantt-tl-dep-edit-divider" }),
7970
8034
  /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "gantt-tl-dep-edit-actions", children: [
7971
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
7972
- "button",
7973
- {
7974
- type: "button",
7975
- className: "gantt-tl-dep-edit-close",
7976
- onClick: () => {
7977
- setPopoverOpen(false);
7978
- onChipSelectClear();
7979
- },
7980
- children: "\u0417\u0430\u043A\u0440\u044B\u0442\u044C"
7981
- }
7982
- ),
7983
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
7984
- "button",
7985
- {
7986
- type: "button",
7987
- className: "gantt-tl-dep-edit-delete",
7988
- onClick: handleTrashClick,
7989
- children: "\u0423\u0434\u0430\u043B\u0438\u0442\u044C \u0441\u0432\u044F\u0437\u044C"
7990
- }
7991
- )
8035
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(Popover, { open: typeMenuOpen, onOpenChange: setTypeMenuOpen, children: [
8036
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
8037
+ "button",
8038
+ {
8039
+ type: "button",
8040
+ className: "gantt-tl-dep-edit-type-trigger",
8041
+ onClick: (e) => e.stopPropagation(),
8042
+ "aria-label": "\u0418\u0437\u043C\u0435\u043D\u0438\u0442\u044C \u0442\u0438\u043F \u0441\u0432\u044F\u0437\u0438",
8043
+ title: "\u0418\u0437\u043C\u0435\u043D\u0438\u0442\u044C \u0442\u0438\u043F \u0441\u0432\u044F\u0437\u0438",
8044
+ children: [
8045
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Icon, {}),
8046
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { children: LINK_TYPE_LABELS_RU2[dep.type] }),
8047
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "gantt-tl-dep-edit-type-caret", "aria-hidden": "true", children: "\u25BE" })
8048
+ ]
8049
+ }
8050
+ ) }),
8051
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(PopoverContent, { portal: true, align: "start", children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: "gantt-tl-dep-type-menu", children: LINK_TYPE_ORDER.map((linkType) => {
8052
+ const TypeIcon = LINK_TYPE_ICONS[linkType];
8053
+ const isCurrent = linkType === dep.type;
8054
+ const isDuplicate = !isCurrent && (task.dependencies ?? []).some(
8055
+ (d) => d.taskId === dep.taskId && d.type === linkType
8056
+ );
8057
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
8058
+ "button",
8059
+ {
8060
+ type: "button",
8061
+ className: `gantt-tl-dep-type-option${isCurrent ? " active" : ""}${isDuplicate ? " gantt-tl-dep-type-option-duplicate" : ""}`,
8062
+ disabled: isDuplicate,
8063
+ onClick: () => {
8064
+ handleTypeChange(linkType);
8065
+ setTypeMenuOpen(false);
8066
+ },
8067
+ title: isDuplicate ? "\u0421\u0432\u044F\u0437\u044C \u0442\u0430\u043A\u043E\u0433\u043E \u0442\u0438\u043F\u0430 \u0443\u0436\u0435 \u0435\u0441\u0442\u044C" : `\u0422\u0438\u043F \u0441\u0432\u044F\u0437\u0438 ${LINK_TYPE_LABELS_RU2[linkType]}`,
8068
+ children: [
8069
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(TypeIcon, {}),
8070
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { children: LINK_TYPE_LABELS_RU2[linkType] })
8071
+ ]
8072
+ },
8073
+ linkType
8074
+ );
8075
+ }) }) })
8076
+ ] }),
8077
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "gantt-tl-dep-edit-actions-right", children: [
8078
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
8079
+ "button",
8080
+ {
8081
+ type: "button",
8082
+ className: "gantt-tl-dep-edit-close",
8083
+ onClick: () => {
8084
+ setPopoverOpen(false);
8085
+ onChipSelectClear();
8086
+ },
8087
+ children: "\u0417\u0430\u043A\u0440\u044B\u0442\u044C"
8088
+ }
8089
+ ),
8090
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
8091
+ "button",
8092
+ {
8093
+ type: "button",
8094
+ className: "gantt-tl-dep-edit-delete",
8095
+ onClick: handleTrashClick,
8096
+ children: "\u0423\u0434\u0430\u043B\u0438\u0442\u044C \u0441\u0432\u044F\u0437\u044C"
8097
+ }
8098
+ )
8099
+ ] })
7992
8100
  ] })
7993
8101
  ] })
7994
8102
  ] })
@@ -9494,7 +9602,7 @@ var TaskListRow = import_react12.default.memo(
9494
9602
  {
9495
9603
  className: "gantt-tl-dep-overflow-list",
9496
9604
  onClick: (e) => e.stopPropagation(),
9497
- children: chips.map(({ dep, lag, predecessorName }) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
9605
+ children: chips.map(({ dep, lag, predecessorName }, chipIndex) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
9498
9606
  DepChip,
9499
9607
  {
9500
9608
  lag,
@@ -9516,7 +9624,7 @@ var TaskListRow = import_react12.default.memo(
9516
9624
  businessDays,
9517
9625
  weekendPredicate
9518
9626
  },
9519
- `${dep.taskId}-${dep.type}`
9627
+ `${dep.taskId}-${chipIndex}`
9520
9628
  ))
9521
9629
  }
9522
9630
  ) })
@@ -9544,7 +9652,8 @@ var TaskListRow = import_react12.default.memo(
9544
9652
  onTasksChange,
9545
9653
  businessDays,
9546
9654
  weekendPredicate
9547
- }
9655
+ },
9656
+ chips[0].dep.taskId
9548
9657
  )
9549
9658
  ) : null,
9550
9659
  !printDependencyLabels && !disableDependencyEditing && !isPicking && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(