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.js CHANGED
@@ -78,7 +78,7 @@ __export(index_exports, {
78
78
  module.exports = __toCommonJS(index_exports);
79
79
 
80
80
  // src/components/GanttChart/GanttChart.tsx
81
- var import_react12 = require("react");
81
+ var import_react13 = require("react");
82
82
 
83
83
  // src/utils/dateUtils.ts
84
84
  var parseUTCDate = (date) => {
@@ -119,9 +119,9 @@ var getDayOffset = (date, monthStart) => {
119
119
  var isToday = (date) => {
120
120
  const now = /* @__PURE__ */ new Date();
121
121
  const today = new Date(Date.UTC(
122
- now.getUTCFullYear(),
123
- now.getUTCMonth(),
124
- now.getUTCDate()
122
+ now.getFullYear(),
123
+ now.getMonth(),
124
+ now.getDate()
125
125
  ));
126
126
  const compareDate = new Date(Date.UTC(
127
127
  date.getUTCFullYear(),
@@ -600,7 +600,7 @@ var calculateGridLines = (dateRange, dayWidth) => {
600
600
  for (let i = 0; i < dateRange.length; i++) {
601
601
  const date = dateRange[i];
602
602
  const x = Math.round(i * dayWidth);
603
- const isMonthStart = date.getUTCDate() === 1;
603
+ const isMonthStart = i === 0 ? false : date.getUTCDate() === 1;
604
604
  const isWeekStart = date.getUTCDay() === 1;
605
605
  lines.push({ x, isMonthStart, isWeekStart });
606
606
  }
@@ -1179,7 +1179,7 @@ var TaskRow = import_react3.default.memo(
1179
1179
  const isExpired = (0, import_react3.useMemo)(() => {
1180
1180
  if (!highlightExpiredTasks) return false;
1181
1181
  const now = /* @__PURE__ */ new Date();
1182
- const today = new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate()));
1182
+ const today = new Date(Date.UTC(now.getFullYear(), now.getMonth(), now.getDate()));
1183
1183
  const taskStart = parseUTCDate(task.startDate);
1184
1184
  const taskEnd = parseUTCDate(task.endDate);
1185
1185
  const actualProgress = task.progress ?? 0;
@@ -1686,7 +1686,7 @@ DependencyLines.displayName = "DependencyLines";
1686
1686
  var DependencyLines_default = DependencyLines;
1687
1687
 
1688
1688
  // src/components/TaskList/TaskList.tsx
1689
- var import_react11 = __toESM(require("react"));
1689
+ var import_react12 = __toESM(require("react"));
1690
1690
 
1691
1691
  // src/components/ui/Popover.tsx
1692
1692
  var RadixPopover = __toESM(require("@radix-ui/react-popover"));
@@ -1855,7 +1855,73 @@ var Calendar = ({
1855
1855
  () => months.map(renderMonth),
1856
1856
  [months, renderMonth]
1857
1857
  );
1858
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { ref: scrollRef, className: "gantt-cal-container", children: renderedMonths });
1858
+ const handleDayShift = (0, import_react8.useCallback)(
1859
+ (deltaDays) => {
1860
+ if (!onSelect || disabled) return;
1861
+ const baseDate = selected ?? /* @__PURE__ */ new Date();
1862
+ onSelect((0, import_date_fns2.addDays)(baseDate, deltaDays));
1863
+ },
1864
+ [onSelect, selected, disabled]
1865
+ );
1866
+ const handleToday = (0, import_react8.useCallback)(() => {
1867
+ if (!onSelect || disabled) return;
1868
+ onSelect(/* @__PURE__ */ new Date());
1869
+ }, [onSelect, disabled]);
1870
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { ref: scrollRef, className: "gantt-cal-container", children: [
1871
+ renderedMonths,
1872
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "gantt-cal-nav", children: [
1873
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1874
+ "button",
1875
+ {
1876
+ type: "button",
1877
+ className: "gantt-btn gantt-btn-sm",
1878
+ onClick: () => handleDayShift(-7),
1879
+ disabled,
1880
+ children: "-7"
1881
+ }
1882
+ ),
1883
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1884
+ "button",
1885
+ {
1886
+ type: "button",
1887
+ className: "gantt-btn gantt-btn-sm",
1888
+ onClick: () => handleDayShift(-1),
1889
+ disabled,
1890
+ children: "-1"
1891
+ }
1892
+ ),
1893
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1894
+ "button",
1895
+ {
1896
+ type: "button",
1897
+ className: "gantt-btn gantt-btn-sm",
1898
+ onClick: handleToday,
1899
+ disabled,
1900
+ children: "\u0421\u0435\u0433\u043E\u0434\u043D\u044F"
1901
+ }
1902
+ ),
1903
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1904
+ "button",
1905
+ {
1906
+ type: "button",
1907
+ className: "gantt-btn gantt-btn-sm",
1908
+ onClick: () => handleDayShift(1),
1909
+ disabled,
1910
+ children: "+1"
1911
+ }
1912
+ ),
1913
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1914
+ "button",
1915
+ {
1916
+ type: "button",
1917
+ className: "gantt-btn gantt-btn-sm",
1918
+ onClick: () => handleDayShift(7),
1919
+ disabled,
1920
+ children: "+7"
1921
+ }
1922
+ )
1923
+ ] })
1924
+ ] });
1859
1925
  };
1860
1926
  Calendar.displayName = "Calendar";
1861
1927
 
@@ -1963,6 +2029,7 @@ var TrashIcon = () => /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("svg", { xm
1963
2029
  /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("path", { d: "M3 6h18" }),
1964
2030
  /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("path", { d: "M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2" })
1965
2031
  ] });
2032
+ var PlusIcon = () => /* @__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: "M12 5v14M5 12h14" }) });
1966
2033
  function formatDepDescription(type, lag) {
1967
2034
  const effectiveLag = lag ?? 0;
1968
2035
  if (type === "FS") {
@@ -2004,12 +2071,19 @@ var DepChip = ({
2004
2071
  const handleClick = (e) => {
2005
2072
  e.stopPropagation();
2006
2073
  if (disableDependencyEditing) return;
2007
- onChipSelect?.(isSelected ? null : { successorId: taskId, predecessorId: dep.taskId, linkType: dep.type });
2008
- if (!isSelected) {
2009
- onRowClick?.(taskId);
2010
- onScrollToTask?.(taskId);
2074
+ if (isSelected) {
2075
+ e.preventDefault();
2076
+ onChipSelect?.(null);
2077
+ return;
2011
2078
  }
2079
+ onChipSelect?.({ successorId: taskId, predecessorId: dep.taskId, linkType: dep.type });
2080
+ onScrollToTask?.(dep.taskId);
2012
2081
  };
2082
+ const handleOpenChange = (0, import_react10.useCallback)((open) => {
2083
+ if (!open) {
2084
+ onChipSelect?.(null);
2085
+ }
2086
+ }, [onChipSelect]);
2013
2087
  const handleTrashClick = (e) => {
2014
2088
  e.stopPropagation();
2015
2089
  onRemoveDependency?.(taskId, dep.taskId, dep.type);
@@ -2018,50 +2092,26 @@ var DepChip = ({
2018
2092
  const Icon = LINK_TYPE_ICONS[dep.type];
2019
2093
  const depPrefix = formatDepDescription(dep.type, lag);
2020
2094
  const depName = predecessorName ?? dep.taskId;
2021
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(Popover, { open: isSelected, onOpenChange: (open) => {
2022
- }, children: [
2023
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("span", { className: "gantt-tl-dep-chip-wrapper", children: [
2024
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2025
- "span",
2026
- {
2027
- className: `gantt-tl-dep-chip${isSelected ? " gantt-tl-dep-chip-selected" : ""}`,
2028
- onClick: handleClick,
2029
- children: /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_jsx_runtime12.Fragment, { children: [
2030
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Icon, {}),
2031
- lag != null && lag !== 0 ? lag > 0 ? `+${lag}` : `${lag}` : ""
2032
- ] })
2033
- }
2034
- ),
2035
- !disableDependencyEditing && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2036
- "button",
2037
- {
2038
- type: "button",
2039
- className: "gantt-tl-dep-chip-trash",
2040
- "aria-label": "\u0423\u0434\u0430\u043B\u0438\u0442\u044C \u0441\u0432\u044F\u0437\u044C",
2041
- onClick: handleTrashClick,
2042
- children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(TrashIcon, {})
2043
- }
2044
- )
2045
- ] }) }),
2046
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
2047
- PopoverContent,
2095
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("span", { className: "gantt-tl-dep-chip-wrapper", children: [
2096
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2097
+ "span",
2048
2098
  {
2049
- portal: true,
2050
- side: "bottom",
2051
- align: "start",
2052
- className: "gantt-tl-dep-info-popover",
2053
- onInteractOutside: (event) => {
2054
- const target = event.target;
2055
- if (target?.closest?.(".gantt-tl-dep-chip") || target?.closest?.(".gantt-tl-dep-delete-label") || target?.closest?.(".gantt-tl-dep-chip-trash")) {
2056
- event.preventDefault();
2057
- } else {
2058
- onChipSelectClear();
2059
- }
2060
- },
2061
- children: [
2062
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "gantt-tl-dep-info-prefix", children: depPrefix }),
2063
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "gantt-tl-dep-info-name", children: depName })
2064
- ]
2099
+ className: `gantt-tl-dep-chip${isSelected ? " gantt-tl-dep-chip-selected" : ""}`,
2100
+ onClick: handleClick,
2101
+ children: /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_jsx_runtime12.Fragment, { children: [
2102
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Icon, {}),
2103
+ lag != null && lag !== 0 ? lag > 0 ? `+${lag}` : `${lag}` : ""
2104
+ ] })
2105
+ }
2106
+ ),
2107
+ !disableDependencyEditing && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2108
+ "button",
2109
+ {
2110
+ type: "button",
2111
+ className: "gantt-tl-dep-chip-trash",
2112
+ "aria-label": "\u0423\u0434\u0430\u043B\u0438\u0442\u044C \u0441\u0432\u044F\u0437\u044C",
2113
+ onClick: handleTrashClick,
2114
+ children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(TrashIcon, {})
2065
2115
  }
2066
2116
  )
2067
2117
  ] });
@@ -2089,12 +2139,19 @@ var TaskListRow = import_react10.default.memo(
2089
2139
  onRemoveDependency,
2090
2140
  selectedChip,
2091
2141
  onChipSelect,
2092
- onScrollToTask
2142
+ onScrollToTask,
2143
+ onDelete,
2144
+ onAdd,
2145
+ onInsertAfter,
2146
+ editingTaskId
2093
2147
  }) => {
2094
2148
  const [editingName, setEditingName] = (0, import_react10.useState)(false);
2095
2149
  const [nameValue, setNameValue] = (0, import_react10.useState)("");
2096
2150
  const nameInputRef = (0, import_react10.useRef)(null);
2097
2151
  const [overflowOpen, setOverflowOpen] = (0, import_react10.useState)(false);
2152
+ const confirmedRef = (0, import_react10.useRef)(false);
2153
+ const autoEditedForRef = (0, import_react10.useRef)(null);
2154
+ const editTriggerRef = (0, import_react10.useRef)("doubleclick");
2098
2155
  const isSelected = selectedTaskId === task.id;
2099
2156
  const isPicking = selectingPredecessorFor != null;
2100
2157
  const isSourceRow = isPicking && selectingPredecessorFor === task.id;
@@ -2118,15 +2175,59 @@ var TaskListRow = import_react10.default.memo(
2118
2175
  (0, import_react10.useEffect)(() => {
2119
2176
  if (editingName && nameInputRef.current) {
2120
2177
  nameInputRef.current.focus();
2178
+ if (editTriggerRef.current === "keypress") {
2179
+ const len = nameInputRef.current.value.length;
2180
+ nameInputRef.current.setSelectionRange(len, len);
2181
+ } else {
2182
+ nameInputRef.current.select();
2183
+ }
2121
2184
  }
2122
2185
  }, [editingName]);
2186
+ (0, import_react10.useEffect)(() => {
2187
+ if (editingTaskId === task.id && !disableTaskNameEditing && autoEditedForRef.current !== editingTaskId) {
2188
+ autoEditedForRef.current = editingTaskId;
2189
+ confirmedRef.current = false;
2190
+ editTriggerRef.current = "autoedit";
2191
+ setNameValue(task.name);
2192
+ setEditingName(true);
2193
+ }
2194
+ }, [editingTaskId, task.id, disableTaskNameEditing]);
2123
2195
  const handleNameClick = (0, import_react10.useCallback)((e) => {
2124
2196
  if (disableTaskNameEditing) return;
2125
2197
  e.stopPropagation();
2198
+ onRowClick?.(task.id);
2199
+ onScrollToTask?.(task.id);
2200
+ }, [task.id, disableTaskNameEditing, onRowClick, onScrollToTask]);
2201
+ const handleNameDoubleClick = (0, import_react10.useCallback)((e) => {
2202
+ if (disableTaskNameEditing) return;
2203
+ e.stopPropagation();
2204
+ confirmedRef.current = false;
2205
+ editTriggerRef.current = "doubleclick";
2126
2206
  setNameValue(task.name);
2127
2207
  setEditingName(true);
2128
2208
  }, [task.name, disableTaskNameEditing]);
2209
+ const handleRowKeyDown = (0, import_react10.useCallback)((e) => {
2210
+ if (!editingName && !disableTaskNameEditing && e.key === "F2") {
2211
+ e.preventDefault();
2212
+ confirmedRef.current = false;
2213
+ editTriggerRef.current = "keypress";
2214
+ setNameValue(task.name);
2215
+ setEditingName(true);
2216
+ return;
2217
+ }
2218
+ if (!editingName && !disableTaskNameEditing && e.key.length === 1 && !e.ctrlKey && !e.metaKey && !e.altKey) {
2219
+ e.preventDefault();
2220
+ confirmedRef.current = false;
2221
+ editTriggerRef.current = "keypress";
2222
+ setNameValue(e.key);
2223
+ setEditingName(true);
2224
+ }
2225
+ }, [editingName, disableTaskNameEditing, task.name]);
2129
2226
  const handleNameSave = (0, import_react10.useCallback)(() => {
2227
+ if (confirmedRef.current) {
2228
+ confirmedRef.current = false;
2229
+ return;
2230
+ }
2130
2231
  if (nameValue.trim()) {
2131
2232
  onTaskChange?.({ ...task, name: nameValue.trim() });
2132
2233
  }
@@ -2136,9 +2237,16 @@ var TaskListRow = import_react10.default.memo(
2136
2237
  setEditingName(false);
2137
2238
  }, []);
2138
2239
  const handleNameKeyDown = (0, import_react10.useCallback)((e) => {
2139
- if (e.key === "Enter") handleNameSave();
2140
- else if (e.key === "Escape") handleNameCancel();
2141
- }, [handleNameSave, handleNameCancel]);
2240
+ if (e.key === "Enter") {
2241
+ confirmedRef.current = true;
2242
+ if (nameValue.trim()) {
2243
+ onTaskChange?.({ ...task, name: nameValue.trim() });
2244
+ }
2245
+ setEditingName(false);
2246
+ } else if (e.key === "Escape") {
2247
+ handleNameCancel();
2248
+ }
2249
+ }, [nameValue, task, onTaskChange, handleNameCancel]);
2142
2250
  const handleStartDateChange = (0, import_react10.useCallback)((newDateISO) => {
2143
2251
  if (!newDateISO) return;
2144
2252
  const origStart = parseUTCDate(task.startDate);
@@ -2163,8 +2271,7 @@ var TaskListRow = import_react10.default.memo(
2163
2271
  const handleNumberClick = (0, import_react10.useCallback)((e) => {
2164
2272
  e.stopPropagation();
2165
2273
  onRowClick?.(task.id);
2166
- onScrollToTask?.(task.id);
2167
- }, [task.id, onRowClick, onScrollToTask]);
2274
+ }, [task.id, onRowClick]);
2168
2275
  const handleAddClick = (0, import_react10.useCallback)((e) => {
2169
2276
  e.stopPropagation();
2170
2277
  onSetSelectingPredecessorFor?.(task.id);
@@ -2175,6 +2282,10 @@ var TaskListRow = import_react10.default.memo(
2175
2282
  if (!selectingPredecessorFor || !activeLinkType) return;
2176
2283
  onAddDependency?.(task.id, selectingPredecessorFor, activeLinkType);
2177
2284
  }, [isPicking, isSourceRow, selectingPredecessorFor, task.id, activeLinkType, onAddDependency]);
2285
+ const handleCancelPicking = (0, import_react10.useCallback)((e) => {
2286
+ e.stopPropagation();
2287
+ onSetSelectingPredecessorFor?.(null);
2288
+ }, [onSetSelectingPredecessorFor]);
2178
2289
  const isSelectedPredecessor = selectedChip != null && selectedChip.predecessorId === task.id;
2179
2290
  const handleDeleteSelected = (0, import_react10.useCallback)((e) => {
2180
2291
  e.stopPropagation();
@@ -2193,23 +2304,17 @@ var TaskListRow = import_react10.default.memo(
2193
2304
  isPicking && !isSourceRow ? "gantt-tl-row-picking" : "",
2194
2305
  isSourceRow ? "gantt-tl-row-picking-self" : ""
2195
2306
  ].filter(Boolean).join(" "),
2196
- style: { minHeight: `${rowHeight}px` },
2307
+ style: { minHeight: `${rowHeight}px`, position: "relative" },
2197
2308
  onClick: handleRowClickInternal,
2309
+ onKeyDown: handleRowKeyDown,
2310
+ tabIndex: isSelected ? 0 : -1,
2198
2311
  children: [
2199
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
2312
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2200
2313
  "div",
2201
2314
  {
2202
2315
  className: "gantt-tl-cell gantt-tl-cell-number",
2203
2316
  onClick: handleNumberClick,
2204
- title: "\u041F\u0435\u0440\u0435\u0439\u0442\u0438 \u043A \u0440\u0430\u0431\u043E\u0442\u0435",
2205
- children: [
2206
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "gantt-tl-num-label", children: rowIndex + 1 }),
2207
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("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: [
2208
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("path", { d: "M17 12H3" }),
2209
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("path", { d: "m11 18 6-6-6-6" }),
2210
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("path", { d: "M21 5v14" })
2211
- ] })
2212
- ]
2317
+ children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "gantt-tl-num-label", children: rowIndex + 1 })
2213
2318
  }
2214
2319
  ),
2215
2320
  /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "gantt-tl-cell gantt-tl-cell-name", children: [
@@ -2232,10 +2337,56 @@ var TaskListRow = import_react10.default.memo(
2232
2337
  type: "button",
2233
2338
  className: `gantt-tl-name-trigger ${disableTaskNameEditing ? "gantt-tl-name-locked" : ""}`,
2234
2339
  onClick: handleNameClick,
2340
+ onDoubleClick: handleNameDoubleClick,
2235
2341
  style: editingName ? { visibility: "hidden", pointerEvents: "none" } : void 0,
2236
2342
  children: task.name
2237
2343
  }
2238
- )
2344
+ ),
2345
+ !editingName && /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "gantt-tl-name-actions", children: [
2346
+ onInsertAfter && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2347
+ "button",
2348
+ {
2349
+ type: "button",
2350
+ className: "gantt-tl-name-action-btn gantt-tl-action-insert",
2351
+ onClick: (e) => {
2352
+ e.stopPropagation();
2353
+ const now = /* @__PURE__ */ new Date();
2354
+ const todayISO = new Date(Date.UTC(
2355
+ now.getUTCFullYear(),
2356
+ now.getUTCMonth(),
2357
+ now.getUTCDate()
2358
+ )).toISOString().split("T")[0];
2359
+ const endISO = new Date(Date.UTC(
2360
+ now.getUTCFullYear(),
2361
+ now.getUTCMonth(),
2362
+ now.getUTCDate() + 7
2363
+ )).toISOString().split("T")[0];
2364
+ const newTask = {
2365
+ id: crypto.randomUUID(),
2366
+ name: "\u041D\u043E\u0432\u0430\u044F \u0437\u0430\u0434\u0430\u0447\u0430",
2367
+ startDate: todayISO,
2368
+ endDate: endISO
2369
+ };
2370
+ onInsertAfter(task.id, newTask);
2371
+ },
2372
+ "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",
2373
+ children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(PlusIcon, {})
2374
+ }
2375
+ ),
2376
+ onDelete && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2377
+ "button",
2378
+ {
2379
+ type: "button",
2380
+ className: "gantt-tl-name-action-btn gantt-tl-action-delete",
2381
+ onClick: (e) => {
2382
+ e.stopPropagation();
2383
+ onDelete(task.id);
2384
+ },
2385
+ "aria-label": "\u0423\u0434\u0430\u043B\u0438\u0442\u044C \u0437\u0430\u0434\u0430\u0447\u0443",
2386
+ children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(TrashIcon, {})
2387
+ }
2388
+ )
2389
+ ] })
2239
2390
  ] }),
2240
2391
  /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "gantt-tl-cell gantt-tl-cell-date", onClick: (e) => e.stopPropagation(), children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2241
2392
  DatePicker,
@@ -2261,7 +2412,7 @@ var TaskListRow = import_react10.default.memo(
2261
2412
  "div",
2262
2413
  {
2263
2414
  className: "gantt-tl-cell gantt-tl-cell-deps",
2264
- onClick: isPicking && !isSourceRow ? handlePredecessorPick : void 0,
2415
+ onClick: isSourceRow ? handleCancelPicking : isPicking ? handlePredecessorPick : void 0,
2265
2416
  children: isSourceRow ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "gantt-tl-dep-source-hint", children: "\u0412\u044B\u0431\u0435\u0440\u0438\u0442\u0435 \u0437\u0430\u0434\u0430\u0447\u0443" }) : isSelectedPredecessor && !disableDependencyEditing ? (
2266
2417
  /* Full-replacement: "Зависит от [name]" → hover → "Удалить" */
2267
2418
  /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
@@ -2338,7 +2489,7 @@ var TaskListRow = import_react10.default.memo(
2338
2489
  "button",
2339
2490
  {
2340
2491
  type: "button",
2341
- className: "gantt-tl-dep-add",
2492
+ className: `gantt-tl-dep-add gantt-tl-dep-add-hover${selectedChip ? " gantt-tl-dep-add-hidden" : ""}`,
2342
2493
  onClick: handleAddClick,
2343
2494
  "aria-label": "\u0414\u043E\u0431\u0430\u0432\u0438\u0442\u044C \u0441\u0432\u044F\u0437\u044C",
2344
2495
  children: "+"
@@ -2354,14 +2505,68 @@ var TaskListRow = import_react10.default.memo(
2354
2505
  );
2355
2506
  TaskListRow.displayName = "TaskListRow";
2356
2507
 
2357
- // src/components/TaskList/TaskList.tsx
2508
+ // src/components/TaskList/NewTaskRow.tsx
2509
+ var import_react11 = require("react");
2358
2510
  var import_jsx_runtime13 = require("react/jsx-runtime");
2511
+ var NewTaskRow = ({ rowHeight, onConfirm, onCancel }) => {
2512
+ const [nameValue, setNameValue] = (0, import_react11.useState)("");
2513
+ const inputRef = (0, import_react11.useRef)(null);
2514
+ const confirmedRef = (0, import_react11.useRef)(false);
2515
+ (0, import_react11.useEffect)(() => {
2516
+ if (inputRef.current) {
2517
+ inputRef.current.focus();
2518
+ inputRef.current.select();
2519
+ }
2520
+ }, []);
2521
+ const handleKeyDown = (e) => {
2522
+ if (e.key === "Enter") {
2523
+ if (nameValue.trim()) {
2524
+ confirmedRef.current = true;
2525
+ onConfirm(nameValue.trim());
2526
+ } else {
2527
+ onCancel();
2528
+ }
2529
+ } else if (e.key === "Escape") {
2530
+ onCancel();
2531
+ }
2532
+ };
2533
+ const handleBlur = () => {
2534
+ if (confirmedRef.current) return;
2535
+ if (nameValue.trim()) {
2536
+ confirmedRef.current = true;
2537
+ onConfirm(nameValue.trim());
2538
+ } else {
2539
+ onCancel();
2540
+ }
2541
+ };
2542
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "gantt-tl-row gantt-tl-row-new", style: { minHeight: `${rowHeight}px` }, children: [
2543
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "gantt-tl-cell gantt-tl-cell-number" }),
2544
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "gantt-tl-cell gantt-tl-cell-name gantt-tl-cell-new-name", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2545
+ Input,
2546
+ {
2547
+ ref: inputRef,
2548
+ value: nameValue,
2549
+ onChange: (e) => setNameValue(e.target.value),
2550
+ onKeyDown: handleKeyDown,
2551
+ onBlur: handleBlur,
2552
+ placeholder: "\u041D\u0430\u0437\u0432\u0430\u043D\u0438\u0435",
2553
+ className: "gantt-tl-name-input"
2554
+ }
2555
+ ) }),
2556
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "gantt-tl-cell" }),
2557
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "gantt-tl-cell" }),
2558
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "gantt-tl-cell" })
2559
+ ] });
2560
+ };
2561
+
2562
+ // src/components/TaskList/TaskList.tsx
2563
+ var import_jsx_runtime14 = require("react/jsx-runtime");
2359
2564
  var LINK_TYPE_ORDER = ["FS", "SS", "FF", "SF"];
2360
2565
  var TaskList = ({
2361
2566
  tasks,
2362
2567
  rowHeight,
2363
2568
  headerHeight,
2364
- taskListWidth = 520,
2569
+ taskListWidth = 472,
2365
2570
  onTaskChange,
2366
2571
  selectedTaskId,
2367
2572
  onTaskSelect,
@@ -2369,26 +2574,30 @@ var TaskList = ({
2369
2574
  disableTaskNameEditing = false,
2370
2575
  disableDependencyEditing = false,
2371
2576
  onScrollToTask,
2372
- onSelectedChipChange
2577
+ onSelectedChipChange,
2578
+ onAdd,
2579
+ onDelete,
2580
+ onInsertAfter,
2581
+ editingTaskId: propEditingTaskId
2373
2582
  }) => {
2374
- const totalHeight = (0, import_react11.useMemo)(
2583
+ const totalHeight = (0, import_react12.useMemo)(
2375
2584
  () => tasks.length * rowHeight,
2376
2585
  [tasks.length, rowHeight]
2377
2586
  );
2378
- const handleRowClick = (0, import_react11.useCallback)((taskId) => {
2587
+ const handleRowClick = (0, import_react12.useCallback)((taskId) => {
2379
2588
  onTaskSelect?.(taskId);
2380
2589
  }, [onTaskSelect]);
2381
- const [activeLinkType, setActiveLinkType] = (0, import_react11.useState)("FS");
2382
- const [selectingPredecessorFor, setSelectingPredecessorFor] = (0, import_react11.useState)(null);
2383
- const [typeMenuOpen, setTypeMenuOpen] = (0, import_react11.useState)(false);
2384
- const [cycleError, setCycleError] = (0, import_react11.useState)(false);
2385
- const overlayRef = (0, import_react11.useRef)(null);
2386
- const [selectedChip, setSelectedChip] = (0, import_react11.useState)(null);
2387
- const handleChipSelect = (0, import_react11.useCallback)((chip) => {
2590
+ const [activeLinkType, setActiveLinkType] = (0, import_react12.useState)("FS");
2591
+ const [selectingPredecessorFor, setSelectingPredecessorFor] = (0, import_react12.useState)(null);
2592
+ const [typeMenuOpen, setTypeMenuOpen] = (0, import_react12.useState)(false);
2593
+ const [cycleError, setCycleError] = (0, import_react12.useState)(false);
2594
+ const overlayRef = (0, import_react12.useRef)(null);
2595
+ const [selectedChip, setSelectedChip] = (0, import_react12.useState)(null);
2596
+ const handleChipSelect = (0, import_react12.useCallback)((chip) => {
2388
2597
  setSelectedChip(chip);
2389
2598
  onSelectedChipChange?.(chip);
2390
2599
  }, [onSelectedChipChange]);
2391
- (0, import_react11.useEffect)(() => {
2600
+ (0, import_react12.useEffect)(() => {
2392
2601
  if (!selectingPredecessorFor && !selectedChip) return;
2393
2602
  const handleKeyDown = (e) => {
2394
2603
  if (e.key === "Escape") {
@@ -2412,7 +2621,7 @@ var TaskList = ({
2412
2621
  document.removeEventListener("mousedown", handleMouseDown, true);
2413
2622
  };
2414
2623
  }, [selectingPredecessorFor, selectedChip, onSelectedChipChange]);
2415
- const handleAddDependency = (0, import_react11.useCallback)((successorTaskId, predecessorTaskId, linkType) => {
2624
+ const handleAddDependency = (0, import_react12.useCallback)((successorTaskId, predecessorTaskId, linkType) => {
2416
2625
  if (successorTaskId === predecessorTaskId) return;
2417
2626
  const successor = tasks.find((t) => t.id === successorTaskId);
2418
2627
  if (!successor) return;
@@ -2461,7 +2670,7 @@ var TaskList = ({
2461
2670
  }
2462
2671
  setSelectingPredecessorFor(null);
2463
2672
  }, [tasks, onTaskChange]);
2464
- const handleRemoveDependency = (0, import_react11.useCallback)((taskId, predecessorTaskId, linkType) => {
2673
+ const handleRemoveDependency = (0, import_react12.useCallback)((taskId, predecessorTaskId, linkType) => {
2465
2674
  const task = tasks.find((t) => t.id === taskId);
2466
2675
  if (!task) return;
2467
2676
  const updatedDeps = (task.dependencies ?? []).filter(
@@ -2469,21 +2678,44 @@ var TaskList = ({
2469
2678
  );
2470
2679
  onTaskChange?.({ ...task, dependencies: updatedDeps });
2471
2680
  }, [tasks, onTaskChange]);
2472
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2681
+ const [isCreating, setIsCreating] = (0, import_react12.useState)(false);
2682
+ const handleConfirmNewTask = (0, import_react12.useCallback)((name) => {
2683
+ const now = /* @__PURE__ */ new Date();
2684
+ const todayISO = new Date(Date.UTC(
2685
+ now.getUTCFullYear(),
2686
+ now.getUTCMonth(),
2687
+ now.getUTCDate()
2688
+ )).toISOString().split("T")[0];
2689
+ const endISO = new Date(Date.UTC(
2690
+ now.getUTCFullYear(),
2691
+ now.getUTCMonth(),
2692
+ now.getUTCDate() + 7
2693
+ )).toISOString().split("T")[0];
2694
+ const newTask = {
2695
+ id: crypto.randomUUID(),
2696
+ name,
2697
+ startDate: todayISO,
2698
+ endDate: endISO
2699
+ };
2700
+ onAdd?.(newTask);
2701
+ setIsCreating(false);
2702
+ }, [onAdd]);
2703
+ const handleCancelNewTask = (0, import_react12.useCallback)(() => setIsCreating(false), []);
2704
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
2473
2705
  "div",
2474
2706
  {
2475
2707
  ref: overlayRef,
2476
2708
  className: `gantt-tl-overlay${show ? "" : " gantt-tl-hidden"}`,
2477
2709
  style: { width: `${taskListWidth}px` },
2478
- children: /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "gantt-tl-table", children: [
2479
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "gantt-tl-header", style: { height: `${headerHeight + 0.5}px` }, children: [
2480
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "gantt-tl-headerCell gantt-tl-cell-number", children: "\u2116" }),
2481
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "gantt-tl-headerCell gantt-tl-cell-name", children: "\u0418\u043C\u044F" }),
2482
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "gantt-tl-headerCell gantt-tl-cell-date", children: "\u041D\u0430\u0447\u0430\u043B\u043E" }),
2483
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "gantt-tl-headerCell gantt-tl-cell-date", children: "\u041E\u043A\u043E\u043D\u0447\u0430\u043D\u0438\u0435" }),
2484
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "gantt-tl-headerCell gantt-tl-cell-deps", style: { position: "relative" }, children: [
2485
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(Popover, { open: typeMenuOpen, onOpenChange: setTypeMenuOpen, children: [
2486
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
2710
+ children: /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "gantt-tl-table", children: [
2711
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "gantt-tl-header", style: { height: `${headerHeight + 0.5}px` }, children: [
2712
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "gantt-tl-headerCell gantt-tl-cell-number", children: "\u2116" }),
2713
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "gantt-tl-headerCell gantt-tl-cell-name", children: "\u0418\u043C\u044F" }),
2714
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "gantt-tl-headerCell gantt-tl-cell-date", children: "\u041D\u0430\u0447\u0430\u043B\u043E" }),
2715
+ /* @__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" }),
2716
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "gantt-tl-headerCell gantt-tl-cell-deps", style: { position: "relative" }, children: [
2717
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(Popover, { open: typeMenuOpen, onOpenChange: setTypeMenuOpen, children: [
2718
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
2487
2719
  "button",
2488
2720
  {
2489
2721
  className: "gantt-tl-dep-type-trigger",
@@ -2491,12 +2723,12 @@ var TaskList = ({
2491
2723
  onClick: (e) => e.stopPropagation(),
2492
2724
  children: [
2493
2725
  "\u0421\u0432\u044F\u0437\u0438 ",
2494
- import_react11.default.createElement(LINK_TYPE_ICONS[activeLinkType]),
2726
+ import_react12.default.createElement(LINK_TYPE_ICONS[activeLinkType]),
2495
2727
  " \u25BE"
2496
2728
  ]
2497
2729
  }
2498
2730
  ) }),
2499
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(PopoverContent, { portal: true, align: "start", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "gantt-tl-dep-type-menu", children: LINK_TYPE_ORDER.map((lt) => /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
2731
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(PopoverContent, { portal: true, align: "start", children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "gantt-tl-dep-type-menu", children: LINK_TYPE_ORDER.map((lt) => /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
2500
2732
  "button",
2501
2733
  {
2502
2734
  className: `gantt-tl-dep-type-option${activeLinkType === lt ? " active" : ""}`,
@@ -2505,17 +2737,17 @@ var TaskList = ({
2505
2737
  setTypeMenuOpen(false);
2506
2738
  },
2507
2739
  children: [
2508
- import_react11.default.createElement(LINK_TYPE_ICONS[lt]),
2509
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { children: LINK_TYPE_LABELS[lt] })
2740
+ import_react12.default.createElement(LINK_TYPE_ICONS[lt]),
2741
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { children: LINK_TYPE_LABELS[lt] })
2510
2742
  ]
2511
2743
  },
2512
2744
  lt
2513
2745
  )) }) })
2514
2746
  ] }),
2515
- cycleError && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "gantt-tl-dep-error", children: "\u0426\u0438\u043A\u043B \u0437\u0430\u0432\u0438\u0441\u0438\u043C\u043E\u0441\u0442\u0435\u0439!" })
2747
+ cycleError && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "gantt-tl-dep-error", children: "\u0426\u0438\u043A\u043B \u0437\u0430\u0432\u0438\u0441\u0438\u043C\u043E\u0441\u0442\u0435\u0439!" })
2516
2748
  ] })
2517
2749
  ] }),
2518
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "gantt-tl-body", style: { height: `${totalHeight}px` }, children: tasks.map((task, index) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2750
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "gantt-tl-body", style: { height: `${totalHeight}px` }, children: tasks.map((task, index) => /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
2519
2751
  TaskListRow,
2520
2752
  {
2521
2753
  task,
@@ -2534,18 +2766,39 @@ var TaskList = ({
2534
2766
  onRemoveDependency: handleRemoveDependency,
2535
2767
  selectedChip,
2536
2768
  onChipSelect: handleChipSelect,
2537
- onScrollToTask
2769
+ onScrollToTask,
2770
+ onDelete,
2771
+ onAdd,
2772
+ onInsertAfter,
2773
+ editingTaskId: propEditingTaskId
2538
2774
  },
2539
2775
  task.id
2540
- )) })
2776
+ )) }),
2777
+ isCreating && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
2778
+ NewTaskRow,
2779
+ {
2780
+ rowHeight,
2781
+ onConfirm: handleConfirmNewTask,
2782
+ onCancel: handleCancelNewTask
2783
+ }
2784
+ ),
2785
+ onAdd && !isCreating && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
2786
+ "button",
2787
+ {
2788
+ className: "gantt-tl-add-btn",
2789
+ onClick: () => setIsCreating(true),
2790
+ type: "button",
2791
+ children: "+ \u0414\u043E\u0431\u0430\u0432\u0438\u0442\u044C \u0437\u0430\u0434\u0430\u0447\u0443"
2792
+ }
2793
+ )
2541
2794
  ] })
2542
2795
  }
2543
2796
  );
2544
2797
  };
2545
2798
 
2546
2799
  // src/components/GanttChart/GanttChart.tsx
2547
- var import_jsx_runtime14 = require("react/jsx-runtime");
2548
- var GanttChart = (0, import_react12.forwardRef)(({
2800
+ var import_jsx_runtime15 = require("react/jsx-runtime");
2801
+ var GanttChart = (0, import_react13.forwardRef)(({
2549
2802
  tasks,
2550
2803
  dayWidth = 40,
2551
2804
  rowHeight = 40,
@@ -2560,35 +2813,39 @@ var GanttChart = (0, import_react12.forwardRef)(({
2560
2813
  taskListWidth = 520,
2561
2814
  disableTaskNameEditing = false,
2562
2815
  disableDependencyEditing = false,
2563
- highlightExpiredTasks = false
2816
+ highlightExpiredTasks = false,
2817
+ onAdd,
2818
+ onDelete,
2819
+ onInsertAfter
2564
2820
  }, ref) => {
2565
- const scrollContainerRef = (0, import_react12.useRef)(null);
2566
- const [selectedTaskId, setSelectedTaskId] = (0, import_react12.useState)(null);
2567
- const [selectedChip, setSelectedChip] = (0, import_react12.useState)(null);
2568
- const dateRange = (0, import_react12.useMemo)(() => getMultiMonthDays(tasks), [tasks]);
2569
- const [validationResult, setValidationResult] = (0, import_react12.useState)(null);
2570
- const [cascadeOverrides, setCascadeOverrides] = (0, import_react12.useState)(/* @__PURE__ */ new Map());
2571
- const gridWidth = (0, import_react12.useMemo)(
2821
+ const scrollContainerRef = (0, import_react13.useRef)(null);
2822
+ const [selectedTaskId, setSelectedTaskId] = (0, import_react13.useState)(null);
2823
+ const [selectedChip, setSelectedChip] = (0, import_react13.useState)(null);
2824
+ const [editingTaskId, setEditingTaskId] = (0, import_react13.useState)(null);
2825
+ const dateRange = (0, import_react13.useMemo)(() => getMultiMonthDays(tasks), [tasks]);
2826
+ const [validationResult, setValidationResult] = (0, import_react13.useState)(null);
2827
+ const [cascadeOverrides, setCascadeOverrides] = (0, import_react13.useState)(/* @__PURE__ */ new Map());
2828
+ const gridWidth = (0, import_react13.useMemo)(
2572
2829
  () => Math.round(dateRange.length * dayWidth),
2573
2830
  [dateRange.length, dayWidth]
2574
2831
  );
2575
- const totalGridHeight = (0, import_react12.useMemo)(
2832
+ const totalGridHeight = (0, import_react13.useMemo)(
2576
2833
  () => tasks.length * rowHeight,
2577
2834
  [tasks.length, rowHeight]
2578
2835
  );
2579
- const monthStart = (0, import_react12.useMemo)(() => {
2836
+ const monthStart = (0, import_react13.useMemo)(() => {
2580
2837
  if (dateRange.length === 0) {
2581
2838
  return new Date(Date.UTC((/* @__PURE__ */ new Date()).getUTCFullYear(), (/* @__PURE__ */ new Date()).getUTCMonth(), 1));
2582
2839
  }
2583
2840
  const firstDay = dateRange[0];
2584
2841
  return new Date(Date.UTC(firstDay.getUTCFullYear(), firstDay.getUTCMonth(), 1));
2585
2842
  }, [dateRange]);
2586
- const todayInRange = (0, import_react12.useMemo)(() => {
2843
+ const todayInRange = (0, import_react13.useMemo)(() => {
2587
2844
  const now = /* @__PURE__ */ new Date();
2588
2845
  const today = new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate()));
2589
2846
  return dateRange.some((day) => day.getTime() === today.getTime());
2590
2847
  }, [dateRange]);
2591
- (0, import_react12.useEffect)(() => {
2848
+ (0, import_react13.useEffect)(() => {
2592
2849
  const container = scrollContainerRef.current;
2593
2850
  if (!container || dateRange.length === 0) return;
2594
2851
  const now = /* @__PURE__ */ new Date();
@@ -2600,7 +2857,7 @@ var GanttChart = (0, import_react12.forwardRef)(({
2600
2857
  const scrollLeft = Math.round(todayOffset - containerWidth / 2 + dayWidth / 2);
2601
2858
  container.scrollLeft = Math.max(0, scrollLeft);
2602
2859
  }, []);
2603
- const scrollToToday = (0, import_react12.useCallback)(() => {
2860
+ const scrollToToday = (0, import_react13.useCallback)(() => {
2604
2861
  const container = scrollContainerRef.current;
2605
2862
  if (!container || dateRange.length === 0) return;
2606
2863
  const now = /* @__PURE__ */ new Date();
@@ -2612,7 +2869,7 @@ var GanttChart = (0, import_react12.forwardRef)(({
2612
2869
  const scrollLeft = Math.round(todayOffset - containerWidth / 2 + dayWidth / 2);
2613
2870
  container.scrollTo({ left: Math.max(0, scrollLeft), behavior: "smooth" });
2614
2871
  }, [dateRange, dayWidth]);
2615
- const scrollToTask = (0, import_react12.useCallback)((taskId) => {
2872
+ const scrollToTask = (0, import_react13.useCallback)((taskId) => {
2616
2873
  const container = scrollContainerRef.current;
2617
2874
  if (!container || dateRange.length === 0) return;
2618
2875
  const task = tasks.find((t) => t.id === taskId);
@@ -2629,7 +2886,7 @@ var GanttChart = (0, import_react12.forwardRef)(({
2629
2886
  const scrollLeft = Math.round(taskOffset - dayWidth * 2);
2630
2887
  container.scrollTo({ left: Math.max(0, scrollLeft), behavior: "smooth" });
2631
2888
  }, [tasks, dateRange, dayWidth]);
2632
- (0, import_react12.useImperativeHandle)(
2889
+ (0, import_react13.useImperativeHandle)(
2633
2890
  ref,
2634
2891
  () => ({
2635
2892
  scrollToToday,
@@ -2637,17 +2894,20 @@ var GanttChart = (0, import_react12.forwardRef)(({
2637
2894
  }),
2638
2895
  [scrollToToday, scrollToTask]
2639
2896
  );
2640
- const [dragGuideLines, setDragGuideLines] = (0, import_react12.useState)(null);
2641
- const [draggedTaskOverride, setDraggedTaskOverride] = (0, import_react12.useState)(null);
2642
- (0, import_react12.useEffect)(() => {
2897
+ const [dragGuideLines, setDragGuideLines] = (0, import_react13.useState)(null);
2898
+ const [draggedTaskOverride, setDraggedTaskOverride] = (0, import_react13.useState)(null);
2899
+ (0, import_react13.useEffect)(() => {
2643
2900
  const result = validateDependencies(tasks);
2644
2901
  setValidationResult(result);
2645
2902
  onValidateDependencies?.(result);
2646
2903
  }, [tasks, onValidateDependencies]);
2647
- const handleTaskChange = (0, import_react12.useCallback)((updatedTask) => {
2904
+ const handleTaskChange = (0, import_react13.useCallback)((updatedTask) => {
2648
2905
  const originalTask = tasks.find((t) => t.id === updatedTask.id);
2649
2906
  if (!originalTask) {
2650
2907
  onChange?.((currentTasks) => currentTasks.map((t) => t.id === updatedTask.id ? updatedTask : t));
2908
+ if (editingTaskId === updatedTask.id) {
2909
+ setEditingTaskId(null);
2910
+ }
2651
2911
  return;
2652
2912
  }
2653
2913
  const origStart = new Date(originalTask.startDate);
@@ -2657,6 +2917,9 @@ var GanttChart = (0, import_react12.forwardRef)(({
2657
2917
  const datesChanged = origStart.getTime() !== newStart.getTime() || origEnd.getTime() !== newEnd.getTime();
2658
2918
  if (!datesChanged) {
2659
2919
  onChange?.((currentTasks) => currentTasks.map((t) => t.id === updatedTask.id ? updatedTask : t));
2920
+ if (editingTaskId === updatedTask.id) {
2921
+ setEditingTaskId(null);
2922
+ }
2660
2923
  return;
2661
2924
  }
2662
2925
  let cascadedTasksForCallback;
@@ -2675,8 +2938,21 @@ var GanttChart = (0, import_react12.forwardRef)(({
2675
2938
  });
2676
2939
  onCascade?.(cascadedTasksForCallback);
2677
2940
  }
2678
- }, [tasks, onChange, disableConstraints, onCascade]);
2679
- const dependencyOverrides = (0, import_react12.useMemo)(() => {
2941
+ }, [tasks, onChange, disableConstraints, onCascade, editingTaskId]);
2942
+ const handleDelete = (0, import_react13.useCallback)((taskId) => {
2943
+ onChange?.(
2944
+ (currentTasks) => currentTasks.filter((t) => t.id !== taskId).map((t) => ({
2945
+ ...t,
2946
+ dependencies: (t.dependencies ?? []).filter((d) => d.taskId !== taskId)
2947
+ }))
2948
+ );
2949
+ onDelete?.(taskId);
2950
+ }, [onChange, onDelete]);
2951
+ const handleInsertAfter = (0, import_react13.useCallback)((taskId, newTask) => {
2952
+ setEditingTaskId(newTask.id);
2953
+ onInsertAfter?.(taskId, newTask);
2954
+ }, [onInsertAfter]);
2955
+ const dependencyOverrides = (0, import_react13.useMemo)(() => {
2680
2956
  const map = new Map(cascadeOverrides);
2681
2957
  if (draggedTaskOverride) {
2682
2958
  map.set(draggedTaskOverride.taskId, {
@@ -2686,21 +2962,21 @@ var GanttChart = (0, import_react12.forwardRef)(({
2686
2962
  }
2687
2963
  return map;
2688
2964
  }, [cascadeOverrides, draggedTaskOverride]);
2689
- const handleCascadeProgress = (0, import_react12.useCallback)((overrides) => {
2965
+ const handleCascadeProgress = (0, import_react13.useCallback)((overrides) => {
2690
2966
  setCascadeOverrides(new Map(overrides));
2691
2967
  }, []);
2692
- const handleCascade = (0, import_react12.useCallback)((cascadedTasks) => {
2968
+ const handleCascade = (0, import_react13.useCallback)((cascadedTasks) => {
2693
2969
  onChange?.((currentTasks) => {
2694
2970
  const cascadeMap = new Map(cascadedTasks.map((t) => [t.id, t]));
2695
2971
  return currentTasks.map((t) => cascadeMap.get(t.id) ?? t);
2696
2972
  });
2697
2973
  onCascade?.(cascadedTasks);
2698
2974
  }, [onChange, onCascade]);
2699
- const handleTaskSelect = (0, import_react12.useCallback)((taskId) => {
2975
+ const handleTaskSelect = (0, import_react13.useCallback)((taskId) => {
2700
2976
  setSelectedTaskId(taskId);
2701
2977
  }, []);
2702
- const panStateRef = (0, import_react12.useRef)(null);
2703
- const handlePanStart = (0, import_react12.useCallback)((e) => {
2978
+ const panStateRef = (0, import_react13.useRef)(null);
2979
+ const handlePanStart = (0, import_react13.useCallback)((e) => {
2704
2980
  if (e.button !== 0) return;
2705
2981
  const target = e.target;
2706
2982
  if (target.closest("[data-taskbar]")) return;
@@ -2721,7 +2997,7 @@ var GanttChart = (0, import_react12.forwardRef)(({
2721
2997
  container.style.cursor = "grabbing";
2722
2998
  e.preventDefault();
2723
2999
  }, []);
2724
- (0, import_react12.useEffect)(() => {
3000
+ (0, import_react13.useEffect)(() => {
2725
3001
  const handlePanMove = (e) => {
2726
3002
  const pan = panStateRef.current;
2727
3003
  if (!pan?.active) return;
@@ -2743,15 +3019,15 @@ var GanttChart = (0, import_react12.forwardRef)(({
2743
3019
  window.removeEventListener("mouseup", handlePanEnd);
2744
3020
  };
2745
3021
  }, []);
2746
- return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "gantt-container", children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
3022
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: "gantt-container", children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
2747
3023
  "div",
2748
3024
  {
2749
3025
  ref: scrollContainerRef,
2750
3026
  className: "gantt-scrollContainer",
2751
3027
  style: { height: containerHeight ?? "auto", cursor: "grab" },
2752
3028
  onMouseDown: handlePanStart,
2753
- children: /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "gantt-scrollContent", children: [
2754
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
3029
+ children: /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "gantt-scrollContent", children: [
3030
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
2755
3031
  TaskList,
2756
3032
  {
2757
3033
  tasks,
@@ -2765,11 +3041,15 @@ var GanttChart = (0, import_react12.forwardRef)(({
2765
3041
  disableTaskNameEditing,
2766
3042
  disableDependencyEditing,
2767
3043
  onScrollToTask: scrollToTask,
2768
- onSelectedChipChange: setSelectedChip
3044
+ onSelectedChipChange: setSelectedChip,
3045
+ onAdd,
3046
+ onDelete: handleDelete,
3047
+ onInsertAfter: handleInsertAfter,
3048
+ editingTaskId
2769
3049
  }
2770
3050
  ),
2771
- /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { style: { minWidth: `${gridWidth}px`, flex: 1 }, children: [
2772
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "gantt-stickyHeader", style: { width: `${gridWidth}px` }, children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
3051
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { style: { minWidth: `${gridWidth}px`, flex: 1 }, children: [
3052
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: "gantt-stickyHeader", style: { width: `${gridWidth}px` }, children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
2773
3053
  TimeScaleHeader_default,
2774
3054
  {
2775
3055
  days: dateRange,
@@ -2777,7 +3057,7 @@ var GanttChart = (0, import_react12.forwardRef)(({
2777
3057
  headerHeight
2778
3058
  }
2779
3059
  ) }),
2780
- /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
3060
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
2781
3061
  "div",
2782
3062
  {
2783
3063
  className: "gantt-taskArea",
@@ -2786,7 +3066,7 @@ var GanttChart = (0, import_react12.forwardRef)(({
2786
3066
  width: `${gridWidth}px`
2787
3067
  },
2788
3068
  children: [
2789
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
3069
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
2790
3070
  GridBackground_default,
2791
3071
  {
2792
3072
  dateRange,
@@ -2794,8 +3074,8 @@ var GanttChart = (0, import_react12.forwardRef)(({
2794
3074
  totalHeight: totalGridHeight
2795
3075
  }
2796
3076
  ),
2797
- todayInRange && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(TodayIndicator_default, { monthStart, dayWidth }),
2798
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
3077
+ todayInRange && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(TodayIndicator_default, { monthStart, dayWidth }),
3078
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
2799
3079
  DependencyLines_default,
2800
3080
  {
2801
3081
  tasks,
@@ -2807,7 +3087,7 @@ var GanttChart = (0, import_react12.forwardRef)(({
2807
3087
  selectedDep: selectedChip
2808
3088
  }
2809
3089
  ),
2810
- dragGuideLines && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
3090
+ dragGuideLines && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
2811
3091
  DragGuideLines_default,
2812
3092
  {
2813
3093
  isDragging: dragGuideLines.isDragging,
@@ -2817,7 +3097,7 @@ var GanttChart = (0, import_react12.forwardRef)(({
2817
3097
  totalHeight: totalGridHeight
2818
3098
  }
2819
3099
  ),
2820
- tasks.map((task, index) => /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
3100
+ tasks.map((task, index) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
2821
3101
  TaskRow_default,
2822
3102
  {
2823
3103
  task,
@@ -2856,9 +3136,9 @@ var GanttChart = (0, import_react12.forwardRef)(({
2856
3136
  GanttChart.displayName = "GanttChart";
2857
3137
 
2858
3138
  // src/components/ui/Button.tsx
2859
- var import_react13 = __toESM(require("react"));
2860
- var import_jsx_runtime15 = require("react/jsx-runtime");
2861
- var Button = import_react13.default.forwardRef(
3139
+ var import_react14 = __toESM(require("react"));
3140
+ var import_jsx_runtime16 = require("react/jsx-runtime");
3141
+ var Button = import_react14.default.forwardRef(
2862
3142
  ({ className, variant = "default", size = "default", children, ...props }, ref) => {
2863
3143
  const classes = [
2864
3144
  "gantt-btn",
@@ -2866,7 +3146,7 @@ var Button = import_react13.default.forwardRef(
2866
3146
  size !== "default" ? `gantt-btn-${size}` : "",
2867
3147
  className || ""
2868
3148
  ].filter(Boolean).join(" ");
2869
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("button", { ref, className: classes, ...props, children });
3149
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("button", { ref, className: classes, ...props, children });
2870
3150
  }
2871
3151
  );
2872
3152
  Button.displayName = "Button";