gantt-lib 0.3.4 → 0.4.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 +17 -1
- package/dist/index.d.ts +17 -1
- package/dist/index.js +433 -153
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +414 -133
- package/dist/index.mjs.map +1 -1
- package/dist/styles.css +106 -23
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
3
|
// src/components/GanttChart/GanttChart.tsx
|
|
4
|
-
import { useMemo as useMemo9, useCallback as useCallback6, useRef as
|
|
4
|
+
import { useMemo as useMemo9, useCallback as useCallback6, useRef as useRef6, useState as useState7, useEffect as useEffect6, useImperativeHandle, forwardRef } from "react";
|
|
5
5
|
|
|
6
6
|
// src/utils/dateUtils.ts
|
|
7
7
|
var parseUTCDate = (date) => {
|
|
@@ -42,9 +42,9 @@ var getDayOffset = (date, monthStart) => {
|
|
|
42
42
|
var isToday = (date) => {
|
|
43
43
|
const now = /* @__PURE__ */ new Date();
|
|
44
44
|
const today = new Date(Date.UTC(
|
|
45
|
-
now.
|
|
46
|
-
now.
|
|
47
|
-
now.
|
|
45
|
+
now.getFullYear(),
|
|
46
|
+
now.getMonth(),
|
|
47
|
+
now.getDate()
|
|
48
48
|
));
|
|
49
49
|
const compareDate = new Date(Date.UTC(
|
|
50
50
|
date.getUTCFullYear(),
|
|
@@ -523,7 +523,7 @@ var calculateGridLines = (dateRange, dayWidth) => {
|
|
|
523
523
|
for (let i = 0; i < dateRange.length; i++) {
|
|
524
524
|
const date = dateRange[i];
|
|
525
525
|
const x = Math.round(i * dayWidth);
|
|
526
|
-
const isMonthStart = date.getUTCDate() === 1;
|
|
526
|
+
const isMonthStart = i === 0 ? false : date.getUTCDate() === 1;
|
|
527
527
|
const isWeekStart = date.getUTCDay() === 1;
|
|
528
528
|
lines.push({ x, isMonthStart, isWeekStart });
|
|
529
529
|
}
|
|
@@ -1102,7 +1102,7 @@ var TaskRow = React2.memo(
|
|
|
1102
1102
|
const isExpired = useMemo2(() => {
|
|
1103
1103
|
if (!highlightExpiredTasks) return false;
|
|
1104
1104
|
const now = /* @__PURE__ */ new Date();
|
|
1105
|
-
const today = new Date(Date.UTC(now.
|
|
1105
|
+
const today = new Date(Date.UTC(now.getFullYear(), now.getMonth(), now.getDate()));
|
|
1106
1106
|
const taskStart = parseUTCDate(task.startDate);
|
|
1107
1107
|
const taskEnd = parseUTCDate(task.endDate);
|
|
1108
1108
|
const actualProgress = task.progress ?? 0;
|
|
@@ -1609,7 +1609,7 @@ DependencyLines.displayName = "DependencyLines";
|
|
|
1609
1609
|
var DependencyLines_default = DependencyLines;
|
|
1610
1610
|
|
|
1611
1611
|
// src/components/TaskList/TaskList.tsx
|
|
1612
|
-
import
|
|
1612
|
+
import React11, { useMemo as useMemo8, useCallback as useCallback5, useState as useState6, useEffect as useEffect5, useRef as useRef5 } from "react";
|
|
1613
1613
|
|
|
1614
1614
|
// src/components/ui/Popover.tsx
|
|
1615
1615
|
import * as RadixPopover from "@radix-ui/react-popover";
|
|
@@ -1683,6 +1683,7 @@ import {
|
|
|
1683
1683
|
format as format2,
|
|
1684
1684
|
addMonths,
|
|
1685
1685
|
subMonths,
|
|
1686
|
+
addDays,
|
|
1686
1687
|
isSameDay,
|
|
1687
1688
|
getDay,
|
|
1688
1689
|
isToday as isToday2,
|
|
@@ -1796,7 +1797,73 @@ var Calendar = ({
|
|
|
1796
1797
|
() => months.map(renderMonth),
|
|
1797
1798
|
[months, renderMonth]
|
|
1798
1799
|
);
|
|
1799
|
-
|
|
1800
|
+
const handleDayShift = useCallback2(
|
|
1801
|
+
(deltaDays) => {
|
|
1802
|
+
if (!onSelect || disabled) return;
|
|
1803
|
+
const baseDate = selected ?? /* @__PURE__ */ new Date();
|
|
1804
|
+
onSelect(addDays(baseDate, deltaDays));
|
|
1805
|
+
},
|
|
1806
|
+
[onSelect, selected, disabled]
|
|
1807
|
+
);
|
|
1808
|
+
const handleToday = useCallback2(() => {
|
|
1809
|
+
if (!onSelect || disabled) return;
|
|
1810
|
+
onSelect(/* @__PURE__ */ new Date());
|
|
1811
|
+
}, [onSelect, disabled]);
|
|
1812
|
+
return /* @__PURE__ */ jsxs6("div", { ref: scrollRef, className: "gantt-cal-container", children: [
|
|
1813
|
+
renderedMonths,
|
|
1814
|
+
/* @__PURE__ */ jsxs6("div", { className: "gantt-cal-nav", children: [
|
|
1815
|
+
/* @__PURE__ */ jsx9(
|
|
1816
|
+
"button",
|
|
1817
|
+
{
|
|
1818
|
+
type: "button",
|
|
1819
|
+
className: "gantt-btn gantt-btn-sm",
|
|
1820
|
+
onClick: () => handleDayShift(-7),
|
|
1821
|
+
disabled,
|
|
1822
|
+
children: "-7"
|
|
1823
|
+
}
|
|
1824
|
+
),
|
|
1825
|
+
/* @__PURE__ */ jsx9(
|
|
1826
|
+
"button",
|
|
1827
|
+
{
|
|
1828
|
+
type: "button",
|
|
1829
|
+
className: "gantt-btn gantt-btn-sm",
|
|
1830
|
+
onClick: () => handleDayShift(-1),
|
|
1831
|
+
disabled,
|
|
1832
|
+
children: "-1"
|
|
1833
|
+
}
|
|
1834
|
+
),
|
|
1835
|
+
/* @__PURE__ */ jsx9(
|
|
1836
|
+
"button",
|
|
1837
|
+
{
|
|
1838
|
+
type: "button",
|
|
1839
|
+
className: "gantt-btn gantt-btn-sm",
|
|
1840
|
+
onClick: handleToday,
|
|
1841
|
+
disabled,
|
|
1842
|
+
children: "\u0421\u0435\u0433\u043E\u0434\u043D\u044F"
|
|
1843
|
+
}
|
|
1844
|
+
),
|
|
1845
|
+
/* @__PURE__ */ jsx9(
|
|
1846
|
+
"button",
|
|
1847
|
+
{
|
|
1848
|
+
type: "button",
|
|
1849
|
+
className: "gantt-btn gantt-btn-sm",
|
|
1850
|
+
onClick: () => handleDayShift(1),
|
|
1851
|
+
disabled,
|
|
1852
|
+
children: "+1"
|
|
1853
|
+
}
|
|
1854
|
+
),
|
|
1855
|
+
/* @__PURE__ */ jsx9(
|
|
1856
|
+
"button",
|
|
1857
|
+
{
|
|
1858
|
+
type: "button",
|
|
1859
|
+
className: "gantt-btn gantt-btn-sm",
|
|
1860
|
+
onClick: () => handleDayShift(7),
|
|
1861
|
+
disabled,
|
|
1862
|
+
children: "+7"
|
|
1863
|
+
}
|
|
1864
|
+
)
|
|
1865
|
+
] })
|
|
1866
|
+
] });
|
|
1800
1867
|
};
|
|
1801
1868
|
Calendar.displayName = "Calendar";
|
|
1802
1869
|
|
|
@@ -1904,6 +1971,7 @@ var TrashIcon = () => /* @__PURE__ */ jsxs9("svg", { xmlns: "http://www.w3.org/2
|
|
|
1904
1971
|
/* @__PURE__ */ jsx12("path", { d: "M3 6h18" }),
|
|
1905
1972
|
/* @__PURE__ */ jsx12("path", { d: "M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2" })
|
|
1906
1973
|
] });
|
|
1974
|
+
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" }) });
|
|
1907
1975
|
function formatDepDescription(type, lag) {
|
|
1908
1976
|
const effectiveLag = lag ?? 0;
|
|
1909
1977
|
if (type === "FS") {
|
|
@@ -1945,12 +2013,19 @@ var DepChip = ({
|
|
|
1945
2013
|
const handleClick = (e) => {
|
|
1946
2014
|
e.stopPropagation();
|
|
1947
2015
|
if (disableDependencyEditing) return;
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
2016
|
+
if (isSelected) {
|
|
2017
|
+
e.preventDefault();
|
|
2018
|
+
onChipSelect?.(null);
|
|
2019
|
+
return;
|
|
1952
2020
|
}
|
|
2021
|
+
onChipSelect?.({ successorId: taskId, predecessorId: dep.taskId, linkType: dep.type });
|
|
2022
|
+
onScrollToTask?.(dep.taskId);
|
|
1953
2023
|
};
|
|
2024
|
+
const handleOpenChange = useCallback4((open) => {
|
|
2025
|
+
if (!open) {
|
|
2026
|
+
onChipSelect?.(null);
|
|
2027
|
+
}
|
|
2028
|
+
}, [onChipSelect]);
|
|
1954
2029
|
const handleTrashClick = (e) => {
|
|
1955
2030
|
e.stopPropagation();
|
|
1956
2031
|
onRemoveDependency?.(taskId, dep.taskId, dep.type);
|
|
@@ -1959,50 +2034,26 @@ var DepChip = ({
|
|
|
1959
2034
|
const Icon = LINK_TYPE_ICONS[dep.type];
|
|
1960
2035
|
const depPrefix = formatDepDescription(dep.type, lag);
|
|
1961
2036
|
const depName = predecessorName ?? dep.taskId;
|
|
1962
|
-
return /* @__PURE__ */ jsxs9(
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
/* @__PURE__ */ jsx12(
|
|
1966
|
-
"span",
|
|
1967
|
-
{
|
|
1968
|
-
className: `gantt-tl-dep-chip${isSelected ? " gantt-tl-dep-chip-selected" : ""}`,
|
|
1969
|
-
onClick: handleClick,
|
|
1970
|
-
children: /* @__PURE__ */ jsxs9(Fragment2, { children: [
|
|
1971
|
-
/* @__PURE__ */ jsx12(Icon, {}),
|
|
1972
|
-
lag != null && lag !== 0 ? lag > 0 ? `+${lag}` : `${lag}` : ""
|
|
1973
|
-
] })
|
|
1974
|
-
}
|
|
1975
|
-
),
|
|
1976
|
-
!disableDependencyEditing && /* @__PURE__ */ jsx12(
|
|
1977
|
-
"button",
|
|
1978
|
-
{
|
|
1979
|
-
type: "button",
|
|
1980
|
-
className: "gantt-tl-dep-chip-trash",
|
|
1981
|
-
"aria-label": "\u0423\u0434\u0430\u043B\u0438\u0442\u044C \u0441\u0432\u044F\u0437\u044C",
|
|
1982
|
-
onClick: handleTrashClick,
|
|
1983
|
-
children: /* @__PURE__ */ jsx12(TrashIcon, {})
|
|
1984
|
-
}
|
|
1985
|
-
)
|
|
1986
|
-
] }) }),
|
|
1987
|
-
/* @__PURE__ */ jsxs9(
|
|
1988
|
-
PopoverContent,
|
|
2037
|
+
return /* @__PURE__ */ jsxs9("span", { className: "gantt-tl-dep-chip-wrapper", children: [
|
|
2038
|
+
/* @__PURE__ */ jsx12(
|
|
2039
|
+
"span",
|
|
1989
2040
|
{
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
2041
|
+
className: `gantt-tl-dep-chip${isSelected ? " gantt-tl-dep-chip-selected" : ""}`,
|
|
2042
|
+
onClick: handleClick,
|
|
2043
|
+
children: /* @__PURE__ */ jsxs9(Fragment2, { children: [
|
|
2044
|
+
/* @__PURE__ */ jsx12(Icon, {}),
|
|
2045
|
+
lag != null && lag !== 0 ? lag > 0 ? `+${lag}` : `${lag}` : ""
|
|
2046
|
+
] })
|
|
2047
|
+
}
|
|
2048
|
+
),
|
|
2049
|
+
!disableDependencyEditing && /* @__PURE__ */ jsx12(
|
|
2050
|
+
"button",
|
|
2051
|
+
{
|
|
2052
|
+
type: "button",
|
|
2053
|
+
className: "gantt-tl-dep-chip-trash",
|
|
2054
|
+
"aria-label": "\u0423\u0434\u0430\u043B\u0438\u0442\u044C \u0441\u0432\u044F\u0437\u044C",
|
|
2055
|
+
onClick: handleTrashClick,
|
|
2056
|
+
children: /* @__PURE__ */ jsx12(TrashIcon, {})
|
|
2006
2057
|
}
|
|
2007
2058
|
)
|
|
2008
2059
|
] });
|
|
@@ -2030,12 +2081,19 @@ var TaskListRow = React9.memo(
|
|
|
2030
2081
|
onRemoveDependency,
|
|
2031
2082
|
selectedChip,
|
|
2032
2083
|
onChipSelect,
|
|
2033
|
-
onScrollToTask
|
|
2084
|
+
onScrollToTask,
|
|
2085
|
+
onDelete,
|
|
2086
|
+
onAdd,
|
|
2087
|
+
onInsertAfter,
|
|
2088
|
+
editingTaskId
|
|
2034
2089
|
}) => {
|
|
2035
2090
|
const [editingName, setEditingName] = useState4(false);
|
|
2036
2091
|
const [nameValue, setNameValue] = useState4("");
|
|
2037
2092
|
const nameInputRef = useRef3(null);
|
|
2038
2093
|
const [overflowOpen, setOverflowOpen] = useState4(false);
|
|
2094
|
+
const confirmedRef = useRef3(false);
|
|
2095
|
+
const autoEditedForRef = useRef3(null);
|
|
2096
|
+
const editTriggerRef = useRef3("doubleclick");
|
|
2039
2097
|
const isSelected = selectedTaskId === task.id;
|
|
2040
2098
|
const isPicking = selectingPredecessorFor != null;
|
|
2041
2099
|
const isSourceRow = isPicking && selectingPredecessorFor === task.id;
|
|
@@ -2059,15 +2117,59 @@ var TaskListRow = React9.memo(
|
|
|
2059
2117
|
useEffect3(() => {
|
|
2060
2118
|
if (editingName && nameInputRef.current) {
|
|
2061
2119
|
nameInputRef.current.focus();
|
|
2120
|
+
if (editTriggerRef.current === "keypress") {
|
|
2121
|
+
const len = nameInputRef.current.value.length;
|
|
2122
|
+
nameInputRef.current.setSelectionRange(len, len);
|
|
2123
|
+
} else {
|
|
2124
|
+
nameInputRef.current.select();
|
|
2125
|
+
}
|
|
2062
2126
|
}
|
|
2063
2127
|
}, [editingName]);
|
|
2128
|
+
useEffect3(() => {
|
|
2129
|
+
if (editingTaskId === task.id && !disableTaskNameEditing && autoEditedForRef.current !== editingTaskId) {
|
|
2130
|
+
autoEditedForRef.current = editingTaskId;
|
|
2131
|
+
confirmedRef.current = false;
|
|
2132
|
+
editTriggerRef.current = "autoedit";
|
|
2133
|
+
setNameValue(task.name);
|
|
2134
|
+
setEditingName(true);
|
|
2135
|
+
}
|
|
2136
|
+
}, [editingTaskId, task.id, disableTaskNameEditing]);
|
|
2064
2137
|
const handleNameClick = useCallback4((e) => {
|
|
2065
2138
|
if (disableTaskNameEditing) return;
|
|
2066
2139
|
e.stopPropagation();
|
|
2140
|
+
onRowClick?.(task.id);
|
|
2141
|
+
onScrollToTask?.(task.id);
|
|
2142
|
+
}, [task.id, disableTaskNameEditing, onRowClick, onScrollToTask]);
|
|
2143
|
+
const handleNameDoubleClick = useCallback4((e) => {
|
|
2144
|
+
if (disableTaskNameEditing) return;
|
|
2145
|
+
e.stopPropagation();
|
|
2146
|
+
confirmedRef.current = false;
|
|
2147
|
+
editTriggerRef.current = "doubleclick";
|
|
2067
2148
|
setNameValue(task.name);
|
|
2068
2149
|
setEditingName(true);
|
|
2069
2150
|
}, [task.name, disableTaskNameEditing]);
|
|
2151
|
+
const handleRowKeyDown = useCallback4((e) => {
|
|
2152
|
+
if (!editingName && !disableTaskNameEditing && e.key === "F2") {
|
|
2153
|
+
e.preventDefault();
|
|
2154
|
+
confirmedRef.current = false;
|
|
2155
|
+
editTriggerRef.current = "keypress";
|
|
2156
|
+
setNameValue(task.name);
|
|
2157
|
+
setEditingName(true);
|
|
2158
|
+
return;
|
|
2159
|
+
}
|
|
2160
|
+
if (!editingName && !disableTaskNameEditing && e.key.length === 1 && !e.ctrlKey && !e.metaKey && !e.altKey) {
|
|
2161
|
+
e.preventDefault();
|
|
2162
|
+
confirmedRef.current = false;
|
|
2163
|
+
editTriggerRef.current = "keypress";
|
|
2164
|
+
setNameValue(e.key);
|
|
2165
|
+
setEditingName(true);
|
|
2166
|
+
}
|
|
2167
|
+
}, [editingName, disableTaskNameEditing, task.name]);
|
|
2070
2168
|
const handleNameSave = useCallback4(() => {
|
|
2169
|
+
if (confirmedRef.current) {
|
|
2170
|
+
confirmedRef.current = false;
|
|
2171
|
+
return;
|
|
2172
|
+
}
|
|
2071
2173
|
if (nameValue.trim()) {
|
|
2072
2174
|
onTaskChange?.({ ...task, name: nameValue.trim() });
|
|
2073
2175
|
}
|
|
@@ -2077,9 +2179,16 @@ var TaskListRow = React9.memo(
|
|
|
2077
2179
|
setEditingName(false);
|
|
2078
2180
|
}, []);
|
|
2079
2181
|
const handleNameKeyDown = useCallback4((e) => {
|
|
2080
|
-
if (e.key === "Enter")
|
|
2081
|
-
|
|
2082
|
-
|
|
2182
|
+
if (e.key === "Enter") {
|
|
2183
|
+
confirmedRef.current = true;
|
|
2184
|
+
if (nameValue.trim()) {
|
|
2185
|
+
onTaskChange?.({ ...task, name: nameValue.trim() });
|
|
2186
|
+
}
|
|
2187
|
+
setEditingName(false);
|
|
2188
|
+
} else if (e.key === "Escape") {
|
|
2189
|
+
handleNameCancel();
|
|
2190
|
+
}
|
|
2191
|
+
}, [nameValue, task, onTaskChange, handleNameCancel]);
|
|
2083
2192
|
const handleStartDateChange = useCallback4((newDateISO) => {
|
|
2084
2193
|
if (!newDateISO) return;
|
|
2085
2194
|
const origStart = parseUTCDate(task.startDate);
|
|
@@ -2104,8 +2213,7 @@ var TaskListRow = React9.memo(
|
|
|
2104
2213
|
const handleNumberClick = useCallback4((e) => {
|
|
2105
2214
|
e.stopPropagation();
|
|
2106
2215
|
onRowClick?.(task.id);
|
|
2107
|
-
|
|
2108
|
-
}, [task.id, onRowClick, onScrollToTask]);
|
|
2216
|
+
}, [task.id, onRowClick]);
|
|
2109
2217
|
const handleAddClick = useCallback4((e) => {
|
|
2110
2218
|
e.stopPropagation();
|
|
2111
2219
|
onSetSelectingPredecessorFor?.(task.id);
|
|
@@ -2116,6 +2224,10 @@ var TaskListRow = React9.memo(
|
|
|
2116
2224
|
if (!selectingPredecessorFor || !activeLinkType) return;
|
|
2117
2225
|
onAddDependency?.(task.id, selectingPredecessorFor, activeLinkType);
|
|
2118
2226
|
}, [isPicking, isSourceRow, selectingPredecessorFor, task.id, activeLinkType, onAddDependency]);
|
|
2227
|
+
const handleCancelPicking = useCallback4((e) => {
|
|
2228
|
+
e.stopPropagation();
|
|
2229
|
+
onSetSelectingPredecessorFor?.(null);
|
|
2230
|
+
}, [onSetSelectingPredecessorFor]);
|
|
2119
2231
|
const isSelectedPredecessor = selectedChip != null && selectedChip.predecessorId === task.id;
|
|
2120
2232
|
const handleDeleteSelected = useCallback4((e) => {
|
|
2121
2233
|
e.stopPropagation();
|
|
@@ -2134,23 +2246,17 @@ var TaskListRow = React9.memo(
|
|
|
2134
2246
|
isPicking && !isSourceRow ? "gantt-tl-row-picking" : "",
|
|
2135
2247
|
isSourceRow ? "gantt-tl-row-picking-self" : ""
|
|
2136
2248
|
].filter(Boolean).join(" "),
|
|
2137
|
-
style: { minHeight: `${rowHeight}px
|
|
2249
|
+
style: { minHeight: `${rowHeight}px`, position: "relative" },
|
|
2138
2250
|
onClick: handleRowClickInternal,
|
|
2251
|
+
onKeyDown: handleRowKeyDown,
|
|
2252
|
+
tabIndex: isSelected ? 0 : -1,
|
|
2139
2253
|
children: [
|
|
2140
|
-
/* @__PURE__ */
|
|
2254
|
+
/* @__PURE__ */ jsx12(
|
|
2141
2255
|
"div",
|
|
2142
2256
|
{
|
|
2143
2257
|
className: "gantt-tl-cell gantt-tl-cell-number",
|
|
2144
2258
|
onClick: handleNumberClick,
|
|
2145
|
-
|
|
2146
|
-
children: [
|
|
2147
|
-
/* @__PURE__ */ jsx12("span", { className: "gantt-tl-num-label", children: rowIndex + 1 }),
|
|
2148
|
-
/* @__PURE__ */ jsxs9("svg", { className: "gantt-tl-num-icon", 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: [
|
|
2149
|
-
/* @__PURE__ */ jsx12("path", { d: "M17 12H3" }),
|
|
2150
|
-
/* @__PURE__ */ jsx12("path", { d: "m11 18 6-6-6-6" }),
|
|
2151
|
-
/* @__PURE__ */ jsx12("path", { d: "M21 5v14" })
|
|
2152
|
-
] })
|
|
2153
|
-
]
|
|
2259
|
+
children: /* @__PURE__ */ jsx12("span", { className: "gantt-tl-num-label", children: rowIndex + 1 })
|
|
2154
2260
|
}
|
|
2155
2261
|
),
|
|
2156
2262
|
/* @__PURE__ */ jsxs9("div", { className: "gantt-tl-cell gantt-tl-cell-name", children: [
|
|
@@ -2173,10 +2279,56 @@ var TaskListRow = React9.memo(
|
|
|
2173
2279
|
type: "button",
|
|
2174
2280
|
className: `gantt-tl-name-trigger ${disableTaskNameEditing ? "gantt-tl-name-locked" : ""}`,
|
|
2175
2281
|
onClick: handleNameClick,
|
|
2282
|
+
onDoubleClick: handleNameDoubleClick,
|
|
2176
2283
|
style: editingName ? { visibility: "hidden", pointerEvents: "none" } : void 0,
|
|
2177
2284
|
children: task.name
|
|
2178
2285
|
}
|
|
2179
|
-
)
|
|
2286
|
+
),
|
|
2287
|
+
!editingName && /* @__PURE__ */ jsxs9("div", { className: "gantt-tl-name-actions", children: [
|
|
2288
|
+
onInsertAfter && /* @__PURE__ */ jsx12(
|
|
2289
|
+
"button",
|
|
2290
|
+
{
|
|
2291
|
+
type: "button",
|
|
2292
|
+
className: "gantt-tl-name-action-btn gantt-tl-action-insert",
|
|
2293
|
+
onClick: (e) => {
|
|
2294
|
+
e.stopPropagation();
|
|
2295
|
+
const now = /* @__PURE__ */ new Date();
|
|
2296
|
+
const todayISO = new Date(Date.UTC(
|
|
2297
|
+
now.getUTCFullYear(),
|
|
2298
|
+
now.getUTCMonth(),
|
|
2299
|
+
now.getUTCDate()
|
|
2300
|
+
)).toISOString().split("T")[0];
|
|
2301
|
+
const endISO = new Date(Date.UTC(
|
|
2302
|
+
now.getUTCFullYear(),
|
|
2303
|
+
now.getUTCMonth(),
|
|
2304
|
+
now.getUTCDate() + 7
|
|
2305
|
+
)).toISOString().split("T")[0];
|
|
2306
|
+
const newTask = {
|
|
2307
|
+
id: crypto.randomUUID(),
|
|
2308
|
+
name: "\u041D\u043E\u0432\u0430\u044F \u0437\u0430\u0434\u0430\u0447\u0430",
|
|
2309
|
+
startDate: todayISO,
|
|
2310
|
+
endDate: endISO
|
|
2311
|
+
};
|
|
2312
|
+
onInsertAfter(task.id, newTask);
|
|
2313
|
+
},
|
|
2314
|
+
"aria-label": "\u0412\u0441\u0442\u0430\u0432\u0438\u0442\u044C \u0437\u0430\u0434\u0430\u0447\u0443 \u043F\u043E\u0441\u043B\u0435 \u044D\u0442\u043E\u0439",
|
|
2315
|
+
children: /* @__PURE__ */ jsx12(PlusIcon, {})
|
|
2316
|
+
}
|
|
2317
|
+
),
|
|
2318
|
+
onDelete && /* @__PURE__ */ jsx12(
|
|
2319
|
+
"button",
|
|
2320
|
+
{
|
|
2321
|
+
type: "button",
|
|
2322
|
+
className: "gantt-tl-name-action-btn gantt-tl-action-delete",
|
|
2323
|
+
onClick: (e) => {
|
|
2324
|
+
e.stopPropagation();
|
|
2325
|
+
onDelete(task.id);
|
|
2326
|
+
},
|
|
2327
|
+
"aria-label": "\u0423\u0434\u0430\u043B\u0438\u0442\u044C \u0437\u0430\u0434\u0430\u0447\u0443",
|
|
2328
|
+
children: /* @__PURE__ */ jsx12(TrashIcon, {})
|
|
2329
|
+
}
|
|
2330
|
+
)
|
|
2331
|
+
] })
|
|
2180
2332
|
] }),
|
|
2181
2333
|
/* @__PURE__ */ jsx12("div", { className: "gantt-tl-cell gantt-tl-cell-date", onClick: (e) => e.stopPropagation(), children: /* @__PURE__ */ jsx12(
|
|
2182
2334
|
DatePicker,
|
|
@@ -2202,7 +2354,7 @@ var TaskListRow = React9.memo(
|
|
|
2202
2354
|
"div",
|
|
2203
2355
|
{
|
|
2204
2356
|
className: "gantt-tl-cell gantt-tl-cell-deps",
|
|
2205
|
-
onClick:
|
|
2357
|
+
onClick: isSourceRow ? handleCancelPicking : isPicking ? handlePredecessorPick : void 0,
|
|
2206
2358
|
children: isSourceRow ? /* @__PURE__ */ jsx12("span", { className: "gantt-tl-dep-source-hint", children: "\u0412\u044B\u0431\u0435\u0440\u0438\u0442\u0435 \u0437\u0430\u0434\u0430\u0447\u0443" }) : isSelectedPredecessor && !disableDependencyEditing ? (
|
|
2207
2359
|
/* Full-replacement: "Зависит от [name]" → hover → "Удалить" */
|
|
2208
2360
|
/* @__PURE__ */ jsxs9(
|
|
@@ -2279,7 +2431,7 @@ var TaskListRow = React9.memo(
|
|
|
2279
2431
|
"button",
|
|
2280
2432
|
{
|
|
2281
2433
|
type: "button",
|
|
2282
|
-
className: "gantt-tl-dep-add"
|
|
2434
|
+
className: `gantt-tl-dep-add gantt-tl-dep-add-hover${selectedChip ? " gantt-tl-dep-add-hidden" : ""}`,
|
|
2283
2435
|
onClick: handleAddClick,
|
|
2284
2436
|
"aria-label": "\u0414\u043E\u0431\u0430\u0432\u0438\u0442\u044C \u0441\u0432\u044F\u0437\u044C",
|
|
2285
2437
|
children: "+"
|
|
@@ -2295,14 +2447,68 @@ var TaskListRow = React9.memo(
|
|
|
2295
2447
|
);
|
|
2296
2448
|
TaskListRow.displayName = "TaskListRow";
|
|
2297
2449
|
|
|
2298
|
-
// src/components/TaskList/
|
|
2450
|
+
// src/components/TaskList/NewTaskRow.tsx
|
|
2451
|
+
import { useState as useState5, useRef as useRef4, useEffect as useEffect4 } from "react";
|
|
2299
2452
|
import { jsx as jsx13, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
2453
|
+
var NewTaskRow = ({ rowHeight, onConfirm, onCancel }) => {
|
|
2454
|
+
const [nameValue, setNameValue] = useState5("");
|
|
2455
|
+
const inputRef = useRef4(null);
|
|
2456
|
+
const confirmedRef = useRef4(false);
|
|
2457
|
+
useEffect4(() => {
|
|
2458
|
+
if (inputRef.current) {
|
|
2459
|
+
inputRef.current.focus();
|
|
2460
|
+
inputRef.current.select();
|
|
2461
|
+
}
|
|
2462
|
+
}, []);
|
|
2463
|
+
const handleKeyDown = (e) => {
|
|
2464
|
+
if (e.key === "Enter") {
|
|
2465
|
+
if (nameValue.trim()) {
|
|
2466
|
+
confirmedRef.current = true;
|
|
2467
|
+
onConfirm(nameValue.trim());
|
|
2468
|
+
} else {
|
|
2469
|
+
onCancel();
|
|
2470
|
+
}
|
|
2471
|
+
} else if (e.key === "Escape") {
|
|
2472
|
+
onCancel();
|
|
2473
|
+
}
|
|
2474
|
+
};
|
|
2475
|
+
const handleBlur = () => {
|
|
2476
|
+
if (confirmedRef.current) return;
|
|
2477
|
+
if (nameValue.trim()) {
|
|
2478
|
+
confirmedRef.current = true;
|
|
2479
|
+
onConfirm(nameValue.trim());
|
|
2480
|
+
} else {
|
|
2481
|
+
onCancel();
|
|
2482
|
+
}
|
|
2483
|
+
};
|
|
2484
|
+
return /* @__PURE__ */ jsxs10("div", { className: "gantt-tl-row gantt-tl-row-new", style: { minHeight: `${rowHeight}px` }, children: [
|
|
2485
|
+
/* @__PURE__ */ jsx13("div", { className: "gantt-tl-cell gantt-tl-cell-number" }),
|
|
2486
|
+
/* @__PURE__ */ jsx13("div", { className: "gantt-tl-cell gantt-tl-cell-name gantt-tl-cell-new-name", children: /* @__PURE__ */ jsx13(
|
|
2487
|
+
Input,
|
|
2488
|
+
{
|
|
2489
|
+
ref: inputRef,
|
|
2490
|
+
value: nameValue,
|
|
2491
|
+
onChange: (e) => setNameValue(e.target.value),
|
|
2492
|
+
onKeyDown: handleKeyDown,
|
|
2493
|
+
onBlur: handleBlur,
|
|
2494
|
+
placeholder: "\u041D\u0430\u0437\u0432\u0430\u043D\u0438\u0435",
|
|
2495
|
+
className: "gantt-tl-name-input"
|
|
2496
|
+
}
|
|
2497
|
+
) }),
|
|
2498
|
+
/* @__PURE__ */ jsx13("div", { className: "gantt-tl-cell" }),
|
|
2499
|
+
/* @__PURE__ */ jsx13("div", { className: "gantt-tl-cell" }),
|
|
2500
|
+
/* @__PURE__ */ jsx13("div", { className: "gantt-tl-cell" })
|
|
2501
|
+
] });
|
|
2502
|
+
};
|
|
2503
|
+
|
|
2504
|
+
// src/components/TaskList/TaskList.tsx
|
|
2505
|
+
import { jsx as jsx14, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
2300
2506
|
var LINK_TYPE_ORDER = ["FS", "SS", "FF", "SF"];
|
|
2301
2507
|
var TaskList = ({
|
|
2302
2508
|
tasks,
|
|
2303
2509
|
rowHeight,
|
|
2304
2510
|
headerHeight,
|
|
2305
|
-
taskListWidth =
|
|
2511
|
+
taskListWidth = 472,
|
|
2306
2512
|
onTaskChange,
|
|
2307
2513
|
selectedTaskId,
|
|
2308
2514
|
onTaskSelect,
|
|
@@ -2310,7 +2516,11 @@ var TaskList = ({
|
|
|
2310
2516
|
disableTaskNameEditing = false,
|
|
2311
2517
|
disableDependencyEditing = false,
|
|
2312
2518
|
onScrollToTask,
|
|
2313
|
-
onSelectedChipChange
|
|
2519
|
+
onSelectedChipChange,
|
|
2520
|
+
onAdd,
|
|
2521
|
+
onDelete,
|
|
2522
|
+
onInsertAfter,
|
|
2523
|
+
editingTaskId: propEditingTaskId
|
|
2314
2524
|
}) => {
|
|
2315
2525
|
const totalHeight = useMemo8(
|
|
2316
2526
|
() => tasks.length * rowHeight,
|
|
@@ -2319,17 +2529,17 @@ var TaskList = ({
|
|
|
2319
2529
|
const handleRowClick = useCallback5((taskId) => {
|
|
2320
2530
|
onTaskSelect?.(taskId);
|
|
2321
2531
|
}, [onTaskSelect]);
|
|
2322
|
-
const [activeLinkType, setActiveLinkType] =
|
|
2323
|
-
const [selectingPredecessorFor, setSelectingPredecessorFor] =
|
|
2324
|
-
const [typeMenuOpen, setTypeMenuOpen] =
|
|
2325
|
-
const [cycleError, setCycleError] =
|
|
2326
|
-
const overlayRef =
|
|
2327
|
-
const [selectedChip, setSelectedChip] =
|
|
2532
|
+
const [activeLinkType, setActiveLinkType] = useState6("FS");
|
|
2533
|
+
const [selectingPredecessorFor, setSelectingPredecessorFor] = useState6(null);
|
|
2534
|
+
const [typeMenuOpen, setTypeMenuOpen] = useState6(false);
|
|
2535
|
+
const [cycleError, setCycleError] = useState6(false);
|
|
2536
|
+
const overlayRef = useRef5(null);
|
|
2537
|
+
const [selectedChip, setSelectedChip] = useState6(null);
|
|
2328
2538
|
const handleChipSelect = useCallback5((chip) => {
|
|
2329
2539
|
setSelectedChip(chip);
|
|
2330
2540
|
onSelectedChipChange?.(chip);
|
|
2331
2541
|
}, [onSelectedChipChange]);
|
|
2332
|
-
|
|
2542
|
+
useEffect5(() => {
|
|
2333
2543
|
if (!selectingPredecessorFor && !selectedChip) return;
|
|
2334
2544
|
const handleKeyDown = (e) => {
|
|
2335
2545
|
if (e.key === "Escape") {
|
|
@@ -2410,21 +2620,44 @@ var TaskList = ({
|
|
|
2410
2620
|
);
|
|
2411
2621
|
onTaskChange?.({ ...task, dependencies: updatedDeps });
|
|
2412
2622
|
}, [tasks, onTaskChange]);
|
|
2413
|
-
|
|
2623
|
+
const [isCreating, setIsCreating] = useState6(false);
|
|
2624
|
+
const handleConfirmNewTask = useCallback5((name) => {
|
|
2625
|
+
const now = /* @__PURE__ */ new Date();
|
|
2626
|
+
const todayISO = new Date(Date.UTC(
|
|
2627
|
+
now.getUTCFullYear(),
|
|
2628
|
+
now.getUTCMonth(),
|
|
2629
|
+
now.getUTCDate()
|
|
2630
|
+
)).toISOString().split("T")[0];
|
|
2631
|
+
const endISO = new Date(Date.UTC(
|
|
2632
|
+
now.getUTCFullYear(),
|
|
2633
|
+
now.getUTCMonth(),
|
|
2634
|
+
now.getUTCDate() + 7
|
|
2635
|
+
)).toISOString().split("T")[0];
|
|
2636
|
+
const newTask = {
|
|
2637
|
+
id: crypto.randomUUID(),
|
|
2638
|
+
name,
|
|
2639
|
+
startDate: todayISO,
|
|
2640
|
+
endDate: endISO
|
|
2641
|
+
};
|
|
2642
|
+
onAdd?.(newTask);
|
|
2643
|
+
setIsCreating(false);
|
|
2644
|
+
}, [onAdd]);
|
|
2645
|
+
const handleCancelNewTask = useCallback5(() => setIsCreating(false), []);
|
|
2646
|
+
return /* @__PURE__ */ jsx14(
|
|
2414
2647
|
"div",
|
|
2415
2648
|
{
|
|
2416
2649
|
ref: overlayRef,
|
|
2417
2650
|
className: `gantt-tl-overlay${show ? "" : " gantt-tl-hidden"}`,
|
|
2418
2651
|
style: { width: `${taskListWidth}px` },
|
|
2419
|
-
children: /* @__PURE__ */
|
|
2420
|
-
/* @__PURE__ */
|
|
2421
|
-
/* @__PURE__ */
|
|
2422
|
-
/* @__PURE__ */
|
|
2423
|
-
/* @__PURE__ */
|
|
2424
|
-
/* @__PURE__ */
|
|
2425
|
-
/* @__PURE__ */
|
|
2426
|
-
/* @__PURE__ */
|
|
2427
|
-
/* @__PURE__ */
|
|
2652
|
+
children: /* @__PURE__ */ jsxs11("div", { className: "gantt-tl-table", children: [
|
|
2653
|
+
/* @__PURE__ */ jsxs11("div", { className: "gantt-tl-header", style: { height: `${headerHeight + 0.5}px` }, children: [
|
|
2654
|
+
/* @__PURE__ */ jsx14("div", { className: "gantt-tl-headerCell gantt-tl-cell-number", children: "\u2116" }),
|
|
2655
|
+
/* @__PURE__ */ jsx14("div", { className: "gantt-tl-headerCell gantt-tl-cell-name", children: "\u0418\u043C\u044F" }),
|
|
2656
|
+
/* @__PURE__ */ jsx14("div", { className: "gantt-tl-headerCell gantt-tl-cell-date", children: "\u041D\u0430\u0447\u0430\u043B\u043E" }),
|
|
2657
|
+
/* @__PURE__ */ jsx14("div", { className: "gantt-tl-headerCell gantt-tl-cell-date", children: "\u041E\u043A\u043E\u043D\u0447\u0430\u043D\u0438\u0435" }),
|
|
2658
|
+
/* @__PURE__ */ jsxs11("div", { className: "gantt-tl-headerCell gantt-tl-cell-deps", style: { position: "relative" }, children: [
|
|
2659
|
+
/* @__PURE__ */ jsxs11(Popover, { open: typeMenuOpen, onOpenChange: setTypeMenuOpen, children: [
|
|
2660
|
+
/* @__PURE__ */ jsx14(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxs11(
|
|
2428
2661
|
"button",
|
|
2429
2662
|
{
|
|
2430
2663
|
className: "gantt-tl-dep-type-trigger",
|
|
@@ -2432,12 +2665,12 @@ var TaskList = ({
|
|
|
2432
2665
|
onClick: (e) => e.stopPropagation(),
|
|
2433
2666
|
children: [
|
|
2434
2667
|
"\u0421\u0432\u044F\u0437\u0438 ",
|
|
2435
|
-
|
|
2668
|
+
React11.createElement(LINK_TYPE_ICONS[activeLinkType]),
|
|
2436
2669
|
" \u25BE"
|
|
2437
2670
|
]
|
|
2438
2671
|
}
|
|
2439
2672
|
) }),
|
|
2440
|
-
/* @__PURE__ */
|
|
2673
|
+
/* @__PURE__ */ jsx14(PopoverContent, { portal: true, align: "start", children: /* @__PURE__ */ jsx14("div", { className: "gantt-tl-dep-type-menu", children: LINK_TYPE_ORDER.map((lt) => /* @__PURE__ */ jsxs11(
|
|
2441
2674
|
"button",
|
|
2442
2675
|
{
|
|
2443
2676
|
className: `gantt-tl-dep-type-option${activeLinkType === lt ? " active" : ""}`,
|
|
@@ -2446,17 +2679,17 @@ var TaskList = ({
|
|
|
2446
2679
|
setTypeMenuOpen(false);
|
|
2447
2680
|
},
|
|
2448
2681
|
children: [
|
|
2449
|
-
|
|
2450
|
-
/* @__PURE__ */
|
|
2682
|
+
React11.createElement(LINK_TYPE_ICONS[lt]),
|
|
2683
|
+
/* @__PURE__ */ jsx14("span", { children: LINK_TYPE_LABELS[lt] })
|
|
2451
2684
|
]
|
|
2452
2685
|
},
|
|
2453
2686
|
lt
|
|
2454
2687
|
)) }) })
|
|
2455
2688
|
] }),
|
|
2456
|
-
cycleError && /* @__PURE__ */
|
|
2689
|
+
cycleError && /* @__PURE__ */ jsx14("div", { className: "gantt-tl-dep-error", children: "\u0426\u0438\u043A\u043B \u0437\u0430\u0432\u0438\u0441\u0438\u043C\u043E\u0441\u0442\u0435\u0439!" })
|
|
2457
2690
|
] })
|
|
2458
2691
|
] }),
|
|
2459
|
-
/* @__PURE__ */
|
|
2692
|
+
/* @__PURE__ */ jsx14("div", { className: "gantt-tl-body", style: { height: `${totalHeight}px` }, children: tasks.map((task, index) => /* @__PURE__ */ jsx14(
|
|
2460
2693
|
TaskListRow,
|
|
2461
2694
|
{
|
|
2462
2695
|
task,
|
|
@@ -2475,17 +2708,38 @@ var TaskList = ({
|
|
|
2475
2708
|
onRemoveDependency: handleRemoveDependency,
|
|
2476
2709
|
selectedChip,
|
|
2477
2710
|
onChipSelect: handleChipSelect,
|
|
2478
|
-
onScrollToTask
|
|
2711
|
+
onScrollToTask,
|
|
2712
|
+
onDelete,
|
|
2713
|
+
onAdd,
|
|
2714
|
+
onInsertAfter,
|
|
2715
|
+
editingTaskId: propEditingTaskId
|
|
2479
2716
|
},
|
|
2480
2717
|
task.id
|
|
2481
|
-
)) })
|
|
2718
|
+
)) }),
|
|
2719
|
+
isCreating && /* @__PURE__ */ jsx14(
|
|
2720
|
+
NewTaskRow,
|
|
2721
|
+
{
|
|
2722
|
+
rowHeight,
|
|
2723
|
+
onConfirm: handleConfirmNewTask,
|
|
2724
|
+
onCancel: handleCancelNewTask
|
|
2725
|
+
}
|
|
2726
|
+
),
|
|
2727
|
+
onAdd && !isCreating && /* @__PURE__ */ jsx14(
|
|
2728
|
+
"button",
|
|
2729
|
+
{
|
|
2730
|
+
className: "gantt-tl-add-btn",
|
|
2731
|
+
onClick: () => setIsCreating(true),
|
|
2732
|
+
type: "button",
|
|
2733
|
+
children: "+ \u0414\u043E\u0431\u0430\u0432\u0438\u0442\u044C \u0437\u0430\u0434\u0430\u0447\u0443"
|
|
2734
|
+
}
|
|
2735
|
+
)
|
|
2482
2736
|
] })
|
|
2483
2737
|
}
|
|
2484
2738
|
);
|
|
2485
2739
|
};
|
|
2486
2740
|
|
|
2487
2741
|
// src/components/GanttChart/GanttChart.tsx
|
|
2488
|
-
import { jsx as
|
|
2742
|
+
import { jsx as jsx15, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
2489
2743
|
var GanttChart = forwardRef(({
|
|
2490
2744
|
tasks,
|
|
2491
2745
|
dayWidth = 40,
|
|
@@ -2501,14 +2755,18 @@ var GanttChart = forwardRef(({
|
|
|
2501
2755
|
taskListWidth = 520,
|
|
2502
2756
|
disableTaskNameEditing = false,
|
|
2503
2757
|
disableDependencyEditing = false,
|
|
2504
|
-
highlightExpiredTasks = false
|
|
2758
|
+
highlightExpiredTasks = false,
|
|
2759
|
+
onAdd,
|
|
2760
|
+
onDelete,
|
|
2761
|
+
onInsertAfter
|
|
2505
2762
|
}, ref) => {
|
|
2506
|
-
const scrollContainerRef =
|
|
2507
|
-
const [selectedTaskId, setSelectedTaskId] =
|
|
2508
|
-
const [selectedChip, setSelectedChip] =
|
|
2763
|
+
const scrollContainerRef = useRef6(null);
|
|
2764
|
+
const [selectedTaskId, setSelectedTaskId] = useState7(null);
|
|
2765
|
+
const [selectedChip, setSelectedChip] = useState7(null);
|
|
2766
|
+
const [editingTaskId, setEditingTaskId] = useState7(null);
|
|
2509
2767
|
const dateRange = useMemo9(() => getMultiMonthDays(tasks), [tasks]);
|
|
2510
|
-
const [validationResult, setValidationResult] =
|
|
2511
|
-
const [cascadeOverrides, setCascadeOverrides] =
|
|
2768
|
+
const [validationResult, setValidationResult] = useState7(null);
|
|
2769
|
+
const [cascadeOverrides, setCascadeOverrides] = useState7(/* @__PURE__ */ new Map());
|
|
2512
2770
|
const gridWidth = useMemo9(
|
|
2513
2771
|
() => Math.round(dateRange.length * dayWidth),
|
|
2514
2772
|
[dateRange.length, dayWidth]
|
|
@@ -2529,7 +2787,7 @@ var GanttChart = forwardRef(({
|
|
|
2529
2787
|
const today = new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate()));
|
|
2530
2788
|
return dateRange.some((day) => day.getTime() === today.getTime());
|
|
2531
2789
|
}, [dateRange]);
|
|
2532
|
-
|
|
2790
|
+
useEffect6(() => {
|
|
2533
2791
|
const container = scrollContainerRef.current;
|
|
2534
2792
|
if (!container || dateRange.length === 0) return;
|
|
2535
2793
|
const now = /* @__PURE__ */ new Date();
|
|
@@ -2578,9 +2836,9 @@ var GanttChart = forwardRef(({
|
|
|
2578
2836
|
}),
|
|
2579
2837
|
[scrollToToday, scrollToTask]
|
|
2580
2838
|
);
|
|
2581
|
-
const [dragGuideLines, setDragGuideLines] =
|
|
2582
|
-
const [draggedTaskOverride, setDraggedTaskOverride] =
|
|
2583
|
-
|
|
2839
|
+
const [dragGuideLines, setDragGuideLines] = useState7(null);
|
|
2840
|
+
const [draggedTaskOverride, setDraggedTaskOverride] = useState7(null);
|
|
2841
|
+
useEffect6(() => {
|
|
2584
2842
|
const result = validateDependencies(tasks);
|
|
2585
2843
|
setValidationResult(result);
|
|
2586
2844
|
onValidateDependencies?.(result);
|
|
@@ -2589,6 +2847,9 @@ var GanttChart = forwardRef(({
|
|
|
2589
2847
|
const originalTask = tasks.find((t) => t.id === updatedTask.id);
|
|
2590
2848
|
if (!originalTask) {
|
|
2591
2849
|
onChange?.((currentTasks) => currentTasks.map((t) => t.id === updatedTask.id ? updatedTask : t));
|
|
2850
|
+
if (editingTaskId === updatedTask.id) {
|
|
2851
|
+
setEditingTaskId(null);
|
|
2852
|
+
}
|
|
2592
2853
|
return;
|
|
2593
2854
|
}
|
|
2594
2855
|
const origStart = new Date(originalTask.startDate);
|
|
@@ -2598,6 +2859,9 @@ var GanttChart = forwardRef(({
|
|
|
2598
2859
|
const datesChanged = origStart.getTime() !== newStart.getTime() || origEnd.getTime() !== newEnd.getTime();
|
|
2599
2860
|
if (!datesChanged) {
|
|
2600
2861
|
onChange?.((currentTasks) => currentTasks.map((t) => t.id === updatedTask.id ? updatedTask : t));
|
|
2862
|
+
if (editingTaskId === updatedTask.id) {
|
|
2863
|
+
setEditingTaskId(null);
|
|
2864
|
+
}
|
|
2601
2865
|
return;
|
|
2602
2866
|
}
|
|
2603
2867
|
let cascadedTasksForCallback;
|
|
@@ -2616,7 +2880,20 @@ var GanttChart = forwardRef(({
|
|
|
2616
2880
|
});
|
|
2617
2881
|
onCascade?.(cascadedTasksForCallback);
|
|
2618
2882
|
}
|
|
2619
|
-
}, [tasks, onChange, disableConstraints, onCascade]);
|
|
2883
|
+
}, [tasks, onChange, disableConstraints, onCascade, editingTaskId]);
|
|
2884
|
+
const handleDelete = useCallback6((taskId) => {
|
|
2885
|
+
onChange?.(
|
|
2886
|
+
(currentTasks) => currentTasks.filter((t) => t.id !== taskId).map((t) => ({
|
|
2887
|
+
...t,
|
|
2888
|
+
dependencies: (t.dependencies ?? []).filter((d) => d.taskId !== taskId)
|
|
2889
|
+
}))
|
|
2890
|
+
);
|
|
2891
|
+
onDelete?.(taskId);
|
|
2892
|
+
}, [onChange, onDelete]);
|
|
2893
|
+
const handleInsertAfter = useCallback6((taskId, newTask) => {
|
|
2894
|
+
setEditingTaskId(newTask.id);
|
|
2895
|
+
onInsertAfter?.(taskId, newTask);
|
|
2896
|
+
}, [onInsertAfter]);
|
|
2620
2897
|
const dependencyOverrides = useMemo9(() => {
|
|
2621
2898
|
const map = new Map(cascadeOverrides);
|
|
2622
2899
|
if (draggedTaskOverride) {
|
|
@@ -2640,7 +2917,7 @@ var GanttChart = forwardRef(({
|
|
|
2640
2917
|
const handleTaskSelect = useCallback6((taskId) => {
|
|
2641
2918
|
setSelectedTaskId(taskId);
|
|
2642
2919
|
}, []);
|
|
2643
|
-
const panStateRef =
|
|
2920
|
+
const panStateRef = useRef6(null);
|
|
2644
2921
|
const handlePanStart = useCallback6((e) => {
|
|
2645
2922
|
if (e.button !== 0) return;
|
|
2646
2923
|
const target = e.target;
|
|
@@ -2662,7 +2939,7 @@ var GanttChart = forwardRef(({
|
|
|
2662
2939
|
container.style.cursor = "grabbing";
|
|
2663
2940
|
e.preventDefault();
|
|
2664
2941
|
}, []);
|
|
2665
|
-
|
|
2942
|
+
useEffect6(() => {
|
|
2666
2943
|
const handlePanMove = (e) => {
|
|
2667
2944
|
const pan = panStateRef.current;
|
|
2668
2945
|
if (!pan?.active) return;
|
|
@@ -2684,15 +2961,15 @@ var GanttChart = forwardRef(({
|
|
|
2684
2961
|
window.removeEventListener("mouseup", handlePanEnd);
|
|
2685
2962
|
};
|
|
2686
2963
|
}, []);
|
|
2687
|
-
return /* @__PURE__ */
|
|
2964
|
+
return /* @__PURE__ */ jsx15("div", { className: "gantt-container", children: /* @__PURE__ */ jsx15(
|
|
2688
2965
|
"div",
|
|
2689
2966
|
{
|
|
2690
2967
|
ref: scrollContainerRef,
|
|
2691
2968
|
className: "gantt-scrollContainer",
|
|
2692
2969
|
style: { height: containerHeight ?? "auto", cursor: "grab" },
|
|
2693
2970
|
onMouseDown: handlePanStart,
|
|
2694
|
-
children: /* @__PURE__ */
|
|
2695
|
-
/* @__PURE__ */
|
|
2971
|
+
children: /* @__PURE__ */ jsxs12("div", { className: "gantt-scrollContent", children: [
|
|
2972
|
+
/* @__PURE__ */ jsx15(
|
|
2696
2973
|
TaskList,
|
|
2697
2974
|
{
|
|
2698
2975
|
tasks,
|
|
@@ -2706,11 +2983,15 @@ var GanttChart = forwardRef(({
|
|
|
2706
2983
|
disableTaskNameEditing,
|
|
2707
2984
|
disableDependencyEditing,
|
|
2708
2985
|
onScrollToTask: scrollToTask,
|
|
2709
|
-
onSelectedChipChange: setSelectedChip
|
|
2986
|
+
onSelectedChipChange: setSelectedChip,
|
|
2987
|
+
onAdd,
|
|
2988
|
+
onDelete: handleDelete,
|
|
2989
|
+
onInsertAfter: handleInsertAfter,
|
|
2990
|
+
editingTaskId
|
|
2710
2991
|
}
|
|
2711
2992
|
),
|
|
2712
|
-
/* @__PURE__ */
|
|
2713
|
-
/* @__PURE__ */
|
|
2993
|
+
/* @__PURE__ */ jsxs12("div", { style: { minWidth: `${gridWidth}px`, flex: 1 }, children: [
|
|
2994
|
+
/* @__PURE__ */ jsx15("div", { className: "gantt-stickyHeader", style: { width: `${gridWidth}px` }, children: /* @__PURE__ */ jsx15(
|
|
2714
2995
|
TimeScaleHeader_default,
|
|
2715
2996
|
{
|
|
2716
2997
|
days: dateRange,
|
|
@@ -2718,7 +2999,7 @@ var GanttChart = forwardRef(({
|
|
|
2718
2999
|
headerHeight
|
|
2719
3000
|
}
|
|
2720
3001
|
) }),
|
|
2721
|
-
/* @__PURE__ */
|
|
3002
|
+
/* @__PURE__ */ jsxs12(
|
|
2722
3003
|
"div",
|
|
2723
3004
|
{
|
|
2724
3005
|
className: "gantt-taskArea",
|
|
@@ -2727,7 +3008,7 @@ var GanttChart = forwardRef(({
|
|
|
2727
3008
|
width: `${gridWidth}px`
|
|
2728
3009
|
},
|
|
2729
3010
|
children: [
|
|
2730
|
-
/* @__PURE__ */
|
|
3011
|
+
/* @__PURE__ */ jsx15(
|
|
2731
3012
|
GridBackground_default,
|
|
2732
3013
|
{
|
|
2733
3014
|
dateRange,
|
|
@@ -2735,8 +3016,8 @@ var GanttChart = forwardRef(({
|
|
|
2735
3016
|
totalHeight: totalGridHeight
|
|
2736
3017
|
}
|
|
2737
3018
|
),
|
|
2738
|
-
todayInRange && /* @__PURE__ */
|
|
2739
|
-
/* @__PURE__ */
|
|
3019
|
+
todayInRange && /* @__PURE__ */ jsx15(TodayIndicator_default, { monthStart, dayWidth }),
|
|
3020
|
+
/* @__PURE__ */ jsx15(
|
|
2740
3021
|
DependencyLines_default,
|
|
2741
3022
|
{
|
|
2742
3023
|
tasks,
|
|
@@ -2748,7 +3029,7 @@ var GanttChart = forwardRef(({
|
|
|
2748
3029
|
selectedDep: selectedChip
|
|
2749
3030
|
}
|
|
2750
3031
|
),
|
|
2751
|
-
dragGuideLines && /* @__PURE__ */
|
|
3032
|
+
dragGuideLines && /* @__PURE__ */ jsx15(
|
|
2752
3033
|
DragGuideLines_default,
|
|
2753
3034
|
{
|
|
2754
3035
|
isDragging: dragGuideLines.isDragging,
|
|
@@ -2758,7 +3039,7 @@ var GanttChart = forwardRef(({
|
|
|
2758
3039
|
totalHeight: totalGridHeight
|
|
2759
3040
|
}
|
|
2760
3041
|
),
|
|
2761
|
-
tasks.map((task, index) => /* @__PURE__ */
|
|
3042
|
+
tasks.map((task, index) => /* @__PURE__ */ jsx15(
|
|
2762
3043
|
TaskRow_default,
|
|
2763
3044
|
{
|
|
2764
3045
|
task,
|
|
@@ -2797,9 +3078,9 @@ var GanttChart = forwardRef(({
|
|
|
2797
3078
|
GanttChart.displayName = "GanttChart";
|
|
2798
3079
|
|
|
2799
3080
|
// src/components/ui/Button.tsx
|
|
2800
|
-
import
|
|
2801
|
-
import { jsx as
|
|
2802
|
-
var Button =
|
|
3081
|
+
import React13 from "react";
|
|
3082
|
+
import { jsx as jsx16 } from "react/jsx-runtime";
|
|
3083
|
+
var Button = React13.forwardRef(
|
|
2803
3084
|
({ className, variant = "default", size = "default", children, ...props }, ref) => {
|
|
2804
3085
|
const classes = [
|
|
2805
3086
|
"gantt-btn",
|
|
@@ -2807,7 +3088,7 @@ var Button = React12.forwardRef(
|
|
|
2807
3088
|
size !== "default" ? `gantt-btn-${size}` : "",
|
|
2808
3089
|
className || ""
|
|
2809
3090
|
].filter(Boolean).join(" ");
|
|
2810
|
-
return /* @__PURE__ */
|
|
3091
|
+
return /* @__PURE__ */ jsx16("button", { ref, className: classes, ...props, children });
|
|
2811
3092
|
}
|
|
2812
3093
|
);
|
|
2813
3094
|
Button.displayName = "Button";
|