gantt-lib 0.1.2 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.css.map +1 -1
- package/dist/index.d.mts +36 -8
- package/dist/index.d.ts +36 -8
- package/dist/index.js +632 -191
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +648 -208
- package/dist/index.mjs.map +1 -1
- package/dist/styles.css +272 -0
- 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
|
|
4
|
+
import { useMemo as useMemo9, useCallback as useCallback6, useRef as useRef5, useState as useState6, useEffect as useEffect5, useImperativeHandle, forwardRef } from "react";
|
|
5
5
|
|
|
6
6
|
// src/utils/dateUtils.ts
|
|
7
7
|
var parseUTCDate = (date) => {
|
|
@@ -195,11 +195,35 @@ function detectCycles(tasks) {
|
|
|
195
195
|
}
|
|
196
196
|
return { hasCycle: false };
|
|
197
197
|
}
|
|
198
|
+
function computeLagFromDates(linkType, predStart, predEnd, succStart, succEnd) {
|
|
199
|
+
const DAY_MS = 24 * 60 * 60 * 1e3;
|
|
200
|
+
const pS = Date.UTC(predStart.getUTCFullYear(), predStart.getUTCMonth(), predStart.getUTCDate());
|
|
201
|
+
const pE = Date.UTC(predEnd.getUTCFullYear(), predEnd.getUTCMonth(), predEnd.getUTCDate());
|
|
202
|
+
const sS = Date.UTC(succStart.getUTCFullYear(), succStart.getUTCMonth(), succStart.getUTCDate());
|
|
203
|
+
const sE = Date.UTC(succEnd.getUTCFullYear(), succEnd.getUTCMonth(), succEnd.getUTCDate());
|
|
204
|
+
switch (linkType) {
|
|
205
|
+
case "FS":
|
|
206
|
+
return Math.round((sS - pE) / DAY_MS) - 1;
|
|
207
|
+
case "SS":
|
|
208
|
+
return Math.round((sS - pS) / DAY_MS);
|
|
209
|
+
case "FF":
|
|
210
|
+
return Math.round((sE - pE) / DAY_MS);
|
|
211
|
+
case "SF":
|
|
212
|
+
return Math.round((sE - pS) / DAY_MS) + 1;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
198
215
|
function calculateSuccessorDate(predecessorStart, predecessorEnd, linkType, lag = 0) {
|
|
199
|
-
const
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
216
|
+
const DAY_MS = 24 * 60 * 60 * 1e3;
|
|
217
|
+
switch (linkType) {
|
|
218
|
+
case "FS":
|
|
219
|
+
return new Date(predecessorEnd.getTime() + (lag + 1) * DAY_MS);
|
|
220
|
+
case "SS":
|
|
221
|
+
return new Date(predecessorStart.getTime() + lag * DAY_MS);
|
|
222
|
+
case "FF":
|
|
223
|
+
return new Date(predecessorEnd.getTime() + lag * DAY_MS);
|
|
224
|
+
case "SF":
|
|
225
|
+
return new Date(predecessorStart.getTime() + (lag - 1) * DAY_MS);
|
|
226
|
+
}
|
|
203
227
|
}
|
|
204
228
|
function validateDependencies(tasks) {
|
|
205
229
|
const errors = [];
|
|
@@ -346,35 +370,10 @@ function recalculateIncomingLags(task, newStartDate, newEndDate, allTasks) {
|
|
|
346
370
|
return task.dependencies.map((dep) => {
|
|
347
371
|
const predecessor = taskById.get(dep.taskId);
|
|
348
372
|
if (!predecessor) return dep;
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
);
|
|
354
|
-
return { ...dep, lag: lagDays };
|
|
355
|
-
}
|
|
356
|
-
if (dep.type === "SS") {
|
|
357
|
-
const predStart = new Date(predecessor.startDate);
|
|
358
|
-
const lagDays = Math.max(0, Math.round(
|
|
359
|
-
(Date.UTC(newStartDate.getUTCFullYear(), newStartDate.getUTCMonth(), newStartDate.getUTCDate()) - Date.UTC(predStart.getUTCFullYear(), predStart.getUTCMonth(), predStart.getUTCDate())) / (24 * 60 * 60 * 1e3)
|
|
360
|
-
));
|
|
361
|
-
return { ...dep, lag: lagDays };
|
|
362
|
-
}
|
|
363
|
-
if (dep.type === "FF") {
|
|
364
|
-
const predEnd = new Date(predecessor.endDate);
|
|
365
|
-
const lagDays = Math.round(
|
|
366
|
-
(Date.UTC(newEndDate.getUTCFullYear(), newEndDate.getUTCMonth(), newEndDate.getUTCDate()) - Date.UTC(predEnd.getUTCFullYear(), predEnd.getUTCMonth(), predEnd.getUTCDate())) / (24 * 60 * 60 * 1e3)
|
|
367
|
-
);
|
|
368
|
-
return { ...dep, lag: lagDays };
|
|
369
|
-
}
|
|
370
|
-
if (dep.type === "SF") {
|
|
371
|
-
const predStart = new Date(predecessor.startDate);
|
|
372
|
-
const lagDays = Math.min(0, Math.round(
|
|
373
|
-
(Date.UTC(newEndDate.getUTCFullYear(), newEndDate.getUTCMonth(), newEndDate.getUTCDate()) - Date.UTC(predStart.getUTCFullYear(), predStart.getUTCMonth(), predStart.getUTCDate()) + 24 * 60 * 60 * 1e3) / (24 * 60 * 60 * 1e3)
|
|
374
|
-
));
|
|
375
|
-
return { ...dep, lag: lagDays };
|
|
376
|
-
}
|
|
377
|
-
return dep;
|
|
373
|
+
const predStart = new Date(predecessor.startDate);
|
|
374
|
+
const predEnd = new Date(predecessor.endDate);
|
|
375
|
+
const lagDays = computeLagFromDates(dep.type, predStart, predEnd, newStartDate, newEndDate);
|
|
376
|
+
return { ...dep, lag: lagDays };
|
|
378
377
|
});
|
|
379
378
|
}
|
|
380
379
|
function getAllDependencyEdges(tasks) {
|
|
@@ -1401,60 +1400,11 @@ var DragGuideLines_default = DragGuideLines;
|
|
|
1401
1400
|
import React5, { useMemo as useMemo5 } from "react";
|
|
1402
1401
|
import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
1403
1402
|
function calculateEffectiveLag(edge, predPosition, succPosition, monthStart, dayWidth) {
|
|
1404
|
-
const
|
|
1405
|
-
const
|
|
1406
|
-
const
|
|
1407
|
-
const
|
|
1408
|
-
|
|
1409
|
-
switch (edge.type) {
|
|
1410
|
-
case "FS":
|
|
1411
|
-
lagMs = Date.UTC(
|
|
1412
|
-
succStartDate.getUTCFullYear(),
|
|
1413
|
-
succStartDate.getUTCMonth(),
|
|
1414
|
-
succStartDate.getUTCDate()
|
|
1415
|
-
) - Date.UTC(
|
|
1416
|
-
predEndDate.getUTCFullYear(),
|
|
1417
|
-
predEndDate.getUTCMonth(),
|
|
1418
|
-
predEndDate.getUTCDate()
|
|
1419
|
-
) - 24 * 60 * 60 * 1e3;
|
|
1420
|
-
break;
|
|
1421
|
-
case "SS":
|
|
1422
|
-
lagMs = Date.UTC(
|
|
1423
|
-
succStartDate.getUTCFullYear(),
|
|
1424
|
-
succStartDate.getUTCMonth(),
|
|
1425
|
-
succStartDate.getUTCDate()
|
|
1426
|
-
) - Date.UTC(
|
|
1427
|
-
predStartDate.getUTCFullYear(),
|
|
1428
|
-
predStartDate.getUTCMonth(),
|
|
1429
|
-
predStartDate.getUTCDate()
|
|
1430
|
-
);
|
|
1431
|
-
break;
|
|
1432
|
-
case "FF":
|
|
1433
|
-
lagMs = Date.UTC(
|
|
1434
|
-
succEndDate.getUTCFullYear(),
|
|
1435
|
-
succEndDate.getUTCMonth(),
|
|
1436
|
-
succEndDate.getUTCDate()
|
|
1437
|
-
) - Date.UTC(
|
|
1438
|
-
predEndDate.getUTCFullYear(),
|
|
1439
|
-
predEndDate.getUTCMonth(),
|
|
1440
|
-
predEndDate.getUTCDate()
|
|
1441
|
-
);
|
|
1442
|
-
break;
|
|
1443
|
-
case "SF":
|
|
1444
|
-
lagMs = Date.UTC(
|
|
1445
|
-
succEndDate.getUTCFullYear(),
|
|
1446
|
-
succEndDate.getUTCMonth(),
|
|
1447
|
-
succEndDate.getUTCDate()
|
|
1448
|
-
) - Date.UTC(
|
|
1449
|
-
predStartDate.getUTCFullYear(),
|
|
1450
|
-
predStartDate.getUTCMonth(),
|
|
1451
|
-
predStartDate.getUTCDate()
|
|
1452
|
-
) + 24 * 60 * 60 * 1e3;
|
|
1453
|
-
break;
|
|
1454
|
-
default:
|
|
1455
|
-
return 0;
|
|
1456
|
-
}
|
|
1457
|
-
return Math.round(lagMs / (24 * 60 * 60 * 1e3));
|
|
1403
|
+
const predStart = pixelsToDate(predPosition.left, monthStart, dayWidth);
|
|
1404
|
+
const predEnd = pixelsToDate(predPosition.right - dayWidth, monthStart, dayWidth);
|
|
1405
|
+
const succStart = pixelsToDate(succPosition.left, monthStart, dayWidth);
|
|
1406
|
+
const succEnd = pixelsToDate(succPosition.right - dayWidth, monthStart, dayWidth);
|
|
1407
|
+
return computeLagFromDates(edge.type, predStart, predEnd, succStart, succEnd);
|
|
1458
1408
|
}
|
|
1459
1409
|
var DependencyLines = React5.memo(({
|
|
1460
1410
|
tasks,
|
|
@@ -1462,7 +1412,8 @@ var DependencyLines = React5.memo(({
|
|
|
1462
1412
|
dayWidth,
|
|
1463
1413
|
rowHeight,
|
|
1464
1414
|
gridWidth,
|
|
1465
|
-
dragOverrides
|
|
1415
|
+
dragOverrides,
|
|
1416
|
+
selectedDep
|
|
1466
1417
|
}) => {
|
|
1467
1418
|
const { taskPositions, taskIndices } = useMemo5(() => {
|
|
1468
1419
|
const positions = /* @__PURE__ */ new Map();
|
|
@@ -1576,30 +1527,60 @@ var DependencyLines = React5.memo(({
|
|
|
1576
1527
|
}
|
|
1577
1528
|
)
|
|
1578
1529
|
}
|
|
1579
|
-
)
|
|
1580
|
-
] }),
|
|
1581
|
-
lines.map(({ id, path, hasCycle, lag, fromX, toX, fromY, reverseOrder }) => /* @__PURE__ */ jsxs5(React5.Fragment, { children: [
|
|
1582
|
-
/* @__PURE__ */ jsx6(
|
|
1583
|
-
"path",
|
|
1584
|
-
{
|
|
1585
|
-
d: path,
|
|
1586
|
-
className: hasCycle ? "gantt-dependency-path gantt-dependency-cycle" : "gantt-dependency-path",
|
|
1587
|
-
markerEnd: hasCycle ? "url(#arrowhead-cycle)" : "url(#arrowhead)"
|
|
1588
|
-
}
|
|
1589
1530
|
),
|
|
1590
|
-
|
|
1591
|
-
"
|
|
1531
|
+
/* @__PURE__ */ jsx6(
|
|
1532
|
+
"marker",
|
|
1592
1533
|
{
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1534
|
+
id: "arrowhead-selected",
|
|
1535
|
+
markerWidth: "8",
|
|
1536
|
+
markerHeight: "6",
|
|
1537
|
+
markerUnits: "userSpaceOnUse",
|
|
1538
|
+
refX: "7",
|
|
1539
|
+
refY: "3",
|
|
1540
|
+
orient: "auto",
|
|
1541
|
+
children: /* @__PURE__ */ jsx6(
|
|
1542
|
+
"polygon",
|
|
1543
|
+
{
|
|
1544
|
+
points: "0 0, 8 3, 0 6",
|
|
1545
|
+
fill: "#ef4444"
|
|
1546
|
+
}
|
|
1547
|
+
)
|
|
1600
1548
|
}
|
|
1601
1549
|
)
|
|
1602
|
-
] },
|
|
1550
|
+
] }),
|
|
1551
|
+
lines.map(({ id, path, hasCycle, lag, fromX, toX, fromY, reverseOrder }) => {
|
|
1552
|
+
const isSelected = selectedDep != null && id === `${selectedDep.predecessorId}-${selectedDep.successorId}-${selectedDep.linkType}`;
|
|
1553
|
+
let pathClassName = "gantt-dependency-path";
|
|
1554
|
+
if (isSelected) pathClassName += " gantt-dependency-selected";
|
|
1555
|
+
else if (hasCycle) pathClassName += " gantt-dependency-cycle";
|
|
1556
|
+
let markerEnd;
|
|
1557
|
+
if (isSelected) markerEnd = "url(#arrowhead-selected)";
|
|
1558
|
+
else if (hasCycle) markerEnd = "url(#arrowhead-cycle)";
|
|
1559
|
+
else markerEnd = "url(#arrowhead)";
|
|
1560
|
+
const lagColor = isSelected ? "#ef4444" : hasCycle ? "var(--gantt-dependency-cycle-color, #ef4444)" : "var(--gantt-dependency-line-color, #666666)";
|
|
1561
|
+
return /* @__PURE__ */ jsxs5(React5.Fragment, { children: [
|
|
1562
|
+
/* @__PURE__ */ jsx6(
|
|
1563
|
+
"path",
|
|
1564
|
+
{
|
|
1565
|
+
d: path,
|
|
1566
|
+
className: pathClassName,
|
|
1567
|
+
markerEnd
|
|
1568
|
+
}
|
|
1569
|
+
),
|
|
1570
|
+
lag !== 0 && /* @__PURE__ */ jsx6(
|
|
1571
|
+
"text",
|
|
1572
|
+
{
|
|
1573
|
+
className: "gantt-dependency-lag-label",
|
|
1574
|
+
x: lag < 0 ? toX + 14 : toX - 14,
|
|
1575
|
+
y: reverseOrder ? fromY - 4 : fromY + 12,
|
|
1576
|
+
textAnchor: "middle",
|
|
1577
|
+
fontSize: "10",
|
|
1578
|
+
fill: lagColor,
|
|
1579
|
+
children: lag > 0 ? `+${lag}` : `${lag}`
|
|
1580
|
+
}
|
|
1581
|
+
)
|
|
1582
|
+
] }, id);
|
|
1583
|
+
})
|
|
1603
1584
|
]
|
|
1604
1585
|
}
|
|
1605
1586
|
);
|
|
@@ -1608,17 +1589,49 @@ DependencyLines.displayName = "DependencyLines";
|
|
|
1608
1589
|
var DependencyLines_default = DependencyLines;
|
|
1609
1590
|
|
|
1610
1591
|
// src/components/TaskList/TaskList.tsx
|
|
1611
|
-
import { useMemo as
|
|
1592
|
+
import React10, { useMemo as useMemo8, useCallback as useCallback5, useState as useState5, useEffect as useEffect4, useRef as useRef4 } from "react";
|
|
1593
|
+
|
|
1594
|
+
// src/components/ui/Popover.tsx
|
|
1595
|
+
import * as RadixPopover from "@radix-ui/react-popover";
|
|
1596
|
+
import { jsx as jsx7 } from "react/jsx-runtime";
|
|
1597
|
+
var Popover = ({ open, onOpenChange, children }) => {
|
|
1598
|
+
return /* @__PURE__ */ jsx7(RadixPopover.Root, { open, onOpenChange, children });
|
|
1599
|
+
};
|
|
1600
|
+
var PopoverTrigger = RadixPopover.Trigger;
|
|
1601
|
+
var PopoverContent = ({
|
|
1602
|
+
children,
|
|
1603
|
+
className,
|
|
1604
|
+
align = "start",
|
|
1605
|
+
side = "bottom",
|
|
1606
|
+
portal = true,
|
|
1607
|
+
collisionPadding = 8
|
|
1608
|
+
}) => {
|
|
1609
|
+
const content = /* @__PURE__ */ jsx7(
|
|
1610
|
+
RadixPopover.Content,
|
|
1611
|
+
{
|
|
1612
|
+
className: `gantt-popover${className ? ` ${className}` : ""}`,
|
|
1613
|
+
align,
|
|
1614
|
+
side,
|
|
1615
|
+
collisionPadding,
|
|
1616
|
+
sideOffset: 4,
|
|
1617
|
+
children
|
|
1618
|
+
}
|
|
1619
|
+
);
|
|
1620
|
+
if (portal) {
|
|
1621
|
+
return /* @__PURE__ */ jsx7(RadixPopover.Portal, { children: content });
|
|
1622
|
+
}
|
|
1623
|
+
return content;
|
|
1624
|
+
};
|
|
1612
1625
|
|
|
1613
1626
|
// src/components/TaskList/TaskListRow.tsx
|
|
1614
|
-
import React9, { useState as useState4, useRef as useRef3, useEffect as useEffect3, useCallback as useCallback4 } from "react";
|
|
1627
|
+
import React9, { useState as useState4, useRef as useRef3, useEffect as useEffect3, useCallback as useCallback4, useMemo as useMemo7 } from "react";
|
|
1615
1628
|
|
|
1616
1629
|
// src/components/ui/Input.tsx
|
|
1617
1630
|
import React6 from "react";
|
|
1618
|
-
import { jsx as
|
|
1631
|
+
import { jsx as jsx8 } from "react/jsx-runtime";
|
|
1619
1632
|
var Input = React6.forwardRef(
|
|
1620
1633
|
({ className, ...props }, ref) => {
|
|
1621
|
-
return /* @__PURE__ */
|
|
1634
|
+
return /* @__PURE__ */ jsx8(
|
|
1622
1635
|
"input",
|
|
1623
1636
|
{
|
|
1624
1637
|
ref,
|
|
@@ -1656,7 +1669,7 @@ import {
|
|
|
1656
1669
|
startOfDay
|
|
1657
1670
|
} from "date-fns";
|
|
1658
1671
|
import { ru as ru2 } from "date-fns/locale";
|
|
1659
|
-
import { jsx as
|
|
1672
|
+
import { jsx as jsx9, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
1660
1673
|
function getDayClassName(day, selected) {
|
|
1661
1674
|
const classes = ["gantt-day-btn"];
|
|
1662
1675
|
if (selected && isSameDay(day, selected)) classes.push("selected");
|
|
@@ -1726,12 +1739,12 @@ var Calendar = ({
|
|
|
1726
1739
|
const emptyDays = (getDay(firstDay) + 6) % 7;
|
|
1727
1740
|
const monthKey = format2(month, "yyyy-MM");
|
|
1728
1741
|
const monthLabel = format2(month, "LLLL yyyy", { locale: ru2 });
|
|
1729
|
-
const emptyCells = Array.from({ length: emptyDays }, (_, i) => /* @__PURE__ */
|
|
1742
|
+
const emptyCells = Array.from({ length: emptyDays }, (_, i) => /* @__PURE__ */ jsx9("div", { className: "gantt-cal-empty-day" }, `e-${i}`));
|
|
1730
1743
|
const dayCells = Array.from({ length: totalDays }, (_, i) => {
|
|
1731
1744
|
const dayNum = i + 1;
|
|
1732
1745
|
const day = new Date(month.getFullYear(), month.getMonth(), dayNum);
|
|
1733
1746
|
const className = getDayClassName(day, selected);
|
|
1734
|
-
return /* @__PURE__ */
|
|
1747
|
+
return /* @__PURE__ */ jsx9(
|
|
1735
1748
|
"button",
|
|
1736
1749
|
{
|
|
1737
1750
|
type: "button",
|
|
@@ -1748,7 +1761,7 @@ var Calendar = ({
|
|
|
1748
1761
|
);
|
|
1749
1762
|
});
|
|
1750
1763
|
return /* @__PURE__ */ jsxs6("div", { className: "gantt-cal-month", "data-month": monthKey, children: [
|
|
1751
|
-
/* @__PURE__ */
|
|
1764
|
+
/* @__PURE__ */ jsx9("div", { className: "gantt-cal-month-header", children: monthLabel }),
|
|
1752
1765
|
/* @__PURE__ */ jsxs6("div", { className: "gantt-cal-month-days", children: [
|
|
1753
1766
|
emptyCells,
|
|
1754
1767
|
dayCells
|
|
@@ -1761,42 +1774,10 @@ var Calendar = ({
|
|
|
1761
1774
|
() => months.map(renderMonth),
|
|
1762
1775
|
[months, renderMonth]
|
|
1763
1776
|
);
|
|
1764
|
-
return /* @__PURE__ */
|
|
1777
|
+
return /* @__PURE__ */ jsx9("div", { ref: scrollRef, className: "gantt-cal-container", children: renderedMonths });
|
|
1765
1778
|
};
|
|
1766
1779
|
Calendar.displayName = "Calendar";
|
|
1767
1780
|
|
|
1768
|
-
// src/components/ui/Popover.tsx
|
|
1769
|
-
import * as RadixPopover from "@radix-ui/react-popover";
|
|
1770
|
-
import { jsx as jsx9 } from "react/jsx-runtime";
|
|
1771
|
-
var Popover = ({ open, onOpenChange, children }) => {
|
|
1772
|
-
return /* @__PURE__ */ jsx9(RadixPopover.Root, { open, onOpenChange, children });
|
|
1773
|
-
};
|
|
1774
|
-
var PopoverTrigger = RadixPopover.Trigger;
|
|
1775
|
-
var PopoverContent = ({
|
|
1776
|
-
children,
|
|
1777
|
-
className,
|
|
1778
|
-
align = "start",
|
|
1779
|
-
side = "bottom",
|
|
1780
|
-
portal = true,
|
|
1781
|
-
collisionPadding = 8
|
|
1782
|
-
}) => {
|
|
1783
|
-
const content = /* @__PURE__ */ jsx9(
|
|
1784
|
-
RadixPopover.Content,
|
|
1785
|
-
{
|
|
1786
|
-
className: `gantt-popover${className ? ` ${className}` : ""}`,
|
|
1787
|
-
align,
|
|
1788
|
-
side,
|
|
1789
|
-
collisionPadding,
|
|
1790
|
-
sideOffset: 4,
|
|
1791
|
-
children
|
|
1792
|
-
}
|
|
1793
|
-
);
|
|
1794
|
-
if (portal) {
|
|
1795
|
-
return /* @__PURE__ */ jsx9(RadixPopover.Portal, { children: content });
|
|
1796
|
-
}
|
|
1797
|
-
return content;
|
|
1798
|
-
};
|
|
1799
|
-
|
|
1800
1781
|
// src/components/ui/DatePicker.tsx
|
|
1801
1782
|
import { jsx as jsx10, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
1802
1783
|
var DatePicker = ({
|
|
@@ -1861,19 +1842,182 @@ var DatePicker = ({
|
|
|
1861
1842
|
};
|
|
1862
1843
|
DatePicker.displayName = "DatePicker";
|
|
1863
1844
|
|
|
1864
|
-
// src/components/TaskList/
|
|
1845
|
+
// src/components/TaskList/DepIcons.tsx
|
|
1865
1846
|
import { jsx as jsx11, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
1847
|
+
var DepIconFS = () => /* @__PURE__ */ jsxs8("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: [
|
|
1848
|
+
/* @__PURE__ */ jsx11("path", { d: "m10 15 5 5 5-5" }),
|
|
1849
|
+
/* @__PURE__ */ jsx11("path", { d: "M4 4h7a4 4 0 0 1 4 4v12" })
|
|
1850
|
+
] });
|
|
1851
|
+
var DepIconSS = () => /* @__PURE__ */ jsxs8("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: [
|
|
1852
|
+
/* @__PURE__ */ jsx11("path", { d: "M3 5v14" }),
|
|
1853
|
+
/* @__PURE__ */ jsx11("path", { d: "M21 12H7" }),
|
|
1854
|
+
/* @__PURE__ */ jsx11("path", { d: "m15 18 6-6-6-6" })
|
|
1855
|
+
] });
|
|
1856
|
+
var DepIconFF = () => /* @__PURE__ */ jsxs8("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: [
|
|
1857
|
+
/* @__PURE__ */ jsx11("path", { d: "M17 12H3" }),
|
|
1858
|
+
/* @__PURE__ */ jsx11("path", { d: "m11 18 6-6-6-6" }),
|
|
1859
|
+
/* @__PURE__ */ jsx11("path", { d: "M21 5v14" })
|
|
1860
|
+
] });
|
|
1861
|
+
var DepIconSF = () => /* @__PURE__ */ jsxs8("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: [
|
|
1862
|
+
/* @__PURE__ */ jsx11("path", { d: "m14 15-5 5-5-5" }),
|
|
1863
|
+
/* @__PURE__ */ jsx11("path", { d: "M20 4h-7a4 4 0 0 0-4 4v12" })
|
|
1864
|
+
] });
|
|
1865
|
+
var LINK_TYPE_ICONS = {
|
|
1866
|
+
FS: DepIconFS,
|
|
1867
|
+
SS: DepIconSS,
|
|
1868
|
+
FF: DepIconFF,
|
|
1869
|
+
SF: DepIconSF
|
|
1870
|
+
};
|
|
1871
|
+
var LINK_TYPE_LABELS = {
|
|
1872
|
+
FS: "\u041E\u043A\u043E\u043D\u0447\u0430\u043D\u0438\u0435-\u043D\u0430\u0447\u0430\u043B\u043E",
|
|
1873
|
+
SS: "\u041D\u0430\u0447\u0430\u043B\u043E-\u043D\u0430\u0447\u0430\u043B\u043E",
|
|
1874
|
+
FF: "\u041E\u043A\u043E\u043D\u0447\u0430\u043D\u0438\u0435-\u043E\u043A\u043E\u043D\u0447\u0430\u043D\u0438\u0435",
|
|
1875
|
+
SF: "\u041D\u0430\u0447\u0430\u043B\u043E-\u043E\u043A\u043E\u043D\u0447\u0430\u043D\u0438\u0435"
|
|
1876
|
+
};
|
|
1877
|
+
|
|
1878
|
+
// src/components/TaskList/TaskListRow.tsx
|
|
1879
|
+
import { Fragment as Fragment2, jsx as jsx12, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
1880
|
+
var TrashIcon = () => /* @__PURE__ */ jsxs9("svg", { xmlns: "http://www.w3.org/2000/svg", width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
1881
|
+
/* @__PURE__ */ jsx12("path", { d: "M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6" }),
|
|
1882
|
+
/* @__PURE__ */ jsx12("path", { d: "M3 6h18" }),
|
|
1883
|
+
/* @__PURE__ */ jsx12("path", { d: "M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2" })
|
|
1884
|
+
] });
|
|
1885
|
+
function formatDepDescription(type, lag) {
|
|
1886
|
+
const effectiveLag = lag ?? 0;
|
|
1887
|
+
if (type === "FS") {
|
|
1888
|
+
if (effectiveLag > 0) return `\u041D\u0430\u0447\u0430\u0442\u044C \u0447\u0435\u0440\u0435\u0437 ${effectiveLag} \u0434\u043D. \u043F\u043E\u0441\u043B\u0435 \u043E\u043A\u043E\u043D\u0447\u0430\u043D\u0438\u044F`;
|
|
1889
|
+
if (effectiveLag < 0) return `\u041D\u0430\u0447\u0430\u0442\u044C \u0437\u0430 ${Math.abs(effectiveLag)} \u0434\u043D. \u0434\u043E \u043E\u043A\u043E\u043D\u0447\u0430\u043D\u0438\u044F`;
|
|
1890
|
+
return `\u041D\u0430\u0447\u0430\u0442\u044C \u0441\u0440\u0430\u0437\u0443 \u043F\u043E\u0441\u043B\u0435 \u043E\u043A\u043E\u043D\u0447\u0430\u043D\u0438\u044F`;
|
|
1891
|
+
}
|
|
1892
|
+
if (type === "FF") {
|
|
1893
|
+
if (effectiveLag > 0) return `\u0417\u0430\u0432\u0435\u0440\u0448\u0438\u0442\u044C \u0447\u0435\u0440\u0435\u0437 ${effectiveLag} \u0434\u043D. \u043F\u043E\u0441\u043B\u0435 \u043E\u043A\u043E\u043D\u0447\u0430\u043D\u0438\u044F`;
|
|
1894
|
+
if (effectiveLag < 0) return `\u0417\u0430\u0432\u0435\u0440\u0448\u0438\u0442\u044C \u0437\u0430 ${Math.abs(effectiveLag)} \u0434\u043D. \u0434\u043E \u043E\u043A\u043E\u043D\u0447\u0430\u043D\u0438\u044F`;
|
|
1895
|
+
return `\u0417\u0430\u0432\u0435\u0440\u0448\u0438\u0442\u044C \u043F\u043E\u0441\u043B\u0435 \u043E\u043A\u043E\u043D\u0447\u0430\u043D\u0438\u044F`;
|
|
1896
|
+
}
|
|
1897
|
+
if (type === "SS") {
|
|
1898
|
+
if (effectiveLag > 0) return `\u041D\u0430\u0447\u0430\u0442\u044C \u0447\u0435\u0440\u0435\u0437 ${effectiveLag} \u0434\u043D. \u043F\u043E\u0441\u043B\u0435 \u043D\u0430\u0447\u0430\u043B\u0430`;
|
|
1899
|
+
if (effectiveLag < 0) return `\u041D\u0430\u0447\u0430\u0442\u044C \u0437\u0430 ${Math.abs(effectiveLag)} \u0434\u043D. \u0434\u043E \u043D\u0430\u0447\u0430\u043B\u0430`;
|
|
1900
|
+
return `\u041D\u0430\u0447\u0430\u0442\u044C \u0432\u043C\u0435\u0441\u0442\u0435 \u0441 \u043D\u0430\u0447\u0430\u043B\u043E\u043C`;
|
|
1901
|
+
}
|
|
1902
|
+
if (type === "SF") {
|
|
1903
|
+
if (effectiveLag > 0) return `\u0417\u0430\u0432\u0435\u0440\u0448\u0438\u0442\u044C \u0447\u0435\u0440\u0435\u0437 ${effectiveLag} \u0434\u043D. \u043F\u043E\u0441\u043B\u0435 \u043D\u0430\u0447\u0430\u043B\u0430`;
|
|
1904
|
+
if (effectiveLag < 0) return `\u0417\u0430\u0432\u0435\u0440\u0448\u0438\u0442\u044C \u0437\u0430 ${Math.abs(effectiveLag)} \u0434\u043D. \u0434\u043E \u043D\u0430\u0447\u0430\u043B\u0430`;
|
|
1905
|
+
return `\u0417\u0430\u0432\u0435\u0440\u0448\u0438\u0442\u044C \u0434\u043E \u043D\u0430\u0447\u0430\u043B\u0430`;
|
|
1906
|
+
}
|
|
1907
|
+
return "";
|
|
1908
|
+
}
|
|
1909
|
+
var DepChip = ({
|
|
1910
|
+
lag,
|
|
1911
|
+
dep,
|
|
1912
|
+
taskId,
|
|
1913
|
+
predecessorName,
|
|
1914
|
+
selectedChip,
|
|
1915
|
+
disableDependencyEditing,
|
|
1916
|
+
onChipSelect,
|
|
1917
|
+
onRowClick,
|
|
1918
|
+
onScrollToTask,
|
|
1919
|
+
onRemoveDependency,
|
|
1920
|
+
onChipSelectClear
|
|
1921
|
+
}) => {
|
|
1922
|
+
const isSelected = selectedChip?.successorId === taskId && selectedChip?.predecessorId === dep.taskId && selectedChip?.linkType === dep.type;
|
|
1923
|
+
const handleClick = (e) => {
|
|
1924
|
+
e.stopPropagation();
|
|
1925
|
+
if (disableDependencyEditing) return;
|
|
1926
|
+
onChipSelect?.(isSelected ? null : { successorId: taskId, predecessorId: dep.taskId, linkType: dep.type });
|
|
1927
|
+
if (!isSelected) {
|
|
1928
|
+
onRowClick?.(taskId);
|
|
1929
|
+
onScrollToTask?.(taskId);
|
|
1930
|
+
}
|
|
1931
|
+
};
|
|
1932
|
+
const handleTrashClick = (e) => {
|
|
1933
|
+
e.stopPropagation();
|
|
1934
|
+
onRemoveDependency?.(taskId, dep.taskId, dep.type);
|
|
1935
|
+
onChipSelectClear();
|
|
1936
|
+
};
|
|
1937
|
+
const Icon = LINK_TYPE_ICONS[dep.type];
|
|
1938
|
+
const depPrefix = formatDepDescription(dep.type, lag);
|
|
1939
|
+
const depName = predecessorName ?? dep.taskId;
|
|
1940
|
+
return /* @__PURE__ */ jsxs9(Popover, { open: isSelected, onOpenChange: (open) => {
|
|
1941
|
+
if (!open) onChipSelectClear();
|
|
1942
|
+
}, children: [
|
|
1943
|
+
/* @__PURE__ */ jsxs9("span", { className: "gantt-tl-dep-chip-wrapper", children: [
|
|
1944
|
+
/* @__PURE__ */ jsx12(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsx12(
|
|
1945
|
+
"span",
|
|
1946
|
+
{
|
|
1947
|
+
className: `gantt-tl-dep-chip${isSelected ? " gantt-tl-dep-chip-selected" : ""}`,
|
|
1948
|
+
onClick: handleClick,
|
|
1949
|
+
children: /* @__PURE__ */ jsxs9(Fragment2, { children: [
|
|
1950
|
+
/* @__PURE__ */ jsx12(Icon, {}),
|
|
1951
|
+
lag != null && lag !== 0 ? lag > 0 ? `+${lag}` : `${lag}` : ""
|
|
1952
|
+
] })
|
|
1953
|
+
}
|
|
1954
|
+
) }),
|
|
1955
|
+
!disableDependencyEditing && /* @__PURE__ */ jsx12(
|
|
1956
|
+
"button",
|
|
1957
|
+
{
|
|
1958
|
+
type: "button",
|
|
1959
|
+
className: "gantt-tl-dep-chip-trash",
|
|
1960
|
+
"aria-label": "\u0423\u0434\u0430\u043B\u0438\u0442\u044C \u0441\u0432\u044F\u0437\u044C",
|
|
1961
|
+
onClick: handleTrashClick,
|
|
1962
|
+
children: /* @__PURE__ */ jsx12(TrashIcon, {})
|
|
1963
|
+
}
|
|
1964
|
+
)
|
|
1965
|
+
] }),
|
|
1966
|
+
/* @__PURE__ */ jsxs9(PopoverContent, { portal: true, side: "bottom", align: "start", className: "gantt-tl-dep-info-popover", children: [
|
|
1967
|
+
/* @__PURE__ */ jsx12("span", { className: "gantt-tl-dep-info-prefix", children: depPrefix }),
|
|
1968
|
+
/* @__PURE__ */ jsx12("span", { className: "gantt-tl-dep-info-name", children: depName })
|
|
1969
|
+
] })
|
|
1970
|
+
] });
|
|
1971
|
+
};
|
|
1866
1972
|
var toISODate = (value) => {
|
|
1867
1973
|
if (value instanceof Date) return value.toISOString().split("T")[0];
|
|
1868
1974
|
if (typeof value === "string" && value.includes("T")) return value.split("T")[0];
|
|
1869
1975
|
return value;
|
|
1870
1976
|
};
|
|
1871
1977
|
var TaskListRow = React9.memo(
|
|
1872
|
-
({
|
|
1978
|
+
({
|
|
1979
|
+
task,
|
|
1980
|
+
rowIndex,
|
|
1981
|
+
rowHeight,
|
|
1982
|
+
onTaskChange,
|
|
1983
|
+
selectedTaskId,
|
|
1984
|
+
onRowClick,
|
|
1985
|
+
disableTaskNameEditing = false,
|
|
1986
|
+
disableDependencyEditing = false,
|
|
1987
|
+
allTasks = [],
|
|
1988
|
+
activeLinkType,
|
|
1989
|
+
selectingPredecessorFor,
|
|
1990
|
+
onSetSelectingPredecessorFor,
|
|
1991
|
+
onAddDependency,
|
|
1992
|
+
onRemoveDependency,
|
|
1993
|
+
selectedChip,
|
|
1994
|
+
onChipSelect,
|
|
1995
|
+
onScrollToTask
|
|
1996
|
+
}) => {
|
|
1873
1997
|
const [editingName, setEditingName] = useState4(false);
|
|
1874
1998
|
const [nameValue, setNameValue] = useState4("");
|
|
1875
1999
|
const nameInputRef = useRef3(null);
|
|
2000
|
+
const [overflowOpen, setOverflowOpen] = useState4(false);
|
|
1876
2001
|
const isSelected = selectedTaskId === task.id;
|
|
2002
|
+
const isPicking = selectingPredecessorFor != null;
|
|
2003
|
+
const isSourceRow = isPicking && selectingPredecessorFor === task.id;
|
|
2004
|
+
const chips = useMemo7(() => {
|
|
2005
|
+
const succStart = new Date(task.startDate);
|
|
2006
|
+
const succEnd = new Date(task.endDate);
|
|
2007
|
+
const taskById = new Map((allTasks ?? []).map((t) => [t.id, t]));
|
|
2008
|
+
return (task.dependencies ?? []).map((dep) => {
|
|
2009
|
+
const pred = taskById.get(dep.taskId);
|
|
2010
|
+
const lag = pred ? computeLagFromDates(
|
|
2011
|
+
dep.type,
|
|
2012
|
+
new Date(pred.startDate),
|
|
2013
|
+
new Date(pred.endDate),
|
|
2014
|
+
succStart,
|
|
2015
|
+
succEnd
|
|
2016
|
+
) : dep.lag ?? 0;
|
|
2017
|
+
return { dep, lag, predecessorName: pred?.name ?? dep.taskId };
|
|
2018
|
+
});
|
|
2019
|
+
}, [task.dependencies, task.startDate, task.endDate, allTasks]);
|
|
2020
|
+
const linkWord = chips.length <= 4 ? "\u0441\u0432\u044F\u0437\u0438" : "\u0441\u0432\u044F\u0437\u0435\u0439";
|
|
1877
2021
|
useEffect3(() => {
|
|
1878
2022
|
if (editingName && nameInputRef.current) {
|
|
1879
2023
|
nameInputRef.current.focus();
|
|
@@ -1919,18 +2063,60 @@ var TaskListRow = React9.memo(
|
|
|
1919
2063
|
const handleRowClickInternal = useCallback4(() => {
|
|
1920
2064
|
onRowClick?.(task.id);
|
|
1921
2065
|
}, [task.id, onRowClick]);
|
|
2066
|
+
const handleNumberClick = useCallback4((e) => {
|
|
2067
|
+
e.stopPropagation();
|
|
2068
|
+
onRowClick?.(task.id);
|
|
2069
|
+
onScrollToTask?.(task.id);
|
|
2070
|
+
}, [task.id, onRowClick, onScrollToTask]);
|
|
2071
|
+
const handleAddClick = useCallback4((e) => {
|
|
2072
|
+
e.stopPropagation();
|
|
2073
|
+
onSetSelectingPredecessorFor?.(task.id);
|
|
2074
|
+
}, [task.id, onSetSelectingPredecessorFor]);
|
|
2075
|
+
const handlePredecessorPick = useCallback4((e) => {
|
|
2076
|
+
e.stopPropagation();
|
|
2077
|
+
if (!isPicking || isSourceRow) return;
|
|
2078
|
+
if (!selectingPredecessorFor || !activeLinkType) return;
|
|
2079
|
+
onAddDependency?.(task.id, selectingPredecessorFor, activeLinkType);
|
|
2080
|
+
}, [isPicking, isSourceRow, selectingPredecessorFor, task.id, activeLinkType, onAddDependency]);
|
|
2081
|
+
const isSelectedPredecessor = selectedChip != null && selectedChip.predecessorId === task.id;
|
|
2082
|
+
const handleDeleteSelected = useCallback4((e) => {
|
|
2083
|
+
e.stopPropagation();
|
|
2084
|
+
if (!selectedChip) return;
|
|
2085
|
+
onRemoveDependency?.(selectedChip.successorId, selectedChip.predecessorId, selectedChip.linkType);
|
|
2086
|
+
onChipSelect?.(null);
|
|
2087
|
+
}, [selectedChip, onRemoveDependency, onChipSelect]);
|
|
1922
2088
|
const startDateISO = toISODate(task.startDate);
|
|
1923
2089
|
const endDateISO = toISODate(task.endDate);
|
|
1924
|
-
return /* @__PURE__ */
|
|
2090
|
+
return /* @__PURE__ */ jsxs9(
|
|
1925
2091
|
"div",
|
|
1926
2092
|
{
|
|
1927
|
-
className:
|
|
2093
|
+
className: [
|
|
2094
|
+
"gantt-tl-row",
|
|
2095
|
+
isSelected ? "gantt-tl-row-selected" : "",
|
|
2096
|
+
isPicking && !isSourceRow ? "gantt-tl-row-picking" : "",
|
|
2097
|
+
isSourceRow ? "gantt-tl-row-picking-self" : ""
|
|
2098
|
+
].filter(Boolean).join(" "),
|
|
1928
2099
|
style: { minHeight: `${rowHeight}px` },
|
|
1929
2100
|
onClick: handleRowClickInternal,
|
|
1930
2101
|
children: [
|
|
1931
|
-
/* @__PURE__ */
|
|
1932
|
-
|
|
1933
|
-
|
|
2102
|
+
/* @__PURE__ */ jsxs9(
|
|
2103
|
+
"div",
|
|
2104
|
+
{
|
|
2105
|
+
className: "gantt-tl-cell gantt-tl-cell-number",
|
|
2106
|
+
onClick: handleNumberClick,
|
|
2107
|
+
title: "\u041F\u0435\u0440\u0435\u0439\u0442\u0438 \u043A \u0440\u0430\u0431\u043E\u0442\u0435",
|
|
2108
|
+
children: [
|
|
2109
|
+
/* @__PURE__ */ jsx12("span", { className: "gantt-tl-num-label", children: rowIndex + 1 }),
|
|
2110
|
+
/* @__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: [
|
|
2111
|
+
/* @__PURE__ */ jsx12("path", { d: "M17 12H3" }),
|
|
2112
|
+
/* @__PURE__ */ jsx12("path", { d: "m11 18 6-6-6-6" }),
|
|
2113
|
+
/* @__PURE__ */ jsx12("path", { d: "M21 5v14" })
|
|
2114
|
+
] })
|
|
2115
|
+
]
|
|
2116
|
+
}
|
|
2117
|
+
),
|
|
2118
|
+
/* @__PURE__ */ jsxs9("div", { className: "gantt-tl-cell gantt-tl-cell-name", children: [
|
|
2119
|
+
editingName && /* @__PURE__ */ jsx12(
|
|
1934
2120
|
Input,
|
|
1935
2121
|
{
|
|
1936
2122
|
ref: nameInputRef,
|
|
@@ -1943,7 +2129,7 @@ var TaskListRow = React9.memo(
|
|
|
1943
2129
|
onClick: (e) => e.stopPropagation()
|
|
1944
2130
|
}
|
|
1945
2131
|
),
|
|
1946
|
-
/* @__PURE__ */
|
|
2132
|
+
/* @__PURE__ */ jsx12(
|
|
1947
2133
|
"button",
|
|
1948
2134
|
{
|
|
1949
2135
|
type: "button",
|
|
@@ -1954,7 +2140,7 @@ var TaskListRow = React9.memo(
|
|
|
1954
2140
|
}
|
|
1955
2141
|
)
|
|
1956
2142
|
] }),
|
|
1957
|
-
/* @__PURE__ */
|
|
2143
|
+
/* @__PURE__ */ jsx12("div", { className: "gantt-tl-cell gantt-tl-cell-date", onClick: (e) => e.stopPropagation(), children: /* @__PURE__ */ jsx12(
|
|
1958
2144
|
DatePicker,
|
|
1959
2145
|
{
|
|
1960
2146
|
value: startDateISO,
|
|
@@ -1964,7 +2150,7 @@ var TaskListRow = React9.memo(
|
|
|
1964
2150
|
disabled: task.locked
|
|
1965
2151
|
}
|
|
1966
2152
|
) }),
|
|
1967
|
-
/* @__PURE__ */
|
|
2153
|
+
/* @__PURE__ */ jsx12("div", { className: "gantt-tl-cell gantt-tl-cell-date", onClick: (e) => e.stopPropagation(), children: /* @__PURE__ */ jsx12(
|
|
1968
2154
|
DatePicker,
|
|
1969
2155
|
{
|
|
1970
2156
|
value: endDateISO,
|
|
@@ -1973,7 +2159,97 @@ var TaskListRow = React9.memo(
|
|
|
1973
2159
|
portal: true,
|
|
1974
2160
|
disabled: task.locked
|
|
1975
2161
|
}
|
|
1976
|
-
) })
|
|
2162
|
+
) }),
|
|
2163
|
+
/* @__PURE__ */ jsx12(
|
|
2164
|
+
"div",
|
|
2165
|
+
{
|
|
2166
|
+
className: "gantt-tl-cell gantt-tl-cell-deps",
|
|
2167
|
+
onClick: isPicking && !isSourceRow ? handlePredecessorPick : void 0,
|
|
2168
|
+
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 ? (
|
|
2169
|
+
/* Full-replacement: "Зависит от [name]" → hover → "Удалить" */
|
|
2170
|
+
/* @__PURE__ */ jsxs9(
|
|
2171
|
+
"button",
|
|
2172
|
+
{
|
|
2173
|
+
type: "button",
|
|
2174
|
+
className: "gantt-tl-dep-delete-label",
|
|
2175
|
+
onClick: handleDeleteSelected,
|
|
2176
|
+
"aria-label": "\u0423\u0434\u0430\u043B\u0438\u0442\u044C \u0441\u0432\u044F\u0437\u044C",
|
|
2177
|
+
children: [
|
|
2178
|
+
/* @__PURE__ */ jsx12("span", { className: "gantt-tl-dep-delete-label-default", children: "\u0421\u0432\u044F\u0437\u0430\u043D\u043E \u0441" }),
|
|
2179
|
+
/* @__PURE__ */ jsx12("span", { className: "gantt-tl-dep-delete-label-hover", children: "\u0423\u0434\u0430\u043B\u0438\u0442\u044C \u0441\u0432\u044F\u0437\u044C" })
|
|
2180
|
+
]
|
|
2181
|
+
}
|
|
2182
|
+
)
|
|
2183
|
+
) : /* @__PURE__ */ jsxs9(Fragment2, { children: [
|
|
2184
|
+
chips.length >= 2 ? (
|
|
2185
|
+
/* 2+ deps — show only "N связей" summary chip that opens a popover */
|
|
2186
|
+
/* @__PURE__ */ jsxs9(Popover, { open: overflowOpen, onOpenChange: setOverflowOpen, children: [
|
|
2187
|
+
/* @__PURE__ */ jsx12(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxs9(
|
|
2188
|
+
"button",
|
|
2189
|
+
{
|
|
2190
|
+
type: "button",
|
|
2191
|
+
className: "gantt-tl-dep-summary-chip",
|
|
2192
|
+
onClick: (e) => {
|
|
2193
|
+
e.stopPropagation();
|
|
2194
|
+
setOverflowOpen((v) => !v);
|
|
2195
|
+
},
|
|
2196
|
+
children: [
|
|
2197
|
+
chips.length,
|
|
2198
|
+
" ",
|
|
2199
|
+
linkWord
|
|
2200
|
+
]
|
|
2201
|
+
}
|
|
2202
|
+
) }),
|
|
2203
|
+
/* @__PURE__ */ jsx12(PopoverContent, { portal: true, align: "start", children: /* @__PURE__ */ jsx12("div", { className: "gantt-tl-dep-overflow-list", onClick: (e) => e.stopPropagation(), children: chips.map(({ dep, lag, predecessorName }) => /* @__PURE__ */ jsx12(
|
|
2204
|
+
DepChip,
|
|
2205
|
+
{
|
|
2206
|
+
lag,
|
|
2207
|
+
dep,
|
|
2208
|
+
taskId: task.id,
|
|
2209
|
+
predecessorName,
|
|
2210
|
+
selectedChip,
|
|
2211
|
+
disableDependencyEditing,
|
|
2212
|
+
onChipSelect,
|
|
2213
|
+
onRowClick,
|
|
2214
|
+
onScrollToTask,
|
|
2215
|
+
onRemoveDependency,
|
|
2216
|
+
onChipSelectClear: () => onChipSelect?.(null)
|
|
2217
|
+
},
|
|
2218
|
+
`${dep.taskId}-${dep.type}`
|
|
2219
|
+
)) }) })
|
|
2220
|
+
] })
|
|
2221
|
+
) : chips.length === 1 ? (
|
|
2222
|
+
/* Single chip — unified DepChip */
|
|
2223
|
+
/* @__PURE__ */ jsx12(
|
|
2224
|
+
DepChip,
|
|
2225
|
+
{
|
|
2226
|
+
lag: chips[0].lag,
|
|
2227
|
+
dep: chips[0].dep,
|
|
2228
|
+
taskId: task.id,
|
|
2229
|
+
predecessorName: chips[0].predecessorName,
|
|
2230
|
+
selectedChip,
|
|
2231
|
+
disableDependencyEditing,
|
|
2232
|
+
onChipSelect,
|
|
2233
|
+
onRowClick,
|
|
2234
|
+
onScrollToTask,
|
|
2235
|
+
onRemoveDependency,
|
|
2236
|
+
onChipSelectClear: () => onChipSelect?.(null)
|
|
2237
|
+
}
|
|
2238
|
+
)
|
|
2239
|
+
) : null,
|
|
2240
|
+
!disableDependencyEditing && !isPicking && /* @__PURE__ */ jsx12(
|
|
2241
|
+
"button",
|
|
2242
|
+
{
|
|
2243
|
+
type: "button",
|
|
2244
|
+
className: "gantt-tl-dep-add",
|
|
2245
|
+
onClick: handleAddClick,
|
|
2246
|
+
"aria-label": "\u0414\u043E\u0431\u0430\u0432\u0438\u0442\u044C \u0441\u0432\u044F\u0437\u044C",
|
|
2247
|
+
children: "+"
|
|
2248
|
+
}
|
|
2249
|
+
)
|
|
2250
|
+
] })
|
|
2251
|
+
}
|
|
2252
|
+
)
|
|
1977
2253
|
]
|
|
1978
2254
|
}
|
|
1979
2255
|
);
|
|
@@ -1982,7 +2258,8 @@ var TaskListRow = React9.memo(
|
|
|
1982
2258
|
TaskListRow.displayName = "TaskListRow";
|
|
1983
2259
|
|
|
1984
2260
|
// src/components/TaskList/TaskList.tsx
|
|
1985
|
-
import { jsx as
|
|
2261
|
+
import { jsx as jsx13, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
2262
|
+
var LINK_TYPE_ORDER = ["FS", "SS", "FF", "SF"];
|
|
1986
2263
|
var TaskList = ({
|
|
1987
2264
|
tasks,
|
|
1988
2265
|
rowHeight,
|
|
@@ -1992,28 +2269,156 @@ var TaskList = ({
|
|
|
1992
2269
|
selectedTaskId,
|
|
1993
2270
|
onTaskSelect,
|
|
1994
2271
|
show = true,
|
|
1995
|
-
disableTaskNameEditing = false
|
|
2272
|
+
disableTaskNameEditing = false,
|
|
2273
|
+
disableDependencyEditing = false,
|
|
2274
|
+
onScrollToTask,
|
|
2275
|
+
onSelectedChipChange
|
|
1996
2276
|
}) => {
|
|
1997
|
-
const totalHeight =
|
|
2277
|
+
const totalHeight = useMemo8(
|
|
1998
2278
|
() => tasks.length * rowHeight,
|
|
1999
2279
|
[tasks.length, rowHeight]
|
|
2000
2280
|
);
|
|
2001
2281
|
const handleRowClick = useCallback5((taskId) => {
|
|
2002
2282
|
onTaskSelect?.(taskId);
|
|
2003
2283
|
}, [onTaskSelect]);
|
|
2004
|
-
|
|
2284
|
+
const [activeLinkType, setActiveLinkType] = useState5("FS");
|
|
2285
|
+
const [selectingPredecessorFor, setSelectingPredecessorFor] = useState5(null);
|
|
2286
|
+
const [typeMenuOpen, setTypeMenuOpen] = useState5(false);
|
|
2287
|
+
const [cycleError, setCycleError] = useState5(false);
|
|
2288
|
+
const overlayRef = useRef4(null);
|
|
2289
|
+
const [selectedChip, setSelectedChip] = useState5(null);
|
|
2290
|
+
const handleChipSelect = useCallback5((chip) => {
|
|
2291
|
+
setSelectedChip(chip);
|
|
2292
|
+
onSelectedChipChange?.(chip);
|
|
2293
|
+
}, [onSelectedChipChange]);
|
|
2294
|
+
useEffect4(() => {
|
|
2295
|
+
if (!selectingPredecessorFor && !selectedChip) return;
|
|
2296
|
+
const handleKeyDown = (e) => {
|
|
2297
|
+
if (e.key === "Escape") {
|
|
2298
|
+
setSelectingPredecessorFor(null);
|
|
2299
|
+
setSelectedChip(null);
|
|
2300
|
+
onSelectedChipChange?.(null);
|
|
2301
|
+
}
|
|
2302
|
+
};
|
|
2303
|
+
const handleMouseDown = (e) => {
|
|
2304
|
+
const target = e.target;
|
|
2305
|
+
if (overlayRef.current?.contains(target)) return;
|
|
2306
|
+
if (target.closest?.(".gantt-popover")) return;
|
|
2307
|
+
setSelectingPredecessorFor(null);
|
|
2308
|
+
setSelectedChip(null);
|
|
2309
|
+
onSelectedChipChange?.(null);
|
|
2310
|
+
};
|
|
2311
|
+
document.addEventListener("keydown", handleKeyDown);
|
|
2312
|
+
document.addEventListener("mousedown", handleMouseDown, true);
|
|
2313
|
+
return () => {
|
|
2314
|
+
document.removeEventListener("keydown", handleKeyDown);
|
|
2315
|
+
document.removeEventListener("mousedown", handleMouseDown, true);
|
|
2316
|
+
};
|
|
2317
|
+
}, [selectingPredecessorFor, selectedChip, onSelectedChipChange]);
|
|
2318
|
+
const handleAddDependency = useCallback5((successorTaskId, predecessorTaskId, linkType) => {
|
|
2319
|
+
if (successorTaskId === predecessorTaskId) return;
|
|
2320
|
+
const successor = tasks.find((t) => t.id === successorTaskId);
|
|
2321
|
+
if (!successor) return;
|
|
2322
|
+
const alreadyExists = (successor.dependencies ?? []).some(
|
|
2323
|
+
(d) => d.taskId === predecessorTaskId && d.type === linkType
|
|
2324
|
+
);
|
|
2325
|
+
if (alreadyExists) {
|
|
2326
|
+
setSelectingPredecessorFor(null);
|
|
2327
|
+
return;
|
|
2328
|
+
}
|
|
2329
|
+
const newDep = { taskId: predecessorTaskId, type: linkType, lag: 0 };
|
|
2330
|
+
const hypothetical = tasks.map(
|
|
2331
|
+
(t) => t.id === successorTaskId ? { ...t, dependencies: [...t.dependencies ?? [], newDep] } : t
|
|
2332
|
+
);
|
|
2333
|
+
const validation = validateDependencies(hypothetical);
|
|
2334
|
+
if (!validation.isValid) {
|
|
2335
|
+
setCycleError(true);
|
|
2336
|
+
setTimeout(() => setCycleError(false), 3e3);
|
|
2337
|
+
return;
|
|
2338
|
+
}
|
|
2339
|
+
const updatedTask = hypothetical.find((t) => t.id === successorTaskId);
|
|
2340
|
+
const predecessor = tasks.find((t) => t.id === predecessorTaskId);
|
|
2341
|
+
if (predecessor) {
|
|
2342
|
+
const predStart = new Date(predecessor.startDate);
|
|
2343
|
+
const predEnd = new Date(predecessor.endDate);
|
|
2344
|
+
const constraintDate = calculateSuccessorDate(predStart, predEnd, linkType, 0);
|
|
2345
|
+
const origSuccessor = tasks.find((t) => t.id === successorTaskId);
|
|
2346
|
+
const durationMs = new Date(origSuccessor.endDate).getTime() - new Date(origSuccessor.startDate).getTime();
|
|
2347
|
+
let newStart;
|
|
2348
|
+
let newEnd;
|
|
2349
|
+
if (linkType === "FS" || linkType === "SS") {
|
|
2350
|
+
newStart = constraintDate;
|
|
2351
|
+
newEnd = new Date(constraintDate.getTime() + durationMs);
|
|
2352
|
+
} else {
|
|
2353
|
+
newEnd = constraintDate;
|
|
2354
|
+
newStart = new Date(constraintDate.getTime() - durationMs);
|
|
2355
|
+
}
|
|
2356
|
+
const snappedTask = {
|
|
2357
|
+
...updatedTask,
|
|
2358
|
+
startDate: newStart.toISOString().split("T")[0],
|
|
2359
|
+
endDate: newEnd.toISOString().split("T")[0]
|
|
2360
|
+
};
|
|
2361
|
+
onTaskChange?.(snappedTask);
|
|
2362
|
+
} else {
|
|
2363
|
+
onTaskChange?.(updatedTask);
|
|
2364
|
+
}
|
|
2365
|
+
setSelectingPredecessorFor(null);
|
|
2366
|
+
}, [tasks, onTaskChange]);
|
|
2367
|
+
const handleRemoveDependency = useCallback5((taskId, predecessorTaskId, linkType) => {
|
|
2368
|
+
const task = tasks.find((t) => t.id === taskId);
|
|
2369
|
+
if (!task) return;
|
|
2370
|
+
const updatedDeps = (task.dependencies ?? []).filter(
|
|
2371
|
+
(d) => !(d.taskId === predecessorTaskId && d.type === linkType)
|
|
2372
|
+
);
|
|
2373
|
+
onTaskChange?.({ ...task, dependencies: updatedDeps });
|
|
2374
|
+
}, [tasks, onTaskChange]);
|
|
2375
|
+
return /* @__PURE__ */ jsx13(
|
|
2005
2376
|
"div",
|
|
2006
2377
|
{
|
|
2378
|
+
ref: overlayRef,
|
|
2007
2379
|
className: `gantt-tl-overlay${show ? "" : " gantt-tl-hidden"}`,
|
|
2008
2380
|
style: { width: `${taskListWidth}px` },
|
|
2009
|
-
children: /* @__PURE__ */
|
|
2010
|
-
/* @__PURE__ */
|
|
2011
|
-
/* @__PURE__ */
|
|
2012
|
-
/* @__PURE__ */
|
|
2013
|
-
/* @__PURE__ */
|
|
2014
|
-
/* @__PURE__ */
|
|
2381
|
+
children: /* @__PURE__ */ jsxs10("div", { className: "gantt-tl-table", children: [
|
|
2382
|
+
/* @__PURE__ */ jsxs10("div", { className: "gantt-tl-header", style: { height: `${headerHeight + 0.5}px` }, children: [
|
|
2383
|
+
/* @__PURE__ */ jsx13("div", { className: "gantt-tl-headerCell gantt-tl-cell-number", children: "\u2116" }),
|
|
2384
|
+
/* @__PURE__ */ jsx13("div", { className: "gantt-tl-headerCell gantt-tl-cell-name", children: "\u0418\u043C\u044F" }),
|
|
2385
|
+
/* @__PURE__ */ jsx13("div", { className: "gantt-tl-headerCell gantt-tl-cell-date", children: "\u041D\u0430\u0447\u0430\u043B\u043E" }),
|
|
2386
|
+
/* @__PURE__ */ jsx13("div", { className: "gantt-tl-headerCell gantt-tl-cell-date", children: "\u041E\u043A\u043E\u043D\u0447\u0430\u043D\u0438\u0435" }),
|
|
2387
|
+
/* @__PURE__ */ jsxs10("div", { className: "gantt-tl-headerCell gantt-tl-cell-deps", style: { position: "relative" }, children: [
|
|
2388
|
+
/* @__PURE__ */ jsxs10(Popover, { open: typeMenuOpen, onOpenChange: setTypeMenuOpen, children: [
|
|
2389
|
+
/* @__PURE__ */ jsx13(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxs10(
|
|
2390
|
+
"button",
|
|
2391
|
+
{
|
|
2392
|
+
className: "gantt-tl-dep-type-trigger",
|
|
2393
|
+
disabled: disableDependencyEditing,
|
|
2394
|
+
onClick: (e) => e.stopPropagation(),
|
|
2395
|
+
children: [
|
|
2396
|
+
"\u0421\u0432\u044F\u0437\u0438 ",
|
|
2397
|
+
React10.createElement(LINK_TYPE_ICONS[activeLinkType]),
|
|
2398
|
+
" \u25BE"
|
|
2399
|
+
]
|
|
2400
|
+
}
|
|
2401
|
+
) }),
|
|
2402
|
+
/* @__PURE__ */ jsx13(PopoverContent, { portal: true, align: "start", children: /* @__PURE__ */ jsx13("div", { className: "gantt-tl-dep-type-menu", children: LINK_TYPE_ORDER.map((lt) => /* @__PURE__ */ jsxs10(
|
|
2403
|
+
"button",
|
|
2404
|
+
{
|
|
2405
|
+
className: `gantt-tl-dep-type-option${activeLinkType === lt ? " active" : ""}`,
|
|
2406
|
+
onClick: () => {
|
|
2407
|
+
setActiveLinkType(lt);
|
|
2408
|
+
setTypeMenuOpen(false);
|
|
2409
|
+
},
|
|
2410
|
+
children: [
|
|
2411
|
+
React10.createElement(LINK_TYPE_ICONS[lt]),
|
|
2412
|
+
/* @__PURE__ */ jsx13("span", { children: LINK_TYPE_LABELS[lt] })
|
|
2413
|
+
]
|
|
2414
|
+
},
|
|
2415
|
+
lt
|
|
2416
|
+
)) }) })
|
|
2417
|
+
] }),
|
|
2418
|
+
cycleError && /* @__PURE__ */ jsx13("div", { className: "gantt-tl-dep-error", children: "\u0426\u0438\u043A\u043B \u0437\u0430\u0432\u0438\u0441\u0438\u043C\u043E\u0441\u0442\u0435\u0439!" })
|
|
2419
|
+
] })
|
|
2015
2420
|
] }),
|
|
2016
|
-
/* @__PURE__ */
|
|
2421
|
+
/* @__PURE__ */ jsx13("div", { className: "gantt-tl-body", style: { height: `${totalHeight}px` }, children: tasks.map((task, index) => /* @__PURE__ */ jsx13(
|
|
2017
2422
|
TaskListRow,
|
|
2018
2423
|
{
|
|
2019
2424
|
task,
|
|
@@ -2022,7 +2427,17 @@ var TaskList = ({
|
|
|
2022
2427
|
onTaskChange,
|
|
2023
2428
|
selectedTaskId,
|
|
2024
2429
|
onRowClick: handleRowClick,
|
|
2025
|
-
disableTaskNameEditing
|
|
2430
|
+
disableTaskNameEditing,
|
|
2431
|
+
disableDependencyEditing,
|
|
2432
|
+
allTasks: tasks,
|
|
2433
|
+
activeLinkType,
|
|
2434
|
+
selectingPredecessorFor,
|
|
2435
|
+
onSetSelectingPredecessorFor: setSelectingPredecessorFor,
|
|
2436
|
+
onAddDependency: handleAddDependency,
|
|
2437
|
+
onRemoveDependency: handleRemoveDependency,
|
|
2438
|
+
selectedChip,
|
|
2439
|
+
onChipSelect: handleChipSelect,
|
|
2440
|
+
onScrollToTask
|
|
2026
2441
|
},
|
|
2027
2442
|
task.id
|
|
2028
2443
|
)) })
|
|
@@ -2032,7 +2447,7 @@ var TaskList = ({
|
|
|
2032
2447
|
};
|
|
2033
2448
|
|
|
2034
2449
|
// src/components/GanttChart/GanttChart.tsx
|
|
2035
|
-
import { jsx as
|
|
2450
|
+
import { jsx as jsx14, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
2036
2451
|
var GanttChart = forwardRef(({
|
|
2037
2452
|
tasks,
|
|
2038
2453
|
dayWidth = 40,
|
|
@@ -2046,34 +2461,36 @@ var GanttChart = forwardRef(({
|
|
|
2046
2461
|
onCascade,
|
|
2047
2462
|
showTaskList = false,
|
|
2048
2463
|
taskListWidth = 520,
|
|
2049
|
-
disableTaskNameEditing = false
|
|
2464
|
+
disableTaskNameEditing = false,
|
|
2465
|
+
disableDependencyEditing = false
|
|
2050
2466
|
}, ref) => {
|
|
2051
|
-
const scrollContainerRef =
|
|
2052
|
-
const [selectedTaskId, setSelectedTaskId] =
|
|
2053
|
-
const
|
|
2054
|
-
const
|
|
2055
|
-
const [
|
|
2056
|
-
const
|
|
2467
|
+
const scrollContainerRef = useRef5(null);
|
|
2468
|
+
const [selectedTaskId, setSelectedTaskId] = useState6(null);
|
|
2469
|
+
const [selectedChip, setSelectedChip] = useState6(null);
|
|
2470
|
+
const dateRange = useMemo9(() => getMultiMonthDays(tasks), [tasks]);
|
|
2471
|
+
const [validationResult, setValidationResult] = useState6(null);
|
|
2472
|
+
const [cascadeOverrides, setCascadeOverrides] = useState6(/* @__PURE__ */ new Map());
|
|
2473
|
+
const gridWidth = useMemo9(
|
|
2057
2474
|
() => Math.round(dateRange.length * dayWidth),
|
|
2058
2475
|
[dateRange.length, dayWidth]
|
|
2059
2476
|
);
|
|
2060
|
-
const totalGridHeight =
|
|
2477
|
+
const totalGridHeight = useMemo9(
|
|
2061
2478
|
() => tasks.length * rowHeight,
|
|
2062
2479
|
[tasks.length, rowHeight]
|
|
2063
2480
|
);
|
|
2064
|
-
const monthStart =
|
|
2481
|
+
const monthStart = useMemo9(() => {
|
|
2065
2482
|
if (dateRange.length === 0) {
|
|
2066
2483
|
return new Date(Date.UTC((/* @__PURE__ */ new Date()).getUTCFullYear(), (/* @__PURE__ */ new Date()).getUTCMonth(), 1));
|
|
2067
2484
|
}
|
|
2068
2485
|
const firstDay = dateRange[0];
|
|
2069
2486
|
return new Date(Date.UTC(firstDay.getUTCFullYear(), firstDay.getUTCMonth(), 1));
|
|
2070
2487
|
}, [dateRange]);
|
|
2071
|
-
const todayInRange =
|
|
2488
|
+
const todayInRange = useMemo9(() => {
|
|
2072
2489
|
const now = /* @__PURE__ */ new Date();
|
|
2073
2490
|
const today = new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate()));
|
|
2074
2491
|
return dateRange.some((day) => day.getTime() === today.getTime());
|
|
2075
2492
|
}, [dateRange]);
|
|
2076
|
-
|
|
2493
|
+
useEffect5(() => {
|
|
2077
2494
|
const container = scrollContainerRef.current;
|
|
2078
2495
|
if (!container || dateRange.length === 0) return;
|
|
2079
2496
|
const now = /* @__PURE__ */ new Date();
|
|
@@ -2097,16 +2514,34 @@ var GanttChart = forwardRef(({
|
|
|
2097
2514
|
const scrollLeft = Math.round(todayOffset - containerWidth / 2 + dayWidth / 2);
|
|
2098
2515
|
container.scrollLeft = Math.max(0, scrollLeft);
|
|
2099
2516
|
}, [dateRange, dayWidth]);
|
|
2517
|
+
const scrollToTask = useCallback6((taskId) => {
|
|
2518
|
+
const container = scrollContainerRef.current;
|
|
2519
|
+
if (!container || dateRange.length === 0) return;
|
|
2520
|
+
const task = tasks.find((t) => t.id === taskId);
|
|
2521
|
+
if (!task) return;
|
|
2522
|
+
const taskStart = new Date(task.startDate);
|
|
2523
|
+
const taskStartUTC = new Date(Date.UTC(
|
|
2524
|
+
taskStart.getUTCFullYear(),
|
|
2525
|
+
taskStart.getUTCMonth(),
|
|
2526
|
+
taskStart.getUTCDate()
|
|
2527
|
+
));
|
|
2528
|
+
const taskIndex = dateRange.findIndex((day) => day.getTime() === taskStartUTC.getTime());
|
|
2529
|
+
if (taskIndex === -1) return;
|
|
2530
|
+
const taskOffset = taskIndex * dayWidth;
|
|
2531
|
+
const scrollLeft = Math.round(taskOffset - dayWidth * 2);
|
|
2532
|
+
container.scrollLeft = Math.max(0, scrollLeft);
|
|
2533
|
+
}, [tasks, dateRange, dayWidth]);
|
|
2100
2534
|
useImperativeHandle(
|
|
2101
2535
|
ref,
|
|
2102
2536
|
() => ({
|
|
2103
|
-
scrollToToday
|
|
2537
|
+
scrollToToday,
|
|
2538
|
+
scrollToTask
|
|
2104
2539
|
}),
|
|
2105
|
-
[scrollToToday]
|
|
2540
|
+
[scrollToToday, scrollToTask]
|
|
2106
2541
|
);
|
|
2107
|
-
const [dragGuideLines, setDragGuideLines] =
|
|
2108
|
-
const [draggedTaskOverride, setDraggedTaskOverride] =
|
|
2109
|
-
|
|
2542
|
+
const [dragGuideLines, setDragGuideLines] = useState6(null);
|
|
2543
|
+
const [draggedTaskOverride, setDraggedTaskOverride] = useState6(null);
|
|
2544
|
+
useEffect5(() => {
|
|
2110
2545
|
const result = validateDependencies(tasks);
|
|
2111
2546
|
setValidationResult(result);
|
|
2112
2547
|
onValidateDependencies?.(result);
|
|
@@ -2135,7 +2570,7 @@ var GanttChart = forwardRef(({
|
|
|
2135
2570
|
});
|
|
2136
2571
|
onCascade?.(allCascaded);
|
|
2137
2572
|
}, [tasks, onChange, disableConstraints, onCascade]);
|
|
2138
|
-
const dependencyOverrides =
|
|
2573
|
+
const dependencyOverrides = useMemo9(() => {
|
|
2139
2574
|
const map = new Map(cascadeOverrides);
|
|
2140
2575
|
if (draggedTaskOverride) {
|
|
2141
2576
|
map.set(draggedTaskOverride.taskId, {
|
|
@@ -2158,7 +2593,7 @@ var GanttChart = forwardRef(({
|
|
|
2158
2593
|
const handleTaskSelect = useCallback6((taskId) => {
|
|
2159
2594
|
setSelectedTaskId(taskId);
|
|
2160
2595
|
}, []);
|
|
2161
|
-
const panStateRef =
|
|
2596
|
+
const panStateRef = useRef5(null);
|
|
2162
2597
|
const handlePanStart = useCallback6((e) => {
|
|
2163
2598
|
if (e.button !== 0) return;
|
|
2164
2599
|
const target = e.target;
|
|
@@ -2180,7 +2615,7 @@ var GanttChart = forwardRef(({
|
|
|
2180
2615
|
container.style.cursor = "grabbing";
|
|
2181
2616
|
e.preventDefault();
|
|
2182
2617
|
}, []);
|
|
2183
|
-
|
|
2618
|
+
useEffect5(() => {
|
|
2184
2619
|
const handlePanMove = (e) => {
|
|
2185
2620
|
const pan = panStateRef.current;
|
|
2186
2621
|
if (!pan?.active) return;
|
|
@@ -2202,15 +2637,15 @@ var GanttChart = forwardRef(({
|
|
|
2202
2637
|
window.removeEventListener("mouseup", handlePanEnd);
|
|
2203
2638
|
};
|
|
2204
2639
|
}, []);
|
|
2205
|
-
return /* @__PURE__ */
|
|
2640
|
+
return /* @__PURE__ */ jsx14("div", { className: "gantt-container", children: /* @__PURE__ */ jsx14(
|
|
2206
2641
|
"div",
|
|
2207
2642
|
{
|
|
2208
2643
|
ref: scrollContainerRef,
|
|
2209
2644
|
className: "gantt-scrollContainer",
|
|
2210
2645
|
style: { height: containerHeight ?? "auto", cursor: "grab" },
|
|
2211
2646
|
onMouseDown: handlePanStart,
|
|
2212
|
-
children: /* @__PURE__ */
|
|
2213
|
-
/* @__PURE__ */
|
|
2647
|
+
children: /* @__PURE__ */ jsxs11("div", { className: "gantt-scrollContent", children: [
|
|
2648
|
+
/* @__PURE__ */ jsx14(
|
|
2214
2649
|
TaskList,
|
|
2215
2650
|
{
|
|
2216
2651
|
tasks,
|
|
@@ -2221,11 +2656,14 @@ var GanttChart = forwardRef(({
|
|
|
2221
2656
|
selectedTaskId: selectedTaskId ?? void 0,
|
|
2222
2657
|
onTaskSelect: handleTaskSelect,
|
|
2223
2658
|
show: showTaskList,
|
|
2224
|
-
disableTaskNameEditing
|
|
2659
|
+
disableTaskNameEditing,
|
|
2660
|
+
disableDependencyEditing,
|
|
2661
|
+
onScrollToTask: scrollToTask,
|
|
2662
|
+
onSelectedChipChange: setSelectedChip
|
|
2225
2663
|
}
|
|
2226
2664
|
),
|
|
2227
|
-
/* @__PURE__ */
|
|
2228
|
-
/* @__PURE__ */
|
|
2665
|
+
/* @__PURE__ */ jsxs11("div", { style: { minWidth: `${gridWidth}px`, flex: 1 }, children: [
|
|
2666
|
+
/* @__PURE__ */ jsx14("div", { className: "gantt-stickyHeader", style: { width: `${gridWidth}px` }, children: /* @__PURE__ */ jsx14(
|
|
2229
2667
|
TimeScaleHeader_default,
|
|
2230
2668
|
{
|
|
2231
2669
|
days: dateRange,
|
|
@@ -2233,7 +2671,7 @@ var GanttChart = forwardRef(({
|
|
|
2233
2671
|
headerHeight
|
|
2234
2672
|
}
|
|
2235
2673
|
) }),
|
|
2236
|
-
/* @__PURE__ */
|
|
2674
|
+
/* @__PURE__ */ jsxs11(
|
|
2237
2675
|
"div",
|
|
2238
2676
|
{
|
|
2239
2677
|
className: "gantt-taskArea",
|
|
@@ -2242,7 +2680,7 @@ var GanttChart = forwardRef(({
|
|
|
2242
2680
|
width: `${gridWidth}px`
|
|
2243
2681
|
},
|
|
2244
2682
|
children: [
|
|
2245
|
-
/* @__PURE__ */
|
|
2683
|
+
/* @__PURE__ */ jsx14(
|
|
2246
2684
|
GridBackground_default,
|
|
2247
2685
|
{
|
|
2248
2686
|
dateRange,
|
|
@@ -2250,8 +2688,8 @@ var GanttChart = forwardRef(({
|
|
|
2250
2688
|
totalHeight: totalGridHeight
|
|
2251
2689
|
}
|
|
2252
2690
|
),
|
|
2253
|
-
todayInRange && /* @__PURE__ */
|
|
2254
|
-
/* @__PURE__ */
|
|
2691
|
+
todayInRange && /* @__PURE__ */ jsx14(TodayIndicator_default, { monthStart, dayWidth }),
|
|
2692
|
+
/* @__PURE__ */ jsx14(
|
|
2255
2693
|
DependencyLines_default,
|
|
2256
2694
|
{
|
|
2257
2695
|
tasks,
|
|
@@ -2259,10 +2697,11 @@ var GanttChart = forwardRef(({
|
|
|
2259
2697
|
dayWidth,
|
|
2260
2698
|
rowHeight,
|
|
2261
2699
|
gridWidth,
|
|
2262
|
-
dragOverrides: dependencyOverrides
|
|
2700
|
+
dragOverrides: dependencyOverrides,
|
|
2701
|
+
selectedDep: selectedChip
|
|
2263
2702
|
}
|
|
2264
2703
|
),
|
|
2265
|
-
dragGuideLines && /* @__PURE__ */
|
|
2704
|
+
dragGuideLines && /* @__PURE__ */ jsx14(
|
|
2266
2705
|
DragGuideLines_default,
|
|
2267
2706
|
{
|
|
2268
2707
|
isDragging: dragGuideLines.isDragging,
|
|
@@ -2272,7 +2711,7 @@ var GanttChart = forwardRef(({
|
|
|
2272
2711
|
totalHeight: totalGridHeight
|
|
2273
2712
|
}
|
|
2274
2713
|
),
|
|
2275
|
-
tasks.map((task, index) => /* @__PURE__ */
|
|
2714
|
+
tasks.map((task, index) => /* @__PURE__ */ jsx14(
|
|
2276
2715
|
TaskRow_default,
|
|
2277
2716
|
{
|
|
2278
2717
|
task,
|
|
@@ -2311,7 +2750,7 @@ GanttChart.displayName = "GanttChart";
|
|
|
2311
2750
|
|
|
2312
2751
|
// src/components/ui/Button.tsx
|
|
2313
2752
|
import React12 from "react";
|
|
2314
|
-
import { jsx as
|
|
2753
|
+
import { jsx as jsx15 } from "react/jsx-runtime";
|
|
2315
2754
|
var Button = React12.forwardRef(
|
|
2316
2755
|
({ className, variant = "default", size = "default", children, ...props }, ref) => {
|
|
2317
2756
|
const classes = [
|
|
@@ -2320,7 +2759,7 @@ var Button = React12.forwardRef(
|
|
|
2320
2759
|
size !== "default" ? `gantt-btn-${size}` : "",
|
|
2321
2760
|
className || ""
|
|
2322
2761
|
].filter(Boolean).join(" ");
|
|
2323
|
-
return /* @__PURE__ */
|
|
2762
|
+
return /* @__PURE__ */ jsx15("button", { ref, className: classes, ...props, children });
|
|
2324
2763
|
}
|
|
2325
2764
|
);
|
|
2326
2765
|
Button.displayName = "Button";
|
|
@@ -2349,6 +2788,7 @@ export {
|
|
|
2349
2788
|
calculateTaskBar,
|
|
2350
2789
|
calculateWeekendBlocks,
|
|
2351
2790
|
cascadeByLinks,
|
|
2791
|
+
computeLagFromDates,
|
|
2352
2792
|
detectCycles,
|
|
2353
2793
|
detectEdgeZone,
|
|
2354
2794
|
formatDateLabel,
|