gantt-lib 0.6.2 → 0.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.css.map +1 -1
- package/dist/index.d.mts +29 -2
- package/dist/index.d.ts +29 -2
- package/dist/index.js +311 -70
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +309 -70
- package/dist/index.mjs.map +1 -1
- package/dist/styles.css +112 -32
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -72,10 +72,12 @@ __export(index_exports, {
|
|
|
72
72
|
getMultiMonthDays: () => getMultiMonthDays,
|
|
73
73
|
getSuccessorChain: () => getSuccessorChain,
|
|
74
74
|
getTransitiveCascadeChain: () => getTransitiveCascadeChain,
|
|
75
|
+
getVisibleReorderPosition: () => getVisibleReorderPosition,
|
|
75
76
|
isTaskParent: () => isTaskParent,
|
|
76
77
|
isToday: () => isToday,
|
|
77
78
|
isWeekend: () => isWeekend,
|
|
78
79
|
normalizeHierarchyTasks: () => normalizeHierarchyTasks,
|
|
80
|
+
normalizeTaskDates: () => normalizeTaskDates,
|
|
79
81
|
parseUTCDate: () => parseUTCDate,
|
|
80
82
|
pixelsToDate: () => pixelsToDate,
|
|
81
83
|
recalculateIncomingLags: () => recalculateIncomingLags,
|
|
@@ -227,6 +229,20 @@ var formatDateLabel = (date) => {
|
|
|
227
229
|
const month = String(parsed.getUTCMonth() + 1).padStart(2, "0");
|
|
228
230
|
return `${day}.${month}`;
|
|
229
231
|
};
|
|
232
|
+
var normalizeTaskDates = (startDate, endDate) => {
|
|
233
|
+
const start = parseUTCDate(startDate);
|
|
234
|
+
const end = parseUTCDate(endDate);
|
|
235
|
+
if (end.getTime() < start.getTime()) {
|
|
236
|
+
return {
|
|
237
|
+
startDate: end.toISOString().split("T")[0],
|
|
238
|
+
endDate: start.toISOString().split("T")[0]
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
return {
|
|
242
|
+
startDate: start.toISOString().split("T")[0],
|
|
243
|
+
endDate: end.toISOString().split("T")[0]
|
|
244
|
+
};
|
|
245
|
+
};
|
|
230
246
|
|
|
231
247
|
// src/utils/dependencyUtils.ts
|
|
232
248
|
function buildAdjacencyList(tasks) {
|
|
@@ -281,33 +297,33 @@ function detectCycles(tasks) {
|
|
|
281
297
|
return { hasCycle: false };
|
|
282
298
|
}
|
|
283
299
|
function computeLagFromDates(linkType, predStart, predEnd, succStart, succEnd) {
|
|
284
|
-
const
|
|
300
|
+
const DAY_MS2 = 24 * 60 * 60 * 1e3;
|
|
285
301
|
const pS = Date.UTC(predStart.getUTCFullYear(), predStart.getUTCMonth(), predStart.getUTCDate());
|
|
286
302
|
const pE = Date.UTC(predEnd.getUTCFullYear(), predEnd.getUTCMonth(), predEnd.getUTCDate());
|
|
287
303
|
const sS = Date.UTC(succStart.getUTCFullYear(), succStart.getUTCMonth(), succStart.getUTCDate());
|
|
288
304
|
const sE = Date.UTC(succEnd.getUTCFullYear(), succEnd.getUTCMonth(), succEnd.getUTCDate());
|
|
289
305
|
switch (linkType) {
|
|
290
306
|
case "FS":
|
|
291
|
-
return Math.round((sS - pE) /
|
|
307
|
+
return Math.round((sS - pE) / DAY_MS2) - 1;
|
|
292
308
|
case "SS":
|
|
293
|
-
return Math.round((sS - pS) /
|
|
309
|
+
return Math.round((sS - pS) / DAY_MS2);
|
|
294
310
|
case "FF":
|
|
295
|
-
return Math.round((sE - pE) /
|
|
311
|
+
return Math.round((sE - pE) / DAY_MS2);
|
|
296
312
|
case "SF":
|
|
297
|
-
return Math.round((sE - pS) /
|
|
313
|
+
return Math.round((sE - pS) / DAY_MS2) + 1;
|
|
298
314
|
}
|
|
299
315
|
}
|
|
300
316
|
function calculateSuccessorDate(predecessorStart, predecessorEnd, linkType, lag = 0) {
|
|
301
|
-
const
|
|
317
|
+
const DAY_MS2 = 24 * 60 * 60 * 1e3;
|
|
302
318
|
switch (linkType) {
|
|
303
319
|
case "FS":
|
|
304
|
-
return new Date(predecessorEnd.getTime() + (lag + 1) *
|
|
320
|
+
return new Date(predecessorEnd.getTime() + (lag + 1) * DAY_MS2);
|
|
305
321
|
case "SS":
|
|
306
|
-
return new Date(predecessorStart.getTime() + lag *
|
|
322
|
+
return new Date(predecessorStart.getTime() + lag * DAY_MS2);
|
|
307
323
|
case "FF":
|
|
308
|
-
return new Date(predecessorEnd.getTime() + lag *
|
|
324
|
+
return new Date(predecessorEnd.getTime() + lag * DAY_MS2);
|
|
309
325
|
case "SF":
|
|
310
|
-
return new Date(predecessorStart.getTime() + (lag - 1) *
|
|
326
|
+
return new Date(predecessorStart.getTime() + (lag - 1) * DAY_MS2);
|
|
311
327
|
}
|
|
312
328
|
}
|
|
313
329
|
function validateDependencies(tasks) {
|
|
@@ -539,13 +555,13 @@ function computeParentProgress(parentId, tasks) {
|
|
|
539
555
|
if (children.length === 0) {
|
|
540
556
|
return 0;
|
|
541
557
|
}
|
|
542
|
-
const
|
|
558
|
+
const DAY_MS2 = 24 * 60 * 60 * 1e3;
|
|
543
559
|
let totalWeight = 0;
|
|
544
560
|
let weightedSum = 0;
|
|
545
561
|
for (const child of children) {
|
|
546
562
|
const start = new Date(child.startDate).getTime();
|
|
547
563
|
const end = new Date(child.endDate).getTime();
|
|
548
|
-
const duration = (end - start +
|
|
564
|
+
const duration = (end - start + DAY_MS2) / DAY_MS2;
|
|
549
565
|
const progress = child.progress ?? 0;
|
|
550
566
|
totalWeight += duration;
|
|
551
567
|
weightedSum += duration * progress;
|
|
@@ -607,7 +623,10 @@ function flattenHierarchy(tasks) {
|
|
|
607
623
|
return result;
|
|
608
624
|
}
|
|
609
625
|
function normalizeHierarchyTasks(tasks) {
|
|
610
|
-
const orderedTasks = flattenHierarchy(tasks).map((task) =>
|
|
626
|
+
const orderedTasks = flattenHierarchy(tasks).map((task) => {
|
|
627
|
+
const { startDate, endDate } = normalizeTaskDates(task.startDate, task.endDate);
|
|
628
|
+
return { ...task, startDate, endDate };
|
|
629
|
+
});
|
|
611
630
|
for (const task of [...orderedTasks].reverse()) {
|
|
612
631
|
if (!isTaskParent(task.id, orderedTasks)) continue;
|
|
613
632
|
const { startDate, endDate } = computeParentDates(task.id, orderedTasks);
|
|
@@ -2082,6 +2101,36 @@ var DependencyLines_default = DependencyLines;
|
|
|
2082
2101
|
// src/components/TaskList/TaskList.tsx
|
|
2083
2102
|
var import_react12 = __toESM(require("react"));
|
|
2084
2103
|
|
|
2104
|
+
// src/utils/taskListReorder.ts
|
|
2105
|
+
function getVisibleReorderPosition(orderedTasks, visibleTasks, movedTaskId, originVisibleIndex, dropVisibleIndex) {
|
|
2106
|
+
const originOrderedIndex = orderedTasks.findIndex((task) => task.id === movedTaskId);
|
|
2107
|
+
if (originOrderedIndex === -1) {
|
|
2108
|
+
return null;
|
|
2109
|
+
}
|
|
2110
|
+
const reorderedWithoutMoved = orderedTasks.filter((task) => task.id !== movedTaskId);
|
|
2111
|
+
const visibleWithoutMoved = visibleTasks.filter((task) => task.id !== movedTaskId);
|
|
2112
|
+
const visibleInsertIndex = originVisibleIndex < dropVisibleIndex ? dropVisibleIndex - 1 : dropVisibleIndex;
|
|
2113
|
+
if (visibleWithoutMoved.length === 0) {
|
|
2114
|
+
return { originOrderedIndex, insertIndex: 0 };
|
|
2115
|
+
}
|
|
2116
|
+
if (visibleInsertIndex <= 0) {
|
|
2117
|
+
return {
|
|
2118
|
+
originOrderedIndex,
|
|
2119
|
+
insertIndex: reorderedWithoutMoved.findIndex((task) => task.id === visibleWithoutMoved[0].id)
|
|
2120
|
+
};
|
|
2121
|
+
}
|
|
2122
|
+
if (visibleInsertIndex >= visibleWithoutMoved.length) {
|
|
2123
|
+
return {
|
|
2124
|
+
originOrderedIndex,
|
|
2125
|
+
insertIndex: reorderedWithoutMoved.length
|
|
2126
|
+
};
|
|
2127
|
+
}
|
|
2128
|
+
return {
|
|
2129
|
+
originOrderedIndex,
|
|
2130
|
+
insertIndex: reorderedWithoutMoved.findIndex((task) => task.id === visibleWithoutMoved[visibleInsertIndex].id)
|
|
2131
|
+
};
|
|
2132
|
+
}
|
|
2133
|
+
|
|
2085
2134
|
// src/components/ui/Popover.tsx
|
|
2086
2135
|
var RadixPopover = __toESM(require("@radix-ui/react-popover"));
|
|
2087
2136
|
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
@@ -2418,6 +2467,16 @@ var LINK_TYPE_LABELS = {
|
|
|
2418
2467
|
|
|
2419
2468
|
// src/components/TaskList/TaskListRow.tsx
|
|
2420
2469
|
var import_jsx_runtime12 = require("react/jsx-runtime");
|
|
2470
|
+
var DAY_MS = 24 * 60 * 60 * 1e3;
|
|
2471
|
+
var getInclusiveDurationDays = (startDate, endDate) => {
|
|
2472
|
+
const start = parseUTCDate(startDate);
|
|
2473
|
+
const end = parseUTCDate(endDate);
|
|
2474
|
+
return Math.max(1, Math.round((end.getTime() - start.getTime()) / DAY_MS) + 1);
|
|
2475
|
+
};
|
|
2476
|
+
var getEndDateFromDuration = (startDate, durationDays) => {
|
|
2477
|
+
const start = parseUTCDate(startDate);
|
|
2478
|
+
return new Date(start.getTime() + (durationDays - 1) * DAY_MS).toISOString().split("T")[0];
|
|
2479
|
+
};
|
|
2421
2480
|
var TrashIcon = () => /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("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: [
|
|
2422
2481
|
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("path", { d: "M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6" }),
|
|
2423
2482
|
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("path", { d: "M3 6h18" }),
|
|
@@ -2432,6 +2491,7 @@ var DragHandleIcon = () => /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("svg",
|
|
|
2432
2491
|
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("circle", { cx: "2", cy: "12", r: "1.5" }),
|
|
2433
2492
|
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("circle", { cx: "8", cy: "12", r: "1.5" })
|
|
2434
2493
|
] });
|
|
2494
|
+
var ChevronRightIcon = () => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("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__ */ (0, import_jsx_runtime12.jsx)("path", { d: "m9 18 6-6-6-6" }) });
|
|
2435
2495
|
var HierarchyButton = ({
|
|
2436
2496
|
isChild,
|
|
2437
2497
|
isParent,
|
|
@@ -2600,11 +2660,16 @@ var TaskListRow = import_react10.default.memo(
|
|
|
2600
2660
|
const [editingName, setEditingName] = (0, import_react10.useState)(false);
|
|
2601
2661
|
const [nameValue, setNameValue] = (0, import_react10.useState)("");
|
|
2602
2662
|
const nameInputRef = (0, import_react10.useRef)(null);
|
|
2663
|
+
const [editingDuration, setEditingDuration] = (0, import_react10.useState)(false);
|
|
2664
|
+
const [durationValue, setDurationValue] = (0, import_react10.useState)(getInclusiveDurationDays(task.startDate, task.endDate));
|
|
2665
|
+
const durationInputRef = (0, import_react10.useRef)(null);
|
|
2603
2666
|
const [editingProgress, setEditingProgress] = (0, import_react10.useState)(false);
|
|
2604
2667
|
const [progressValue, setProgressValue] = (0, import_react10.useState)(0);
|
|
2605
2668
|
const progressInputRef = (0, import_react10.useRef)(null);
|
|
2606
2669
|
const [overflowOpen, setOverflowOpen] = (0, import_react10.useState)(false);
|
|
2607
|
-
const
|
|
2670
|
+
const nameConfirmedRef = (0, import_react10.useRef)(false);
|
|
2671
|
+
const durationConfirmedRef = (0, import_react10.useRef)(false);
|
|
2672
|
+
const progressConfirmedRef = (0, import_react10.useRef)(false);
|
|
2608
2673
|
const autoEditedForRef = (0, import_react10.useRef)(null);
|
|
2609
2674
|
const editTriggerRef = (0, import_react10.useRef)("doubleclick");
|
|
2610
2675
|
const [deletePending, setDeletePending] = (0, import_react10.useState)(false);
|
|
@@ -2659,7 +2724,7 @@ var TaskListRow = import_react10.default.memo(
|
|
|
2659
2724
|
(0, import_react10.useEffect)(() => {
|
|
2660
2725
|
if (editingTaskId === task.id && !disableTaskNameEditing && autoEditedForRef.current !== editingTaskId) {
|
|
2661
2726
|
autoEditedForRef.current = editingTaskId;
|
|
2662
|
-
|
|
2727
|
+
nameConfirmedRef.current = false;
|
|
2663
2728
|
editTriggerRef.current = "autoedit";
|
|
2664
2729
|
setNameValue(task.name);
|
|
2665
2730
|
setEditingName(true);
|
|
@@ -2674,7 +2739,7 @@ var TaskListRow = import_react10.default.memo(
|
|
|
2674
2739
|
const handleNameDoubleClick = (0, import_react10.useCallback)((e) => {
|
|
2675
2740
|
if (disableTaskNameEditing) return;
|
|
2676
2741
|
e.stopPropagation();
|
|
2677
|
-
|
|
2742
|
+
nameConfirmedRef.current = false;
|
|
2678
2743
|
editTriggerRef.current = "doubleclick";
|
|
2679
2744
|
setNameValue(task.name);
|
|
2680
2745
|
setEditingName(true);
|
|
@@ -2683,7 +2748,7 @@ var TaskListRow = import_react10.default.memo(
|
|
|
2683
2748
|
if (editingProgress) return;
|
|
2684
2749
|
if (!editingName && !disableTaskNameEditing && e.key === "F2") {
|
|
2685
2750
|
e.preventDefault();
|
|
2686
|
-
|
|
2751
|
+
nameConfirmedRef.current = false;
|
|
2687
2752
|
editTriggerRef.current = "keypress";
|
|
2688
2753
|
setNameValue(task.name);
|
|
2689
2754
|
setEditingName(true);
|
|
@@ -2691,15 +2756,15 @@ var TaskListRow = import_react10.default.memo(
|
|
|
2691
2756
|
}
|
|
2692
2757
|
if (!editingName && !disableTaskNameEditing && e.key.length === 1 && !e.ctrlKey && !e.metaKey && !e.altKey) {
|
|
2693
2758
|
e.preventDefault();
|
|
2694
|
-
|
|
2759
|
+
nameConfirmedRef.current = false;
|
|
2695
2760
|
editTriggerRef.current = "keypress";
|
|
2696
2761
|
setNameValue(e.key);
|
|
2697
2762
|
setEditingName(true);
|
|
2698
2763
|
}
|
|
2699
2764
|
}, [editingName, disableTaskNameEditing, task.name]);
|
|
2700
2765
|
const handleNameSave = (0, import_react10.useCallback)(() => {
|
|
2701
|
-
if (
|
|
2702
|
-
|
|
2766
|
+
if (nameConfirmedRef.current) {
|
|
2767
|
+
nameConfirmedRef.current = false;
|
|
2703
2768
|
return;
|
|
2704
2769
|
}
|
|
2705
2770
|
if (nameValue.trim()) {
|
|
@@ -2712,7 +2777,7 @@ var TaskListRow = import_react10.default.memo(
|
|
|
2712
2777
|
}, []);
|
|
2713
2778
|
const handleNameKeyDown = (0, import_react10.useCallback)((e) => {
|
|
2714
2779
|
if (e.key === "Enter") {
|
|
2715
|
-
|
|
2780
|
+
nameConfirmedRef.current = true;
|
|
2716
2781
|
if (nameValue.trim()) {
|
|
2717
2782
|
onTaskChange?.({ ...task, name: nameValue.trim() });
|
|
2718
2783
|
}
|
|
@@ -2721,15 +2786,54 @@ var TaskListRow = import_react10.default.memo(
|
|
|
2721
2786
|
handleNameCancel();
|
|
2722
2787
|
}
|
|
2723
2788
|
}, [nameValue, task, onTaskChange, handleNameCancel]);
|
|
2789
|
+
const handleDurationClick = (0, import_react10.useCallback)((e) => {
|
|
2790
|
+
if (task.locked) return;
|
|
2791
|
+
e.stopPropagation();
|
|
2792
|
+
durationConfirmedRef.current = false;
|
|
2793
|
+
setDurationValue(getInclusiveDurationDays(task.startDate, task.endDate));
|
|
2794
|
+
setEditingDuration(true);
|
|
2795
|
+
}, [task.locked, task.startDate, task.endDate]);
|
|
2796
|
+
const applyDurationChange = (0, import_react10.useCallback)((nextDuration) => {
|
|
2797
|
+
const normalizedDuration = Math.max(1, Math.round(nextDuration) || 1);
|
|
2798
|
+
setDurationValue(normalizedDuration);
|
|
2799
|
+
}, []);
|
|
2800
|
+
const handleDurationSave = (0, import_react10.useCallback)(() => {
|
|
2801
|
+
if (durationConfirmedRef.current) {
|
|
2802
|
+
durationConfirmedRef.current = false;
|
|
2803
|
+
return;
|
|
2804
|
+
}
|
|
2805
|
+
const normalizedDuration = Math.max(1, Math.round(durationValue) || 1);
|
|
2806
|
+
onTaskChange?.({ ...task, endDate: getEndDateFromDuration(task.startDate, normalizedDuration) });
|
|
2807
|
+
setEditingDuration(false);
|
|
2808
|
+
}, [durationValue, task, onTaskChange]);
|
|
2809
|
+
const handleDurationCancel = (0, import_react10.useCallback)(() => {
|
|
2810
|
+
setDurationValue(getInclusiveDurationDays(task.startDate, task.endDate));
|
|
2811
|
+
setEditingDuration(false);
|
|
2812
|
+
}, [task.startDate, task.endDate]);
|
|
2813
|
+
const handleDurationAdjust = (0, import_react10.useCallback)((delta) => {
|
|
2814
|
+
applyDurationChange(durationValue + delta);
|
|
2815
|
+
}, [applyDurationChange, durationValue]);
|
|
2816
|
+
const handleDurationKeyDown = (0, import_react10.useCallback)((e) => {
|
|
2817
|
+
e.stopPropagation();
|
|
2818
|
+
if (e.key === "Enter") {
|
|
2819
|
+
durationConfirmedRef.current = true;
|
|
2820
|
+
const normalizedDuration = Math.max(1, Math.round(durationValue) || 1);
|
|
2821
|
+
onTaskChange?.({ ...task, endDate: getEndDateFromDuration(task.startDate, normalizedDuration) });
|
|
2822
|
+
setEditingDuration(false);
|
|
2823
|
+
} else if (e.key === "Escape") {
|
|
2824
|
+
handleDurationCancel();
|
|
2825
|
+
}
|
|
2826
|
+
}, [durationValue, task, onTaskChange, handleDurationCancel]);
|
|
2724
2827
|
const handleProgressClick = (0, import_react10.useCallback)((e) => {
|
|
2828
|
+
if (task.locked) return;
|
|
2725
2829
|
e.stopPropagation();
|
|
2726
|
-
|
|
2830
|
+
progressConfirmedRef.current = false;
|
|
2727
2831
|
setProgressValue(task.progress ?? 0);
|
|
2728
2832
|
setEditingProgress(true);
|
|
2729
|
-
}, [task.progress]);
|
|
2833
|
+
}, [task.progress, task.locked]);
|
|
2730
2834
|
const handleProgressSave = (0, import_react10.useCallback)(() => {
|
|
2731
|
-
if (
|
|
2732
|
-
|
|
2835
|
+
if (progressConfirmedRef.current) {
|
|
2836
|
+
progressConfirmedRef.current = false;
|
|
2733
2837
|
return;
|
|
2734
2838
|
}
|
|
2735
2839
|
const clampedValue = Math.max(0, Math.min(100, progressValue));
|
|
@@ -2739,10 +2843,13 @@ var TaskListRow = import_react10.default.memo(
|
|
|
2739
2843
|
const handleProgressCancel = (0, import_react10.useCallback)(() => {
|
|
2740
2844
|
setEditingProgress(false);
|
|
2741
2845
|
}, []);
|
|
2846
|
+
const handleProgressAdjust = (0, import_react10.useCallback)((delta) => {
|
|
2847
|
+
setProgressValue((current) => Math.max(0, Math.min(100, current + delta)));
|
|
2848
|
+
}, []);
|
|
2742
2849
|
const handleProgressKeyDown = (0, import_react10.useCallback)((e) => {
|
|
2743
2850
|
e.stopPropagation();
|
|
2744
2851
|
if (e.key === "Enter") {
|
|
2745
|
-
|
|
2852
|
+
progressConfirmedRef.current = true;
|
|
2746
2853
|
const clampedValue = Math.max(0, Math.min(100, progressValue));
|
|
2747
2854
|
onTaskChange?.({ ...task, progress: clampedValue });
|
|
2748
2855
|
setEditingProgress(false);
|
|
@@ -2756,6 +2863,15 @@ var TaskListRow = import_react10.default.memo(
|
|
|
2756
2863
|
progressInputRef.current.select();
|
|
2757
2864
|
}
|
|
2758
2865
|
}, [editingProgress]);
|
|
2866
|
+
(0, import_react10.useEffect)(() => {
|
|
2867
|
+
setDurationValue(getInclusiveDurationDays(task.startDate, task.endDate));
|
|
2868
|
+
}, [task.startDate, task.endDate]);
|
|
2869
|
+
(0, import_react10.useEffect)(() => {
|
|
2870
|
+
if (editingDuration && durationInputRef.current) {
|
|
2871
|
+
durationInputRef.current.focus();
|
|
2872
|
+
durationInputRef.current.select();
|
|
2873
|
+
}
|
|
2874
|
+
}, [editingDuration]);
|
|
2759
2875
|
const handleStartDateChange = (0, import_react10.useCallback)((newDateISO) => {
|
|
2760
2876
|
if (!newDateISO) return;
|
|
2761
2877
|
const origStart = parseUTCDate(task.startDate);
|
|
@@ -2763,7 +2879,11 @@ var TaskListRow = import_react10.default.memo(
|
|
|
2763
2879
|
const durationMs = origEnd.getTime() - origStart.getTime();
|
|
2764
2880
|
const newStart = /* @__PURE__ */ new Date(newDateISO + "T00:00:00Z");
|
|
2765
2881
|
const newEnd = new Date(newStart.getTime() + durationMs);
|
|
2766
|
-
|
|
2882
|
+
const { startDate: normalizedStart, endDate: normalizedEnd } = normalizeTaskDates(
|
|
2883
|
+
newDateISO,
|
|
2884
|
+
newEnd.toISOString().split("T")[0]
|
|
2885
|
+
);
|
|
2886
|
+
onTaskChange?.({ ...task, startDate: normalizedStart, endDate: normalizedEnd });
|
|
2767
2887
|
}, [task, onTaskChange]);
|
|
2768
2888
|
const handleEndDateChange = (0, import_react10.useCallback)((newDateISO) => {
|
|
2769
2889
|
if (!newDateISO) return;
|
|
@@ -2772,7 +2892,11 @@ var TaskListRow = import_react10.default.memo(
|
|
|
2772
2892
|
const durationMs = origEnd.getTime() - origStart.getTime();
|
|
2773
2893
|
const newEnd = /* @__PURE__ */ new Date(newDateISO + "T00:00:00Z");
|
|
2774
2894
|
const newStart = new Date(newEnd.getTime() - durationMs);
|
|
2775
|
-
|
|
2895
|
+
const { startDate: normalizedStart, endDate: normalizedEnd } = normalizeTaskDates(
|
|
2896
|
+
newStart.toISOString().split("T")[0],
|
|
2897
|
+
newDateISO
|
|
2898
|
+
);
|
|
2899
|
+
onTaskChange?.({ ...task, startDate: normalizedStart, endDate: normalizedEnd });
|
|
2776
2900
|
}, [task, onTaskChange]);
|
|
2777
2901
|
const handleRowClickInternal = (0, import_react10.useCallback)(() => {
|
|
2778
2902
|
onRowClick?.(task.id);
|
|
@@ -2820,7 +2944,7 @@ var TaskListRow = import_react10.default.memo(
|
|
|
2820
2944
|
onChipSelect?.(null);
|
|
2821
2945
|
}, [selectedChip, onRemoveDependency, onChipSelect]);
|
|
2822
2946
|
const startDateISO = toISODate(task.startDate);
|
|
2823
|
-
const endDateISO = toISODate(task.endDate);
|
|
2947
|
+
const endDateISO = editingDuration ? getEndDateFromDuration(task.startDate, durationValue) : toISODate(task.endDate);
|
|
2824
2948
|
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
2825
2949
|
"div",
|
|
2826
2950
|
{
|
|
@@ -2846,21 +2970,12 @@ var TaskListRow = import_react10.default.memo(
|
|
|
2846
2970
|
},
|
|
2847
2971
|
tabIndex: isSelected ? 0 : -1,
|
|
2848
2972
|
children: [
|
|
2849
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.
|
|
2973
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
2850
2974
|
"div",
|
|
2851
2975
|
{
|
|
2852
2976
|
className: "gantt-tl-cell gantt-tl-cell-number",
|
|
2853
2977
|
onClick: handleNumberClick,
|
|
2854
|
-
children:
|
|
2855
|
-
"button",
|
|
2856
|
-
{
|
|
2857
|
-
type: "button",
|
|
2858
|
-
className: "gantt-tl-collapse-btn",
|
|
2859
|
-
onClick: handleToggleCollapse,
|
|
2860
|
-
"aria-label": isCollapsed ? "\u0420\u0430\u0437\u0432\u0435\u0440\u043D\u0443\u0442\u044C" : "\u0421\u0432\u0435\u0440\u043D\u0443\u0442\u044C",
|
|
2861
|
-
children: isCollapsed ? "+" : "-"
|
|
2862
|
-
}
|
|
2863
|
-
) : /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_jsx_runtime12.Fragment, { children: [
|
|
2978
|
+
children: [
|
|
2864
2979
|
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
2865
2980
|
"span",
|
|
2866
2981
|
{
|
|
@@ -2876,10 +2991,20 @@ var TaskListRow = import_react10.default.memo(
|
|
|
2876
2991
|
}
|
|
2877
2992
|
),
|
|
2878
2993
|
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "gantt-tl-num-label", children: rowIndex + 1 })
|
|
2879
|
-
]
|
|
2994
|
+
]
|
|
2880
2995
|
}
|
|
2881
2996
|
),
|
|
2882
2997
|
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "gantt-tl-cell gantt-tl-cell-name", children: [
|
|
2998
|
+
isParent && !editingName && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
2999
|
+
"button",
|
|
3000
|
+
{
|
|
3001
|
+
type: "button",
|
|
3002
|
+
className: `gantt-tl-collapse-btn ${isCollapsed ? "gantt-tl-collapse-btn-collapsed" : ""}`,
|
|
3003
|
+
onClick: handleToggleCollapse,
|
|
3004
|
+
"aria-label": isCollapsed ? "Expand children" : "Collapse children",
|
|
3005
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(ChevronRightIcon, {})
|
|
3006
|
+
}
|
|
3007
|
+
),
|
|
2883
3008
|
editingName && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
2884
3009
|
Input,
|
|
2885
3010
|
{
|
|
@@ -2889,7 +3014,7 @@ var TaskListRow = import_react10.default.memo(
|
|
|
2889
3014
|
onChange: (e) => setNameValue(e.target.value),
|
|
2890
3015
|
onBlur: handleNameSave,
|
|
2891
3016
|
onKeyDown: handleNameKeyDown,
|
|
2892
|
-
className: "gantt-tl-name-input",
|
|
3017
|
+
className: ["gantt-tl-name-input", isChild ? "gantt-tl-name-input-child" : ""].filter(Boolean).join(" "),
|
|
2893
3018
|
onClick: (e) => e.stopPropagation()
|
|
2894
3019
|
}
|
|
2895
3020
|
),
|
|
@@ -2897,7 +3022,13 @@ var TaskListRow = import_react10.default.memo(
|
|
|
2897
3022
|
"button",
|
|
2898
3023
|
{
|
|
2899
3024
|
type: "button",
|
|
2900
|
-
className:
|
|
3025
|
+
className: [
|
|
3026
|
+
"gantt-tl-name-trigger",
|
|
3027
|
+
disableTaskNameEditing ? "gantt-tl-name-locked" : "",
|
|
3028
|
+
isParent ? "gantt-tl-name-trigger-parent" : "",
|
|
3029
|
+
isChild ? "gantt-tl-name-trigger-child" : ""
|
|
3030
|
+
].filter(Boolean).join(" "),
|
|
3031
|
+
title: task.name,
|
|
2901
3032
|
onClick: handleNameClick,
|
|
2902
3033
|
onDoubleClick: handleNameDoubleClick,
|
|
2903
3034
|
style: editingName ? { visibility: "hidden", pointerEvents: "none" } : void 0,
|
|
@@ -2986,22 +3117,91 @@ var TaskListRow = import_react10.default.memo(
|
|
|
2986
3117
|
disabled: task.locked
|
|
2987
3118
|
}
|
|
2988
3119
|
) }),
|
|
3120
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "gantt-tl-cell gantt-tl-cell-duration", onClick: handleDurationClick, children: [
|
|
3121
|
+
editingDuration && /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "gantt-tl-number-editor", onClick: (e) => e.stopPropagation(), children: [
|
|
3122
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
3123
|
+
Input,
|
|
3124
|
+
{
|
|
3125
|
+
ref: durationInputRef,
|
|
3126
|
+
type: "number",
|
|
3127
|
+
min: 1,
|
|
3128
|
+
step: 1,
|
|
3129
|
+
value: durationValue,
|
|
3130
|
+
onChange: (e) => applyDurationChange(parseInt(e.target.value, 10) || 1),
|
|
3131
|
+
onBlur: handleDurationSave,
|
|
3132
|
+
onKeyDown: handleDurationKeyDown,
|
|
3133
|
+
className: "gantt-tl-number-input"
|
|
3134
|
+
}
|
|
3135
|
+
),
|
|
3136
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "gantt-tl-number-steppers", "aria-hidden": "true", children: [
|
|
3137
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
3138
|
+
"button",
|
|
3139
|
+
{
|
|
3140
|
+
type: "button",
|
|
3141
|
+
className: "gantt-tl-number-stepper",
|
|
3142
|
+
tabIndex: -1,
|
|
3143
|
+
onMouseDown: (e) => e.preventDefault(),
|
|
3144
|
+
onClick: () => handleDurationAdjust(1),
|
|
3145
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("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__ */ (0, import_jsx_runtime12.jsx)("path", { d: "m18 15-6-6-6 6" }) })
|
|
3146
|
+
}
|
|
3147
|
+
),
|
|
3148
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
3149
|
+
"button",
|
|
3150
|
+
{
|
|
3151
|
+
type: "button",
|
|
3152
|
+
className: "gantt-tl-number-stepper",
|
|
3153
|
+
tabIndex: -1,
|
|
3154
|
+
onMouseDown: (e) => e.preventDefault(),
|
|
3155
|
+
onClick: () => handleDurationAdjust(-1),
|
|
3156
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("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__ */ (0, import_jsx_runtime12.jsx)("path", { d: "m6 9 6 6 6-6" }) })
|
|
3157
|
+
}
|
|
3158
|
+
)
|
|
3159
|
+
] })
|
|
3160
|
+
] }),
|
|
3161
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { style: editingDuration ? { visibility: "hidden", pointerEvents: "none" } : void 0, children: getInclusiveDurationDays(task.startDate, task.endDate) })
|
|
3162
|
+
] }),
|
|
2989
3163
|
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "gantt-tl-cell gantt-tl-cell-progress", onClick: handleProgressClick, children: [
|
|
2990
|
-
editingProgress && /* @__PURE__ */ (0, import_jsx_runtime12.
|
|
2991
|
-
|
|
2992
|
-
|
|
2993
|
-
|
|
2994
|
-
|
|
2995
|
-
|
|
2996
|
-
|
|
2997
|
-
|
|
2998
|
-
|
|
2999
|
-
|
|
3000
|
-
|
|
3001
|
-
|
|
3002
|
-
|
|
3003
|
-
|
|
3004
|
-
|
|
3164
|
+
editingProgress && /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "gantt-tl-number-editor", onClick: (e) => e.stopPropagation(), children: [
|
|
3165
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
3166
|
+
Input,
|
|
3167
|
+
{
|
|
3168
|
+
ref: progressInputRef,
|
|
3169
|
+
type: "number",
|
|
3170
|
+
min: 0,
|
|
3171
|
+
max: 100,
|
|
3172
|
+
step: 1,
|
|
3173
|
+
value: progressValue,
|
|
3174
|
+
onChange: (e) => setProgressValue(parseInt(e.target.value, 10) || 0),
|
|
3175
|
+
onBlur: handleProgressSave,
|
|
3176
|
+
onKeyDown: handleProgressKeyDown,
|
|
3177
|
+
className: "gantt-tl-number-input"
|
|
3178
|
+
}
|
|
3179
|
+
),
|
|
3180
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "gantt-tl-number-steppers", "aria-hidden": "true", children: [
|
|
3181
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
3182
|
+
"button",
|
|
3183
|
+
{
|
|
3184
|
+
type: "button",
|
|
3185
|
+
className: "gantt-tl-number-stepper",
|
|
3186
|
+
tabIndex: -1,
|
|
3187
|
+
onMouseDown: (e) => e.preventDefault(),
|
|
3188
|
+
onClick: () => handleProgressAdjust(1),
|
|
3189
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("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__ */ (0, import_jsx_runtime12.jsx)("path", { d: "m18 15-6-6-6 6" }) })
|
|
3190
|
+
}
|
|
3191
|
+
),
|
|
3192
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
3193
|
+
"button",
|
|
3194
|
+
{
|
|
3195
|
+
type: "button",
|
|
3196
|
+
className: "gantt-tl-number-stepper",
|
|
3197
|
+
tabIndex: -1,
|
|
3198
|
+
onMouseDown: (e) => e.preventDefault(),
|
|
3199
|
+
onClick: () => handleProgressAdjust(-1),
|
|
3200
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("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__ */ (0, import_jsx_runtime12.jsx)("path", { d: "m6 9 6 6 6-6" }) })
|
|
3201
|
+
}
|
|
3202
|
+
)
|
|
3203
|
+
] })
|
|
3204
|
+
] }),
|
|
3005
3205
|
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { style: editingProgress ? { visibility: "hidden", pointerEvents: "none" } : void 0, children: task.progress ? `${Math.round(task.progress)}%` : "0%" })
|
|
3006
3206
|
] }),
|
|
3007
3207
|
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
@@ -3158,15 +3358,17 @@ var NewTaskRow = ({ rowHeight, onConfirm, onCancel }) => {
|
|
|
3158
3358
|
// src/components/TaskList/TaskList.tsx
|
|
3159
3359
|
var import_jsx_runtime14 = require("react/jsx-runtime");
|
|
3160
3360
|
var LINK_TYPE_ORDER = ["FS", "SS", "FF", "SF"];
|
|
3361
|
+
var MIN_TASK_LIST_WIDTH = 640;
|
|
3161
3362
|
var TaskList = ({
|
|
3162
3363
|
tasks,
|
|
3163
3364
|
rowHeight,
|
|
3164
3365
|
headerHeight,
|
|
3165
|
-
taskListWidth =
|
|
3366
|
+
taskListWidth = 640,
|
|
3166
3367
|
onTaskChange,
|
|
3167
3368
|
selectedTaskId,
|
|
3168
3369
|
onTaskSelect,
|
|
3169
3370
|
show = true,
|
|
3371
|
+
hasRightShadow = false,
|
|
3170
3372
|
disableTaskNameEditing = false,
|
|
3171
3373
|
disableDependencyEditing = false,
|
|
3172
3374
|
onScrollToTask,
|
|
@@ -3305,11 +3507,13 @@ var TaskList = ({
|
|
|
3305
3507
|
const [draggingIndex, setDraggingIndex] = (0, import_react12.useState)(null);
|
|
3306
3508
|
const [dragOverIndex, setDragOverIndex] = (0, import_react12.useState)(null);
|
|
3307
3509
|
const dragOriginIndexRef = (0, import_react12.useRef)(null);
|
|
3510
|
+
const dragTaskIdRef = (0, import_react12.useRef)(null);
|
|
3308
3511
|
const handleDragStart = (0, import_react12.useCallback)((index, e) => {
|
|
3309
3512
|
e.dataTransfer.effectAllowed = "move";
|
|
3310
3513
|
setDraggingIndex(index);
|
|
3311
3514
|
dragOriginIndexRef.current = index;
|
|
3312
|
-
|
|
3515
|
+
dragTaskIdRef.current = visibleTasks[index]?.id ?? null;
|
|
3516
|
+
}, [visibleTasks]);
|
|
3313
3517
|
const handleDragOver = (0, import_react12.useCallback)((index, e) => {
|
|
3314
3518
|
e.preventDefault();
|
|
3315
3519
|
e.dataTransfer.dropEffect = "move";
|
|
@@ -3317,16 +3521,32 @@ var TaskList = ({
|
|
|
3317
3521
|
}, []);
|
|
3318
3522
|
const handleDrop = (0, import_react12.useCallback)((dropIndex, e) => {
|
|
3319
3523
|
e.preventDefault();
|
|
3320
|
-
const
|
|
3321
|
-
|
|
3524
|
+
const originVisibleIndex = dragOriginIndexRef.current;
|
|
3525
|
+
const movedTaskId = dragTaskIdRef.current;
|
|
3526
|
+
if (originVisibleIndex === null || movedTaskId === null || originVisibleIndex === dropIndex) {
|
|
3527
|
+
setDraggingIndex(null);
|
|
3528
|
+
setDragOverIndex(null);
|
|
3529
|
+
dragOriginIndexRef.current = null;
|
|
3530
|
+
dragTaskIdRef.current = null;
|
|
3531
|
+
return;
|
|
3532
|
+
}
|
|
3533
|
+
const reorderPosition = getVisibleReorderPosition(
|
|
3534
|
+
orderedTasks,
|
|
3535
|
+
visibleTasks,
|
|
3536
|
+
movedTaskId,
|
|
3537
|
+
originVisibleIndex,
|
|
3538
|
+
dropIndex
|
|
3539
|
+
);
|
|
3540
|
+
if (!reorderPosition) {
|
|
3322
3541
|
setDraggingIndex(null);
|
|
3323
3542
|
setDragOverIndex(null);
|
|
3324
3543
|
dragOriginIndexRef.current = null;
|
|
3544
|
+
dragTaskIdRef.current = null;
|
|
3325
3545
|
return;
|
|
3326
3546
|
}
|
|
3547
|
+
const { originOrderedIndex, insertIndex } = reorderPosition;
|
|
3327
3548
|
const reordered = [...orderedTasks];
|
|
3328
|
-
const [moved] = reordered.splice(
|
|
3329
|
-
const insertIndex = dropIndex === visibleTasks.length ? visibleTasks.length - 1 : originIndex < dropIndex ? dropIndex - 1 : dropIndex;
|
|
3549
|
+
const [moved] = reordered.splice(originOrderedIndex, 1);
|
|
3330
3550
|
const isChild = !!moved.parentId;
|
|
3331
3551
|
const isParent = tasks.some((t) => t.parentId === moved.id);
|
|
3332
3552
|
const taskType = isParent ? "PARENT" : isChild ? "CHILD" : "ROOT";
|
|
@@ -3336,10 +3556,11 @@ var TaskList = ({
|
|
|
3336
3556
|
name: moved.name,
|
|
3337
3557
|
type: taskType,
|
|
3338
3558
|
parentId: moved.parentId,
|
|
3339
|
-
originIndex,
|
|
3559
|
+
originIndex: originOrderedIndex,
|
|
3560
|
+
originVisibleIndex,
|
|
3340
3561
|
dropIndex,
|
|
3341
3562
|
insertIndex,
|
|
3342
|
-
direction:
|
|
3563
|
+
direction: originVisibleIndex < dropIndex ? "DOWN" : "UP"
|
|
3343
3564
|
});
|
|
3344
3565
|
console.log("[TASKS ARRAY LENGTH]", orderedTasks.length);
|
|
3345
3566
|
let inferredParentId;
|
|
@@ -3426,11 +3647,13 @@ var TaskList = ({
|
|
|
3426
3647
|
setDraggingIndex(null);
|
|
3427
3648
|
setDragOverIndex(null);
|
|
3428
3649
|
dragOriginIndexRef.current = null;
|
|
3429
|
-
|
|
3650
|
+
dragTaskIdRef.current = null;
|
|
3651
|
+
}, [orderedTasks, visibleTasks, onReorder, onTaskSelect]);
|
|
3430
3652
|
const handleDragEnd = (0, import_react12.useCallback)(() => {
|
|
3431
3653
|
setDraggingIndex(null);
|
|
3432
3654
|
setDragOverIndex(null);
|
|
3433
3655
|
dragOriginIndexRef.current = null;
|
|
3656
|
+
dragTaskIdRef.current = null;
|
|
3434
3657
|
}, []);
|
|
3435
3658
|
const handleConfirmNewTask = (0, import_react12.useCallback)((name) => {
|
|
3436
3659
|
const now = /* @__PURE__ */ new Date();
|
|
@@ -3454,18 +3677,20 @@ var TaskList = ({
|
|
|
3454
3677
|
setIsCreating(false);
|
|
3455
3678
|
}, [onAdd]);
|
|
3456
3679
|
const handleCancelNewTask = (0, import_react12.useCallback)(() => setIsCreating(false), []);
|
|
3680
|
+
const effectiveTaskListWidth = Math.max(taskListWidth, MIN_TASK_LIST_WIDTH);
|
|
3457
3681
|
return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
3458
3682
|
"div",
|
|
3459
3683
|
{
|
|
3460
3684
|
ref: overlayRef,
|
|
3461
|
-
className: `gantt-tl-overlay${show ? "" : " gantt-tl-hidden"}`,
|
|
3462
|
-
style: { width: `${
|
|
3685
|
+
className: `gantt-tl-overlay${show ? "" : " gantt-tl-hidden"}${hasRightShadow ? " gantt-tl-overlay-shadowed" : ""}`,
|
|
3686
|
+
style: { width: `${effectiveTaskListWidth}px`, minWidth: `${MIN_TASK_LIST_WIDTH}px` },
|
|
3463
3687
|
children: /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "gantt-tl-table", children: [
|
|
3464
3688
|
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "gantt-tl-header", style: { height: `${headerHeight + 0.5}px` }, children: [
|
|
3465
3689
|
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "gantt-tl-headerCell gantt-tl-cell-number", children: "\u2116" }),
|
|
3466
3690
|
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "gantt-tl-headerCell gantt-tl-cell-name", children: "\u0418\u043C\u044F" }),
|
|
3467
3691
|
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "gantt-tl-headerCell gantt-tl-cell-date", children: "\u041D\u0430\u0447\u0430\u043B\u043E" }),
|
|
3468
3692
|
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "gantt-tl-headerCell gantt-tl-cell-date", children: "\u041E\u043A\u043E\u043D\u0447\u0430\u043D\u0438\u0435" }),
|
|
3693
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "gantt-tl-headerCell gantt-tl-cell-duration", children: "\u0414\u043D." }),
|
|
3469
3694
|
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "gantt-tl-headerCell gantt-tl-cell-progress", children: "%" }),
|
|
3470
3695
|
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "gantt-tl-headerCell gantt-tl-cell-deps", style: { position: "relative" }, children: [
|
|
3471
3696
|
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(Popover, { open: typeMenuOpen, onOpenChange: setTypeMenuOpen, children: [
|
|
@@ -3591,7 +3816,7 @@ var GanttChart = (0, import_react13.forwardRef)(({
|
|
|
3591
3816
|
disableConstraints,
|
|
3592
3817
|
onCascade,
|
|
3593
3818
|
showTaskList = false,
|
|
3594
|
-
taskListWidth =
|
|
3819
|
+
taskListWidth = 660,
|
|
3595
3820
|
disableTaskNameEditing = false,
|
|
3596
3821
|
disableDependencyEditing = false,
|
|
3597
3822
|
highlightExpiredTasks = false,
|
|
@@ -3603,6 +3828,7 @@ var GanttChart = (0, import_react13.forwardRef)(({
|
|
|
3603
3828
|
}, ref) => {
|
|
3604
3829
|
const scrollContainerRef = (0, import_react13.useRef)(null);
|
|
3605
3830
|
const [selectedTaskId, setSelectedTaskId] = (0, import_react13.useState)(null);
|
|
3831
|
+
const [taskListHasRightShadow, setTaskListHasRightShadow] = (0, import_react13.useState)(false);
|
|
3606
3832
|
const [selectedChip, setSelectedChip] = (0, import_react13.useState)(null);
|
|
3607
3833
|
const [collapsedParentIds, setCollapsedParentIds] = (0, import_react13.useState)(/* @__PURE__ */ new Set());
|
|
3608
3834
|
const [editingTaskId, setEditingTaskId] = (0, import_react13.useState)(null);
|
|
@@ -3649,6 +3875,18 @@ var GanttChart = (0, import_react13.forwardRef)(({
|
|
|
3649
3875
|
const scrollLeft = Math.round(todayOffset - containerWidth / 2 + dayWidth / 2);
|
|
3650
3876
|
container.scrollLeft = Math.max(0, scrollLeft);
|
|
3651
3877
|
}, []);
|
|
3878
|
+
(0, import_react13.useEffect)(() => {
|
|
3879
|
+
const container = scrollContainerRef.current;
|
|
3880
|
+
if (!container) return;
|
|
3881
|
+
const updateShadow = () => {
|
|
3882
|
+
setTaskListHasRightShadow(container.scrollLeft > 0);
|
|
3883
|
+
};
|
|
3884
|
+
updateShadow();
|
|
3885
|
+
container.addEventListener("scroll", updateShadow, { passive: true });
|
|
3886
|
+
return () => {
|
|
3887
|
+
container.removeEventListener("scroll", updateShadow);
|
|
3888
|
+
};
|
|
3889
|
+
}, []);
|
|
3652
3890
|
const scrollToToday = (0, import_react13.useCallback)(() => {
|
|
3653
3891
|
const container = scrollContainerRef.current;
|
|
3654
3892
|
if (!container || dateRange.length === 0) return;
|
|
@@ -4052,6 +4290,7 @@ var GanttChart = (0, import_react13.forwardRef)(({
|
|
|
4052
4290
|
selectedTaskId: selectedTaskId ?? void 0,
|
|
4053
4291
|
onTaskSelect: handleTaskSelect,
|
|
4054
4292
|
show: showTaskList,
|
|
4293
|
+
hasRightShadow: taskListHasRightShadow,
|
|
4055
4294
|
disableTaskNameEditing,
|
|
4056
4295
|
disableDependencyEditing,
|
|
4057
4296
|
onScrollToTask: scrollToTask,
|
|
@@ -4215,10 +4454,12 @@ Button.displayName = "Button";
|
|
|
4215
4454
|
getMultiMonthDays,
|
|
4216
4455
|
getSuccessorChain,
|
|
4217
4456
|
getTransitiveCascadeChain,
|
|
4457
|
+
getVisibleReorderPosition,
|
|
4218
4458
|
isTaskParent,
|
|
4219
4459
|
isToday,
|
|
4220
4460
|
isWeekend,
|
|
4221
4461
|
normalizeHierarchyTasks,
|
|
4462
|
+
normalizeTaskDates,
|
|
4222
4463
|
parseUTCDate,
|
|
4223
4464
|
pixelsToDate,
|
|
4224
4465
|
recalculateIncomingLags,
|