gantt-lib 0.17.2 → 0.18.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
@@ -1,3 +1,5 @@
1
+ "use client";
2
+
1
3
  "use client";
2
4
  var __defProp = Object.defineProperty;
3
5
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
@@ -2391,7 +2393,13 @@ var PopoverContent = ({
2391
2393
 
2392
2394
  // src/components/TaskList/TaskListRow.tsx
2393
2395
  init_dateUtils();
2394
- import React9, { useState as useState4, useRef as useRef4, useEffect as useEffect4, useCallback as useCallback4, useMemo as useMemo7 } from "react";
2396
+ import React9, {
2397
+ useState as useState4,
2398
+ useRef as useRef4,
2399
+ useEffect as useEffect4,
2400
+ useCallback as useCallback4,
2401
+ useMemo as useMemo7
2402
+ } from "react";
2395
2403
 
2396
2404
  // src/components/ui/Input.tsx
2397
2405
  import React6 from "react";
@@ -2828,18 +2836,49 @@ var DAY_MS2 = 24 * 60 * 60 * 1e3;
2828
2836
  var getInclusiveDurationDays = (startDate, endDate) => {
2829
2837
  const start = parseUTCDate(startDate);
2830
2838
  const end = parseUTCDate(endDate);
2831
- return Math.max(1, Math.round((end.getTime() - start.getTime()) / DAY_MS2) + 1);
2839
+ return Math.max(
2840
+ 1,
2841
+ Math.round((end.getTime() - start.getTime()) / DAY_MS2) + 1
2842
+ );
2832
2843
  };
2833
2844
  var getEndDateFromDuration = (startDate, durationDays) => {
2834
2845
  const start = parseUTCDate(startDate);
2835
2846
  return new Date(start.getTime() + (durationDays - 1) * DAY_MS2).toISOString().split("T")[0];
2836
2847
  };
2837
- var TrashIcon = () => /* @__PURE__ */ jsxs9("svg", { xmlns: "http://www.w3.org/2000/svg", width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
2838
- /* @__PURE__ */ jsx12("path", { d: "M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6" }),
2839
- /* @__PURE__ */ jsx12("path", { d: "M3 6h18" }),
2840
- /* @__PURE__ */ jsx12("path", { d: "M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2" })
2841
- ] });
2842
- var PlusIcon = () => /* @__PURE__ */ jsx12("svg", { xmlns: "http://www.w3.org/2000/svg", width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx12("path", { d: "M12 5v14M5 12h14" }) });
2848
+ var TrashIcon = () => /* @__PURE__ */ jsxs9(
2849
+ "svg",
2850
+ {
2851
+ xmlns: "http://www.w3.org/2000/svg",
2852
+ width: "12",
2853
+ height: "12",
2854
+ viewBox: "0 0 24 24",
2855
+ fill: "none",
2856
+ stroke: "currentColor",
2857
+ strokeWidth: "2",
2858
+ strokeLinecap: "round",
2859
+ strokeLinejoin: "round",
2860
+ children: [
2861
+ /* @__PURE__ */ jsx12("path", { d: "M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6" }),
2862
+ /* @__PURE__ */ jsx12("path", { d: "M3 6h18" }),
2863
+ /* @__PURE__ */ jsx12("path", { d: "M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2" })
2864
+ ]
2865
+ }
2866
+ );
2867
+ var PlusIcon = () => /* @__PURE__ */ jsx12(
2868
+ "svg",
2869
+ {
2870
+ xmlns: "http://www.w3.org/2000/svg",
2871
+ width: "14",
2872
+ height: "14",
2873
+ viewBox: "0 0 24 24",
2874
+ fill: "none",
2875
+ stroke: "currentColor",
2876
+ strokeWidth: "2",
2877
+ strokeLinecap: "round",
2878
+ strokeLinejoin: "round",
2879
+ children: /* @__PURE__ */ jsx12("path", { d: "M12 5v14M5 12h14" })
2880
+ }
2881
+ );
2843
2882
  var DragHandleIcon = () => /* @__PURE__ */ jsxs9("svg", { width: "10", height: "14", viewBox: "0 0 10 14", fill: "currentColor", children: [
2844
2883
  /* @__PURE__ */ jsx12("circle", { cx: "2", cy: "2", r: "1.5" }),
2845
2884
  /* @__PURE__ */ jsx12("circle", { cx: "8", cy: "2", r: "1.5" }),
@@ -2848,51 +2887,94 @@ var DragHandleIcon = () => /* @__PURE__ */ jsxs9("svg", { width: "10", height: "
2848
2887
  /* @__PURE__ */ jsx12("circle", { cx: "2", cy: "12", r: "1.5" }),
2849
2888
  /* @__PURE__ */ jsx12("circle", { cx: "8", cy: "12", r: "1.5" })
2850
2889
  ] });
2851
- var ChevronRightIcon = () => /* @__PURE__ */ jsx12("svg", { xmlns: "http://www.w3.org/2000/svg", width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx12("path", { d: "m9 18 6-6-6-6" }) });
2852
- var HierarchyConnectorIcon = ({ isLastChild }) => /* @__PURE__ */ jsxs9("span", { className: `gantt-tl-hierarchy-connector${isLastChild ? " gantt-tl-hierarchy-connector--last" : ""}`, "aria-hidden": "true", children: [
2853
- /* @__PURE__ */ jsx12("span", { className: "gantt-tl-hc-vline" }),
2854
- /* @__PURE__ */ jsx12("span", { className: "gantt-tl-hc-hline" }),
2855
- /* @__PURE__ */ jsx12("span", { className: "gantt-tl-hc-dot" })
2856
- ] });
2890
+ var ChevronRightIcon = () => /* @__PURE__ */ jsx12(
2891
+ "svg",
2892
+ {
2893
+ xmlns: "http://www.w3.org/2000/svg",
2894
+ width: "14",
2895
+ height: "14",
2896
+ viewBox: "0 0 24 24",
2897
+ fill: "none",
2898
+ stroke: "currentColor",
2899
+ strokeWidth: "2",
2900
+ strokeLinecap: "round",
2901
+ strokeLinejoin: "round",
2902
+ children: /* @__PURE__ */ jsx12("path", { d: "m9 18 6-6-6-6" })
2903
+ }
2904
+ );
2905
+ var ArrowLeft = () => /* @__PURE__ */ jsxs9(
2906
+ "svg",
2907
+ {
2908
+ xmlns: "http://www.w3.org/2000/svg",
2909
+ width: "16",
2910
+ height: "16",
2911
+ viewBox: "0 0 24 24",
2912
+ fill: "none",
2913
+ stroke: "currentColor",
2914
+ strokeWidth: "2",
2915
+ strokeLinecap: "round",
2916
+ strokeLinejoin: "round",
2917
+ children: [
2918
+ /* @__PURE__ */ jsx12("path", { d: "m12 19-7-7 7-7" }),
2919
+ /* @__PURE__ */ jsx12("path", { d: "M19 12H5" })
2920
+ ]
2921
+ }
2922
+ );
2923
+ var ArrowRight = () => /* @__PURE__ */ jsxs9(
2924
+ "svg",
2925
+ {
2926
+ xmlns: "http://www.w3.org/2000/svg",
2927
+ width: "16",
2928
+ height: "16",
2929
+ viewBox: "0 0 24 24",
2930
+ fill: "none",
2931
+ stroke: "currentColor",
2932
+ strokeWidth: "2",
2933
+ strokeLinecap: "round",
2934
+ strokeLinejoin: "round",
2935
+ children: [
2936
+ /* @__PURE__ */ jsx12("path", { d: "M5 12h14" }),
2937
+ /* @__PURE__ */ jsx12("path", { d: "m12 5 7 7-7 7" })
2938
+ ]
2939
+ }
2940
+ );
2857
2941
  var HierarchyButton = ({
2858
2942
  isChild,
2859
- isParent,
2860
- rowIndex,
2943
+ rowIndex: _rowIndex,
2861
2944
  onPromote,
2862
2945
  onDemote
2863
2946
  }) => {
2864
2947
  const canPromote = isChild && onPromote;
2865
- const canDemote = !isParent && onDemote && rowIndex > 0;
2866
- if (!canPromote && !canDemote) {
2867
- return null;
2868
- }
2869
- const handleClick = (e) => {
2870
- e.stopPropagation();
2871
- if (canPromote) {
2872
- onPromote(e);
2873
- } else if (canDemote) {
2874
- onDemote(e);
2875
- }
2876
- };
2877
- const title = canPromote ? "\u041F\u043E\u0432\u044B\u0441\u0438\u0442\u044C (\u0441\u0434\u0435\u043B\u0430\u0442\u044C \u043A\u043E\u0440\u043D\u0435\u0432\u043E\u0439)" : "\u041F\u043E\u043D\u0438\u0437\u0438\u0442\u044C (\u0441\u0434\u0435\u043B\u0430\u0442\u044C \u043F\u043E\u0434\u0447\u0438\u043D\u0435\u043D\u043D\u043E\u0439)";
2878
- const ArrowLeft = () => /* @__PURE__ */ jsxs9("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
2879
- /* @__PURE__ */ jsx12("path", { d: "m12 19-7-7 7-7" }),
2880
- /* @__PURE__ */ jsx12("path", { d: "M19 12H5" })
2881
- ] });
2882
- const ArrowRight = () => /* @__PURE__ */ jsxs9("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
2883
- /* @__PURE__ */ jsx12("path", { d: "M5 12h14" }),
2884
- /* @__PURE__ */ jsx12("path", { d: "m12 5 7 7-7 7" })
2948
+ const canDemote = !!onDemote;
2949
+ if (!canPromote && !canDemote) return null;
2950
+ return /* @__PURE__ */ jsxs9(Fragment2, { children: [
2951
+ canPromote && /* @__PURE__ */ jsx12(
2952
+ "button",
2953
+ {
2954
+ type: "button",
2955
+ className: "gantt-tl-name-action-btn gantt-tl-action-hierarchy",
2956
+ onClick: (e) => {
2957
+ e.stopPropagation();
2958
+ onPromote(e);
2959
+ },
2960
+ title: "\u041F\u043E\u0432\u044B\u0441\u0438\u0442\u044C \u0443\u0440\u043E\u0432\u0435\u043D\u044C",
2961
+ children: /* @__PURE__ */ jsx12(ArrowLeft, {})
2962
+ }
2963
+ ),
2964
+ canDemote && /* @__PURE__ */ jsx12(
2965
+ "button",
2966
+ {
2967
+ type: "button",
2968
+ className: "gantt-tl-name-action-btn gantt-tl-action-hierarchy",
2969
+ onClick: (e) => {
2970
+ e.stopPropagation();
2971
+ onDemote(e);
2972
+ },
2973
+ title: "\u041F\u043E\u043D\u0438\u0437\u0438\u0442\u044C \u0443\u0440\u043E\u0432\u0435\u043D\u044C",
2974
+ children: /* @__PURE__ */ jsx12(ArrowRight, {})
2975
+ }
2976
+ )
2885
2977
  ] });
2886
- return /* @__PURE__ */ jsx12(
2887
- "button",
2888
- {
2889
- type: "button",
2890
- className: "gantt-tl-name-action-btn gantt-tl-action-hierarchy",
2891
- onClick: handleClick,
2892
- title,
2893
- children: canPromote ? /* @__PURE__ */ jsx12(ArrowLeft, {}) : /* @__PURE__ */ jsx12(ArrowRight, {})
2894
- }
2895
- );
2896
2978
  };
2897
2979
  var DepChip = ({
2898
2980
  lag,
@@ -2924,71 +3006,91 @@ var DepChip = ({
2924
3006
  const nextOpen = !popoverOpen;
2925
3007
  setPopoverOpen(nextOpen);
2926
3008
  if (nextOpen) {
2927
- onChipSelect?.({ successorId: taskId, predecessorId: dep.taskId, linkType: dep.type });
3009
+ onChipSelect?.({
3010
+ successorId: taskId,
3011
+ predecessorId: dep.taskId,
3012
+ linkType: dep.type
3013
+ });
2928
3014
  onScrollToTask?.(dep.taskId);
2929
3015
  } else {
2930
3016
  onChipSelect?.(null);
2931
3017
  }
2932
3018
  };
2933
- const handleOpenChange = useCallback4((open) => {
2934
- setPopoverOpen(open);
2935
- if (!open) {
2936
- onChipSelect?.(null);
2937
- }
2938
- }, [onChipSelect]);
3019
+ const handleOpenChange = useCallback4(
3020
+ (open) => {
3021
+ setPopoverOpen(open);
3022
+ if (!open) {
3023
+ onChipSelect?.(null);
3024
+ }
3025
+ },
3026
+ [onChipSelect]
3027
+ );
2939
3028
  const handleTrashClick = (e) => {
2940
3029
  e.stopPropagation();
2941
3030
  onRemoveDependency?.(taskId, dep.taskId, dep.type);
2942
3031
  onChipSelectClear();
2943
3032
  setPopoverOpen(false);
2944
3033
  };
2945
- const handleLagChange = useCallback4((newLag) => {
2946
- if (!onTasksChange || !allTasks) return;
2947
- const taskById = new Map(allTasks.map((t) => [t.id, t]));
2948
- const predecessor = taskById.get(dep.taskId);
2949
- if (!predecessor) return;
2950
- const predStart = parseUTCDate(predecessor.startDate);
2951
- const predEnd = parseUTCDate(predecessor.endDate);
2952
- const origStart = parseUTCDate(task.startDate);
2953
- const origEnd = parseUTCDate(task.endDate);
2954
- const durationMs = origEnd.getTime() - origStart.getTime();
2955
- const constraintDate = calculateSuccessorDate(predStart, predEnd, dep.type, newLag);
2956
- let newStart, newEnd;
2957
- if (dep.type === "FS" || dep.type === "SS") {
2958
- newStart = constraintDate;
2959
- newEnd = new Date(constraintDate.getTime() + durationMs);
2960
- } else {
2961
- newEnd = constraintDate;
2962
- newStart = new Date(constraintDate.getTime() - durationMs);
2963
- }
2964
- onTasksChange([{
2965
- ...task,
2966
- startDate: newStart.toISOString().split("T")[0],
2967
- endDate: newEnd.toISOString().split("T")[0]
2968
- }]);
2969
- }, [dep, task, allTasks, onTasksChange]);
2970
- const handleInputCommit = useCallback4((raw) => {
2971
- if (raw === "") {
2972
- handleLagChange(0);
2973
- return;
2974
- }
2975
- const parsed = parseInt(raw, 10);
2976
- const effectiveLag2 = lag ?? 0;
2977
- if (isNaN(parsed)) {
2978
- const abs = Math.abs(effectiveLag2);
2979
- setInputAbs(abs === 0 ? "" : String(abs));
2980
- return;
2981
- }
2982
- let newLag;
2983
- if (parsed === 0) {
2984
- newLag = 0;
2985
- } else if (dep.type === "SF") {
2986
- newLag = -Math.abs(parsed);
2987
- } else {
2988
- newLag = parsed;
2989
- }
2990
- if (newLag !== effectiveLag2) handleLagChange(newLag);
2991
- }, [lag, dep.type, handleLagChange]);
3034
+ const handleLagChange = useCallback4(
3035
+ (newLag) => {
3036
+ if (!onTasksChange || !allTasks) return;
3037
+ const taskById = new Map(allTasks.map((t) => [t.id, t]));
3038
+ const predecessor = taskById.get(dep.taskId);
3039
+ if (!predecessor) return;
3040
+ const predStart = parseUTCDate(predecessor.startDate);
3041
+ const predEnd = parseUTCDate(predecessor.endDate);
3042
+ const origStart = parseUTCDate(task.startDate);
3043
+ const origEnd = parseUTCDate(task.endDate);
3044
+ const durationMs = origEnd.getTime() - origStart.getTime();
3045
+ const constraintDate = calculateSuccessorDate(
3046
+ predStart,
3047
+ predEnd,
3048
+ dep.type,
3049
+ newLag
3050
+ );
3051
+ let newStart, newEnd;
3052
+ if (dep.type === "FS" || dep.type === "SS") {
3053
+ newStart = constraintDate;
3054
+ newEnd = new Date(constraintDate.getTime() + durationMs);
3055
+ } else {
3056
+ newEnd = constraintDate;
3057
+ newStart = new Date(constraintDate.getTime() - durationMs);
3058
+ }
3059
+ onTasksChange([
3060
+ {
3061
+ ...task,
3062
+ startDate: newStart.toISOString().split("T")[0],
3063
+ endDate: newEnd.toISOString().split("T")[0]
3064
+ }
3065
+ ]);
3066
+ },
3067
+ [dep, task, allTasks, onTasksChange]
3068
+ );
3069
+ const handleInputCommit = useCallback4(
3070
+ (raw) => {
3071
+ if (raw === "") {
3072
+ handleLagChange(0);
3073
+ return;
3074
+ }
3075
+ const parsed = parseInt(raw, 10);
3076
+ const effectiveLag2 = lag ?? 0;
3077
+ if (isNaN(parsed)) {
3078
+ const abs = Math.abs(effectiveLag2);
3079
+ setInputAbs(abs === 0 ? "" : String(abs));
3080
+ return;
3081
+ }
3082
+ let newLag;
3083
+ if (parsed === 0) {
3084
+ newLag = 0;
3085
+ } else if (dep.type === "SF") {
3086
+ newLag = -Math.abs(parsed);
3087
+ } else {
3088
+ newLag = parsed;
3089
+ }
3090
+ if (newLag !== effectiveLag2) handleLagChange(newLag);
3091
+ },
3092
+ [lag, dep.type, handleLagChange]
3093
+ );
2992
3094
  const Icon = LINK_TYPE_ICONS[dep.type];
2993
3095
  const depName = predecessorName ?? dep.taskId;
2994
3096
  const effectiveLag = lag ?? 0;
@@ -3027,67 +3129,92 @@ var DepChip = ({
3027
3129
  ]
3028
3130
  }
3029
3131
  ) }),
3030
- /* @__PURE__ */ jsx12(PopoverContent, { className: "gantt-tl-dep-edit-popover", portal: true, align: "start", children: /* @__PURE__ */ jsxs9("div", { onClick: (e) => e.stopPropagation(), children: [
3031
- /* @__PURE__ */ jsx12("div", { className: "gantt-tl-dep-edit-task", children: task.name }),
3032
- /* @__PURE__ */ jsxs9("div", { className: "gantt-tl-dep-edit-row", children: [
3033
- /* @__PURE__ */ jsxs9("span", { className: "gantt-tl-dep-edit-label", children: [
3034
- actionVerb,
3035
- preWord ? ` ${preWord}` : ""
3036
- ] }),
3037
- /* @__PURE__ */ jsx12("button", { type: "button", className: "gantt-tl-dep-edit-btn", onClick: () => handleLagChange(effectiveLag - 1), children: "\u2212" }),
3038
- /* @__PURE__ */ jsx12(
3039
- "input",
3040
- {
3041
- type: "number",
3042
- className: "gantt-tl-dep-edit-input",
3043
- value: inputAbs,
3044
- placeholder: zeroPlaceholder,
3045
- min: "0",
3046
- onChange: (e) => setInputAbs(e.target.value),
3047
- onFocus: (e) => e.target.select(),
3048
- onBlur: (e) => handleInputCommit(e.target.value),
3049
- onKeyDown: (e) => {
3050
- if (e.key === "Enter") handleInputCommit(inputAbs);
3051
- }
3052
- }
3053
- ),
3054
- !(dep.type === "SF" && effectiveLag === 0) && /* @__PURE__ */ jsx12("button", { type: "button", className: "gantt-tl-dep-edit-btn", onClick: () => handleLagChange(effectiveLag + 1), children: "+" }),
3055
- effectiveLag !== 0 && /* @__PURE__ */ jsx12("span", { children: "\u0434." }),
3056
- /* @__PURE__ */ jsx12("span", { children: afterWhat })
3057
- ] }),
3058
- /* @__PURE__ */ jsx12("div", { className: "gantt-tl-dep-edit-pred", children: depName }),
3059
- !disableDependencyEditing && /* @__PURE__ */ jsxs9(Fragment2, { children: [
3060
- /* @__PURE__ */ jsx12("hr", { className: "gantt-tl-dep-edit-divider" }),
3061
- /* @__PURE__ */ jsxs9("div", { className: "gantt-tl-dep-edit-actions", children: [
3062
- /* @__PURE__ */ jsx12(
3063
- "button",
3064
- {
3065
- type: "button",
3066
- className: "gantt-tl-dep-edit-close",
3067
- onClick: () => {
3068
- setPopoverOpen(false);
3069
- onChipSelectClear();
3070
- },
3071
- children: "\u0417\u0430\u043A\u0440\u044B\u0442\u044C"
3072
- }
3073
- ),
3074
- /* @__PURE__ */ jsx12(
3075
- "button",
3076
- {
3077
- type: "button",
3078
- className: "gantt-tl-dep-edit-delete",
3079
- onClick: handleTrashClick,
3080
- children: "\u0423\u0434\u0430\u043B\u0438\u0442\u044C \u0441\u0432\u044F\u0437\u044C"
3081
- }
3082
- )
3132
+ /* @__PURE__ */ jsx12(
3133
+ PopoverContent,
3134
+ {
3135
+ className: "gantt-tl-dep-edit-popover",
3136
+ portal: true,
3137
+ align: "start",
3138
+ children: /* @__PURE__ */ jsxs9("div", { onClick: (e) => e.stopPropagation(), children: [
3139
+ /* @__PURE__ */ jsx12("div", { className: "gantt-tl-dep-edit-task", children: task.name }),
3140
+ /* @__PURE__ */ jsxs9("div", { className: "gantt-tl-dep-edit-row", children: [
3141
+ /* @__PURE__ */ jsxs9("span", { className: "gantt-tl-dep-edit-label", children: [
3142
+ actionVerb,
3143
+ preWord ? ` ${preWord}` : ""
3144
+ ] }),
3145
+ /* @__PURE__ */ jsx12(
3146
+ "button",
3147
+ {
3148
+ type: "button",
3149
+ className: "gantt-tl-dep-edit-btn",
3150
+ onClick: () => handleLagChange(effectiveLag - 1),
3151
+ children: "\u2212"
3152
+ }
3153
+ ),
3154
+ /* @__PURE__ */ jsx12(
3155
+ "input",
3156
+ {
3157
+ type: "number",
3158
+ className: "gantt-tl-dep-edit-input",
3159
+ value: inputAbs,
3160
+ placeholder: zeroPlaceholder,
3161
+ min: "0",
3162
+ onChange: (e) => setInputAbs(e.target.value),
3163
+ onFocus: (e) => e.target.select(),
3164
+ onBlur: (e) => handleInputCommit(e.target.value),
3165
+ onKeyDown: (e) => {
3166
+ if (e.key === "Enter") handleInputCommit(inputAbs);
3167
+ }
3168
+ }
3169
+ ),
3170
+ !(dep.type === "SF" && effectiveLag === 0) && /* @__PURE__ */ jsx12(
3171
+ "button",
3172
+ {
3173
+ type: "button",
3174
+ className: "gantt-tl-dep-edit-btn",
3175
+ onClick: () => handleLagChange(effectiveLag + 1),
3176
+ children: "+"
3177
+ }
3178
+ ),
3179
+ effectiveLag !== 0 && /* @__PURE__ */ jsx12("span", { children: "\u0434." }),
3180
+ /* @__PURE__ */ jsx12("span", { children: afterWhat })
3181
+ ] }),
3182
+ /* @__PURE__ */ jsx12("div", { className: "gantt-tl-dep-edit-pred", children: depName }),
3183
+ !disableDependencyEditing && /* @__PURE__ */ jsxs9(Fragment2, { children: [
3184
+ /* @__PURE__ */ jsx12("hr", { className: "gantt-tl-dep-edit-divider" }),
3185
+ /* @__PURE__ */ jsxs9("div", { className: "gantt-tl-dep-edit-actions", children: [
3186
+ /* @__PURE__ */ jsx12(
3187
+ "button",
3188
+ {
3189
+ type: "button",
3190
+ className: "gantt-tl-dep-edit-close",
3191
+ onClick: () => {
3192
+ setPopoverOpen(false);
3193
+ onChipSelectClear();
3194
+ },
3195
+ children: "\u0417\u0430\u043A\u0440\u044B\u0442\u044C"
3196
+ }
3197
+ ),
3198
+ /* @__PURE__ */ jsx12(
3199
+ "button",
3200
+ {
3201
+ type: "button",
3202
+ className: "gantt-tl-dep-edit-delete",
3203
+ onClick: handleTrashClick,
3204
+ children: "\u0423\u0434\u0430\u043B\u0438\u0442\u044C \u0441\u0432\u044F\u0437\u044C"
3205
+ }
3206
+ )
3207
+ ] })
3208
+ ] })
3083
3209
  ] })
3084
- ] })
3085
- ] }) })
3210
+ }
3211
+ )
3086
3212
  ] });
3087
3213
  };
3088
3214
  var toISODate = (value) => {
3089
3215
  if (value instanceof Date) return value.toISOString().split("T")[0];
3090
- if (typeof value === "string" && value.includes("T")) return value.split("T")[0];
3216
+ if (typeof value === "string" && value.includes("T"))
3217
+ return value.split("T")[0];
3091
3218
  return value;
3092
3219
  };
3093
3220
  var TaskListRow = React9.memo(
@@ -3124,13 +3251,17 @@ var TaskListRow = React9.memo(
3124
3251
  onToggleCollapse,
3125
3252
  onPromoteTask,
3126
3253
  onDemoteTask,
3127
- isLastChild = true
3254
+ isLastChild = true,
3255
+ nestingDepth = 0,
3256
+ ancestorContinues = []
3128
3257
  }) => {
3129
3258
  const [editingName, setEditingName] = useState4(false);
3130
3259
  const [nameValue, setNameValue] = useState4("");
3131
3260
  const nameInputRef = useRef4(null);
3132
3261
  const [editingDuration, setEditingDuration] = useState4(false);
3133
- const [durationValue, setDurationValue] = useState4(getInclusiveDurationDays(task.startDate, task.endDate));
3262
+ const [durationValue, setDurationValue] = useState4(
3263
+ getInclusiveDurationDays(task.startDate, task.endDate)
3264
+ );
3134
3265
  const durationInputRef = useRef4(null);
3135
3266
  const [editingProgress, setEditingProgress] = useState4(false);
3136
3267
  const [progressValue, setProgressValue] = useState4(0);
@@ -3140,11 +3271,16 @@ var TaskListRow = React9.memo(
3140
3271
  const durationConfirmedRef = useRef4(false);
3141
3272
  const progressConfirmedRef = useRef4(false);
3142
3273
  const autoEditedForRef = useRef4(null);
3143
- const editTriggerRef = useRef4("doubleclick");
3274
+ const editTriggerRef = useRef4(
3275
+ "doubleclick"
3276
+ );
3144
3277
  const [deletePending, setDeletePending] = useState4(false);
3145
3278
  const deleteButtonRef = useRef4(null);
3146
3279
  const isSelected = selectedTaskId === task.id;
3147
- const isParent = useMemo7(() => isTaskParent(task.id, allTasks), [task.id, allTasks]);
3280
+ const isParent = useMemo7(
3281
+ () => isTaskParent(task.id, allTasks),
3282
+ [task.id, allTasks]
3283
+ );
3148
3284
  const isChild = task.parentId !== void 0;
3149
3285
  const isCollapsed = collapsedParentIds.has(task.id);
3150
3286
  const isPicking = selectingPredecessorFor != null;
@@ -3199,31 +3335,40 @@ var TaskListRow = React9.memo(
3199
3335
  setEditingName(true);
3200
3336
  }
3201
3337
  }, [editingTaskId, task.id, disableTaskNameEditing]);
3202
- const handleNameClick = useCallback4((e) => {
3203
- if (disableTaskNameEditing) return;
3204
- e.stopPropagation();
3205
- onRowClick?.(task.id);
3206
- onScrollToTask?.(task.id);
3207
- }, [task.id, disableTaskNameEditing, onRowClick, onScrollToTask]);
3208
- const handleNameDoubleClick = useCallback4((e) => {
3209
- if (disableTaskNameEditing) return;
3210
- e.stopPropagation();
3211
- nameConfirmedRef.current = false;
3212
- editTriggerRef.current = "doubleclick";
3213
- setNameValue(task.name);
3214
- setEditingName(true);
3215
- }, [task.name, disableTaskNameEditing]);
3216
- const handleRowKeyDown = useCallback4((e) => {
3217
- if (editingProgress) return;
3218
- if (!editingName && !disableTaskNameEditing && e.key === "F2") {
3219
- e.preventDefault();
3338
+ const handleNameClick = useCallback4(
3339
+ (e) => {
3340
+ if (disableTaskNameEditing) return;
3341
+ e.stopPropagation();
3342
+ onRowClick?.(task.id);
3343
+ onScrollToTask?.(task.id);
3344
+ },
3345
+ [task.id, disableTaskNameEditing, onRowClick, onScrollToTask]
3346
+ );
3347
+ const handleNameDoubleClick = useCallback4(
3348
+ (e) => {
3349
+ if (disableTaskNameEditing) return;
3350
+ e.stopPropagation();
3220
3351
  nameConfirmedRef.current = false;
3221
- editTriggerRef.current = "keypress";
3352
+ editTriggerRef.current = "doubleclick";
3222
3353
  setNameValue(task.name);
3223
3354
  setEditingName(true);
3224
- return;
3225
- }
3226
- }, [editingName, disableTaskNameEditing, task.name]);
3355
+ },
3356
+ [task.name, disableTaskNameEditing]
3357
+ );
3358
+ const handleRowKeyDown = useCallback4(
3359
+ (e) => {
3360
+ if (editingProgress) return;
3361
+ if (!editingName && !disableTaskNameEditing && e.key === "F2") {
3362
+ e.preventDefault();
3363
+ nameConfirmedRef.current = false;
3364
+ editTriggerRef.current = "keypress";
3365
+ setNameValue(task.name);
3366
+ setEditingName(true);
3367
+ return;
3368
+ }
3369
+ },
3370
+ [editingName, disableTaskNameEditing, task.name]
3371
+ );
3227
3372
  const handleNameSave = useCallback4(() => {
3228
3373
  if (nameConfirmedRef.current) {
3229
3374
  nameConfirmedRef.current = false;
@@ -3237,24 +3382,32 @@ var TaskListRow = React9.memo(
3237
3382
  const handleNameCancel = useCallback4(() => {
3238
3383
  setEditingName(false);
3239
3384
  }, []);
3240
- const handleNameKeyDown = useCallback4((e) => {
3241
- if (e.key === "Enter") {
3242
- nameConfirmedRef.current = true;
3243
- if (nameValue.trim()) {
3244
- onTasksChange?.([{ ...task, name: nameValue.trim() }]);
3385
+ const handleNameKeyDown = useCallback4(
3386
+ (e) => {
3387
+ if (e.key === "Enter") {
3388
+ nameConfirmedRef.current = true;
3389
+ if (nameValue.trim()) {
3390
+ onTasksChange?.([{ ...task, name: nameValue.trim() }]);
3391
+ }
3392
+ setEditingName(false);
3393
+ } else if (e.key === "Escape") {
3394
+ handleNameCancel();
3245
3395
  }
3246
- setEditingName(false);
3247
- } else if (e.key === "Escape") {
3248
- handleNameCancel();
3249
- }
3250
- }, [nameValue, task, onTasksChange, handleNameCancel]);
3251
- const handleDurationClick = useCallback4((e) => {
3252
- if (task.locked) return;
3253
- e.stopPropagation();
3254
- durationConfirmedRef.current = false;
3255
- setDurationValue(getInclusiveDurationDays(task.startDate, task.endDate));
3256
- setEditingDuration(true);
3257
- }, [task.locked, task.startDate, task.endDate]);
3396
+ },
3397
+ [nameValue, task, onTasksChange, handleNameCancel]
3398
+ );
3399
+ const handleDurationClick = useCallback4(
3400
+ (e) => {
3401
+ if (task.locked) return;
3402
+ e.stopPropagation();
3403
+ durationConfirmedRef.current = false;
3404
+ setDurationValue(
3405
+ getInclusiveDurationDays(task.startDate, task.endDate)
3406
+ );
3407
+ setEditingDuration(true);
3408
+ },
3409
+ [task.locked, task.startDate, task.endDate]
3410
+ );
3258
3411
  const applyDurationChange = useCallback4((nextDuration) => {
3259
3412
  const normalizedDuration = Math.max(1, Math.round(nextDuration) || 1);
3260
3413
  setDurationValue(normalizedDuration);
@@ -3265,34 +3418,59 @@ var TaskListRow = React9.memo(
3265
3418
  return;
3266
3419
  }
3267
3420
  const normalizedDuration = Math.max(1, Math.round(durationValue) || 1);
3268
- onTasksChange?.([{ ...task, endDate: getEndDateFromDuration(task.startDate, normalizedDuration) }]);
3421
+ onTasksChange?.([
3422
+ {
3423
+ ...task,
3424
+ endDate: getEndDateFromDuration(task.startDate, normalizedDuration)
3425
+ }
3426
+ ]);
3269
3427
  setEditingDuration(false);
3270
3428
  }, [durationValue, task, onTasksChange]);
3271
3429
  const handleDurationCancel = useCallback4(() => {
3272
3430
  setDurationValue(getInclusiveDurationDays(task.startDate, task.endDate));
3273
3431
  setEditingDuration(false);
3274
3432
  }, [task.startDate, task.endDate]);
3275
- const handleDurationAdjust = useCallback4((delta) => {
3276
- applyDurationChange(durationValue + delta);
3277
- }, [applyDurationChange, durationValue]);
3278
- const handleDurationKeyDown = useCallback4((e) => {
3279
- e.stopPropagation();
3280
- if (e.key === "Enter") {
3281
- durationConfirmedRef.current = true;
3282
- const normalizedDuration = Math.max(1, Math.round(durationValue) || 1);
3283
- onTasksChange?.([{ ...task, endDate: getEndDateFromDuration(task.startDate, normalizedDuration) }]);
3284
- setEditingDuration(false);
3285
- } else if (e.key === "Escape") {
3286
- handleDurationCancel();
3287
- }
3288
- }, [durationValue, task, onTasksChange, handleDurationCancel]);
3289
- const handleProgressClick = useCallback4((e) => {
3290
- if (task.locked) return;
3291
- e.stopPropagation();
3292
- progressConfirmedRef.current = false;
3293
- setProgressValue(task.progress ?? 0);
3294
- setEditingProgress(true);
3295
- }, [task.progress, task.locked]);
3433
+ const handleDurationAdjust = useCallback4(
3434
+ (delta) => {
3435
+ applyDurationChange(durationValue + delta);
3436
+ },
3437
+ [applyDurationChange, durationValue]
3438
+ );
3439
+ const handleDurationKeyDown = useCallback4(
3440
+ (e) => {
3441
+ e.stopPropagation();
3442
+ if (e.key === "Enter") {
3443
+ durationConfirmedRef.current = true;
3444
+ const normalizedDuration = Math.max(
3445
+ 1,
3446
+ Math.round(durationValue) || 1
3447
+ );
3448
+ onTasksChange?.([
3449
+ {
3450
+ ...task,
3451
+ endDate: getEndDateFromDuration(
3452
+ task.startDate,
3453
+ normalizedDuration
3454
+ )
3455
+ }
3456
+ ]);
3457
+ setEditingDuration(false);
3458
+ } else if (e.key === "Escape") {
3459
+ handleDurationCancel();
3460
+ }
3461
+ },
3462
+ [durationValue, task, onTasksChange, handleDurationCancel]
3463
+ );
3464
+ const handleProgressClick = useCallback4(
3465
+ (e) => {
3466
+ if (task.locked) return;
3467
+ e.stopPropagation();
3468
+ progressConfirmedRef.current = false;
3469
+ setProgressValue(task.progress ?? 0);
3470
+ setEditingProgress(true);
3471
+ },
3472
+ [task.progress, task.locked]
3473
+ );
3296
3474
  const handleProgressSave = useCallback4(() => {
3297
3475
  if (progressConfirmedRef.current) {
3298
3476
  progressConfirmedRef.current = false;
@@ -3315,28 +3493,36 @@ var TaskListRow = React9.memo(
3315
3493
  setEditingProgress(false);
3316
3494
  }, []);
3317
3495
  const handleProgressAdjust = useCallback4((delta) => {
3318
- setProgressValue((current) => Math.max(0, Math.min(100, current + delta)));
3496
+ setProgressValue(
3497
+ (current) => Math.max(0, Math.min(100, current + delta))
3498
+ );
3319
3499
  }, []);
3320
- const handleProgressKeyDown = useCallback4((e) => {
3321
- e.stopPropagation();
3322
- if (e.key === "Enter") {
3323
- progressConfirmedRef.current = true;
3324
- const clampedValue = Math.max(0, Math.min(100, progressValue));
3325
- if ((clampedValue === 100 || clampedValue === 0) && isTaskParent(task.id, allTasks)) {
3326
- const children = getChildren(task.id, allTasks);
3327
- const updatedTasks = [
3328
- { ...task, progress: clampedValue },
3329
- ...children.map((child) => ({ ...child, progress: clampedValue }))
3330
- ];
3331
- onTasksChange?.(updatedTasks);
3332
- } else {
3333
- onTasksChange?.([{ ...task, progress: clampedValue }]);
3500
+ const handleProgressKeyDown = useCallback4(
3501
+ (e) => {
3502
+ e.stopPropagation();
3503
+ if (e.key === "Enter") {
3504
+ progressConfirmedRef.current = true;
3505
+ const clampedValue = Math.max(0, Math.min(100, progressValue));
3506
+ if ((clampedValue === 100 || clampedValue === 0) && isTaskParent(task.id, allTasks)) {
3507
+ const children = getChildren(task.id, allTasks);
3508
+ const updatedTasks = [
3509
+ { ...task, progress: clampedValue },
3510
+ ...children.map((child) => ({
3511
+ ...child,
3512
+ progress: clampedValue
3513
+ }))
3514
+ ];
3515
+ onTasksChange?.(updatedTasks);
3516
+ } else {
3517
+ onTasksChange?.([{ ...task, progress: clampedValue }]);
3518
+ }
3519
+ setEditingProgress(false);
3520
+ } else if (e.key === "Escape") {
3521
+ handleProgressCancel();
3334
3522
  }
3335
- setEditingProgress(false);
3336
- } else if (e.key === "Escape") {
3337
- handleProgressCancel();
3338
- }
3339
- }, [progressValue, task, onTasksChange, handleProgressCancel, allTasks]);
3523
+ },
3524
+ [progressValue, task, onTasksChange, handleProgressCancel, allTasks]
3525
+ );
3340
3526
  useEffect4(() => {
3341
3527
  if (editingProgress && progressInputRef.current) {
3342
3528
  progressInputRef.current.focus();
@@ -3352,77 +3538,111 @@ var TaskListRow = React9.memo(
3352
3538
  durationInputRef.current.select();
3353
3539
  }
3354
3540
  }, [editingDuration]);
3355
- const handleStartDateChange = useCallback4((newDateISO) => {
3356
- if (!newDateISO) return;
3357
- const origStart = parseUTCDate(task.startDate);
3358
- const origEnd = parseUTCDate(task.endDate);
3359
- const durationMs = origEnd.getTime() - origStart.getTime();
3360
- const newStart = /* @__PURE__ */ new Date(newDateISO + "T00:00:00Z");
3361
- const newEnd = new Date(newStart.getTime() + durationMs);
3362
- const { startDate: normalizedStart, endDate: normalizedEnd } = normalizeTaskDates(
3363
- newDateISO,
3364
- newEnd.toISOString().split("T")[0]
3365
- );
3366
- onTasksChange?.([{ ...task, startDate: normalizedStart, endDate: normalizedEnd }]);
3367
- }, [task, onTasksChange]);
3368
- const handleEndDateChange = useCallback4((newDateISO) => {
3369
- if (!newDateISO) return;
3370
- const origStart = parseUTCDate(task.startDate);
3371
- const origEnd = parseUTCDate(task.endDate);
3372
- const durationMs = origEnd.getTime() - origStart.getTime();
3373
- const newEnd = /* @__PURE__ */ new Date(newDateISO + "T00:00:00Z");
3374
- const newStart = new Date(newEnd.getTime() - durationMs);
3375
- const { startDate: normalizedStart, endDate: normalizedEnd } = normalizeTaskDates(
3376
- newStart.toISOString().split("T")[0],
3377
- newDateISO
3378
- );
3379
- onTasksChange?.([{ ...task, startDate: normalizedStart, endDate: normalizedEnd }]);
3380
- }, [task, onTasksChange]);
3541
+ const handleStartDateChange = useCallback4(
3542
+ (newDateISO) => {
3543
+ if (!newDateISO) return;
3544
+ const origStart = parseUTCDate(task.startDate);
3545
+ const origEnd = parseUTCDate(task.endDate);
3546
+ const durationMs = origEnd.getTime() - origStart.getTime();
3547
+ const newStart = /* @__PURE__ */ new Date(newDateISO + "T00:00:00Z");
3548
+ const newEnd = new Date(newStart.getTime() + durationMs);
3549
+ const { startDate: normalizedStart, endDate: normalizedEnd } = normalizeTaskDates(newDateISO, newEnd.toISOString().split("T")[0]);
3550
+ onTasksChange?.([
3551
+ { ...task, startDate: normalizedStart, endDate: normalizedEnd }
3552
+ ]);
3553
+ },
3554
+ [task, onTasksChange]
3555
+ );
3556
+ const handleEndDateChange = useCallback4(
3557
+ (newDateISO) => {
3558
+ if (!newDateISO) return;
3559
+ const origStart = parseUTCDate(task.startDate);
3560
+ const origEnd = parseUTCDate(task.endDate);
3561
+ const durationMs = origEnd.getTime() - origStart.getTime();
3562
+ const newEnd = /* @__PURE__ */ new Date(newDateISO + "T00:00:00Z");
3563
+ const newStart = new Date(newEnd.getTime() - durationMs);
3564
+ const { startDate: normalizedStart, endDate: normalizedEnd } = normalizeTaskDates(newStart.toISOString().split("T")[0], newDateISO);
3565
+ onTasksChange?.([
3566
+ { ...task, startDate: normalizedStart, endDate: normalizedEnd }
3567
+ ]);
3568
+ },
3569
+ [task, onTasksChange]
3570
+ );
3381
3571
  const handleRowClickInternal = useCallback4(() => {
3382
3572
  onRowClick?.(task.id);
3383
3573
  }, [task.id, onRowClick]);
3384
- const handleNumberClick = useCallback4((e) => {
3385
- e.stopPropagation();
3386
- onRowClick?.(task.id);
3387
- }, [task.id, onRowClick]);
3388
- const handleToggleCollapse = useCallback4((e) => {
3389
- e.stopPropagation();
3390
- onToggleCollapse?.(task.id);
3391
- }, [task.id, onToggleCollapse]);
3392
- const handlePromote = useCallback4((e) => {
3393
- e.stopPropagation();
3394
- onPromoteTask?.(task.id);
3395
- }, [task.id, onPromoteTask]);
3396
- const handleDemote = useCallback4((e) => {
3397
- e.stopPropagation();
3398
- const currentIndex = allTasks.findIndex((t) => t.id === task.id);
3399
- if (currentIndex > 0) {
3400
- const previousTask = allTasks[currentIndex - 1];
3401
- const targetParentId = previousTask.parentId || previousTask.id;
3402
- onDemoteTask?.(task.id, targetParentId);
3403
- }
3404
- }, [task.id, allTasks, onDemoteTask]);
3405
- const handleAddClick = useCallback4((e) => {
3406
- e.stopPropagation();
3407
- onSetSelectingPredecessorFor?.(task.id);
3408
- }, [task.id, onSetSelectingPredecessorFor]);
3409
- const handlePredecessorPick = useCallback4((e) => {
3410
- e.stopPropagation();
3411
- if (!isPicking || isSourceRow) return;
3412
- if (!selectingPredecessorFor || !activeLinkType) return;
3413
- onAddDependency?.(task.id, selectingPredecessorFor, activeLinkType);
3414
- }, [isPicking, isSourceRow, selectingPredecessorFor, task.id, activeLinkType, onAddDependency]);
3415
- const handleCancelPicking = useCallback4((e) => {
3416
- e.stopPropagation();
3417
- onSetSelectingPredecessorFor?.(null);
3418
- }, [onSetSelectingPredecessorFor]);
3574
+ const handleNumberClick = useCallback4(
3575
+ (e) => {
3576
+ e.stopPropagation();
3577
+ onRowClick?.(task.id);
3578
+ },
3579
+ [task.id, onRowClick]
3580
+ );
3581
+ const handleToggleCollapse = useCallback4(
3582
+ (e) => {
3583
+ e.stopPropagation();
3584
+ onToggleCollapse?.(task.id);
3585
+ },
3586
+ [task.id, onToggleCollapse]
3587
+ );
3588
+ const handlePromote = useCallback4(
3589
+ (e) => {
3590
+ e.stopPropagation();
3591
+ onPromoteTask?.(task.id);
3592
+ },
3593
+ [task.id, onPromoteTask]
3594
+ );
3595
+ const handleDemote = useCallback4(
3596
+ (e) => {
3597
+ e.stopPropagation();
3598
+ onDemoteTask?.(task.id, "");
3599
+ },
3600
+ [task.id, onDemoteTask]
3601
+ );
3602
+ const handleAddClick = useCallback4(
3603
+ (e) => {
3604
+ e.stopPropagation();
3605
+ onSetSelectingPredecessorFor?.(task.id);
3606
+ },
3607
+ [task.id, onSetSelectingPredecessorFor]
3608
+ );
3609
+ const handlePredecessorPick = useCallback4(
3610
+ (e) => {
3611
+ e.stopPropagation();
3612
+ if (!isPicking || isSourceRow) return;
3613
+ if (!selectingPredecessorFor || !activeLinkType) return;
3614
+ onAddDependency?.(task.id, selectingPredecessorFor, activeLinkType);
3615
+ },
3616
+ [
3617
+ isPicking,
3618
+ isSourceRow,
3619
+ selectingPredecessorFor,
3620
+ task.id,
3621
+ activeLinkType,
3622
+ onAddDependency
3623
+ ]
3624
+ );
3625
+ const handleCancelPicking = useCallback4(
3626
+ (e) => {
3627
+ e.stopPropagation();
3628
+ onSetSelectingPredecessorFor?.(null);
3629
+ },
3630
+ [onSetSelectingPredecessorFor]
3631
+ );
3419
3632
  const isSelectedPredecessor = selectedChip != null && selectedChip.predecessorId === task.id;
3420
- const handleDeleteSelected = useCallback4((e) => {
3421
- e.stopPropagation();
3422
- if (!selectedChip) return;
3423
- onRemoveDependency?.(selectedChip.successorId, selectedChip.predecessorId, selectedChip.linkType);
3424
- onChipSelect?.(null);
3425
- }, [selectedChip, onRemoveDependency, onChipSelect]);
3633
+ const handleDeleteSelected = useCallback4(
3634
+ (e) => {
3635
+ e.stopPropagation();
3636
+ if (!selectedChip) return;
3637
+ onRemoveDependency?.(
3638
+ selectedChip.successorId,
3639
+ selectedChip.predecessorId,
3640
+ selectedChip.linkType
3641
+ );
3642
+ onChipSelect?.(null);
3643
+ },
3644
+ [selectedChip, onRemoveDependency, onChipSelect]
3645
+ );
3426
3646
  const startDateISO = toISODate(task.startDate);
3427
3647
  const endDateISO = editingDuration ? getEndDateFromDuration(task.startDate, durationValue) : toISODate(task.endDate);
3428
3648
  return /* @__PURE__ */ jsxs9(
@@ -3475,13 +3695,78 @@ var TaskListRow = React9.memo(
3475
3695
  }
3476
3696
  ),
3477
3697
  /* @__PURE__ */ jsxs9("div", { className: "gantt-tl-cell gantt-tl-cell-name", children: [
3478
- isChild && !editingName && /* @__PURE__ */ jsx12(HierarchyConnectorIcon, { isLastChild }),
3698
+ isChild && !editingName && /* @__PURE__ */ jsxs9(Fragment2, { children: [
3699
+ ancestorContinues.map(
3700
+ (continues, idx) => continues ? /* @__PURE__ */ jsx12(
3701
+ "span",
3702
+ {
3703
+ style: {
3704
+ position: "absolute",
3705
+ left: `${idx * 20 + 9}px`,
3706
+ top: 0,
3707
+ height: `${rowHeight}px`,
3708
+ width: "1.5px",
3709
+ background: "#d4bceb",
3710
+ borderRadius: "1px",
3711
+ pointerEvents: "none"
3712
+ }
3713
+ },
3714
+ idx
3715
+ ) : null
3716
+ ),
3717
+ /* @__PURE__ */ jsx12(
3718
+ "span",
3719
+ {
3720
+ style: {
3721
+ position: "absolute",
3722
+ left: `${(nestingDepth - 1) * 20 + 9}px`,
3723
+ top: 0,
3724
+ height: isLastChild ? `${rowHeight / 2}px` : `${rowHeight}px`,
3725
+ width: "1.5px",
3726
+ background: "#d4bceb",
3727
+ borderRadius: "1px",
3728
+ pointerEvents: "none"
3729
+ }
3730
+ }
3731
+ ),
3732
+ /* @__PURE__ */ jsx12(
3733
+ "span",
3734
+ {
3735
+ style: {
3736
+ position: "absolute",
3737
+ left: `${(nestingDepth - 1) * 20 + 9}px`,
3738
+ top: `${rowHeight / 2 - 0.75}px`,
3739
+ width: "8px",
3740
+ height: "1.5px",
3741
+ background: "#d4bceb",
3742
+ borderRadius: "1px",
3743
+ pointerEvents: "none"
3744
+ }
3745
+ }
3746
+ ),
3747
+ /* @__PURE__ */ jsx12(
3748
+ "span",
3749
+ {
3750
+ style: {
3751
+ position: "absolute",
3752
+ left: `${(nestingDepth - 1) * 20 + 15}px`,
3753
+ top: `${rowHeight / 2 - 2}px`,
3754
+ width: "4px",
3755
+ height: "4px",
3756
+ borderRadius: "50%",
3757
+ background: "#d4bceb",
3758
+ pointerEvents: "none"
3759
+ }
3760
+ }
3761
+ )
3762
+ ] }),
3479
3763
  isParent && !editingName && /* @__PURE__ */ jsx12(
3480
3764
  "button",
3481
3765
  {
3482
3766
  type: "button",
3483
3767
  className: `gantt-tl-collapse-btn ${isCollapsed ? "gantt-tl-collapse-btn-collapsed" : ""}`,
3484
3768
  onClick: handleToggleCollapse,
3769
+ style: { left: `${nestingDepth * 20 + 4}px` },
3485
3770
  "aria-label": isCollapsed ? "Expand children" : "Collapse children",
3486
3771
  children: /* @__PURE__ */ jsx12(ChevronRightIcon, {})
3487
3772
  }
@@ -3495,7 +3780,10 @@ var TaskListRow = React9.memo(
3495
3780
  onChange: (e) => setNameValue(e.target.value),
3496
3781
  onBlur: handleNameSave,
3497
3782
  onKeyDown: handleNameKeyDown,
3498
- className: ["gantt-tl-name-input", isChild ? "gantt-tl-name-input-child" : ""].filter(Boolean).join(" "),
3783
+ className: "gantt-tl-name-input",
3784
+ style: {
3785
+ paddingLeft: nestingDepth > 0 ? `${nestingDepth * 20 + 24}px` : void 0
3786
+ },
3499
3787
  onClick: (e) => e.stopPropagation()
3500
3788
  }
3501
3789
  ),
@@ -3505,14 +3793,15 @@ var TaskListRow = React9.memo(
3505
3793
  type: "button",
3506
3794
  className: [
3507
3795
  "gantt-tl-name-trigger",
3508
- disableTaskNameEditing ? "gantt-tl-name-locked" : "",
3509
- isParent ? "gantt-tl-name-trigger-parent" : "",
3510
- isChild ? "gantt-tl-name-trigger-child" : ""
3796
+ disableTaskNameEditing ? "gantt-tl-name-locked" : ""
3511
3797
  ].filter(Boolean).join(" "),
3512
3798
  title: task.name,
3513
3799
  onClick: handleNameClick,
3514
3800
  onDoubleClick: handleNameDoubleClick,
3515
- style: editingName ? { visibility: "hidden", pointerEvents: "none" } : void 0,
3801
+ style: {
3802
+ paddingLeft: nestingDepth > 0 ? `${nestingDepth * 20 + (isParent ? 26 : 8)}px` : isParent ? "26px" : void 0,
3803
+ ...editingName ? { visibility: "hidden", pointerEvents: "none" } : void 0
3804
+ },
3516
3805
  children: task.name
3517
3806
  }
3518
3807
  ),
@@ -3525,16 +3814,20 @@ var TaskListRow = React9.memo(
3525
3814
  onClick: (e) => {
3526
3815
  e.stopPropagation();
3527
3816
  const now = /* @__PURE__ */ new Date();
3528
- const todayISO = new Date(Date.UTC(
3529
- now.getUTCFullYear(),
3530
- now.getUTCMonth(),
3531
- now.getUTCDate()
3532
- )).toISOString().split("T")[0];
3533
- const endISO = new Date(Date.UTC(
3534
- now.getUTCFullYear(),
3535
- now.getUTCMonth(),
3536
- now.getUTCDate() + 7
3537
- )).toISOString().split("T")[0];
3817
+ const todayISO = new Date(
3818
+ Date.UTC(
3819
+ now.getUTCFullYear(),
3820
+ now.getUTCMonth(),
3821
+ now.getUTCDate()
3822
+ )
3823
+ ).toISOString().split("T")[0];
3824
+ const endISO = new Date(
3825
+ Date.UTC(
3826
+ now.getUTCFullYear(),
3827
+ now.getUTCMonth(),
3828
+ now.getUTCDate() + 7
3829
+ )
3830
+ ).toISOString().split("T")[0];
3538
3831
  const newTask = {
3539
3832
  id: crypto.randomUUID(),
3540
3833
  name: "\u041D\u043E\u0432\u0430\u044F \u0437\u0430\u0434\u0430\u0447\u0430",
@@ -3570,7 +3863,6 @@ var TaskListRow = React9.memo(
3570
3863
  HierarchyButton,
3571
3864
  {
3572
3865
  isChild,
3573
- isParent,
3574
3866
  rowIndex,
3575
3867
  onPromote: onPromoteTask ? handlePromote : void 0,
3576
3868
  onDemote: onDemoteTask ? handleDemote : void 0
@@ -3578,113 +3870,228 @@ var TaskListRow = React9.memo(
3578
3870
  )
3579
3871
  ] })
3580
3872
  ] }),
3581
- /* @__PURE__ */ jsx12("div", { className: "gantt-tl-cell gantt-tl-cell-date", onClick: (e) => e.stopPropagation(), children: /* @__PURE__ */ jsx12(
3582
- DatePicker,
3873
+ /* @__PURE__ */ jsx12(
3874
+ "div",
3583
3875
  {
3584
- value: startDateISO,
3585
- onChange: handleStartDateChange,
3586
- format: "dd.MM.yy",
3587
- portal: true,
3588
- disabled: task.locked
3876
+ className: "gantt-tl-cell gantt-tl-cell-date",
3877
+ onClick: (e) => e.stopPropagation(),
3878
+ children: /* @__PURE__ */ jsx12(
3879
+ DatePicker,
3880
+ {
3881
+ value: startDateISO,
3882
+ onChange: handleStartDateChange,
3883
+ format: "dd.MM.yy",
3884
+ portal: true,
3885
+ disabled: task.locked
3886
+ }
3887
+ )
3589
3888
  }
3590
- ) }),
3591
- /* @__PURE__ */ jsx12("div", { className: "gantt-tl-cell gantt-tl-cell-date", onClick: (e) => e.stopPropagation(), children: /* @__PURE__ */ jsx12(
3592
- DatePicker,
3889
+ ),
3890
+ /* @__PURE__ */ jsx12(
3891
+ "div",
3593
3892
  {
3594
- value: endDateISO,
3595
- onChange: handleEndDateChange,
3596
- format: "dd.MM.yy",
3597
- portal: true,
3598
- disabled: task.locked
3599
- }
3600
- ) }),
3601
- /* @__PURE__ */ jsxs9("div", { className: "gantt-tl-cell gantt-tl-cell-duration", onClick: handleDurationClick, children: [
3602
- editingDuration && /* @__PURE__ */ jsxs9("div", { className: "gantt-tl-number-editor", onClick: (e) => e.stopPropagation(), children: [
3603
- /* @__PURE__ */ jsx12(
3604
- Input,
3893
+ className: "gantt-tl-cell gantt-tl-cell-date",
3894
+ onClick: (e) => e.stopPropagation(),
3895
+ children: /* @__PURE__ */ jsx12(
3896
+ DatePicker,
3605
3897
  {
3606
- ref: durationInputRef,
3607
- type: "number",
3608
- min: 1,
3609
- step: 1,
3610
- value: durationValue,
3611
- onChange: (e) => applyDurationChange(parseInt(e.target.value, 10) || 1),
3612
- onBlur: handleDurationSave,
3613
- onKeyDown: handleDurationKeyDown,
3614
- className: "gantt-tl-number-input"
3898
+ value: endDateISO,
3899
+ onChange: handleEndDateChange,
3900
+ format: "dd.MM.yy",
3901
+ portal: true,
3902
+ disabled: task.locked
3615
3903
  }
3616
- ),
3617
- /* @__PURE__ */ jsxs9("div", { className: "gantt-tl-number-steppers", "aria-hidden": "true", children: [
3618
- /* @__PURE__ */ jsx12(
3619
- "button",
3904
+ )
3905
+ }
3906
+ ),
3907
+ /* @__PURE__ */ jsxs9(
3908
+ "div",
3909
+ {
3910
+ className: "gantt-tl-cell gantt-tl-cell-duration",
3911
+ onClick: handleDurationClick,
3912
+ children: [
3913
+ editingDuration && /* @__PURE__ */ jsxs9(
3914
+ "div",
3620
3915
  {
3621
- type: "button",
3622
- className: "gantt-tl-number-stepper",
3623
- tabIndex: -1,
3624
- onMouseDown: (e) => e.preventDefault(),
3625
- onClick: () => handleDurationAdjust(1),
3626
- children: /* @__PURE__ */ jsx12("svg", { xmlns: "http://www.w3.org/2000/svg", width: "10", height: "10", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx12("path", { d: "m18 15-6-6-6 6" }) })
3916
+ className: "gantt-tl-number-editor",
3917
+ onClick: (e) => e.stopPropagation(),
3918
+ children: [
3919
+ /* @__PURE__ */ jsx12(
3920
+ Input,
3921
+ {
3922
+ ref: durationInputRef,
3923
+ type: "number",
3924
+ min: 1,
3925
+ step: 1,
3926
+ value: durationValue,
3927
+ onChange: (e) => applyDurationChange(parseInt(e.target.value, 10) || 1),
3928
+ onBlur: handleDurationSave,
3929
+ onKeyDown: handleDurationKeyDown,
3930
+ className: "gantt-tl-number-input"
3931
+ }
3932
+ ),
3933
+ /* @__PURE__ */ jsxs9("div", { className: "gantt-tl-number-steppers", "aria-hidden": "true", children: [
3934
+ /* @__PURE__ */ jsx12(
3935
+ "button",
3936
+ {
3937
+ type: "button",
3938
+ className: "gantt-tl-number-stepper",
3939
+ tabIndex: -1,
3940
+ onMouseDown: (e) => e.preventDefault(),
3941
+ onClick: () => handleDurationAdjust(1),
3942
+ children: /* @__PURE__ */ jsx12(
3943
+ "svg",
3944
+ {
3945
+ xmlns: "http://www.w3.org/2000/svg",
3946
+ width: "10",
3947
+ height: "10",
3948
+ viewBox: "0 0 24 24",
3949
+ fill: "none",
3950
+ stroke: "currentColor",
3951
+ strokeWidth: "2",
3952
+ strokeLinecap: "round",
3953
+ strokeLinejoin: "round",
3954
+ children: /* @__PURE__ */ jsx12("path", { d: "m18 15-6-6-6 6" })
3955
+ }
3956
+ )
3957
+ }
3958
+ ),
3959
+ /* @__PURE__ */ jsx12(
3960
+ "button",
3961
+ {
3962
+ type: "button",
3963
+ className: "gantt-tl-number-stepper",
3964
+ tabIndex: -1,
3965
+ onMouseDown: (e) => e.preventDefault(),
3966
+ onClick: () => handleDurationAdjust(-1),
3967
+ children: /* @__PURE__ */ jsx12(
3968
+ "svg",
3969
+ {
3970
+ xmlns: "http://www.w3.org/2000/svg",
3971
+ width: "10",
3972
+ height: "10",
3973
+ viewBox: "0 0 24 24",
3974
+ fill: "none",
3975
+ stroke: "currentColor",
3976
+ strokeWidth: "2",
3977
+ strokeLinecap: "round",
3978
+ strokeLinejoin: "round",
3979
+ children: /* @__PURE__ */ jsx12("path", { d: "m6 9 6 6 6-6" })
3980
+ }
3981
+ )
3982
+ }
3983
+ )
3984
+ ] })
3985
+ ]
3627
3986
  }
3628
3987
  ),
3629
3988
  /* @__PURE__ */ jsx12(
3630
- "button",
3989
+ "span",
3631
3990
  {
3632
- type: "button",
3633
- className: "gantt-tl-number-stepper",
3634
- tabIndex: -1,
3635
- onMouseDown: (e) => e.preventDefault(),
3636
- onClick: () => handleDurationAdjust(-1),
3637
- children: /* @__PURE__ */ jsx12("svg", { xmlns: "http://www.w3.org/2000/svg", width: "10", height: "10", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx12("path", { d: "m6 9 6 6 6-6" }) })
3991
+ style: editingDuration ? { visibility: "hidden", pointerEvents: "none" } : void 0,
3992
+ children: getInclusiveDurationDays(task.startDate, task.endDate)
3638
3993
  }
3639
3994
  )
3640
- ] })
3641
- ] }),
3642
- /* @__PURE__ */ jsx12("span", { style: editingDuration ? { visibility: "hidden", pointerEvents: "none" } : void 0, children: getInclusiveDurationDays(task.startDate, task.endDate) })
3643
- ] }),
3644
- /* @__PURE__ */ jsxs9("div", { className: "gantt-tl-cell gantt-tl-cell-progress", onClick: handleProgressClick, children: [
3645
- editingProgress && /* @__PURE__ */ jsxs9("div", { className: "gantt-tl-number-editor", onClick: (e) => e.stopPropagation(), children: [
3646
- /* @__PURE__ */ jsx12(
3647
- Input,
3648
- {
3649
- ref: progressInputRef,
3650
- type: "number",
3651
- min: 0,
3652
- max: 100,
3653
- step: 1,
3654
- value: progressValue,
3655
- onChange: (e) => setProgressValue(parseInt(e.target.value, 10) || 0),
3656
- onBlur: handleProgressSave,
3657
- onKeyDown: handleProgressKeyDown,
3658
- className: "gantt-tl-number-input"
3659
- }
3660
- ),
3661
- /* @__PURE__ */ jsxs9("div", { className: "gantt-tl-number-steppers", "aria-hidden": "true", children: [
3662
- /* @__PURE__ */ jsx12(
3663
- "button",
3995
+ ]
3996
+ }
3997
+ ),
3998
+ /* @__PURE__ */ jsxs9(
3999
+ "div",
4000
+ {
4001
+ className: "gantt-tl-cell gantt-tl-cell-progress",
4002
+ onClick: handleProgressClick,
4003
+ children: [
4004
+ editingProgress && /* @__PURE__ */ jsxs9(
4005
+ "div",
3664
4006
  {
3665
- type: "button",
3666
- className: "gantt-tl-number-stepper",
3667
- tabIndex: -1,
3668
- onMouseDown: (e) => e.preventDefault(),
3669
- onClick: () => handleProgressAdjust(1),
3670
- children: /* @__PURE__ */ jsx12("svg", { xmlns: "http://www.w3.org/2000/svg", width: "10", height: "10", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx12("path", { d: "m18 15-6-6-6 6" }) })
4007
+ className: "gantt-tl-number-editor",
4008
+ onClick: (e) => e.stopPropagation(),
4009
+ children: [
4010
+ /* @__PURE__ */ jsx12(
4011
+ Input,
4012
+ {
4013
+ ref: progressInputRef,
4014
+ type: "number",
4015
+ min: 0,
4016
+ max: 100,
4017
+ step: 1,
4018
+ value: progressValue,
4019
+ onChange: (e) => setProgressValue(parseInt(e.target.value, 10) || 0),
4020
+ onBlur: handleProgressSave,
4021
+ onKeyDown: handleProgressKeyDown,
4022
+ className: "gantt-tl-number-input"
4023
+ }
4024
+ ),
4025
+ /* @__PURE__ */ jsxs9("div", { className: "gantt-tl-number-steppers", "aria-hidden": "true", children: [
4026
+ /* @__PURE__ */ jsx12(
4027
+ "button",
4028
+ {
4029
+ type: "button",
4030
+ className: "gantt-tl-number-stepper",
4031
+ tabIndex: -1,
4032
+ onMouseDown: (e) => e.preventDefault(),
4033
+ onClick: () => handleProgressAdjust(1),
4034
+ children: /* @__PURE__ */ jsx12(
4035
+ "svg",
4036
+ {
4037
+ xmlns: "http://www.w3.org/2000/svg",
4038
+ width: "10",
4039
+ height: "10",
4040
+ viewBox: "0 0 24 24",
4041
+ fill: "none",
4042
+ stroke: "currentColor",
4043
+ strokeWidth: "2",
4044
+ strokeLinecap: "round",
4045
+ strokeLinejoin: "round",
4046
+ children: /* @__PURE__ */ jsx12("path", { d: "m18 15-6-6-6 6" })
4047
+ }
4048
+ )
4049
+ }
4050
+ ),
4051
+ /* @__PURE__ */ jsx12(
4052
+ "button",
4053
+ {
4054
+ type: "button",
4055
+ className: "gantt-tl-number-stepper",
4056
+ tabIndex: -1,
4057
+ onMouseDown: (e) => e.preventDefault(),
4058
+ onClick: () => handleProgressAdjust(-1),
4059
+ children: /* @__PURE__ */ jsx12(
4060
+ "svg",
4061
+ {
4062
+ xmlns: "http://www.w3.org/2000/svg",
4063
+ width: "10",
4064
+ height: "10",
4065
+ viewBox: "0 0 24 24",
4066
+ fill: "none",
4067
+ stroke: "currentColor",
4068
+ strokeWidth: "2",
4069
+ strokeLinecap: "round",
4070
+ strokeLinejoin: "round",
4071
+ children: /* @__PURE__ */ jsx12("path", { d: "m6 9 6 6 6-6" })
4072
+ }
4073
+ )
4074
+ }
4075
+ )
4076
+ ] })
4077
+ ]
3671
4078
  }
3672
4079
  ),
3673
4080
  /* @__PURE__ */ jsx12(
3674
- "button",
4081
+ "span",
3675
4082
  {
3676
- type: "button",
3677
- className: "gantt-tl-number-stepper",
3678
- tabIndex: -1,
3679
- onMouseDown: (e) => e.preventDefault(),
3680
- onClick: () => handleProgressAdjust(-1),
3681
- children: /* @__PURE__ */ jsx12("svg", { xmlns: "http://www.w3.org/2000/svg", width: "10", height: "10", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx12("path", { d: "m6 9 6 6 6-6" }) })
4083
+ style: editingProgress ? { visibility: "hidden", pointerEvents: "none" } : task.progress === 100 ? {
4084
+ backgroundColor: "#17c864",
4085
+ borderRadius: "4px",
4086
+ padding: "2px 4px",
4087
+ color: "#ffffff"
4088
+ } : void 0,
4089
+ children: task.progress ? Math.round(task.progress) === 100 ? "100" : `${Math.round(task.progress)}%` : "0%"
3682
4090
  }
3683
4091
  )
3684
- ] })
3685
- ] }),
3686
- /* @__PURE__ */ jsx12("span", { style: editingProgress ? { visibility: "hidden", pointerEvents: "none" } : void 0, children: task.progress ? `${Math.round(task.progress)}%` : "0%" })
3687
- ] }),
4092
+ ]
4093
+ }
4094
+ ),
3688
4095
  /* @__PURE__ */ jsx12(
3689
4096
  "div",
3690
4097
  {
@@ -3725,26 +4132,33 @@ var TaskListRow = React9.memo(
3725
4132
  ]
3726
4133
  }
3727
4134
  ) }),
3728
- /* @__PURE__ */ jsx12(PopoverContent, { portal: true, align: "start", children: /* @__PURE__ */ jsx12("div", { className: "gantt-tl-dep-overflow-list", onClick: (e) => e.stopPropagation(), children: chips.map(({ dep, lag, predecessorName }) => /* @__PURE__ */ jsx12(
3729
- DepChip,
4135
+ /* @__PURE__ */ jsx12(PopoverContent, { portal: true, align: "start", children: /* @__PURE__ */ jsx12(
4136
+ "div",
3730
4137
  {
3731
- lag,
3732
- dep,
3733
- taskId: task.id,
3734
- predecessorName,
3735
- selectedChip,
3736
- disableDependencyEditing,
3737
- onChipSelect,
3738
- onRowClick,
3739
- onScrollToTask,
3740
- onRemoveDependency,
3741
- onChipSelectClear: () => onChipSelect?.(null),
3742
- task,
3743
- allTasks,
3744
- onTasksChange
3745
- },
3746
- `${dep.taskId}-${dep.type}`
3747
- )) }) })
4138
+ className: "gantt-tl-dep-overflow-list",
4139
+ onClick: (e) => e.stopPropagation(),
4140
+ children: chips.map(({ dep, lag, predecessorName }) => /* @__PURE__ */ jsx12(
4141
+ DepChip,
4142
+ {
4143
+ lag,
4144
+ dep,
4145
+ taskId: task.id,
4146
+ predecessorName,
4147
+ selectedChip,
4148
+ disableDependencyEditing,
4149
+ onChipSelect,
4150
+ onRowClick,
4151
+ onScrollToTask,
4152
+ onRemoveDependency,
4153
+ onChipSelectClear: () => onChipSelect?.(null),
4154
+ task,
4155
+ allTasks,
4156
+ onTasksChange
4157
+ },
4158
+ `${dep.taskId}-${dep.type}`
4159
+ ))
4160
+ }
4161
+ ) })
3748
4162
  ] })
3749
4163
  ) : chips.length === 1 ? (
3750
4164
  /* Single chip — unified DepChip */
@@ -3943,6 +4357,25 @@ var TaskList = ({
3943
4357
  () => visibleTasks.length * rowHeight,
3944
4358
  [visibleTasks.length, rowHeight]
3945
4359
  );
4360
+ const nestingDepthMap = useMemo8(() => {
4361
+ const depthMap = /* @__PURE__ */ new Map();
4362
+ const taskById = new Map(tasks.map((t) => [t.id, t]));
4363
+ function getDepth(taskId) {
4364
+ if (depthMap.has(taskId)) return depthMap.get(taskId);
4365
+ const task = taskById.get(taskId);
4366
+ if (!task || !task.parentId || !taskById.has(task.parentId)) {
4367
+ depthMap.set(taskId, 0);
4368
+ return 0;
4369
+ }
4370
+ const depth = getDepth(task.parentId) + 1;
4371
+ depthMap.set(taskId, depth);
4372
+ return depth;
4373
+ }
4374
+ for (const task of tasks) {
4375
+ getDepth(task.id);
4376
+ }
4377
+ return depthMap;
4378
+ }, [tasks]);
3946
4379
  const lastChildIds = useMemo8(() => {
3947
4380
  const last = /* @__PURE__ */ new Set();
3948
4381
  const seenParents = /* @__PURE__ */ new Set();
@@ -3955,6 +4388,20 @@ var TaskList = ({
3955
4388
  }
3956
4389
  return last;
3957
4390
  }, [visibleTasks]);
4391
+ const ancestorContinuesMap = useMemo8(() => {
4392
+ const taskById = new Map(tasks.map((t) => [t.id, t]));
4393
+ const map = /* @__PURE__ */ new Map();
4394
+ for (const task of visibleTasks) {
4395
+ const continues = [];
4396
+ let current = taskById.get(task.id);
4397
+ while (current?.parentId && taskById.has(current.parentId)) {
4398
+ continues.unshift(!lastChildIds.has(current.id));
4399
+ current = taskById.get(current.parentId);
4400
+ }
4401
+ map.set(task.id, continues.slice(0, -1));
4402
+ }
4403
+ return map;
4404
+ }, [tasks, visibleTasks, lastChildIds]);
3958
4405
  const handleRowClick = useCallback5((taskId) => {
3959
4406
  onTaskSelect?.(taskId);
3960
4407
  }, [onTaskSelect]);
@@ -4065,9 +4512,6 @@ var TaskList = ({
4065
4512
  if (dropTarget.parentId === draggedTaskId) {
4066
4513
  return false;
4067
4514
  }
4068
- if (dropTarget.parentId) {
4069
- return false;
4070
- }
4071
4515
  const draggedTask = orderedTasks.find((t) => t.id === draggedTaskId);
4072
4516
  if (!draggedTask) return true;
4073
4517
  const descendants = getAllDescendants(draggedTaskId, orderedTasks);
@@ -4213,6 +4657,52 @@ var TaskList = ({
4213
4657
  setIsCreating(false);
4214
4658
  }, [onAdd]);
4215
4659
  const handleCancelNewTask = useCallback5(() => setIsCreating(false), []);
4660
+ function getTaskDepth(task, tasks2) {
4661
+ if (!task) return 0;
4662
+ let depth = 0;
4663
+ let current = task;
4664
+ while (current) {
4665
+ if (!current.parentId) break;
4666
+ depth++;
4667
+ const parentId = current.parentId;
4668
+ current = tasks2.find((t) => t.id === parentId);
4669
+ }
4670
+ return depth;
4671
+ }
4672
+ const handleDemoteWrapper = useCallback5((taskId, _newParentId) => {
4673
+ const taskIndex = visibleTasks.findIndex((t) => t.id === taskId);
4674
+ const currentTask = visibleTasks[taskIndex];
4675
+ const currentDepth = getTaskDepth(currentTask, orderedTasks);
4676
+ if (taskIndex > 0) {
4677
+ for (let i = taskIndex - 1; i >= 0; i--) {
4678
+ const previousTask = visibleTasks[i];
4679
+ const previousDepth = getTaskDepth(previousTask, orderedTasks);
4680
+ if (previousDepth === currentDepth) {
4681
+ onDemoteTask?.(taskId, previousTask.id);
4682
+ return;
4683
+ }
4684
+ if (previousDepth < currentDepth) {
4685
+ break;
4686
+ }
4687
+ }
4688
+ return;
4689
+ }
4690
+ const demotedTask = orderedTasks.find((t) => t.id === taskId);
4691
+ if (!demotedTask) return;
4692
+ const newSectionTask = {
4693
+ id: crypto.randomUUID(),
4694
+ name: "\u041D\u043E\u0432\u044B\u0439 \u0440\u0430\u0437\u0434\u0435\u043B",
4695
+ startDate: demotedTask.startDate,
4696
+ endDate: demotedTask.endDate
4697
+ };
4698
+ const updatedTasks = [
4699
+ newSectionTask,
4700
+ ...orderedTasks.map(
4701
+ (t) => t.id === taskId ? { ...t, parentId: newSectionTask.id } : t
4702
+ )
4703
+ ];
4704
+ onReorder?.(updatedTasks, taskId, newSectionTask.id);
4705
+ }, [visibleTasks, orderedTasks, onDemoteTask, onReorder]);
4216
4706
  const effectiveTaskListWidth = Math.max(taskListWidth, MIN_TASK_LIST_WIDTH);
4217
4707
  return /* @__PURE__ */ jsx14(
4218
4708
  "div",
@@ -4296,8 +4786,10 @@ var TaskList = ({
4296
4786
  collapsedParentIds,
4297
4787
  onToggleCollapse: handleToggleCollapse,
4298
4788
  onPromoteTask,
4299
- onDemoteTask,
4300
- isLastChild: lastChildIds.has(task.id)
4789
+ onDemoteTask: onDemoteTask ? handleDemoteWrapper : void 0,
4790
+ isLastChild: lastChildIds.has(task.id),
4791
+ nestingDepth: nestingDepthMap.get(task.id) ?? 0,
4792
+ ancestorContinues: ancestorContinuesMap.get(task.id) ?? []
4301
4793
  },
4302
4794
  task.id
4303
4795
  )) }),
@@ -4606,6 +5098,17 @@ var GanttChart = forwardRef(({
4606
5098
  }),
4607
5099
  [scrollToToday, scrollToTask, handleCollapseAll, handleExpandAll]
4608
5100
  );
5101
+ function getTaskDepth(taskId, tasks2) {
5102
+ let depth = 0;
5103
+ let current = tasks2.find((t) => t.id === taskId);
5104
+ while (current) {
5105
+ if (!current.parentId) break;
5106
+ depth++;
5107
+ const parentId = current.parentId;
5108
+ current = tasks2.find((t) => t.id === parentId);
5109
+ }
5110
+ return depth;
5111
+ }
4609
5112
  const handlePromoteTask = useCallback6((taskId) => {
4610
5113
  if (onPromoteTask) {
4611
5114
  onPromoteTask(taskId);
@@ -4615,20 +5118,20 @@ var GanttChart = forwardRef(({
4615
5118
  if (!taskToPromote || !taskToPromote.parentId) {
4616
5119
  return;
4617
5120
  }
4618
- const parentId = taskToPromote.parentId;
4619
- const siblings = tasks.filter((t) => t.parentId === parentId);
5121
+ const depth = getTaskDepth(taskId, tasks);
5122
+ const grandparentId = depth > 1 ? tasks.find((t) => t.id === taskToPromote.parentId)?.parentId : void 0;
5123
+ const currentParentId = taskToPromote.parentId;
5124
+ const siblings = tasks.filter((t) => t.parentId === currentParentId);
5125
+ const promotedTask = { ...taskToPromote, parentId: grandparentId };
4620
5126
  if (siblings.length <= 1) {
4621
- const promotedTask2 = { ...taskToPromote, parentId: void 0 };
4622
- onTasksChange?.([promotedTask2]);
5127
+ onTasksChange?.([promotedTask]);
4623
5128
  return;
4624
5129
  }
4625
- const lastSiblingIndex = tasks.map((t, i) => ({ task: t, index: i })).filter(({ task }) => task.parentId === parentId).sort((a, b) => b.index - a.index)[0];
5130
+ const lastSiblingIndex = tasks.map((t, i) => ({ task: t, index: i })).filter(({ task }) => task.parentId === currentParentId).sort((a, b) => b.index - a.index)[0];
4626
5131
  if (!lastSiblingIndex) {
4627
- const promotedTask2 = { ...taskToPromote, parentId: void 0 };
4628
- onTasksChange?.([promotedTask2]);
5132
+ onTasksChange?.([promotedTask]);
4629
5133
  return;
4630
5134
  }
4631
- const promotedTask = { ...taskToPromote, parentId: void 0 };
4632
5135
  const reorderedTasks = normalizeHierarchyTasks([
4633
5136
  ...tasks.filter((t) => t.id !== taskId).slice(0, lastSiblingIndex.index + 1),
4634
5137
  promotedTask,