gantt-lib 0.17.2 → 0.19.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;
@@ -23,6 +25,8 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
23
25
  // src/utils/dateUtils.ts
24
26
  var dateUtils_exports = {};
25
27
  __export(dateUtils_exports, {
28
+ createDateKey: () => createDateKey,
29
+ createIsWeekendPredicate: () => createIsWeekendPredicate,
26
30
  formatDateLabel: () => formatDateLabel,
27
31
  getDayOffset: () => getDayOffset,
28
32
  getMonthBlocks: () => getMonthBlocks,
@@ -37,7 +41,7 @@ __export(dateUtils_exports, {
37
41
  normalizeTaskDates: () => normalizeTaskDates,
38
42
  parseUTCDate: () => parseUTCDate
39
43
  });
40
- var parseUTCDate, getMonthDays, getDayOffset, isToday, isWeekend, getMultiMonthDays, getMonthSpans, formatDateLabel, getWeekBlocks, getWeekSpans, getMonthBlocks, getYearSpans, normalizeTaskDates;
44
+ var parseUTCDate, getMonthDays, getDayOffset, isToday, isWeekend, createDateKey, createIsWeekendPredicate, getMultiMonthDays, getMonthSpans, formatDateLabel, getWeekBlocks, getWeekSpans, getMonthBlocks, getYearSpans, normalizeTaskDates;
41
45
  var init_dateUtils = __esm({
42
46
  "src/utils/dateUtils.ts"() {
43
47
  "use strict";
@@ -94,6 +98,41 @@ var init_dateUtils = __esm({
94
98
  const day = date.getUTCDay();
95
99
  return day === 0 || day === 6;
96
100
  };
101
+ createDateKey = (date) => {
102
+ return `${date.getUTCFullYear()}-${date.getUTCMonth()}-${date.getUTCDate()}`;
103
+ };
104
+ createIsWeekendPredicate = (config) => {
105
+ const { weekends, workdays, isWeekend: customPredicate } = config;
106
+ if (customPredicate) {
107
+ return customPredicate;
108
+ }
109
+ if (workdays && workdays.length > 0) {
110
+ const workdaySet = new Set(workdays.map(createDateKey));
111
+ return (date) => {
112
+ const key = createDateKey(date);
113
+ if (workdaySet.has(key)) {
114
+ return false;
115
+ }
116
+ const dayOfWeek = date.getUTCDay();
117
+ return dayOfWeek === 0 || dayOfWeek === 6;
118
+ };
119
+ }
120
+ if (weekends && weekends.length > 0) {
121
+ const weekendSet = new Set(weekends.map(createDateKey));
122
+ return (date) => {
123
+ const key = createDateKey(date);
124
+ if (weekendSet.has(key)) {
125
+ return true;
126
+ }
127
+ const dayOfWeek = date.getUTCDay();
128
+ return dayOfWeek === 0 || dayOfWeek === 6;
129
+ };
130
+ }
131
+ return (date) => {
132
+ const dayOfWeek = date.getUTCDay();
133
+ return dayOfWeek === 0 || dayOfWeek === 6;
134
+ };
135
+ };
97
136
  getMultiMonthDays = (tasks) => {
98
137
  if (!tasks || tasks.length === 0) {
99
138
  return getMonthDays(/* @__PURE__ */ new Date());
@@ -817,7 +856,8 @@ var TimeScaleHeader = ({
817
856
  days,
818
857
  dayWidth,
819
858
  headerHeight,
820
- viewMode = "day"
859
+ viewMode = "day",
860
+ isCustomWeekend
821
861
  }) => {
822
862
  const monthSpans = useMemo(() => getMonthSpans(days), [days]);
823
863
  const rowHeight = headerHeight / 2;
@@ -981,12 +1021,12 @@ var TimeScaleHeader = ({
981
1021
  ) : (
982
1022
  // Day-view row 2: individual day numbers (existing code)
983
1023
  days.map((day, index) => {
984
- const isWeekend3 = day.getDay() === 0 || day.getDay() === 6;
1024
+ const isWeekendDay = isCustomWeekend ? isCustomWeekend(day) : day.getUTCDay() === 0 || day.getUTCDay() === 6;
985
1025
  const prevDay = days[index - 1];
986
- const isMonthBoundary = index > 0 && prevDay && prevDay.getMonth() !== day.getMonth();
1026
+ const isMonthBoundary = index > 0 && prevDay && prevDay.getUTCMonth() !== day.getUTCMonth();
987
1027
  const now = /* @__PURE__ */ new Date();
988
1028
  const isTodayDate = day.getUTCFullYear() === now.getFullYear() && day.getUTCMonth() === now.getMonth() && day.getUTCDate() === now.getDate();
989
- return /* @__PURE__ */ jsx("div", { className: `gantt-tsh-dayCell ${isWeekend3 ? "gantt-tsh-weekendDay" : ""} ${isTodayDate ? "gantt-tsh-today" : ""}`, children: /* @__PURE__ */ jsx("span", { className: "gantt-tsh-dayLabel", children: format(day, "d") }) }, `day-${index}`);
1029
+ return /* @__PURE__ */ jsx("div", { className: `gantt-tsh-dayCell ${isWeekendDay ? "gantt-tsh-weekendDay" : ""} ${isTodayDate ? "gantt-tsh-today" : ""}`, children: /* @__PURE__ */ jsx("span", { className: "gantt-tsh-dayLabel", children: format(day, "d") }) }, `day-${index}`);
990
1030
  })
991
1031
  )
992
1032
  }
@@ -1079,14 +1119,13 @@ var calculateGridLines = (dateRange, dayWidth) => {
1079
1119
  }
1080
1120
  return lines;
1081
1121
  };
1082
- var calculateWeekendBlocks = (dateRange, dayWidth) => {
1122
+ var calculateWeekendBlocks = (dateRange, dayWidth, isCustomWeekend) => {
1083
1123
  const blocks = [];
1084
1124
  let inWeekend = false;
1085
1125
  let weekendStartIndex = -1;
1086
1126
  for (let i = 0; i < dateRange.length; i++) {
1087
1127
  const date = dateRange[i];
1088
- const dayOfWeek = date.getUTCDay();
1089
- const isWeekend3 = dayOfWeek === 0 || dayOfWeek === 6;
1128
+ const isWeekend3 = isCustomWeekend ? isCustomWeekend(date) : date.getUTCDay() === 0 || date.getUTCDay() === 6;
1090
1129
  if (isWeekend3 && !inWeekend) {
1091
1130
  inWeekend = true;
1092
1131
  weekendStartIndex = i;
@@ -1902,10 +1941,10 @@ import React4, { useMemo as useMemo4 } from "react";
1902
1941
  import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
1903
1942
  var arePropsEqual2 = (prevProps, nextProps) => {
1904
1943
  return prevProps.dayWidth === nextProps.dayWidth && prevProps.dateRange.length === nextProps.dateRange.length && prevProps.totalHeight === nextProps.totalHeight && // skip re-render only when totalHeight unchanged
1905
- prevProps.viewMode === nextProps.viewMode;
1944
+ prevProps.viewMode === nextProps.viewMode && prevProps.isCustomWeekend === nextProps.isCustomWeekend;
1906
1945
  };
1907
1946
  var GridBackground = React4.memo(
1908
- ({ dateRange, dayWidth, totalHeight, viewMode = "day" }) => {
1947
+ ({ dateRange, dayWidth, totalHeight, viewMode = "day", isCustomWeekend }) => {
1909
1948
  const weekGridLines = useMemo4(() => {
1910
1949
  if (viewMode !== "week") return [];
1911
1950
  return calculateWeekGridLines(dateRange, dayWidth);
@@ -1920,8 +1959,8 @@ var GridBackground = React4.memo(
1920
1959
  }, [dateRange, dayWidth, viewMode]);
1921
1960
  const weekendBlocks = useMemo4(() => {
1922
1961
  if (viewMode === "week" || viewMode === "month") return [];
1923
- return calculateWeekendBlocks(dateRange, dayWidth);
1924
- }, [dateRange, dayWidth, viewMode]);
1962
+ return calculateWeekendBlocks(dateRange, dayWidth, isCustomWeekend);
1963
+ }, [dateRange, dayWidth, viewMode, isCustomWeekend]);
1925
1964
  const gridWidth = useMemo4(() => {
1926
1965
  return Math.round(dateRange.length * dayWidth);
1927
1966
  }, [dateRange.length, dayWidth]);
@@ -2391,7 +2430,13 @@ var PopoverContent = ({
2391
2430
 
2392
2431
  // src/components/TaskList/TaskListRow.tsx
2393
2432
  init_dateUtils();
2394
- import React9, { useState as useState4, useRef as useRef4, useEffect as useEffect4, useCallback as useCallback4, useMemo as useMemo7 } from "react";
2433
+ import React9, {
2434
+ useState as useState4,
2435
+ useRef as useRef4,
2436
+ useEffect as useEffect4,
2437
+ useCallback as useCallback4,
2438
+ useMemo as useMemo7
2439
+ } from "react";
2395
2440
 
2396
2441
  // src/components/ui/Input.tsx
2397
2442
  import React6 from "react";
@@ -2415,6 +2460,7 @@ import { useState as useState3, useCallback as useCallback3, useEffect as useEff
2415
2460
  import { format as format3, isValid, parse, addDays, addMonths as addMonths2, addYears, subMonths as subMonths2, subYears, subDays } from "date-fns";
2416
2461
 
2417
2462
  // src/components/ui/Calendar.tsx
2463
+ init_dateUtils();
2418
2464
  import {
2419
2465
  useState as useState2,
2420
2466
  useRef as useRef2,
@@ -2437,11 +2483,11 @@ import {
2437
2483
  } from "date-fns";
2438
2484
  import { ru as ru2 } from "date-fns/locale";
2439
2485
  import { jsx as jsx9, jsxs as jsxs6 } from "react/jsx-runtime";
2440
- function getDayClassName(day, selected) {
2486
+ function getDayClassName(day, selected, isWeekendProp) {
2441
2487
  const classes = ["gantt-day-btn"];
2442
2488
  if (selected && isSameDay(day, selected)) classes.push("selected");
2443
2489
  if (isToday2(day)) classes.push("today");
2444
- if (isWeekend2(day)) classes.push("weekend");
2490
+ if (isWeekendProp ? isWeekendProp(day) : isWeekend2(day)) classes.push("weekend");
2445
2491
  if (isBefore(day, startOfDay(/* @__PURE__ */ new Date())) && !isToday2(day)) classes.push("past");
2446
2492
  return classes.join(" ");
2447
2493
  }
@@ -2450,9 +2496,22 @@ var Calendar = ({
2450
2496
  onSelect,
2451
2497
  initialDate,
2452
2498
  mode = "single",
2453
- disabled = false
2499
+ disabled = false,
2500
+ isWeekend: isWeekendProp,
2501
+ weekends,
2502
+ workdays
2454
2503
  }) => {
2455
2504
  const scrollRef = useRef2(null);
2505
+ const derivedWeekendPredicate = useMemo6(() => {
2506
+ if (isWeekendProp) return isWeekendProp;
2507
+ if (weekends || workdays) {
2508
+ return createIsWeekendPredicate({
2509
+ weekends: weekends ?? [],
2510
+ workdays: workdays ?? []
2511
+ });
2512
+ }
2513
+ return void 0;
2514
+ }, [isWeekendProp, weekends, workdays]);
2456
2515
  const initialMonth = useMemo6(
2457
2516
  () => startOfMonth(initialDate ?? selected ?? /* @__PURE__ */ new Date()),
2458
2517
  // eslint-disable-next-line react-hooks/exhaustive-deps
@@ -2506,11 +2565,13 @@ var Calendar = ({
2506
2565
  const emptyDays = (getDay(firstDay) + 6) % 7;
2507
2566
  const monthKey = format2(month, "yyyy-MM");
2508
2567
  const monthLabel = format2(month, "LLLL yyyy", { locale: ru2 });
2568
+ const weekdayLabels = ["\u041F\u043D", "\u0412\u0442", "\u0421\u0440", "\u0427\u0442", "\u041F\u0442", "\u0421\u0431", "\u0412\u0441"];
2569
+ const weekdayHeaders = weekdayLabels.map((label, i) => /* @__PURE__ */ jsx9("div", { className: "gantt-cal-weekday", children: label }, `wd-${i}`));
2509
2570
  const emptyCells = Array.from({ length: emptyDays }, (_, i) => /* @__PURE__ */ jsx9("div", { className: "gantt-cal-empty-day" }, `e-${i}`));
2510
2571
  const dayCells = Array.from({ length: totalDays }, (_, i) => {
2511
2572
  const dayNum = i + 1;
2512
- const day = new Date(month.getFullYear(), month.getMonth(), dayNum);
2513
- const className = getDayClassName(day, selected);
2573
+ const day = new Date(Date.UTC(month.getFullYear(), month.getMonth(), dayNum));
2574
+ const className = getDayClassName(day, selected, derivedWeekendPredicate);
2514
2575
  return /* @__PURE__ */ jsx9(
2515
2576
  "button",
2516
2577
  {
@@ -2519,7 +2580,7 @@ var Calendar = ({
2519
2580
  disabled,
2520
2581
  onClick: () => {
2521
2582
  if (!disabled && onSelect) {
2522
- onSelect(new Date(month.getFullYear(), month.getMonth(), dayNum));
2583
+ onSelect(new Date(Date.UTC(month.getFullYear(), month.getMonth(), dayNum)));
2523
2584
  }
2524
2585
  },
2525
2586
  children: dayNum
@@ -2530,12 +2591,13 @@ var Calendar = ({
2530
2591
  return /* @__PURE__ */ jsxs6("div", { className: "gantt-cal-month", "data-month": monthKey, children: [
2531
2592
  /* @__PURE__ */ jsx9("div", { className: "gantt-cal-month-header", children: monthLabel }),
2532
2593
  /* @__PURE__ */ jsxs6("div", { className: "gantt-cal-month-days", children: [
2594
+ weekdayHeaders,
2533
2595
  emptyCells,
2534
2596
  dayCells
2535
2597
  ] })
2536
2598
  ] }, monthKey);
2537
2599
  },
2538
- [selected, onSelect, disabled]
2600
+ [selected, onSelect, disabled, derivedWeekendPredicate]
2539
2601
  );
2540
2602
  const renderedMonths = useMemo6(
2541
2603
  () => months.map(renderMonth),
@@ -2559,7 +2621,10 @@ var DatePicker = ({
2559
2621
  placeholder = "Pick a date",
2560
2622
  portal = true,
2561
2623
  className,
2562
- disabled = false
2624
+ disabled = false,
2625
+ weekends,
2626
+ workdays,
2627
+ isWeekend: isWeekend3
2563
2628
  }) => {
2564
2629
  const [open, setOpen] = useState3(false);
2565
2630
  const [inputValue, setInputValue] = useState3("");
@@ -2779,7 +2844,10 @@ var DatePicker = ({
2779
2844
  mode: "single",
2780
2845
  selected: selectedDate,
2781
2846
  onSelect: handleCalendarSelect,
2782
- initialDate: selectedDate
2847
+ initialDate: selectedDate,
2848
+ weekends,
2849
+ workdays,
2850
+ isWeekend: isWeekend3
2783
2851
  }
2784
2852
  )
2785
2853
  ]
@@ -2828,18 +2896,49 @@ var DAY_MS2 = 24 * 60 * 60 * 1e3;
2828
2896
  var getInclusiveDurationDays = (startDate, endDate) => {
2829
2897
  const start = parseUTCDate(startDate);
2830
2898
  const end = parseUTCDate(endDate);
2831
- return Math.max(1, Math.round((end.getTime() - start.getTime()) / DAY_MS2) + 1);
2899
+ return Math.max(
2900
+ 1,
2901
+ Math.round((end.getTime() - start.getTime()) / DAY_MS2) + 1
2902
+ );
2832
2903
  };
2833
2904
  var getEndDateFromDuration = (startDate, durationDays) => {
2834
2905
  const start = parseUTCDate(startDate);
2835
2906
  return new Date(start.getTime() + (durationDays - 1) * DAY_MS2).toISOString().split("T")[0];
2836
2907
  };
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" }) });
2908
+ var TrashIcon = () => /* @__PURE__ */ jsxs9(
2909
+ "svg",
2910
+ {
2911
+ xmlns: "http://www.w3.org/2000/svg",
2912
+ width: "12",
2913
+ height: "12",
2914
+ viewBox: "0 0 24 24",
2915
+ fill: "none",
2916
+ stroke: "currentColor",
2917
+ strokeWidth: "2",
2918
+ strokeLinecap: "round",
2919
+ strokeLinejoin: "round",
2920
+ children: [
2921
+ /* @__PURE__ */ jsx12("path", { d: "M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6" }),
2922
+ /* @__PURE__ */ jsx12("path", { d: "M3 6h18" }),
2923
+ /* @__PURE__ */ jsx12("path", { d: "M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2" })
2924
+ ]
2925
+ }
2926
+ );
2927
+ var PlusIcon = () => /* @__PURE__ */ jsx12(
2928
+ "svg",
2929
+ {
2930
+ xmlns: "http://www.w3.org/2000/svg",
2931
+ width: "14",
2932
+ height: "14",
2933
+ viewBox: "0 0 24 24",
2934
+ fill: "none",
2935
+ stroke: "currentColor",
2936
+ strokeWidth: "2",
2937
+ strokeLinecap: "round",
2938
+ strokeLinejoin: "round",
2939
+ children: /* @__PURE__ */ jsx12("path", { d: "M12 5v14M5 12h14" })
2940
+ }
2941
+ );
2843
2942
  var DragHandleIcon = () => /* @__PURE__ */ jsxs9("svg", { width: "10", height: "14", viewBox: "0 0 10 14", fill: "currentColor", children: [
2844
2943
  /* @__PURE__ */ jsx12("circle", { cx: "2", cy: "2", r: "1.5" }),
2845
2944
  /* @__PURE__ */ jsx12("circle", { cx: "8", cy: "2", r: "1.5" }),
@@ -2848,51 +2947,94 @@ var DragHandleIcon = () => /* @__PURE__ */ jsxs9("svg", { width: "10", height: "
2848
2947
  /* @__PURE__ */ jsx12("circle", { cx: "2", cy: "12", r: "1.5" }),
2849
2948
  /* @__PURE__ */ jsx12("circle", { cx: "8", cy: "12", r: "1.5" })
2850
2949
  ] });
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
- ] });
2950
+ var ChevronRightIcon = () => /* @__PURE__ */ jsx12(
2951
+ "svg",
2952
+ {
2953
+ xmlns: "http://www.w3.org/2000/svg",
2954
+ width: "14",
2955
+ height: "14",
2956
+ viewBox: "0 0 24 24",
2957
+ fill: "none",
2958
+ stroke: "currentColor",
2959
+ strokeWidth: "2",
2960
+ strokeLinecap: "round",
2961
+ strokeLinejoin: "round",
2962
+ children: /* @__PURE__ */ jsx12("path", { d: "m9 18 6-6-6-6" })
2963
+ }
2964
+ );
2965
+ var ArrowLeft = () => /* @__PURE__ */ jsxs9(
2966
+ "svg",
2967
+ {
2968
+ xmlns: "http://www.w3.org/2000/svg",
2969
+ width: "16",
2970
+ height: "16",
2971
+ viewBox: "0 0 24 24",
2972
+ fill: "none",
2973
+ stroke: "currentColor",
2974
+ strokeWidth: "2",
2975
+ strokeLinecap: "round",
2976
+ strokeLinejoin: "round",
2977
+ children: [
2978
+ /* @__PURE__ */ jsx12("path", { d: "m12 19-7-7 7-7" }),
2979
+ /* @__PURE__ */ jsx12("path", { d: "M19 12H5" })
2980
+ ]
2981
+ }
2982
+ );
2983
+ var ArrowRight = () => /* @__PURE__ */ jsxs9(
2984
+ "svg",
2985
+ {
2986
+ xmlns: "http://www.w3.org/2000/svg",
2987
+ width: "16",
2988
+ height: "16",
2989
+ viewBox: "0 0 24 24",
2990
+ fill: "none",
2991
+ stroke: "currentColor",
2992
+ strokeWidth: "2",
2993
+ strokeLinecap: "round",
2994
+ strokeLinejoin: "round",
2995
+ children: [
2996
+ /* @__PURE__ */ jsx12("path", { d: "M5 12h14" }),
2997
+ /* @__PURE__ */ jsx12("path", { d: "m12 5 7 7-7 7" })
2998
+ ]
2999
+ }
3000
+ );
2857
3001
  var HierarchyButton = ({
2858
3002
  isChild,
2859
- isParent,
2860
- rowIndex,
3003
+ rowIndex: _rowIndex,
2861
3004
  onPromote,
2862
3005
  onDemote
2863
3006
  }) => {
2864
3007
  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" })
3008
+ const canDemote = !!onDemote;
3009
+ if (!canPromote && !canDemote) return null;
3010
+ return /* @__PURE__ */ jsxs9(Fragment2, { children: [
3011
+ canPromote && /* @__PURE__ */ jsx12(
3012
+ "button",
3013
+ {
3014
+ type: "button",
3015
+ className: "gantt-tl-name-action-btn gantt-tl-action-hierarchy",
3016
+ onClick: (e) => {
3017
+ e.stopPropagation();
3018
+ onPromote(e);
3019
+ },
3020
+ title: "\u041F\u043E\u0432\u044B\u0441\u0438\u0442\u044C \u0443\u0440\u043E\u0432\u0435\u043D\u044C",
3021
+ children: /* @__PURE__ */ jsx12(ArrowLeft, {})
3022
+ }
3023
+ ),
3024
+ canDemote && /* @__PURE__ */ jsx12(
3025
+ "button",
3026
+ {
3027
+ type: "button",
3028
+ className: "gantt-tl-name-action-btn gantt-tl-action-hierarchy",
3029
+ onClick: (e) => {
3030
+ e.stopPropagation();
3031
+ onDemote(e);
3032
+ },
3033
+ title: "\u041F\u043E\u043D\u0438\u0437\u0438\u0442\u044C \u0443\u0440\u043E\u0432\u0435\u043D\u044C",
3034
+ children: /* @__PURE__ */ jsx12(ArrowRight, {})
3035
+ }
3036
+ )
2885
3037
  ] });
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
3038
  };
2897
3039
  var DepChip = ({
2898
3040
  lag,
@@ -2924,71 +3066,91 @@ var DepChip = ({
2924
3066
  const nextOpen = !popoverOpen;
2925
3067
  setPopoverOpen(nextOpen);
2926
3068
  if (nextOpen) {
2927
- onChipSelect?.({ successorId: taskId, predecessorId: dep.taskId, linkType: dep.type });
3069
+ onChipSelect?.({
3070
+ successorId: taskId,
3071
+ predecessorId: dep.taskId,
3072
+ linkType: dep.type
3073
+ });
2928
3074
  onScrollToTask?.(dep.taskId);
2929
3075
  } else {
2930
3076
  onChipSelect?.(null);
2931
3077
  }
2932
3078
  };
2933
- const handleOpenChange = useCallback4((open) => {
2934
- setPopoverOpen(open);
2935
- if (!open) {
2936
- onChipSelect?.(null);
2937
- }
2938
- }, [onChipSelect]);
3079
+ const handleOpenChange = useCallback4(
3080
+ (open) => {
3081
+ setPopoverOpen(open);
3082
+ if (!open) {
3083
+ onChipSelect?.(null);
3084
+ }
3085
+ },
3086
+ [onChipSelect]
3087
+ );
2939
3088
  const handleTrashClick = (e) => {
2940
3089
  e.stopPropagation();
2941
3090
  onRemoveDependency?.(taskId, dep.taskId, dep.type);
2942
3091
  onChipSelectClear();
2943
3092
  setPopoverOpen(false);
2944
3093
  };
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]);
3094
+ const handleLagChange = useCallback4(
3095
+ (newLag) => {
3096
+ if (!onTasksChange || !allTasks) return;
3097
+ const taskById = new Map(allTasks.map((t) => [t.id, t]));
3098
+ const predecessor = taskById.get(dep.taskId);
3099
+ if (!predecessor) return;
3100
+ const predStart = parseUTCDate(predecessor.startDate);
3101
+ const predEnd = parseUTCDate(predecessor.endDate);
3102
+ const origStart = parseUTCDate(task.startDate);
3103
+ const origEnd = parseUTCDate(task.endDate);
3104
+ const durationMs = origEnd.getTime() - origStart.getTime();
3105
+ const constraintDate = calculateSuccessorDate(
3106
+ predStart,
3107
+ predEnd,
3108
+ dep.type,
3109
+ newLag
3110
+ );
3111
+ let newStart, newEnd;
3112
+ if (dep.type === "FS" || dep.type === "SS") {
3113
+ newStart = constraintDate;
3114
+ newEnd = new Date(constraintDate.getTime() + durationMs);
3115
+ } else {
3116
+ newEnd = constraintDate;
3117
+ newStart = new Date(constraintDate.getTime() - durationMs);
3118
+ }
3119
+ onTasksChange([
3120
+ {
3121
+ ...task,
3122
+ startDate: newStart.toISOString().split("T")[0],
3123
+ endDate: newEnd.toISOString().split("T")[0]
3124
+ }
3125
+ ]);
3126
+ },
3127
+ [dep, task, allTasks, onTasksChange]
3128
+ );
3129
+ const handleInputCommit = useCallback4(
3130
+ (raw) => {
3131
+ if (raw === "") {
3132
+ handleLagChange(0);
3133
+ return;
3134
+ }
3135
+ const parsed = parseInt(raw, 10);
3136
+ const effectiveLag2 = lag ?? 0;
3137
+ if (isNaN(parsed)) {
3138
+ const abs = Math.abs(effectiveLag2);
3139
+ setInputAbs(abs === 0 ? "" : String(abs));
3140
+ return;
3141
+ }
3142
+ let newLag;
3143
+ if (parsed === 0) {
3144
+ newLag = 0;
3145
+ } else if (dep.type === "SF") {
3146
+ newLag = -Math.abs(parsed);
3147
+ } else {
3148
+ newLag = parsed;
3149
+ }
3150
+ if (newLag !== effectiveLag2) handleLagChange(newLag);
3151
+ },
3152
+ [lag, dep.type, handleLagChange]
3153
+ );
2992
3154
  const Icon = LINK_TYPE_ICONS[dep.type];
2993
3155
  const depName = predecessorName ?? dep.taskId;
2994
3156
  const effectiveLag = lag ?? 0;
@@ -3027,67 +3189,92 @@ var DepChip = ({
3027
3189
  ]
3028
3190
  }
3029
3191
  ) }),
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
- )
3192
+ /* @__PURE__ */ jsx12(
3193
+ PopoverContent,
3194
+ {
3195
+ className: "gantt-tl-dep-edit-popover",
3196
+ portal: true,
3197
+ align: "start",
3198
+ children: /* @__PURE__ */ jsxs9("div", { onClick: (e) => e.stopPropagation(), children: [
3199
+ /* @__PURE__ */ jsx12("div", { className: "gantt-tl-dep-edit-task", children: task.name }),
3200
+ /* @__PURE__ */ jsxs9("div", { className: "gantt-tl-dep-edit-row", children: [
3201
+ /* @__PURE__ */ jsxs9("span", { className: "gantt-tl-dep-edit-label", children: [
3202
+ actionVerb,
3203
+ preWord ? ` ${preWord}` : ""
3204
+ ] }),
3205
+ /* @__PURE__ */ jsx12(
3206
+ "button",
3207
+ {
3208
+ type: "button",
3209
+ className: "gantt-tl-dep-edit-btn",
3210
+ onClick: () => handleLagChange(effectiveLag - 1),
3211
+ children: "\u2212"
3212
+ }
3213
+ ),
3214
+ /* @__PURE__ */ jsx12(
3215
+ "input",
3216
+ {
3217
+ type: "number",
3218
+ className: "gantt-tl-dep-edit-input",
3219
+ value: inputAbs,
3220
+ placeholder: zeroPlaceholder,
3221
+ min: "0",
3222
+ onChange: (e) => setInputAbs(e.target.value),
3223
+ onFocus: (e) => e.target.select(),
3224
+ onBlur: (e) => handleInputCommit(e.target.value),
3225
+ onKeyDown: (e) => {
3226
+ if (e.key === "Enter") handleInputCommit(inputAbs);
3227
+ }
3228
+ }
3229
+ ),
3230
+ !(dep.type === "SF" && effectiveLag === 0) && /* @__PURE__ */ jsx12(
3231
+ "button",
3232
+ {
3233
+ type: "button",
3234
+ className: "gantt-tl-dep-edit-btn",
3235
+ onClick: () => handleLagChange(effectiveLag + 1),
3236
+ children: "+"
3237
+ }
3238
+ ),
3239
+ effectiveLag !== 0 && /* @__PURE__ */ jsx12("span", { children: "\u0434." }),
3240
+ /* @__PURE__ */ jsx12("span", { children: afterWhat })
3241
+ ] }),
3242
+ /* @__PURE__ */ jsx12("div", { className: "gantt-tl-dep-edit-pred", children: depName }),
3243
+ !disableDependencyEditing && /* @__PURE__ */ jsxs9(Fragment2, { children: [
3244
+ /* @__PURE__ */ jsx12("hr", { className: "gantt-tl-dep-edit-divider" }),
3245
+ /* @__PURE__ */ jsxs9("div", { className: "gantt-tl-dep-edit-actions", children: [
3246
+ /* @__PURE__ */ jsx12(
3247
+ "button",
3248
+ {
3249
+ type: "button",
3250
+ className: "gantt-tl-dep-edit-close",
3251
+ onClick: () => {
3252
+ setPopoverOpen(false);
3253
+ onChipSelectClear();
3254
+ },
3255
+ children: "\u0417\u0430\u043A\u0440\u044B\u0442\u044C"
3256
+ }
3257
+ ),
3258
+ /* @__PURE__ */ jsx12(
3259
+ "button",
3260
+ {
3261
+ type: "button",
3262
+ className: "gantt-tl-dep-edit-delete",
3263
+ onClick: handleTrashClick,
3264
+ children: "\u0423\u0434\u0430\u043B\u0438\u0442\u044C \u0441\u0432\u044F\u0437\u044C"
3265
+ }
3266
+ )
3267
+ ] })
3268
+ ] })
3083
3269
  ] })
3084
- ] })
3085
- ] }) })
3270
+ }
3271
+ )
3086
3272
  ] });
3087
3273
  };
3088
3274
  var toISODate = (value) => {
3089
3275
  if (value instanceof Date) return value.toISOString().split("T")[0];
3090
- if (typeof value === "string" && value.includes("T")) return value.split("T")[0];
3276
+ if (typeof value === "string" && value.includes("T"))
3277
+ return value.split("T")[0];
3091
3278
  return value;
3092
3279
  };
3093
3280
  var TaskListRow = React9.memo(
@@ -3124,13 +3311,20 @@ var TaskListRow = React9.memo(
3124
3311
  onToggleCollapse,
3125
3312
  onPromoteTask,
3126
3313
  onDemoteTask,
3127
- isLastChild = true
3314
+ isLastChild = true,
3315
+ nestingDepth = 0,
3316
+ ancestorContinues = [],
3317
+ weekends,
3318
+ workdays,
3319
+ isWeekend: isWeekend3
3128
3320
  }) => {
3129
3321
  const [editingName, setEditingName] = useState4(false);
3130
3322
  const [nameValue, setNameValue] = useState4("");
3131
3323
  const nameInputRef = useRef4(null);
3132
3324
  const [editingDuration, setEditingDuration] = useState4(false);
3133
- const [durationValue, setDurationValue] = useState4(getInclusiveDurationDays(task.startDate, task.endDate));
3325
+ const [durationValue, setDurationValue] = useState4(
3326
+ getInclusiveDurationDays(task.startDate, task.endDate)
3327
+ );
3134
3328
  const durationInputRef = useRef4(null);
3135
3329
  const [editingProgress, setEditingProgress] = useState4(false);
3136
3330
  const [progressValue, setProgressValue] = useState4(0);
@@ -3140,11 +3334,16 @@ var TaskListRow = React9.memo(
3140
3334
  const durationConfirmedRef = useRef4(false);
3141
3335
  const progressConfirmedRef = useRef4(false);
3142
3336
  const autoEditedForRef = useRef4(null);
3143
- const editTriggerRef = useRef4("doubleclick");
3337
+ const editTriggerRef = useRef4(
3338
+ "doubleclick"
3339
+ );
3144
3340
  const [deletePending, setDeletePending] = useState4(false);
3145
3341
  const deleteButtonRef = useRef4(null);
3146
3342
  const isSelected = selectedTaskId === task.id;
3147
- const isParent = useMemo7(() => isTaskParent(task.id, allTasks), [task.id, allTasks]);
3343
+ const isParent = useMemo7(
3344
+ () => isTaskParent(task.id, allTasks),
3345
+ [task.id, allTasks]
3346
+ );
3148
3347
  const isChild = task.parentId !== void 0;
3149
3348
  const isCollapsed = collapsedParentIds.has(task.id);
3150
3349
  const isPicking = selectingPredecessorFor != null;
@@ -3199,31 +3398,40 @@ var TaskListRow = React9.memo(
3199
3398
  setEditingName(true);
3200
3399
  }
3201
3400
  }, [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();
3401
+ const handleNameClick = useCallback4(
3402
+ (e) => {
3403
+ if (disableTaskNameEditing) return;
3404
+ e.stopPropagation();
3405
+ onRowClick?.(task.id);
3406
+ onScrollToTask?.(task.id);
3407
+ },
3408
+ [task.id, disableTaskNameEditing, onRowClick, onScrollToTask]
3409
+ );
3410
+ const handleNameDoubleClick = useCallback4(
3411
+ (e) => {
3412
+ if (disableTaskNameEditing) return;
3413
+ e.stopPropagation();
3220
3414
  nameConfirmedRef.current = false;
3221
- editTriggerRef.current = "keypress";
3415
+ editTriggerRef.current = "doubleclick";
3222
3416
  setNameValue(task.name);
3223
3417
  setEditingName(true);
3224
- return;
3225
- }
3226
- }, [editingName, disableTaskNameEditing, task.name]);
3418
+ },
3419
+ [task.name, disableTaskNameEditing]
3420
+ );
3421
+ const handleRowKeyDown = useCallback4(
3422
+ (e) => {
3423
+ if (editingProgress) return;
3424
+ if (!editingName && !disableTaskNameEditing && e.key === "F2") {
3425
+ e.preventDefault();
3426
+ nameConfirmedRef.current = false;
3427
+ editTriggerRef.current = "keypress";
3428
+ setNameValue(task.name);
3429
+ setEditingName(true);
3430
+ return;
3431
+ }
3432
+ },
3433
+ [editingName, disableTaskNameEditing, task.name]
3434
+ );
3227
3435
  const handleNameSave = useCallback4(() => {
3228
3436
  if (nameConfirmedRef.current) {
3229
3437
  nameConfirmedRef.current = false;
@@ -3237,24 +3445,32 @@ var TaskListRow = React9.memo(
3237
3445
  const handleNameCancel = useCallback4(() => {
3238
3446
  setEditingName(false);
3239
3447
  }, []);
3240
- const handleNameKeyDown = useCallback4((e) => {
3241
- if (e.key === "Enter") {
3242
- nameConfirmedRef.current = true;
3243
- if (nameValue.trim()) {
3244
- onTasksChange?.([{ ...task, name: nameValue.trim() }]);
3448
+ const handleNameKeyDown = useCallback4(
3449
+ (e) => {
3450
+ if (e.key === "Enter") {
3451
+ nameConfirmedRef.current = true;
3452
+ if (nameValue.trim()) {
3453
+ onTasksChange?.([{ ...task, name: nameValue.trim() }]);
3454
+ }
3455
+ setEditingName(false);
3456
+ } else if (e.key === "Escape") {
3457
+ handleNameCancel();
3245
3458
  }
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]);
3459
+ },
3460
+ [nameValue, task, onTasksChange, handleNameCancel]
3461
+ );
3462
+ const handleDurationClick = useCallback4(
3463
+ (e) => {
3464
+ if (task.locked) return;
3465
+ e.stopPropagation();
3466
+ durationConfirmedRef.current = false;
3467
+ setDurationValue(
3468
+ getInclusiveDurationDays(task.startDate, task.endDate)
3469
+ );
3470
+ setEditingDuration(true);
3471
+ },
3472
+ [task.locked, task.startDate, task.endDate]
3473
+ );
3258
3474
  const applyDurationChange = useCallback4((nextDuration) => {
3259
3475
  const normalizedDuration = Math.max(1, Math.round(nextDuration) || 1);
3260
3476
  setDurationValue(normalizedDuration);
@@ -3265,34 +3481,59 @@ var TaskListRow = React9.memo(
3265
3481
  return;
3266
3482
  }
3267
3483
  const normalizedDuration = Math.max(1, Math.round(durationValue) || 1);
3268
- onTasksChange?.([{ ...task, endDate: getEndDateFromDuration(task.startDate, normalizedDuration) }]);
3484
+ onTasksChange?.([
3485
+ {
3486
+ ...task,
3487
+ endDate: getEndDateFromDuration(task.startDate, normalizedDuration)
3488
+ }
3489
+ ]);
3269
3490
  setEditingDuration(false);
3270
3491
  }, [durationValue, task, onTasksChange]);
3271
3492
  const handleDurationCancel = useCallback4(() => {
3272
3493
  setDurationValue(getInclusiveDurationDays(task.startDate, task.endDate));
3273
3494
  setEditingDuration(false);
3274
3495
  }, [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]);
3496
+ const handleDurationAdjust = useCallback4(
3497
+ (delta) => {
3498
+ applyDurationChange(durationValue + delta);
3499
+ },
3500
+ [applyDurationChange, durationValue]
3501
+ );
3502
+ const handleDurationKeyDown = useCallback4(
3503
+ (e) => {
3504
+ e.stopPropagation();
3505
+ if (e.key === "Enter") {
3506
+ durationConfirmedRef.current = true;
3507
+ const normalizedDuration = Math.max(
3508
+ 1,
3509
+ Math.round(durationValue) || 1
3510
+ );
3511
+ onTasksChange?.([
3512
+ {
3513
+ ...task,
3514
+ endDate: getEndDateFromDuration(
3515
+ task.startDate,
3516
+ normalizedDuration
3517
+ )
3518
+ }
3519
+ ]);
3520
+ setEditingDuration(false);
3521
+ } else if (e.key === "Escape") {
3522
+ handleDurationCancel();
3523
+ }
3524
+ },
3525
+ [durationValue, task, onTasksChange, handleDurationCancel]
3526
+ );
3527
+ const handleProgressClick = useCallback4(
3528
+ (e) => {
3529
+ if (task.locked) return;
3530
+ e.stopPropagation();
3531
+ progressConfirmedRef.current = false;
3532
+ setProgressValue(task.progress ?? 0);
3533
+ setEditingProgress(true);
3534
+ },
3535
+ [task.progress, task.locked]
3536
+ );
3296
3537
  const handleProgressSave = useCallback4(() => {
3297
3538
  if (progressConfirmedRef.current) {
3298
3539
  progressConfirmedRef.current = false;
@@ -3315,28 +3556,36 @@ var TaskListRow = React9.memo(
3315
3556
  setEditingProgress(false);
3316
3557
  }, []);
3317
3558
  const handleProgressAdjust = useCallback4((delta) => {
3318
- setProgressValue((current) => Math.max(0, Math.min(100, current + delta)));
3559
+ setProgressValue(
3560
+ (current) => Math.max(0, Math.min(100, current + delta))
3561
+ );
3319
3562
  }, []);
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 }]);
3563
+ const handleProgressKeyDown = useCallback4(
3564
+ (e) => {
3565
+ e.stopPropagation();
3566
+ if (e.key === "Enter") {
3567
+ progressConfirmedRef.current = true;
3568
+ const clampedValue = Math.max(0, Math.min(100, progressValue));
3569
+ if ((clampedValue === 100 || clampedValue === 0) && isTaskParent(task.id, allTasks)) {
3570
+ const children = getChildren(task.id, allTasks);
3571
+ const updatedTasks = [
3572
+ { ...task, progress: clampedValue },
3573
+ ...children.map((child) => ({
3574
+ ...child,
3575
+ progress: clampedValue
3576
+ }))
3577
+ ];
3578
+ onTasksChange?.(updatedTasks);
3579
+ } else {
3580
+ onTasksChange?.([{ ...task, progress: clampedValue }]);
3581
+ }
3582
+ setEditingProgress(false);
3583
+ } else if (e.key === "Escape") {
3584
+ handleProgressCancel();
3334
3585
  }
3335
- setEditingProgress(false);
3336
- } else if (e.key === "Escape") {
3337
- handleProgressCancel();
3338
- }
3339
- }, [progressValue, task, onTasksChange, handleProgressCancel, allTasks]);
3586
+ },
3587
+ [progressValue, task, onTasksChange, handleProgressCancel, allTasks]
3588
+ );
3340
3589
  useEffect4(() => {
3341
3590
  if (editingProgress && progressInputRef.current) {
3342
3591
  progressInputRef.current.focus();
@@ -3352,77 +3601,111 @@ var TaskListRow = React9.memo(
3352
3601
  durationInputRef.current.select();
3353
3602
  }
3354
3603
  }, [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]);
3604
+ const handleStartDateChange = useCallback4(
3605
+ (newDateISO) => {
3606
+ if (!newDateISO) return;
3607
+ const origStart = parseUTCDate(task.startDate);
3608
+ const origEnd = parseUTCDate(task.endDate);
3609
+ const durationMs = origEnd.getTime() - origStart.getTime();
3610
+ const newStart = /* @__PURE__ */ new Date(newDateISO + "T00:00:00Z");
3611
+ const newEnd = new Date(newStart.getTime() + durationMs);
3612
+ const { startDate: normalizedStart, endDate: normalizedEnd } = normalizeTaskDates(newDateISO, newEnd.toISOString().split("T")[0]);
3613
+ onTasksChange?.([
3614
+ { ...task, startDate: normalizedStart, endDate: normalizedEnd }
3615
+ ]);
3616
+ },
3617
+ [task, onTasksChange]
3618
+ );
3619
+ const handleEndDateChange = useCallback4(
3620
+ (newDateISO) => {
3621
+ if (!newDateISO) return;
3622
+ const origStart = parseUTCDate(task.startDate);
3623
+ const origEnd = parseUTCDate(task.endDate);
3624
+ const durationMs = origEnd.getTime() - origStart.getTime();
3625
+ const newEnd = /* @__PURE__ */ new Date(newDateISO + "T00:00:00Z");
3626
+ const newStart = new Date(newEnd.getTime() - durationMs);
3627
+ const { startDate: normalizedStart, endDate: normalizedEnd } = normalizeTaskDates(newStart.toISOString().split("T")[0], newDateISO);
3628
+ onTasksChange?.([
3629
+ { ...task, startDate: normalizedStart, endDate: normalizedEnd }
3630
+ ]);
3631
+ },
3632
+ [task, onTasksChange]
3633
+ );
3381
3634
  const handleRowClickInternal = useCallback4(() => {
3382
3635
  onRowClick?.(task.id);
3383
3636
  }, [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]);
3637
+ const handleNumberClick = useCallback4(
3638
+ (e) => {
3639
+ e.stopPropagation();
3640
+ onRowClick?.(task.id);
3641
+ },
3642
+ [task.id, onRowClick]
3643
+ );
3644
+ const handleToggleCollapse = useCallback4(
3645
+ (e) => {
3646
+ e.stopPropagation();
3647
+ onToggleCollapse?.(task.id);
3648
+ },
3649
+ [task.id, onToggleCollapse]
3650
+ );
3651
+ const handlePromote = useCallback4(
3652
+ (e) => {
3653
+ e.stopPropagation();
3654
+ onPromoteTask?.(task.id);
3655
+ },
3656
+ [task.id, onPromoteTask]
3657
+ );
3658
+ const handleDemote = useCallback4(
3659
+ (e) => {
3660
+ e.stopPropagation();
3661
+ onDemoteTask?.(task.id, "");
3662
+ },
3663
+ [task.id, onDemoteTask]
3664
+ );
3665
+ const handleAddClick = useCallback4(
3666
+ (e) => {
3667
+ e.stopPropagation();
3668
+ onSetSelectingPredecessorFor?.(task.id);
3669
+ },
3670
+ [task.id, onSetSelectingPredecessorFor]
3671
+ );
3672
+ const handlePredecessorPick = useCallback4(
3673
+ (e) => {
3674
+ e.stopPropagation();
3675
+ if (!isPicking || isSourceRow) return;
3676
+ if (!selectingPredecessorFor || !activeLinkType) return;
3677
+ onAddDependency?.(task.id, selectingPredecessorFor, activeLinkType);
3678
+ },
3679
+ [
3680
+ isPicking,
3681
+ isSourceRow,
3682
+ selectingPredecessorFor,
3683
+ task.id,
3684
+ activeLinkType,
3685
+ onAddDependency
3686
+ ]
3687
+ );
3688
+ const handleCancelPicking = useCallback4(
3689
+ (e) => {
3690
+ e.stopPropagation();
3691
+ onSetSelectingPredecessorFor?.(null);
3692
+ },
3693
+ [onSetSelectingPredecessorFor]
3694
+ );
3419
3695
  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]);
3696
+ const handleDeleteSelected = useCallback4(
3697
+ (e) => {
3698
+ e.stopPropagation();
3699
+ if (!selectedChip) return;
3700
+ onRemoveDependency?.(
3701
+ selectedChip.successorId,
3702
+ selectedChip.predecessorId,
3703
+ selectedChip.linkType
3704
+ );
3705
+ onChipSelect?.(null);
3706
+ },
3707
+ [selectedChip, onRemoveDependency, onChipSelect]
3708
+ );
3426
3709
  const startDateISO = toISODate(task.startDate);
3427
3710
  const endDateISO = editingDuration ? getEndDateFromDuration(task.startDate, durationValue) : toISODate(task.endDate);
3428
3711
  return /* @__PURE__ */ jsxs9(
@@ -3475,13 +3758,78 @@ var TaskListRow = React9.memo(
3475
3758
  }
3476
3759
  ),
3477
3760
  /* @__PURE__ */ jsxs9("div", { className: "gantt-tl-cell gantt-tl-cell-name", children: [
3478
- isChild && !editingName && /* @__PURE__ */ jsx12(HierarchyConnectorIcon, { isLastChild }),
3761
+ isChild && !editingName && /* @__PURE__ */ jsxs9(Fragment2, { children: [
3762
+ ancestorContinues.map(
3763
+ (continues, idx) => continues ? /* @__PURE__ */ jsx12(
3764
+ "span",
3765
+ {
3766
+ style: {
3767
+ position: "absolute",
3768
+ left: `${idx * 20 + 9}px`,
3769
+ top: 0,
3770
+ height: `${rowHeight}px`,
3771
+ width: "1.5px",
3772
+ background: "#d4bceb",
3773
+ borderRadius: "1px",
3774
+ pointerEvents: "none"
3775
+ }
3776
+ },
3777
+ idx
3778
+ ) : null
3779
+ ),
3780
+ /* @__PURE__ */ jsx12(
3781
+ "span",
3782
+ {
3783
+ style: {
3784
+ position: "absolute",
3785
+ left: `${(nestingDepth - 1) * 20 + 9}px`,
3786
+ top: 0,
3787
+ height: isLastChild ? `${rowHeight / 2}px` : `${rowHeight}px`,
3788
+ width: "1.5px",
3789
+ background: "#d4bceb",
3790
+ borderRadius: "1px",
3791
+ pointerEvents: "none"
3792
+ }
3793
+ }
3794
+ ),
3795
+ /* @__PURE__ */ jsx12(
3796
+ "span",
3797
+ {
3798
+ style: {
3799
+ position: "absolute",
3800
+ left: `${(nestingDepth - 1) * 20 + 9}px`,
3801
+ top: `${rowHeight / 2 - 0.75}px`,
3802
+ width: "8px",
3803
+ height: "1.5px",
3804
+ background: "#d4bceb",
3805
+ borderRadius: "1px",
3806
+ pointerEvents: "none"
3807
+ }
3808
+ }
3809
+ ),
3810
+ /* @__PURE__ */ jsx12(
3811
+ "span",
3812
+ {
3813
+ style: {
3814
+ position: "absolute",
3815
+ left: `${(nestingDepth - 1) * 20 + 15}px`,
3816
+ top: `${rowHeight / 2 - 2}px`,
3817
+ width: "4px",
3818
+ height: "4px",
3819
+ borderRadius: "50%",
3820
+ background: "#d4bceb",
3821
+ pointerEvents: "none"
3822
+ }
3823
+ }
3824
+ )
3825
+ ] }),
3479
3826
  isParent && !editingName && /* @__PURE__ */ jsx12(
3480
3827
  "button",
3481
3828
  {
3482
3829
  type: "button",
3483
3830
  className: `gantt-tl-collapse-btn ${isCollapsed ? "gantt-tl-collapse-btn-collapsed" : ""}`,
3484
3831
  onClick: handleToggleCollapse,
3832
+ style: { left: `${nestingDepth * 20 + 4}px` },
3485
3833
  "aria-label": isCollapsed ? "Expand children" : "Collapse children",
3486
3834
  children: /* @__PURE__ */ jsx12(ChevronRightIcon, {})
3487
3835
  }
@@ -3495,7 +3843,10 @@ var TaskListRow = React9.memo(
3495
3843
  onChange: (e) => setNameValue(e.target.value),
3496
3844
  onBlur: handleNameSave,
3497
3845
  onKeyDown: handleNameKeyDown,
3498
- className: ["gantt-tl-name-input", isChild ? "gantt-tl-name-input-child" : ""].filter(Boolean).join(" "),
3846
+ className: "gantt-tl-name-input",
3847
+ style: {
3848
+ paddingLeft: nestingDepth > 0 ? `${nestingDepth * 20 + 24}px` : void 0
3849
+ },
3499
3850
  onClick: (e) => e.stopPropagation()
3500
3851
  }
3501
3852
  ),
@@ -3505,14 +3856,15 @@ var TaskListRow = React9.memo(
3505
3856
  type: "button",
3506
3857
  className: [
3507
3858
  "gantt-tl-name-trigger",
3508
- disableTaskNameEditing ? "gantt-tl-name-locked" : "",
3509
- isParent ? "gantt-tl-name-trigger-parent" : "",
3510
- isChild ? "gantt-tl-name-trigger-child" : ""
3859
+ disableTaskNameEditing ? "gantt-tl-name-locked" : ""
3511
3860
  ].filter(Boolean).join(" "),
3512
3861
  title: task.name,
3513
3862
  onClick: handleNameClick,
3514
3863
  onDoubleClick: handleNameDoubleClick,
3515
- style: editingName ? { visibility: "hidden", pointerEvents: "none" } : void 0,
3864
+ style: {
3865
+ paddingLeft: nestingDepth > 0 ? `${nestingDepth * 20 + (isParent ? 26 : 8)}px` : isParent ? "26px" : void 0,
3866
+ ...editingName ? { visibility: "hidden", pointerEvents: "none" } : void 0
3867
+ },
3516
3868
  children: task.name
3517
3869
  }
3518
3870
  ),
@@ -3525,16 +3877,20 @@ var TaskListRow = React9.memo(
3525
3877
  onClick: (e) => {
3526
3878
  e.stopPropagation();
3527
3879
  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];
3880
+ const todayISO = new Date(
3881
+ Date.UTC(
3882
+ now.getUTCFullYear(),
3883
+ now.getUTCMonth(),
3884
+ now.getUTCDate()
3885
+ )
3886
+ ).toISOString().split("T")[0];
3887
+ const endISO = new Date(
3888
+ Date.UTC(
3889
+ now.getUTCFullYear(),
3890
+ now.getUTCMonth(),
3891
+ now.getUTCDate() + 7
3892
+ )
3893
+ ).toISOString().split("T")[0];
3538
3894
  const newTask = {
3539
3895
  id: crypto.randomUUID(),
3540
3896
  name: "\u041D\u043E\u0432\u0430\u044F \u0437\u0430\u0434\u0430\u0447\u0430",
@@ -3570,7 +3926,6 @@ var TaskListRow = React9.memo(
3570
3926
  HierarchyButton,
3571
3927
  {
3572
3928
  isChild,
3573
- isParent,
3574
3929
  rowIndex,
3575
3930
  onPromote: onPromoteTask ? handlePromote : void 0,
3576
3931
  onDemote: onDemoteTask ? handleDemote : void 0
@@ -3578,113 +3933,234 @@ var TaskListRow = React9.memo(
3578
3933
  )
3579
3934
  ] })
3580
3935
  ] }),
3581
- /* @__PURE__ */ jsx12("div", { className: "gantt-tl-cell gantt-tl-cell-date", onClick: (e) => e.stopPropagation(), children: /* @__PURE__ */ jsx12(
3582
- DatePicker,
3936
+ /* @__PURE__ */ jsx12(
3937
+ "div",
3583
3938
  {
3584
- value: startDateISO,
3585
- onChange: handleStartDateChange,
3586
- format: "dd.MM.yy",
3587
- portal: true,
3588
- disabled: task.locked
3939
+ className: "gantt-tl-cell gantt-tl-cell-date",
3940
+ onClick: (e) => e.stopPropagation(),
3941
+ children: /* @__PURE__ */ jsx12(
3942
+ DatePicker,
3943
+ {
3944
+ value: startDateISO,
3945
+ onChange: handleStartDateChange,
3946
+ format: "dd.MM.yy",
3947
+ portal: true,
3948
+ disabled: task.locked,
3949
+ weekends,
3950
+ workdays,
3951
+ isWeekend: isWeekend3
3952
+ }
3953
+ )
3589
3954
  }
3590
- ) }),
3591
- /* @__PURE__ */ jsx12("div", { className: "gantt-tl-cell gantt-tl-cell-date", onClick: (e) => e.stopPropagation(), children: /* @__PURE__ */ jsx12(
3592
- DatePicker,
3955
+ ),
3956
+ /* @__PURE__ */ jsx12(
3957
+ "div",
3593
3958
  {
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,
3959
+ className: "gantt-tl-cell gantt-tl-cell-date",
3960
+ onClick: (e) => e.stopPropagation(),
3961
+ children: /* @__PURE__ */ jsx12(
3962
+ DatePicker,
3605
3963
  {
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"
3964
+ value: endDateISO,
3965
+ onChange: handleEndDateChange,
3966
+ format: "dd.MM.yy",
3967
+ portal: true,
3968
+ disabled: task.locked,
3969
+ weekends,
3970
+ workdays,
3971
+ isWeekend: isWeekend3
3615
3972
  }
3616
- ),
3617
- /* @__PURE__ */ jsxs9("div", { className: "gantt-tl-number-steppers", "aria-hidden": "true", children: [
3618
- /* @__PURE__ */ jsx12(
3619
- "button",
3973
+ )
3974
+ }
3975
+ ),
3976
+ /* @__PURE__ */ jsxs9(
3977
+ "div",
3978
+ {
3979
+ className: "gantt-tl-cell gantt-tl-cell-duration",
3980
+ onClick: handleDurationClick,
3981
+ children: [
3982
+ editingDuration && /* @__PURE__ */ jsxs9(
3983
+ "div",
3620
3984
  {
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" }) })
3985
+ className: "gantt-tl-number-editor",
3986
+ onClick: (e) => e.stopPropagation(),
3987
+ children: [
3988
+ /* @__PURE__ */ jsx12(
3989
+ Input,
3990
+ {
3991
+ ref: durationInputRef,
3992
+ type: "number",
3993
+ min: 1,
3994
+ step: 1,
3995
+ value: durationValue,
3996
+ onChange: (e) => applyDurationChange(parseInt(e.target.value, 10) || 1),
3997
+ onBlur: handleDurationSave,
3998
+ onKeyDown: handleDurationKeyDown,
3999
+ className: "gantt-tl-number-input"
4000
+ }
4001
+ ),
4002
+ /* @__PURE__ */ jsxs9("div", { className: "gantt-tl-number-steppers", "aria-hidden": "true", children: [
4003
+ /* @__PURE__ */ jsx12(
4004
+ "button",
4005
+ {
4006
+ type: "button",
4007
+ className: "gantt-tl-number-stepper",
4008
+ tabIndex: -1,
4009
+ onMouseDown: (e) => e.preventDefault(),
4010
+ onClick: () => handleDurationAdjust(1),
4011
+ children: /* @__PURE__ */ jsx12(
4012
+ "svg",
4013
+ {
4014
+ xmlns: "http://www.w3.org/2000/svg",
4015
+ width: "10",
4016
+ height: "10",
4017
+ viewBox: "0 0 24 24",
4018
+ fill: "none",
4019
+ stroke: "currentColor",
4020
+ strokeWidth: "2",
4021
+ strokeLinecap: "round",
4022
+ strokeLinejoin: "round",
4023
+ children: /* @__PURE__ */ jsx12("path", { d: "m18 15-6-6-6 6" })
4024
+ }
4025
+ )
4026
+ }
4027
+ ),
4028
+ /* @__PURE__ */ jsx12(
4029
+ "button",
4030
+ {
4031
+ type: "button",
4032
+ className: "gantt-tl-number-stepper",
4033
+ tabIndex: -1,
4034
+ onMouseDown: (e) => e.preventDefault(),
4035
+ onClick: () => handleDurationAdjust(-1),
4036
+ children: /* @__PURE__ */ jsx12(
4037
+ "svg",
4038
+ {
4039
+ xmlns: "http://www.w3.org/2000/svg",
4040
+ width: "10",
4041
+ height: "10",
4042
+ viewBox: "0 0 24 24",
4043
+ fill: "none",
4044
+ stroke: "currentColor",
4045
+ strokeWidth: "2",
4046
+ strokeLinecap: "round",
4047
+ strokeLinejoin: "round",
4048
+ children: /* @__PURE__ */ jsx12("path", { d: "m6 9 6 6 6-6" })
4049
+ }
4050
+ )
4051
+ }
4052
+ )
4053
+ ] })
4054
+ ]
3627
4055
  }
3628
4056
  ),
3629
4057
  /* @__PURE__ */ jsx12(
3630
- "button",
4058
+ "span",
3631
4059
  {
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" }) })
4060
+ style: editingDuration ? { visibility: "hidden", pointerEvents: "none" } : void 0,
4061
+ children: getInclusiveDurationDays(task.startDate, task.endDate)
3638
4062
  }
3639
4063
  )
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",
4064
+ ]
4065
+ }
4066
+ ),
4067
+ /* @__PURE__ */ jsxs9(
4068
+ "div",
4069
+ {
4070
+ className: "gantt-tl-cell gantt-tl-cell-progress",
4071
+ onClick: handleProgressClick,
4072
+ children: [
4073
+ editingProgress && /* @__PURE__ */ jsxs9(
4074
+ "div",
3664
4075
  {
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" }) })
4076
+ className: "gantt-tl-number-editor",
4077
+ onClick: (e) => e.stopPropagation(),
4078
+ children: [
4079
+ /* @__PURE__ */ jsx12(
4080
+ Input,
4081
+ {
4082
+ ref: progressInputRef,
4083
+ type: "number",
4084
+ min: 0,
4085
+ max: 100,
4086
+ step: 1,
4087
+ value: progressValue,
4088
+ onChange: (e) => setProgressValue(parseInt(e.target.value, 10) || 0),
4089
+ onBlur: handleProgressSave,
4090
+ onKeyDown: handleProgressKeyDown,
4091
+ className: "gantt-tl-number-input"
4092
+ }
4093
+ ),
4094
+ /* @__PURE__ */ jsxs9("div", { className: "gantt-tl-number-steppers", "aria-hidden": "true", children: [
4095
+ /* @__PURE__ */ jsx12(
4096
+ "button",
4097
+ {
4098
+ type: "button",
4099
+ className: "gantt-tl-number-stepper",
4100
+ tabIndex: -1,
4101
+ onMouseDown: (e) => e.preventDefault(),
4102
+ onClick: () => handleProgressAdjust(1),
4103
+ children: /* @__PURE__ */ jsx12(
4104
+ "svg",
4105
+ {
4106
+ xmlns: "http://www.w3.org/2000/svg",
4107
+ width: "10",
4108
+ height: "10",
4109
+ viewBox: "0 0 24 24",
4110
+ fill: "none",
4111
+ stroke: "currentColor",
4112
+ strokeWidth: "2",
4113
+ strokeLinecap: "round",
4114
+ strokeLinejoin: "round",
4115
+ children: /* @__PURE__ */ jsx12("path", { d: "m18 15-6-6-6 6" })
4116
+ }
4117
+ )
4118
+ }
4119
+ ),
4120
+ /* @__PURE__ */ jsx12(
4121
+ "button",
4122
+ {
4123
+ type: "button",
4124
+ className: "gantt-tl-number-stepper",
4125
+ tabIndex: -1,
4126
+ onMouseDown: (e) => e.preventDefault(),
4127
+ onClick: () => handleProgressAdjust(-1),
4128
+ children: /* @__PURE__ */ jsx12(
4129
+ "svg",
4130
+ {
4131
+ xmlns: "http://www.w3.org/2000/svg",
4132
+ width: "10",
4133
+ height: "10",
4134
+ viewBox: "0 0 24 24",
4135
+ fill: "none",
4136
+ stroke: "currentColor",
4137
+ strokeWidth: "2",
4138
+ strokeLinecap: "round",
4139
+ strokeLinejoin: "round",
4140
+ children: /* @__PURE__ */ jsx12("path", { d: "m6 9 6 6 6-6" })
4141
+ }
4142
+ )
4143
+ }
4144
+ )
4145
+ ] })
4146
+ ]
3671
4147
  }
3672
4148
  ),
3673
4149
  /* @__PURE__ */ jsx12(
3674
- "button",
4150
+ "span",
3675
4151
  {
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" }) })
4152
+ style: editingProgress ? { visibility: "hidden", pointerEvents: "none" } : task.progress === 100 ? {
4153
+ backgroundColor: "#17c864",
4154
+ borderRadius: "4px",
4155
+ padding: "2px 4px",
4156
+ color: "#ffffff"
4157
+ } : void 0,
4158
+ children: task.progress ? Math.round(task.progress) === 100 ? "100" : `${Math.round(task.progress)}%` : "0%"
3682
4159
  }
3683
4160
  )
3684
- ] })
3685
- ] }),
3686
- /* @__PURE__ */ jsx12("span", { style: editingProgress ? { visibility: "hidden", pointerEvents: "none" } : void 0, children: task.progress ? `${Math.round(task.progress)}%` : "0%" })
3687
- ] }),
4161
+ ]
4162
+ }
4163
+ ),
3688
4164
  /* @__PURE__ */ jsx12(
3689
4165
  "div",
3690
4166
  {
@@ -3725,26 +4201,33 @@ var TaskListRow = React9.memo(
3725
4201
  ]
3726
4202
  }
3727
4203
  ) }),
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,
4204
+ /* @__PURE__ */ jsx12(PopoverContent, { portal: true, align: "start", children: /* @__PURE__ */ jsx12(
4205
+ "div",
3730
4206
  {
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
- )) }) })
4207
+ className: "gantt-tl-dep-overflow-list",
4208
+ onClick: (e) => e.stopPropagation(),
4209
+ children: chips.map(({ dep, lag, predecessorName }) => /* @__PURE__ */ jsx12(
4210
+ DepChip,
4211
+ {
4212
+ lag,
4213
+ dep,
4214
+ taskId: task.id,
4215
+ predecessorName,
4216
+ selectedChip,
4217
+ disableDependencyEditing,
4218
+ onChipSelect,
4219
+ onRowClick,
4220
+ onScrollToTask,
4221
+ onRemoveDependency,
4222
+ onChipSelectClear: () => onChipSelect?.(null),
4223
+ task,
4224
+ allTasks,
4225
+ onTasksChange
4226
+ },
4227
+ `${dep.taskId}-${dep.type}`
4228
+ ))
4229
+ }
4230
+ ) })
3748
4231
  ] })
3749
4232
  ) : chips.length === 1 ? (
3750
4233
  /* Single chip — unified DepChip */
@@ -3909,7 +4392,10 @@ var TaskList = ({
3909
4392
  collapsedParentIds: externalCollapsedParentIds,
3910
4393
  onToggleCollapse: externalOnToggleCollapse,
3911
4394
  onPromoteTask,
3912
- onDemoteTask
4395
+ onDemoteTask,
4396
+ weekends,
4397
+ workdays,
4398
+ isWeekend: isWeekend3
3913
4399
  }) => {
3914
4400
  const [internalCollapsedParentIds, setInternalCollapsedParentIds] = useState6(/* @__PURE__ */ new Set());
3915
4401
  const collapsedParentIds = externalCollapsedParentIds ?? internalCollapsedParentIds;
@@ -3943,6 +4429,25 @@ var TaskList = ({
3943
4429
  () => visibleTasks.length * rowHeight,
3944
4430
  [visibleTasks.length, rowHeight]
3945
4431
  );
4432
+ const nestingDepthMap = useMemo8(() => {
4433
+ const depthMap = /* @__PURE__ */ new Map();
4434
+ const taskById = new Map(tasks.map((t) => [t.id, t]));
4435
+ function getDepth(taskId) {
4436
+ if (depthMap.has(taskId)) return depthMap.get(taskId);
4437
+ const task = taskById.get(taskId);
4438
+ if (!task || !task.parentId || !taskById.has(task.parentId)) {
4439
+ depthMap.set(taskId, 0);
4440
+ return 0;
4441
+ }
4442
+ const depth = getDepth(task.parentId) + 1;
4443
+ depthMap.set(taskId, depth);
4444
+ return depth;
4445
+ }
4446
+ for (const task of tasks) {
4447
+ getDepth(task.id);
4448
+ }
4449
+ return depthMap;
4450
+ }, [tasks]);
3946
4451
  const lastChildIds = useMemo8(() => {
3947
4452
  const last = /* @__PURE__ */ new Set();
3948
4453
  const seenParents = /* @__PURE__ */ new Set();
@@ -3955,6 +4460,20 @@ var TaskList = ({
3955
4460
  }
3956
4461
  return last;
3957
4462
  }, [visibleTasks]);
4463
+ const ancestorContinuesMap = useMemo8(() => {
4464
+ const taskById = new Map(tasks.map((t) => [t.id, t]));
4465
+ const map = /* @__PURE__ */ new Map();
4466
+ for (const task of visibleTasks) {
4467
+ const continues = [];
4468
+ let current = taskById.get(task.id);
4469
+ while (current?.parentId && taskById.has(current.parentId)) {
4470
+ continues.unshift(!lastChildIds.has(current.id));
4471
+ current = taskById.get(current.parentId);
4472
+ }
4473
+ map.set(task.id, continues.slice(0, -1));
4474
+ }
4475
+ return map;
4476
+ }, [tasks, visibleTasks, lastChildIds]);
3958
4477
  const handleRowClick = useCallback5((taskId) => {
3959
4478
  onTaskSelect?.(taskId);
3960
4479
  }, [onTaskSelect]);
@@ -4065,9 +4584,6 @@ var TaskList = ({
4065
4584
  if (dropTarget.parentId === draggedTaskId) {
4066
4585
  return false;
4067
4586
  }
4068
- if (dropTarget.parentId) {
4069
- return false;
4070
- }
4071
4587
  const draggedTask = orderedTasks.find((t) => t.id === draggedTaskId);
4072
4588
  if (!draggedTask) return true;
4073
4589
  const descendants = getAllDescendants(draggedTaskId, orderedTasks);
@@ -4213,6 +4729,52 @@ var TaskList = ({
4213
4729
  setIsCreating(false);
4214
4730
  }, [onAdd]);
4215
4731
  const handleCancelNewTask = useCallback5(() => setIsCreating(false), []);
4732
+ function getTaskDepth(task, tasks2) {
4733
+ if (!task) return 0;
4734
+ let depth = 0;
4735
+ let current = task;
4736
+ while (current) {
4737
+ if (!current.parentId) break;
4738
+ depth++;
4739
+ const parentId = current.parentId;
4740
+ current = tasks2.find((t) => t.id === parentId);
4741
+ }
4742
+ return depth;
4743
+ }
4744
+ const handleDemoteWrapper = useCallback5((taskId, _newParentId) => {
4745
+ const taskIndex = visibleTasks.findIndex((t) => t.id === taskId);
4746
+ const currentTask = visibleTasks[taskIndex];
4747
+ const currentDepth = getTaskDepth(currentTask, orderedTasks);
4748
+ if (taskIndex > 0) {
4749
+ for (let i = taskIndex - 1; i >= 0; i--) {
4750
+ const previousTask = visibleTasks[i];
4751
+ const previousDepth = getTaskDepth(previousTask, orderedTasks);
4752
+ if (previousDepth === currentDepth) {
4753
+ onDemoteTask?.(taskId, previousTask.id);
4754
+ return;
4755
+ }
4756
+ if (previousDepth < currentDepth) {
4757
+ break;
4758
+ }
4759
+ }
4760
+ return;
4761
+ }
4762
+ const demotedTask = orderedTasks.find((t) => t.id === taskId);
4763
+ if (!demotedTask) return;
4764
+ const newSectionTask = {
4765
+ id: crypto.randomUUID(),
4766
+ name: "\u041D\u043E\u0432\u044B\u0439 \u0440\u0430\u0437\u0434\u0435\u043B",
4767
+ startDate: demotedTask.startDate,
4768
+ endDate: demotedTask.endDate
4769
+ };
4770
+ const updatedTasks = [
4771
+ newSectionTask,
4772
+ ...orderedTasks.map(
4773
+ (t) => t.id === taskId ? { ...t, parentId: newSectionTask.id } : t
4774
+ )
4775
+ ];
4776
+ onReorder?.(updatedTasks, taskId, newSectionTask.id);
4777
+ }, [visibleTasks, orderedTasks, onDemoteTask, onReorder]);
4216
4778
  const effectiveTaskListWidth = Math.max(taskListWidth, MIN_TASK_LIST_WIDTH);
4217
4779
  return /* @__PURE__ */ jsx14(
4218
4780
  "div",
@@ -4296,8 +4858,13 @@ var TaskList = ({
4296
4858
  collapsedParentIds,
4297
4859
  onToggleCollapse: handleToggleCollapse,
4298
4860
  onPromoteTask,
4299
- onDemoteTask,
4300
- isLastChild: lastChildIds.has(task.id)
4861
+ onDemoteTask: onDemoteTask ? handleDemoteWrapper : void 0,
4862
+ isLastChild: lastChildIds.has(task.id),
4863
+ nestingDepth: nestingDepthMap.get(task.id) ?? 0,
4864
+ ancestorContinues: ancestorContinuesMap.get(task.id) ?? [],
4865
+ weekends,
4866
+ workdays,
4867
+ isWeekend: isWeekend3
4301
4868
  },
4302
4869
  task.id
4303
4870
  )) }),
@@ -4365,7 +4932,10 @@ var GanttChart = forwardRef(({
4365
4932
  onPromoteTask,
4366
4933
  onDemoteTask,
4367
4934
  enableAddTask = true,
4368
- viewMode = "day"
4935
+ viewMode = "day",
4936
+ weekends,
4937
+ workdays,
4938
+ isWeekend: isWeekend3
4369
4939
  }, ref) => {
4370
4940
  const scrollContainerRef = useRef7(null);
4371
4941
  const [selectedTaskId, setSelectedTaskId] = useState7(null);
@@ -4374,6 +4944,10 @@ var GanttChart = forwardRef(({
4374
4944
  const [collapsedParentIds, setCollapsedParentIds] = useState7(/* @__PURE__ */ new Set());
4375
4945
  const [editingTaskId, setEditingTaskId] = useState7(null);
4376
4946
  const normalizedTasks = useMemo9(() => normalizeHierarchyTasks(tasks), [tasks]);
4947
+ const isCustomWeekend = useMemo9(
4948
+ () => createIsWeekendPredicate({ weekends, workdays, isWeekend: isWeekend3 }),
4949
+ [weekends, workdays, isWeekend3]
4950
+ );
4377
4951
  const dateRange = useMemo9(() => getMultiMonthDays(normalizedTasks), [normalizedTasks]);
4378
4952
  const [validationResult, setValidationResult] = useState7(null);
4379
4953
  const [cascadeOverrides, setCascadeOverrides] = useState7(/* @__PURE__ */ new Map());
@@ -4606,6 +5180,17 @@ var GanttChart = forwardRef(({
4606
5180
  }),
4607
5181
  [scrollToToday, scrollToTask, handleCollapseAll, handleExpandAll]
4608
5182
  );
5183
+ function getTaskDepth(taskId, tasks2) {
5184
+ let depth = 0;
5185
+ let current = tasks2.find((t) => t.id === taskId);
5186
+ while (current) {
5187
+ if (!current.parentId) break;
5188
+ depth++;
5189
+ const parentId = current.parentId;
5190
+ current = tasks2.find((t) => t.id === parentId);
5191
+ }
5192
+ return depth;
5193
+ }
4609
5194
  const handlePromoteTask = useCallback6((taskId) => {
4610
5195
  if (onPromoteTask) {
4611
5196
  onPromoteTask(taskId);
@@ -4615,20 +5200,20 @@ var GanttChart = forwardRef(({
4615
5200
  if (!taskToPromote || !taskToPromote.parentId) {
4616
5201
  return;
4617
5202
  }
4618
- const parentId = taskToPromote.parentId;
4619
- const siblings = tasks.filter((t) => t.parentId === parentId);
5203
+ const depth = getTaskDepth(taskId, tasks);
5204
+ const grandparentId = depth > 1 ? tasks.find((t) => t.id === taskToPromote.parentId)?.parentId : void 0;
5205
+ const currentParentId = taskToPromote.parentId;
5206
+ const siblings = tasks.filter((t) => t.parentId === currentParentId);
5207
+ const promotedTask = { ...taskToPromote, parentId: grandparentId };
4620
5208
  if (siblings.length <= 1) {
4621
- const promotedTask2 = { ...taskToPromote, parentId: void 0 };
4622
- onTasksChange?.([promotedTask2]);
5209
+ onTasksChange?.([promotedTask]);
4623
5210
  return;
4624
5211
  }
4625
- const lastSiblingIndex = tasks.map((t, i) => ({ task: t, index: i })).filter(({ task }) => task.parentId === parentId).sort((a, b) => b.index - a.index)[0];
5212
+ const lastSiblingIndex = tasks.map((t, i) => ({ task: t, index: i })).filter(({ task }) => task.parentId === currentParentId).sort((a, b) => b.index - a.index)[0];
4626
5213
  if (!lastSiblingIndex) {
4627
- const promotedTask2 = { ...taskToPromote, parentId: void 0 };
4628
- onTasksChange?.([promotedTask2]);
5214
+ onTasksChange?.([promotedTask]);
4629
5215
  return;
4630
5216
  }
4631
- const promotedTask = { ...taskToPromote, parentId: void 0 };
4632
5217
  const reorderedTasks = normalizeHierarchyTasks([
4633
5218
  ...tasks.filter((t) => t.id !== taskId).slice(0, lastSiblingIndex.index + 1),
4634
5219
  promotedTask,
@@ -4754,7 +5339,10 @@ var GanttChart = forwardRef(({
4754
5339
  collapsedParentIds,
4755
5340
  onToggleCollapse: handleToggleCollapse,
4756
5341
  onPromoteTask: onPromoteTask ?? handlePromoteTask,
4757
- onDemoteTask: onDemoteTask ?? handleDemoteTask
5342
+ onDemoteTask: onDemoteTask ?? handleDemoteTask,
5343
+ weekends,
5344
+ workdays,
5345
+ isWeekend: isWeekend3
4758
5346
  }
4759
5347
  ),
4760
5348
  /* @__PURE__ */ jsxs12("div", { style: { minWidth: `${gridWidth}px`, flex: 1 }, children: [
@@ -4764,7 +5352,8 @@ var GanttChart = forwardRef(({
4764
5352
  days: dateRange,
4765
5353
  dayWidth,
4766
5354
  headerHeight,
4767
- viewMode
5355
+ viewMode,
5356
+ isCustomWeekend
4768
5357
  }
4769
5358
  ) }),
4770
5359
  /* @__PURE__ */ jsxs12(
@@ -4782,7 +5371,8 @@ var GanttChart = forwardRef(({
4782
5371
  dateRange,
4783
5372
  dayWidth,
4784
5373
  totalHeight: totalGridHeight,
4785
- viewMode
5374
+ viewMode,
5375
+ isCustomWeekend
4786
5376
  }
4787
5377
  ),
4788
5378
  todayInRange && /* @__PURE__ */ jsx15(TodayIndicator_default, { monthStart, dayWidth }),
@@ -4896,6 +5486,8 @@ export {
4896
5486
  computeLagFromDates,
4897
5487
  computeParentDates,
4898
5488
  computeParentProgress,
5489
+ createDateKey,
5490
+ createIsWeekendPredicate,
4899
5491
  detectCycles,
4900
5492
  detectEdgeZone,
4901
5493
  findParentId,