gantt-lib 0.142.2 → 0.143.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 +8 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +383 -176
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +611 -404
- package/dist/index.mjs.map +1 -1
- package/dist/styles.css +36 -8
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"use client";
|
|
4
4
|
|
|
5
5
|
// src/components/GanttChart/GanttChart.tsx
|
|
6
|
-
import { useMemo as useMemo14, useCallback as
|
|
6
|
+
import { useMemo as useMemo14, useCallback as useCallback11, useRef as useRef14, useState as useState13, useEffect as useEffect12, useImperativeHandle, forwardRef } from "react";
|
|
7
7
|
|
|
8
8
|
// src/core/scheduling/dateMath.ts
|
|
9
9
|
var DAY_MS = 24 * 60 * 60 * 1e3;
|
|
@@ -4610,6 +4610,7 @@ function createTaskPreviewPositionStore() {
|
|
|
4610
4610
|
}
|
|
4611
4611
|
function createActivityPreviewStore() {
|
|
4612
4612
|
let overridesByTask = /* @__PURE__ */ new Map();
|
|
4613
|
+
let draggedRange;
|
|
4613
4614
|
const listenersByTaskId = /* @__PURE__ */ new Map();
|
|
4614
4615
|
function notify(taskIds) {
|
|
4615
4616
|
for (const taskId of taskIds) {
|
|
@@ -4630,6 +4631,16 @@ function createActivityPreviewStore() {
|
|
|
4630
4631
|
}
|
|
4631
4632
|
};
|
|
4632
4633
|
},
|
|
4634
|
+
getActivityRange(taskId, activityId) {
|
|
4635
|
+
return draggedRange?.taskId === taskId && draggedRange.activityId === activityId ? draggedRange : void 0;
|
|
4636
|
+
},
|
|
4637
|
+
setActivityRange(taskId, activityId, range) {
|
|
4638
|
+
if (draggedRange?.taskId === taskId && draggedRange.activityId === activityId && draggedRange.startDate.getTime() === range.startDate.getTime() && draggedRange.endDate.getTime() === range.endDate.getTime()) return;
|
|
4639
|
+
const changed = /* @__PURE__ */ new Set([taskId]);
|
|
4640
|
+
if (draggedRange) changed.add(draggedRange.taskId);
|
|
4641
|
+
draggedRange = { taskId, activityId, ...range };
|
|
4642
|
+
notify(changed);
|
|
4643
|
+
},
|
|
4633
4644
|
getTaskOverrides(taskId) {
|
|
4634
4645
|
return overridesByTask.get(taskId);
|
|
4635
4646
|
},
|
|
@@ -4650,10 +4661,10 @@ function createActivityPreviewStore() {
|
|
|
4650
4661
|
notify(changedTaskIds);
|
|
4651
4662
|
},
|
|
4652
4663
|
clear() {
|
|
4653
|
-
if (overridesByTask.size === 0)
|
|
4654
|
-
return;
|
|
4655
|
-
}
|
|
4664
|
+
if (overridesByTask.size === 0 && !draggedRange) return;
|
|
4656
4665
|
const changedTaskIds = new Set(overridesByTask.keys());
|
|
4666
|
+
if (draggedRange) changedTaskIds.add(draggedRange.taskId);
|
|
4667
|
+
draggedRange = void 0;
|
|
4657
4668
|
overridesByTask = /* @__PURE__ */ new Map();
|
|
4658
4669
|
notify(changedTaskIds);
|
|
4659
4670
|
}
|
|
@@ -4999,13 +5010,6 @@ var TaskRow = React2.memo(
|
|
|
4999
5010
|
const activityDragStart = useRef2(null);
|
|
5000
5011
|
const activityConstraintRef = useRef2(null);
|
|
5001
5012
|
const [activityBlockedBy, setActivityBlockedBy] = useState2(null);
|
|
5002
|
-
const visibleActivitySegments = useMemo2(() => {
|
|
5003
|
-
if (!activityLayout) return [];
|
|
5004
|
-
const window2 = horizontalWindow;
|
|
5005
|
-
if (!window2) return activityLayout.segments;
|
|
5006
|
-
const draggedId = activityDrag?.id;
|
|
5007
|
-
return activityLayout.segments.filter((segment) => segment.id === draggedId || segment.left <= window2.endPx && segment.left + segment.width >= window2.startPx);
|
|
5008
|
-
}, [activityLayout, horizontalWindow, activityDrag?.id]);
|
|
5009
5013
|
const subscribeActivityOverrides = useCallback2(
|
|
5010
5014
|
(listener) => activityPreviewStore?.subscribeTask(task.id, listener) ?? (() => {
|
|
5011
5015
|
}),
|
|
@@ -5020,6 +5024,15 @@ var TaskRow = React2.memo(
|
|
|
5020
5024
|
getActivityOverridesSnapshot,
|
|
5021
5025
|
() => void 0
|
|
5022
5026
|
);
|
|
5027
|
+
const visibleActivitySegments = useMemo2(() => {
|
|
5028
|
+
if (!activityLayout) return [];
|
|
5029
|
+
if (!horizontalWindow) return activityLayout.segments;
|
|
5030
|
+
return activityLayout.segments.filter((segment) => {
|
|
5031
|
+
if (segment.id === activityDrag?.id) return true;
|
|
5032
|
+
const left2 = segment.left + (activityOverrides?.get(segment.id) ?? 0) * dayWidth;
|
|
5033
|
+
return left2 <= horizontalWindow.endPx && left2 + segment.width >= horizontalWindow.startPx;
|
|
5034
|
+
});
|
|
5035
|
+
}, [activityLayout, horizontalWindow, activityDrag?.id, activityOverrides, dayWidth]);
|
|
5023
5036
|
const subscribeActivityBlock = useCallback2(
|
|
5024
5037
|
(listener) => activityBlockStore?.subscribeTask(task.id, listener) ?? (() => {
|
|
5025
5038
|
}),
|
|
@@ -5145,6 +5158,11 @@ var TaskRow = React2.memo(
|
|
|
5145
5158
|
});
|
|
5146
5159
|
}
|
|
5147
5160
|
publishChainPreview(activityDrag.id, activityDrag.mode, clamped);
|
|
5161
|
+
const sourceActivity = task.activities?.find((activity) => activity.id === activityDrag.id);
|
|
5162
|
+
if (sourceActivity) activityPreviewStore?.setActivityRange?.(task.id, activityDrag.id, {
|
|
5163
|
+
startDate: shiftActivityDay(sourceActivity.startDate, activityDrag.mode === "resize-right" ? 0 : clamped),
|
|
5164
|
+
endDate: shiftActivityDay(sourceActivity.endDate, activityDrag.mode === "resize-left" ? 0 : clamped)
|
|
5165
|
+
});
|
|
5148
5166
|
};
|
|
5149
5167
|
const onUp = () => {
|
|
5150
5168
|
activityPreviewStore?.clear();
|
|
@@ -5250,6 +5268,53 @@ var TaskRow = React2.memo(
|
|
|
5250
5268
|
}
|
|
5251
5269
|
return { left: segment.left, width: segment.width + activityDrag.dayDelta * dayWidth };
|
|
5252
5270
|
};
|
|
5271
|
+
const activityLinks = useMemo2(() => {
|
|
5272
|
+
const gaps = [];
|
|
5273
|
+
const elbows = [];
|
|
5274
|
+
if (!showActivityLinks || !renderActivities || !activityLayout) return { gaps, elbows };
|
|
5275
|
+
const activities = task.activities ?? [];
|
|
5276
|
+
const segmentById = new Map(activityLayout.segments.map((segment) => [segment.id, segment]));
|
|
5277
|
+
const visibleIds = new Set(visibleActivitySegments.map((segment) => segment.id));
|
|
5278
|
+
const laneTopY = (lane) => activityTopOffset + lane * ACTIVITY_LANE_STEP + (ACTIVITY_LANE_STEP - ACTIVITY_LANE_BAR_HEIGHT) / 2;
|
|
5279
|
+
const liveRect = (segment) => {
|
|
5280
|
+
const geometry = liveActivityGeometry(segment);
|
|
5281
|
+
const chainDelta = activityOverrides?.get(segment.id) ?? 0;
|
|
5282
|
+
const left2 = geometry.left + (chainDelta !== 0 ? chainDelta * dayWidth : 0);
|
|
5283
|
+
return { left: left2, right: left2 + geometry.width };
|
|
5284
|
+
};
|
|
5285
|
+
for (let index = 0; index < activities.length - 1; index += 1) {
|
|
5286
|
+
const predecessor = segmentById.get(activities[index].id);
|
|
5287
|
+
const successor = segmentById.get(activities[index + 1].id);
|
|
5288
|
+
if (!predecessor || !successor) continue;
|
|
5289
|
+
if (!visibleIds.has(predecessor.id) || !visibleIds.has(successor.id)) continue;
|
|
5290
|
+
const lag = activities[index + 1].lag ?? 0;
|
|
5291
|
+
const predRect = liveRect(predecessor);
|
|
5292
|
+
const succRect = liveRect(successor);
|
|
5293
|
+
if (predecessor.lane === successor.lane && succRect.left >= predRect.right) {
|
|
5294
|
+
const width2 = succRect.left - predRect.right;
|
|
5295
|
+
if (width2 >= 1) {
|
|
5296
|
+
gaps.push({ key: `${predecessor.id}->${successor.id}`, left: predRect.right, width: width2, lane: predecessor.lane, lag });
|
|
5297
|
+
}
|
|
5298
|
+
continue;
|
|
5299
|
+
}
|
|
5300
|
+
const predecessorLaneTop = laneTopY(predecessor.lane);
|
|
5301
|
+
const successorLaneTop = laneTopY(successor.lane);
|
|
5302
|
+
const sameLane = predecessor.lane === successor.lane;
|
|
5303
|
+
const reverseOrder = !sameLane && successorLaneTop < predecessorLaneTop;
|
|
5304
|
+
const fromY = reverseOrder ? predecessorLaneTop + 6 : predecessorLaneTop + ACTIVITY_LANE_BAR_HEIGHT - 6;
|
|
5305
|
+
const toY = reverseOrder ? successorLaneTop + ACTIVITY_LANE_BAR_HEIGHT - 6 : successorLaneTop + (sameLane ? ACTIVITY_LANE_STEP : 0) + 6;
|
|
5306
|
+
const fromX = predRect.right;
|
|
5307
|
+
const toX = succRect.left;
|
|
5308
|
+
elbows.push({
|
|
5309
|
+
key: `${predecessor.id}->${successor.id}`,
|
|
5310
|
+
d: calculateDependencyPath({ x: fromX, y: fromY }, { x: toX, y: toY }, false),
|
|
5311
|
+
lagX: toX - 14,
|
|
5312
|
+
lagY: reverseOrder ? fromY - 4 : fromY + 12,
|
|
5313
|
+
lag
|
|
5314
|
+
});
|
|
5315
|
+
}
|
|
5316
|
+
return { gaps, elbows };
|
|
5317
|
+
}, [showActivityLinks, renderActivities, activityLayout, visibleActivitySegments, activityTopOffset, activityOverrides, activityDrag, dayWidth, task.activities]);
|
|
5253
5318
|
const activityTipData = useMemo2(() => {
|
|
5254
5319
|
if (!activityTipId || !task.activities) return null;
|
|
5255
5320
|
const activity = task.activities.find((item) => item.id === activityTipId);
|
|
@@ -5321,72 +5386,121 @@ var TaskRow = React2.memo(
|
|
|
5321
5386
|
}
|
|
5322
5387
|
}
|
|
5323
5388
|
),
|
|
5324
|
-
renderActivities && activityLayout && /* @__PURE__ */
|
|
5325
|
-
|
|
5326
|
-
|
|
5327
|
-
|
|
5328
|
-
|
|
5329
|
-
|
|
5330
|
-
|
|
5331
|
-
|
|
5332
|
-
|
|
5333
|
-
|
|
5334
|
-
|
|
5335
|
-
|
|
5336
|
-
|
|
5337
|
-
|
|
5338
|
-
|
|
5339
|
-
"data-activity-id": segment.id,
|
|
5340
|
-
className: `gantt-tr-activityBar${isDraggingActivity ? " gantt-tr-activityBar-dragging" : ""}${isBlockingActivity ? " gantt-tr-activityBar-blocking" : ""}${isAtLimit ? " gantt-tr-activityBar-atLimit" : ""}${isActiveActivity ? " gantt-tr-activityBar-active" : ""}${isDimmed ? " gantt-tr-activityBar-dimmed" : ""}${isChainHighlighted ? " gantt-tr-activityBar-chain" : ""}${activityDragEnabled ? "" : " gantt-tr-activityBar-locked"}`,
|
|
5341
|
-
style: {
|
|
5342
|
-
left: `${liveLeft}px`,
|
|
5343
|
-
width: `${live.width}px`,
|
|
5344
|
-
top: `${activityTopOffset + segment.lane * ACTIVITY_LANE_STEP + (ACTIVITY_LANE_STEP - ACTIVITY_LANE_BAR_HEIGHT) / 2}px`,
|
|
5345
|
-
height: `${ACTIVITY_LANE_BAR_HEIGHT}px`,
|
|
5346
|
-
backgroundColor: segment.color || "var(--gantt-task-bar-default-color)"
|
|
5347
|
-
},
|
|
5348
|
-
onMouseDown: (event) => {
|
|
5349
|
-
if (!activityDragEnabled) return;
|
|
5350
|
-
const activationKey = activityOwnerKey(task.id, segment.id);
|
|
5351
|
-
const isActive = activityActivationStore?.getActiveKey() === activationKey;
|
|
5352
|
-
if (activationVisualEnabled && !isActive) {
|
|
5353
|
-
activityActivationStore?.setActiveKey(activationKey);
|
|
5389
|
+
renderActivities && activityLayout && /* @__PURE__ */ jsxs2("div", { className: "gantt-tr-activityLanes", children: [
|
|
5390
|
+
activityLinks.elbows.length > 0 && /* @__PURE__ */ jsxs2("svg", { className: "gantt-tr-activityLinksSvg", width: "100%", height: "100%", "aria-hidden": "true", children: [
|
|
5391
|
+
/* @__PURE__ */ jsx2("defs", { children: /* @__PURE__ */ jsx2("marker", { id: "arrowhead", markerWidth: "8", markerHeight: "6", markerUnits: "userSpaceOnUse", refX: "7", refY: "3", orient: "auto", children: /* @__PURE__ */ jsx2("polygon", { points: "0 0, 8 3, 0 6", fill: "var(--gantt-dependency-line-color, #666666)" }) }) }),
|
|
5392
|
+
activityLinks.elbows.map((link) => /* @__PURE__ */ jsxs2("g", { children: [
|
|
5393
|
+
/* @__PURE__ */ jsx2("path", { className: "gantt-dependency-path", d: link.d, markerEnd: "url(#arrowhead)" }),
|
|
5394
|
+
showActivityLag && link.lag !== 0 && /* @__PURE__ */ jsx2(
|
|
5395
|
+
"text",
|
|
5396
|
+
{
|
|
5397
|
+
className: "gantt-dependency-lag-label",
|
|
5398
|
+
x: link.lagX,
|
|
5399
|
+
y: link.lagY,
|
|
5400
|
+
textAnchor: "middle",
|
|
5401
|
+
fontSize: "10",
|
|
5402
|
+
fill: "var(--gantt-dependency-line-color, #666666)",
|
|
5403
|
+
children: link.lag > 0 ? `+${link.lag}` : `${link.lag}`
|
|
5354
5404
|
}
|
|
5355
|
-
|
|
5356
|
-
|
|
5357
|
-
|
|
5358
|
-
|
|
5359
|
-
|
|
5360
|
-
|
|
5361
|
-
|
|
5362
|
-
|
|
5363
|
-
|
|
5405
|
+
)
|
|
5406
|
+
] }, link.key))
|
|
5407
|
+
] }),
|
|
5408
|
+
visibleActivitySegments.map((segment) => {
|
|
5409
|
+
const live = liveActivityGeometry(segment);
|
|
5410
|
+
const chainDelta = activityOverrides?.get(segment.id) ?? 0;
|
|
5411
|
+
const activityProgress = segment.progress === void 0 ? 0 : Math.min(100, Math.max(0, Math.round(segment.progress)));
|
|
5412
|
+
const liveLeft = live.left + (chainDelta !== 0 ? chainDelta * dayWidth : 0);
|
|
5413
|
+
const isDraggingActivity = activityDrag?.id === segment.id;
|
|
5414
|
+
const isBlockingActivity = blockedActivityIds?.has(segment.id) ?? false;
|
|
5415
|
+
const isAtLimit = isDraggingActivity && activityBlockedBy !== null;
|
|
5416
|
+
const isActiveActivity = activationVisualEnabled && activeActivityKey === activityOwnerKey(task.id, segment.id);
|
|
5417
|
+
const isSameWorkType = activeWork !== null && (segment.id === activeWork.id || activeWork.name !== null && segment.name === activeWork.name);
|
|
5418
|
+
const isDimmed = dimOthers && activeWork !== null && !isSameWorkType;
|
|
5419
|
+
const isChainHighlighted = highlightChain && activeWork !== null && isSameWorkType;
|
|
5420
|
+
return /* @__PURE__ */ jsxs2(
|
|
5421
|
+
"div",
|
|
5422
|
+
{
|
|
5423
|
+
"data-activity-id": segment.id,
|
|
5424
|
+
className: `gantt-tr-activityBar${isDraggingActivity ? " gantt-tr-activityBar-dragging" : ""}${isBlockingActivity ? " gantt-tr-activityBar-blocking" : ""}${isAtLimit ? " gantt-tr-activityBar-atLimit" : ""}${isActiveActivity ? " gantt-tr-activityBar-active" : ""}${isDimmed ? " gantt-tr-activityBar-dimmed" : ""}${isChainHighlighted ? " gantt-tr-activityBar-chain" : ""}${activityDragEnabled ? "" : " gantt-tr-activityBar-locked"}`,
|
|
5425
|
+
style: {
|
|
5426
|
+
left: `${liveLeft}px`,
|
|
5427
|
+
width: `${live.width}px`,
|
|
5428
|
+
top: `${activityTopOffset + segment.lane * ACTIVITY_LANE_STEP + (ACTIVITY_LANE_STEP - ACTIVITY_LANE_BAR_HEIGHT) / 2}px`,
|
|
5429
|
+
height: `${ACTIVITY_LANE_BAR_HEIGHT}px`,
|
|
5430
|
+
backgroundColor: segment.color || "var(--gantt-task-bar-default-color)"
|
|
5431
|
+
},
|
|
5432
|
+
onMouseDown: (event) => {
|
|
5433
|
+
if (!activityDragEnabled) return;
|
|
5434
|
+
const activationKey = activityOwnerKey(task.id, segment.id);
|
|
5435
|
+
const isActive = activityActivationStore?.getActiveKey() === activationKey;
|
|
5436
|
+
if (activationVisualEnabled && !isActive) {
|
|
5437
|
+
activityActivationStore?.setActiveKey(activationKey);
|
|
5438
|
+
}
|
|
5439
|
+
if (activityClickToDrag && !isActive) return;
|
|
5440
|
+
const target = event.target;
|
|
5441
|
+
const mode = target.closest(".gantt-tr-resizeHandleLeft") ? "resize-left" : target.closest(".gantt-tr-resizeHandleRight") ? "resize-right" : "move";
|
|
5442
|
+
handleActivityPointerDown(segment, mode)(event);
|
|
5443
|
+
},
|
|
5444
|
+
onMouseEnter: (event) => {
|
|
5445
|
+
if (activityDrag || activityDragOwner?.get()) return;
|
|
5446
|
+
setActivityTipPosition(anchorActivityTip(event.currentTarget.getBoundingClientRect()));
|
|
5447
|
+
setActivityTipId(segment.id);
|
|
5448
|
+
},
|
|
5449
|
+
onMouseLeave: () => {
|
|
5450
|
+
if (!activityDrag) {
|
|
5451
|
+
setActivityTipId((current) => current === segment.id ? null : current);
|
|
5452
|
+
activityTipAnchor.current = null;
|
|
5453
|
+
setActivityTipPosition(null);
|
|
5454
|
+
}
|
|
5455
|
+
},
|
|
5456
|
+
children: [
|
|
5457
|
+
activityProgress > 0 && /* @__PURE__ */ jsx2(
|
|
5458
|
+
"span",
|
|
5459
|
+
{
|
|
5460
|
+
className: "gantt-tr-activityProgress",
|
|
5461
|
+
style: { width: `${activityProgress}%` }
|
|
5462
|
+
}
|
|
5463
|
+
),
|
|
5464
|
+
/* @__PURE__ */ jsx2("span", { className: "gantt-tr-activityName", style: { color: activityTextColor(segment.color) }, children: segment.name }),
|
|
5465
|
+
activityDragEnabled && /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
5466
|
+
/* @__PURE__ */ jsx2("div", { className: "gantt-tr-resizeHandle gantt-tr-resizeHandleLeft" }),
|
|
5467
|
+
/* @__PURE__ */ jsx2("div", { className: "gantt-tr-resizeHandle gantt-tr-resizeHandleRight" })
|
|
5468
|
+
] })
|
|
5469
|
+
]
|
|
5364
5470
|
},
|
|
5365
|
-
|
|
5366
|
-
|
|
5367
|
-
|
|
5368
|
-
|
|
5369
|
-
|
|
5471
|
+
segment.id
|
|
5472
|
+
);
|
|
5473
|
+
}),
|
|
5474
|
+
activityLinks.gaps.map((gap) => /* @__PURE__ */ jsxs2(React2.Fragment, { children: [
|
|
5475
|
+
/* @__PURE__ */ jsx2(
|
|
5476
|
+
"span",
|
|
5477
|
+
{
|
|
5478
|
+
className: "gantt-tr-activityLink",
|
|
5479
|
+
"aria-hidden": "true",
|
|
5480
|
+
style: {
|
|
5481
|
+
left: `${gap.left}px`,
|
|
5482
|
+
width: `${gap.width}px`,
|
|
5483
|
+
top: `${activityTopOffset + gap.lane * ACTIVITY_LANE_STEP + ACTIVITY_LANE_STEP / 2}px`
|
|
5370
5484
|
}
|
|
5371
|
-
}
|
|
5372
|
-
|
|
5373
|
-
|
|
5374
|
-
|
|
5375
|
-
|
|
5376
|
-
|
|
5377
|
-
|
|
5378
|
-
|
|
5379
|
-
|
|
5380
|
-
|
|
5381
|
-
|
|
5382
|
-
|
|
5383
|
-
|
|
5384
|
-
|
|
5385
|
-
|
|
5386
|
-
|
|
5387
|
-
|
|
5388
|
-
)
|
|
5389
|
-
|
|
5485
|
+
}
|
|
5486
|
+
),
|
|
5487
|
+
showActivityLag && gap.lag > 0 && /* @__PURE__ */ jsxs2(
|
|
5488
|
+
"span",
|
|
5489
|
+
{
|
|
5490
|
+
className: "gantt-tr-activityLag",
|
|
5491
|
+
title: `\u0417\u0430\u0437\u043E\u0440 ${gap.lag} \u0434`,
|
|
5492
|
+
style: {
|
|
5493
|
+
left: `${gap.left + gap.width - 14}px`,
|
|
5494
|
+
top: `${activityTopOffset + gap.lane * ACTIVITY_LANE_STEP + ACTIVITY_LANE_STEP / 2}px`
|
|
5495
|
+
},
|
|
5496
|
+
children: [
|
|
5497
|
+
"+",
|
|
5498
|
+
gap.lag
|
|
5499
|
+
]
|
|
5500
|
+
}
|
|
5501
|
+
)
|
|
5502
|
+
] }, gap.key))
|
|
5503
|
+
] }),
|
|
5390
5504
|
!renderActivities && /* @__PURE__ */ jsxs2(
|
|
5391
5505
|
"div",
|
|
5392
5506
|
{
|
|
@@ -5929,7 +6043,7 @@ var DragGuideLines = ({
|
|
|
5929
6043
|
var DragGuideLines_default = DragGuideLines;
|
|
5930
6044
|
|
|
5931
6045
|
// src/components/DependencyLines/DependencyLines.tsx
|
|
5932
|
-
import React6, { useId, useMemo as useMemo6, useState as useState3 } from "react";
|
|
6046
|
+
import React6, { useCallback as useCallback3, useId, useMemo as useMemo6, useState as useState3 } from "react";
|
|
5933
6047
|
import { Fragment as Fragment3, jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
5934
6048
|
function isTaskHidden(taskId, collapsedParentIds, taskMap) {
|
|
5935
6049
|
const task = taskMap.get(taskId);
|
|
@@ -5959,6 +6073,74 @@ function areBothHiddenInSameParent(predecessorId, successorId, collapsedParentId
|
|
|
5959
6073
|
return predVisibleAncestor.id === succVisibleAncestor.id;
|
|
5960
6074
|
}
|
|
5961
6075
|
var EMPTY_COLLAPSED_PARENT_IDS = /* @__PURE__ */ new Set();
|
|
6076
|
+
var DependencyLineView = React6.memo(function DependencyLineView2({
|
|
6077
|
+
line,
|
|
6078
|
+
hovered,
|
|
6079
|
+
selected,
|
|
6080
|
+
showLag,
|
|
6081
|
+
markerPrefix,
|
|
6082
|
+
onLineHover,
|
|
6083
|
+
onLineLeave,
|
|
6084
|
+
onDependencyClick
|
|
6085
|
+
}) {
|
|
6086
|
+
const { id, predecessorId, successorId, linkType, path, hasCycle, lag, toX, fromY, reverseOrder, isVirtual, isCoupling } = line;
|
|
6087
|
+
const interactive = !isCoupling && onDependencyClick !== void 0;
|
|
6088
|
+
let pathClassName = "gantt-dependency-path";
|
|
6089
|
+
if (selected) pathClassName += " gantt-dependency-selected";
|
|
6090
|
+
else if (hasCycle) pathClassName += " gantt-dependency-cycle";
|
|
6091
|
+
else if (line.isCritical) pathClassName += " gantt-dependency-critical";
|
|
6092
|
+
if (isVirtual && !selected) pathClassName += " gantt-dependency-virtual";
|
|
6093
|
+
let markerEnd;
|
|
6094
|
+
if (hovered) markerEnd = `url(#${markerPrefix}-arrowhead-hover)`;
|
|
6095
|
+
else if (selected) markerEnd = `url(#${markerPrefix}-arrowhead-selected)`;
|
|
6096
|
+
else if (hasCycle) markerEnd = `url(#${markerPrefix}-arrowhead-cycle)`;
|
|
6097
|
+
else if (line.isCritical) markerEnd = `url(#${markerPrefix}-arrowhead-critical)`;
|
|
6098
|
+
else markerEnd = `url(#${markerPrefix}-arrowhead)`;
|
|
6099
|
+
const lagColor = selected ? "#ef4444" : hasCycle ? "var(--gantt-dependency-cycle-color, #ef4444)" : line.isCritical ? "var(--gantt-critical-path-color, #dc2626)" : "var(--gantt-dependency-line-color, #666666)";
|
|
6100
|
+
return /* @__PURE__ */ jsxs5(React6.Fragment, { children: [
|
|
6101
|
+
/* @__PURE__ */ jsx7(
|
|
6102
|
+
"g",
|
|
6103
|
+
{
|
|
6104
|
+
className: `gantt-dependency-line${interactive ? "" : " gantt-dependency-line-static"}${hovered && interactive ? " gantt-dependency-line-hovered" : ""}`,
|
|
6105
|
+
onPointerEnter: interactive ? () => onLineHover(id) : void 0,
|
|
6106
|
+
onPointerLeave: interactive ? () => onLineLeave(id) : void 0,
|
|
6107
|
+
onClick: interactive ? (event) => {
|
|
6108
|
+
event.stopPropagation();
|
|
6109
|
+
onDependencyClick?.({
|
|
6110
|
+
predecessorId,
|
|
6111
|
+
successorId,
|
|
6112
|
+
linkType,
|
|
6113
|
+
x: toX,
|
|
6114
|
+
y: reverseOrder ? fromY - 4 : fromY + 12
|
|
6115
|
+
});
|
|
6116
|
+
} : void 0,
|
|
6117
|
+
role: interactive ? "button" : void 0,
|
|
6118
|
+
"aria-label": interactive ? `\u0421\u0432\u044F\u0437\u044C ${linkType}` : void 0,
|
|
6119
|
+
children: isCoupling ? /* @__PURE__ */ jsx7("line", { x1: toX - 4.5, y1: fromY, x2: toX + 4.5, y2: fromY, className: `${pathClassName} gantt-dependency-coupling` }) : /* @__PURE__ */ jsxs5(Fragment3, { children: [
|
|
6120
|
+
interactive && /* @__PURE__ */ jsx7("path", { d: path, className: "gantt-dependency-hit-area" }),
|
|
6121
|
+
/* @__PURE__ */ jsx7("path", { d: path, className: pathClassName, markerEnd })
|
|
6122
|
+
] })
|
|
6123
|
+
}
|
|
6124
|
+
),
|
|
6125
|
+
showLag && lag !== 0 && /* @__PURE__ */ jsx7(
|
|
6126
|
+
"text",
|
|
6127
|
+
{
|
|
6128
|
+
className: "gantt-dependency-lag-label",
|
|
6129
|
+
x: lag < 0 ? toX + 14 : toX - 14,
|
|
6130
|
+
y: reverseOrder ? fromY - 4 : fromY + 12,
|
|
6131
|
+
textAnchor: "middle",
|
|
6132
|
+
fontSize: "10",
|
|
6133
|
+
fill: lagColor,
|
|
6134
|
+
children: lag > 0 ? `+${lag}` : `${lag}`
|
|
6135
|
+
}
|
|
6136
|
+
)
|
|
6137
|
+
] });
|
|
6138
|
+
}, (prev, next) => (
|
|
6139
|
+
// Сравнение по значению, а не по ссылке линии: пересчёт геометрии на каждом
|
|
6140
|
+
// бакете вертикальной прокрутки создаёт новые объекты линий с той же
|
|
6141
|
+
// геометрией — пере-рендерить их нельзя, иначе пан дёргается.
|
|
6142
|
+
prev.line.id === next.line.id && prev.line.predecessorId === next.line.predecessorId && prev.line.successorId === next.line.successorId && prev.line.linkType === next.line.linkType && prev.line.path === next.line.path && prev.line.hasCycle === next.line.hasCycle && prev.line.lag === next.line.lag && prev.line.toX === next.line.toX && prev.line.fromY === next.line.fromY && prev.line.reverseOrder === next.line.reverseOrder && prev.line.isVirtual === next.line.isVirtual && prev.line.isCritical === next.line.isCritical && prev.line.isCoupling === next.line.isCoupling && prev.hovered === next.hovered && prev.selected === next.selected && prev.showLag === next.showLag && prev.markerPrefix === next.markerPrefix && prev.onLineHover === next.onLineHover && prev.onLineLeave === next.onLineLeave && prev.onDependencyClick === next.onDependencyClick
|
|
6143
|
+
));
|
|
5962
6144
|
var DependencyLines = React6.memo(({
|
|
5963
6145
|
tasks,
|
|
5964
6146
|
allTasks,
|
|
@@ -5974,6 +6156,7 @@ var DependencyLines = React6.memo(({
|
|
|
5974
6156
|
dragOverrides,
|
|
5975
6157
|
selectedDep,
|
|
5976
6158
|
criticalTaskIds,
|
|
6159
|
+
cycleTaskIds,
|
|
5977
6160
|
showLag = true,
|
|
5978
6161
|
activityEndpoints = false,
|
|
5979
6162
|
businessDays = true,
|
|
@@ -5984,13 +6167,16 @@ var DependencyLines = React6.memo(({
|
|
|
5984
6167
|
const markerPrefix = `gantt-dependency-${useId().replace(/[^a-zA-Z0-9_-]/g, "")}`;
|
|
5985
6168
|
const markerId = (kind) => `${markerPrefix}-${kind}`;
|
|
5986
6169
|
const [hoveredLineId, setHoveredLineId] = useState3(null);
|
|
6170
|
+
const handleLineHover = useCallback3((id) => setHoveredLineId(id), []);
|
|
6171
|
+
const handleLineLeave = useCallback3((id) => setHoveredLineId((current) => current === id ? null : current), []);
|
|
5987
6172
|
const tasksForPositions = allTasks ?? tasks;
|
|
6173
|
+
const geometryTasks = activityEndpoints ? tasksForPositions : tasks;
|
|
5988
6174
|
const { taskPositions, taskIndices, hiddenTaskIds } = useMemo6(() => {
|
|
5989
6175
|
const positions = /* @__PURE__ */ new Map();
|
|
5990
6176
|
const indices = /* @__PURE__ */ new Map();
|
|
5991
6177
|
const hidden = /* @__PURE__ */ new Set();
|
|
5992
6178
|
const taskMap = new Map(tasksForPositions.map((t) => [t.id, t]));
|
|
5993
|
-
|
|
6179
|
+
geometryTasks.forEach((task, index) => {
|
|
5994
6180
|
const override = dragOverrides?.get(task.id);
|
|
5995
6181
|
const computed = resolveTaskHorizontalGeometry(task, monthStart, dayWidth, override);
|
|
5996
6182
|
const rowIndex = rowIndexByTaskId?.get(task.id) ?? index;
|
|
@@ -6046,18 +6232,19 @@ var DependencyLines = React6.memo(({
|
|
|
6046
6232
|
}
|
|
6047
6233
|
}
|
|
6048
6234
|
return { taskPositions: positions, taskIndices: indices, hiddenTaskIds: hidden };
|
|
6049
|
-
}, [
|
|
6235
|
+
}, [geometryTasks, tasksForPositions, allTasks, collapsedParentIds, monthStart, dayWidth, rowHeight, rowTops, rowHeights, dragOverrides, rowIndexByTaskId]);
|
|
6050
6236
|
const tasksForCycleDetection = allTasks ?? tasks;
|
|
6051
6237
|
const cycleInfo = useMemo6(() => {
|
|
6238
|
+
if (cycleTaskIds) return cycleTaskIds;
|
|
6052
6239
|
const result = detectCycles(tasksForCycleDetection);
|
|
6053
|
-
const
|
|
6054
|
-
return
|
|
6055
|
-
}, [tasksForCycleDetection]);
|
|
6240
|
+
const detectedCycleIds = new Set(result.cyclePath || []);
|
|
6241
|
+
return detectedCycleIds;
|
|
6242
|
+
}, [tasksForCycleDetection, cycleTaskIds]);
|
|
6056
6243
|
const lines = useMemo6(() => {
|
|
6057
|
-
const tasksForEdges = allTasks ??
|
|
6244
|
+
const tasksForEdges = allTasks ?? geometryTasks;
|
|
6058
6245
|
const taskMap = new Map(tasksForEdges.map((task) => [task.id, task]));
|
|
6059
6246
|
const positionedTaskIds = Array.from(taskPositions.keys());
|
|
6060
|
-
const renderedTaskIdSet = new Set(
|
|
6247
|
+
const renderedTaskIdSet = new Set(geometryTasks.map((t) => t.id));
|
|
6061
6248
|
const lines2 = [];
|
|
6062
6249
|
for (const successorId of positionedTaskIds) {
|
|
6063
6250
|
const successorTaskForEdges = taskMap.get(successorId);
|
|
@@ -6152,16 +6339,20 @@ var DependencyLines = React6.memo(({
|
|
|
6152
6339
|
}
|
|
6153
6340
|
}
|
|
6154
6341
|
return lines2;
|
|
6155
|
-
}, [
|
|
6342
|
+
}, [geometryTasks, allTasks, taskPositions, taskIndices, cycleInfo, collapsedParentIds, criticalTaskIds, activityEndpoints]);
|
|
6156
6343
|
const visibleLines = useMemo6(() => {
|
|
6157
|
-
|
|
6158
|
-
return lines.filter((line) =>
|
|
6159
|
-
|
|
6344
|
+
const renderedIds = activityEndpoints ? new Set(tasks.map((task) => task.id)) : void 0;
|
|
6345
|
+
return lines.filter((line) => {
|
|
6346
|
+
if (renderedIds && !renderedIds.has(line.predecessorId) && !renderedIds.has(line.successorId)) return false;
|
|
6347
|
+
return !horizontalWindow || Math.max(line.fromX, line.toX) >= horizontalWindow.startPx && Math.min(line.fromX, line.toX) <= horizontalWindow.endPx;
|
|
6348
|
+
});
|
|
6349
|
+
}, [lines, activityEndpoints, tasks, horizontalWindow?.startPx, horizontalWindow?.endPx]);
|
|
6160
6350
|
const svgHeight = totalHeight ?? tasks.length * rowHeight;
|
|
6351
|
+
const interactive = onDependencyClick !== void 0;
|
|
6161
6352
|
return /* @__PURE__ */ jsxs5(
|
|
6162
6353
|
"svg",
|
|
6163
6354
|
{
|
|
6164
|
-
className: "gantt-dependencies-svg"
|
|
6355
|
+
className: `gantt-dependencies-svg${interactive ? "" : " gantt-dependencies-svg-static"}`,
|
|
6165
6356
|
"data-testid": "dependency-lines-svg",
|
|
6166
6357
|
width: gridWidth,
|
|
6167
6358
|
height: svgHeight,
|
|
@@ -6264,63 +6455,22 @@ var DependencyLines = React6.memo(({
|
|
|
6264
6455
|
}
|
|
6265
6456
|
)
|
|
6266
6457
|
] }),
|
|
6267
|
-
visibleLines.map((
|
|
6268
|
-
const
|
|
6269
|
-
|
|
6270
|
-
|
|
6271
|
-
|
|
6272
|
-
|
|
6273
|
-
|
|
6274
|
-
|
|
6275
|
-
|
|
6276
|
-
|
|
6277
|
-
|
|
6278
|
-
|
|
6279
|
-
|
|
6280
|
-
|
|
6281
|
-
|
|
6282
|
-
|
|
6283
|
-
/* @__PURE__ */ jsx7(
|
|
6284
|
-
"g",
|
|
6285
|
-
{
|
|
6286
|
-
className: `gantt-dependency-line${isHovered ? " gantt-dependency-line-hovered" : ""}`,
|
|
6287
|
-
onPointerEnter: () => setHoveredLineId(id),
|
|
6288
|
-
onPointerLeave: () => setHoveredLineId((current) => current === id ? null : current),
|
|
6289
|
-
onClick: (event) => {
|
|
6290
|
-
event.stopPropagation();
|
|
6291
|
-
onDependencyClick?.({
|
|
6292
|
-
predecessorId,
|
|
6293
|
-
successorId,
|
|
6294
|
-
linkType,
|
|
6295
|
-
x: toX,
|
|
6296
|
-
y: reverseOrder ? fromY - 4 : fromY + 12
|
|
6297
|
-
});
|
|
6298
|
-
},
|
|
6299
|
-
role: "button",
|
|
6300
|
-
"aria-label": `\u0421\u0432\u044F\u0437\u044C ${linkType}`,
|
|
6301
|
-
children: isCoupling ? /* @__PURE__ */ jsxs5(Fragment3, { children: [
|
|
6302
|
-
/* @__PURE__ */ jsx7("title", { children: "\u041F\u043E\u0441\u043B\u0435 \u043E\u043A\u043E\u043D\u0447\u0430\u043D\u0438\u044F \xB7 \u0431\u0435\u0437 \u043B\u0430\u0433\u0430" }),
|
|
6303
|
-
/* @__PURE__ */ jsx7("circle", { cx: toX, cy: fromY, r: 12, className: "gantt-dependency-coupling-hit-area" }),
|
|
6304
|
-
/* @__PURE__ */ jsx7("circle", { cx: toX, cy: fromY, r: 4, className: `${pathClassName} gantt-dependency-coupling` })
|
|
6305
|
-
] }) : /* @__PURE__ */ jsxs5(Fragment3, { children: [
|
|
6306
|
-
/* @__PURE__ */ jsx7("path", { d: path, className: "gantt-dependency-hit-area" }),
|
|
6307
|
-
/* @__PURE__ */ jsx7("path", { d: path, className: pathClassName, markerEnd })
|
|
6308
|
-
] })
|
|
6309
|
-
}
|
|
6310
|
-
),
|
|
6311
|
-
showLag && lag !== 0 && /* @__PURE__ */ jsx7(
|
|
6312
|
-
"text",
|
|
6313
|
-
{
|
|
6314
|
-
className: "gantt-dependency-lag-label",
|
|
6315
|
-
x: lag < 0 ? toX + 14 : toX - 14,
|
|
6316
|
-
y: reverseOrder ? fromY - 4 : fromY + 12,
|
|
6317
|
-
textAnchor: "middle",
|
|
6318
|
-
fontSize: "10",
|
|
6319
|
-
fill: lagColor,
|
|
6320
|
-
children: lag > 0 ? `+${lag}` : `${lag}`
|
|
6321
|
-
}
|
|
6322
|
-
)
|
|
6323
|
-
] }, id);
|
|
6458
|
+
visibleLines.map((line) => {
|
|
6459
|
+
const isSelected = selectedDep != null && line.id === `${selectedDep.predecessorId}-${selectedDep.successorId}-${selectedDep.linkType}`;
|
|
6460
|
+
return /* @__PURE__ */ jsx7(
|
|
6461
|
+
DependencyLineView,
|
|
6462
|
+
{
|
|
6463
|
+
line,
|
|
6464
|
+
hovered: hoveredLineId === line.id,
|
|
6465
|
+
selected: isSelected,
|
|
6466
|
+
showLag,
|
|
6467
|
+
markerPrefix,
|
|
6468
|
+
onLineHover: handleLineHover,
|
|
6469
|
+
onLineLeave: handleLineLeave,
|
|
6470
|
+
onDependencyClick
|
|
6471
|
+
},
|
|
6472
|
+
line.id
|
|
6473
|
+
);
|
|
6324
6474
|
})
|
|
6325
6475
|
]
|
|
6326
6476
|
}
|
|
@@ -6330,9 +6480,17 @@ DependencyLines.displayName = "DependencyLines";
|
|
|
6330
6480
|
var DependencyLines_default = DependencyLines;
|
|
6331
6481
|
|
|
6332
6482
|
// src/components/DependencyLines/ActivityDependencyLines.tsx
|
|
6333
|
-
import { useEffect as useEffect3, useMemo as useMemo7, useReducer } from "react";
|
|
6483
|
+
import { useEffect as useEffect3, useMemo as useMemo7, useReducer, useRef as useRef3 } from "react";
|
|
6334
6484
|
import { jsx as jsx8 } from "react/jsx-runtime";
|
|
6335
6485
|
var activityKey = (taskId, activityId) => JSON.stringify([taskId, activityId]);
|
|
6486
|
+
var sameDependencies = (left, right) => {
|
|
6487
|
+
if (left === right) return true;
|
|
6488
|
+
if (!left || !right || left.length !== right.length) return false;
|
|
6489
|
+
return left.every((dep, index) => {
|
|
6490
|
+
const other = right[index];
|
|
6491
|
+
return dep.taskId === other.taskId && dep.type === other.type && dep.lag === other.lag && dep.hidden === other.hidden;
|
|
6492
|
+
});
|
|
6493
|
+
};
|
|
6336
6494
|
function ActivityDependencyLines(props) {
|
|
6337
6495
|
const { tasks, dependencies, monthStart, dayWidth, previewStore } = props;
|
|
6338
6496
|
const [previewVersion, refresh] = useReducer((value) => value + 1, 0);
|
|
@@ -6340,15 +6498,29 @@ function ActivityDependencyLines(props) {
|
|
|
6340
6498
|
const cleanups = tasks.filter((task) => task.activities?.length).map((task) => previewStore?.subscribeTask(task.id, refresh));
|
|
6341
6499
|
return () => cleanups.forEach((cleanup) => cleanup?.());
|
|
6342
6500
|
}, [tasks, previewStore]);
|
|
6501
|
+
const cycleTaskIds = useMemo7(() => {
|
|
6502
|
+
const incoming = /* @__PURE__ */ new Map();
|
|
6503
|
+
for (const edge of dependencies) {
|
|
6504
|
+
const id = activityKey(edge.successorTaskId, edge.successorActivityId);
|
|
6505
|
+
const values = incoming.get(id) ?? [];
|
|
6506
|
+
values.push({ taskId: activityKey(edge.predecessorTaskId, edge.predecessorActivityId), type: edge.type, lag: edge.lag ?? 0 });
|
|
6507
|
+
incoming.set(id, values);
|
|
6508
|
+
}
|
|
6509
|
+
const nodes = tasks.flatMap((task) => (task.activities ?? []).map((activity) => ({ id: activityKey(task.id, activity.id), name: activity.name, startDate: activity.startDate, endDate: activity.endDate, dependencies: incoming.get(activityKey(task.id, activity.id)) })));
|
|
6510
|
+
return new Set(detectCycles(nodes).cyclePath ?? []);
|
|
6511
|
+
}, [tasks, dependencies]);
|
|
6512
|
+
const layoutCacheRef = useRef3(/* @__PURE__ */ new Map());
|
|
6343
6513
|
const layout = useMemo7(() => {
|
|
6344
|
-
const flattened = [],
|
|
6514
|
+
const flattened = [], tops = [], heights = [];
|
|
6515
|
+
const nodesByTaskId = /* @__PURE__ */ new Map();
|
|
6345
6516
|
const indices = /* @__PURE__ */ new Map();
|
|
6346
6517
|
const neededRows = /* @__PURE__ */ new Set();
|
|
6347
6518
|
const incoming = /* @__PURE__ */ new Map();
|
|
6348
6519
|
const selected = props.highlight ? new Set(props.highlight.activities.map((activity) => activityKey(activity.taskId, activity.activityId))) : void 0;
|
|
6349
6520
|
const highlightMode = props.highlight?.mode ?? "chain";
|
|
6350
6521
|
for (const edge of dependencies) {
|
|
6351
|
-
|
|
6522
|
+
const isCrossRow = edge.predecessorTaskId !== edge.successorTaskId;
|
|
6523
|
+
if (isCrossRow && !props.highlight) continue;
|
|
6352
6524
|
if (selected) {
|
|
6353
6525
|
const fromSelected = selected.has(activityKey(edge.predecessorTaskId, edge.predecessorActivityId));
|
|
6354
6526
|
const toSelected = selected.has(activityKey(edge.successorTaskId, edge.successorActivityId));
|
|
@@ -6361,33 +6533,75 @@ function ActivityDependencyLines(props) {
|
|
|
6361
6533
|
neededRows.add(edge.successorTaskId);
|
|
6362
6534
|
const id = activityKey(edge.successorTaskId, edge.successorActivityId);
|
|
6363
6535
|
const values = incoming.get(id) ?? [];
|
|
6364
|
-
values.push({ taskId: activityKey(edge.predecessorTaskId, edge.predecessorActivityId), type: edge.type, lag: edge.lag });
|
|
6536
|
+
values.push({ taskId: activityKey(edge.predecessorTaskId, edge.predecessorActivityId), type: edge.type, lag: edge.lag ?? 0 });
|
|
6365
6537
|
incoming.set(id, values);
|
|
6366
6538
|
}
|
|
6539
|
+
const monthStartMs = monthStart.getTime();
|
|
6540
|
+
const cache = layoutCacheRef.current;
|
|
6367
6541
|
for (const task of tasks) {
|
|
6368
6542
|
if (!neededRows.has(task.id)) continue;
|
|
6369
6543
|
const row = props.rowIndexByTaskId.get(task.id);
|
|
6370
6544
|
if (row === void 0 || !task.activities?.length) continue;
|
|
6371
6545
|
const height = props.rowHeights[row] ?? props.rowHeight;
|
|
6372
6546
|
if (height < props.rowHeight) continue;
|
|
6373
|
-
const
|
|
6374
|
-
const
|
|
6375
|
-
|
|
6376
|
-
for (const activity of
|
|
6377
|
-
const
|
|
6378
|
-
|
|
6379
|
-
|
|
6380
|
-
|
|
6547
|
+
const activities = task.activities;
|
|
6548
|
+
const overrides = previewStore?.getTaskOverrides(task.id);
|
|
6549
|
+
let range;
|
|
6550
|
+
for (const activity of activities) {
|
|
6551
|
+
const current = previewStore?.getActivityRange?.(task.id, activity.id);
|
|
6552
|
+
if (current) {
|
|
6553
|
+
range = current;
|
|
6554
|
+
break;
|
|
6555
|
+
}
|
|
6556
|
+
}
|
|
6557
|
+
let entry = cache.get(task.id);
|
|
6558
|
+
const reusable = entry && entry.activities === activities && entry.monthStartMs === monthStartMs && entry.dayWidth === dayWidth && entry.overrides === overrides && entry.range === range && entry.nodes.length === activities.length && entry.nodes.every((node, index) => node.name === activities[index].name && node.startDate === activities[index].startDate && node.endDate === activities[index].endDate && sameDependencies(node.dependencies, incoming.get(node.id)));
|
|
6559
|
+
if (!entry || !reusable) {
|
|
6560
|
+
const liveActivities = activities.map((activity) => {
|
|
6561
|
+
const activityRange = previewStore?.getActivityRange?.(task.id, activity.id);
|
|
6562
|
+
if (activityRange) return { ...activity, startDate: activityRange.startDate, endDate: activityRange.endDate };
|
|
6563
|
+
const delta = overrides?.get(activity.id) ?? 0;
|
|
6564
|
+
if (delta === 0) return activity;
|
|
6565
|
+
return { ...activity, startDate: shiftActivityDate(activity.startDate, delta), endDate: shiftActivityDate(activity.endDate, delta) };
|
|
6566
|
+
});
|
|
6567
|
+
const packed = computeActivityLanes(liveActivities, monthStart, dayWidth);
|
|
6568
|
+
const lanes = new Map(packed.segments.map((segment) => [segment.id, segment.lane]));
|
|
6569
|
+
const rawIds = liveActivities.map((activity) => activity.id);
|
|
6570
|
+
const nodes = liveActivities.map((activity) => ({
|
|
6571
|
+
id: activityKey(task.id, activity.id),
|
|
6572
|
+
name: activity.name,
|
|
6573
|
+
startDate: activity.startDate,
|
|
6574
|
+
endDate: activity.endDate,
|
|
6575
|
+
dependencies: incoming.get(activityKey(task.id, activity.id))
|
|
6576
|
+
}));
|
|
6577
|
+
entry = { activities, monthStartMs, dayWidth, overrides, range, laneCount: packed.laneCount, lanes, rawIds, nodes };
|
|
6578
|
+
cache.set(task.id, entry);
|
|
6579
|
+
}
|
|
6580
|
+
const offset = Math.max(0, (height - entry.laneCount * ACTIVITY_LANE_STEP) / 2);
|
|
6581
|
+
nodesByTaskId.set(task.id, entry.nodes);
|
|
6582
|
+
entry.nodes.forEach((node, nodeIndex) => {
|
|
6583
|
+
const lane = entry.lanes.get(entry.rawIds[nodeIndex]) ?? 0;
|
|
6584
|
+
const index = flattened.length;
|
|
6381
6585
|
flattened.push(node);
|
|
6382
|
-
|
|
6383
|
-
|
|
6384
|
-
tops.push((props.rowTops[row] ?? row * props.rowHeight) + offset + segment.lane * ACTIVITY_LANE_STEP + (ACTIVITY_LANE_STEP - ACTIVITY_LANE_BAR_HEIGHT) / 2);
|
|
6586
|
+
indices.set(node.id, index);
|
|
6587
|
+
tops.push((props.rowTops[row] ?? row * props.rowHeight) + offset + lane * ACTIVITY_LANE_STEP + (ACTIVITY_LANE_STEP - ACTIVITY_LANE_BAR_HEIGHT) / 2);
|
|
6385
6588
|
heights.push(ACTIVITY_LANE_BAR_HEIGHT);
|
|
6386
|
-
}
|
|
6589
|
+
});
|
|
6590
|
+
}
|
|
6591
|
+
for (const taskId of cache.keys()) {
|
|
6592
|
+
if (!nodesByTaskId.has(taskId)) cache.delete(taskId);
|
|
6387
6593
|
}
|
|
6388
|
-
return { flattened,
|
|
6389
|
-
}, [tasks, dependencies, props.highlight, monthStart, dayWidth, props.rowIndexByTaskId, props.rowTops, props.rowHeights, props.rowHeight,
|
|
6390
|
-
|
|
6594
|
+
return { flattened, nodesByTaskId, indices, tops, heights };
|
|
6595
|
+
}, [tasks, dependencies, props.highlight, monthStart, dayWidth, props.rowIndexByTaskId, props.rowTops, props.rowHeights, props.rowHeight, previewStore, previewVersion]);
|
|
6596
|
+
const rendered = useMemo7(() => {
|
|
6597
|
+
const nodes = [];
|
|
6598
|
+
for (const taskId of props.renderedTaskIds) {
|
|
6599
|
+
const rowNodes = layout.nodesByTaskId.get(taskId);
|
|
6600
|
+
if (rowNodes) nodes.push(...rowNodes);
|
|
6601
|
+
}
|
|
6602
|
+
return nodes;
|
|
6603
|
+
}, [layout, props.renderedTaskIds]);
|
|
6604
|
+
return /* @__PURE__ */ jsx8(DependencyLines, { tasks: rendered, allTasks: layout.flattened, monthStart, dayWidth, rowHeight: ACTIVITY_LANE_BAR_HEIGHT, gridWidth: props.gridWidth, totalHeight: props.totalHeight, rowIndexByTaskId: layout.indices, rowTops: layout.tops, rowHeights: layout.heights, horizontalWindow: props.horizontalWindow, showLag: props.showLag, cycleTaskIds, activityEndpoints: true });
|
|
6391
6605
|
}
|
|
6392
6606
|
|
|
6393
6607
|
// src/components/DependencyCreationOverlay/DependencyCreationOverlay.tsx
|
|
@@ -6447,7 +6661,7 @@ var DependencyCreationOverlay = ({ drag, width, height }) => {
|
|
|
6447
6661
|
};
|
|
6448
6662
|
|
|
6449
6663
|
// src/components/TaskList/TaskList.tsx
|
|
6450
|
-
import React14, { useMemo as useMemo10, useCallback as
|
|
6664
|
+
import React14, { useMemo as useMemo10, useCallback as useCallback7, useState as useState8, useEffect as useEffect8, useRef as useRef9 } from "react";
|
|
6451
6665
|
|
|
6452
6666
|
// src/utils/taskListReorder.ts
|
|
6453
6667
|
function getDescendantIds(taskId, tasks) {
|
|
@@ -6653,9 +6867,9 @@ var PopoverContent = ({
|
|
|
6653
6867
|
// src/components/TaskList/TaskListRow.tsx
|
|
6654
6868
|
import React11, {
|
|
6655
6869
|
useState as useState6,
|
|
6656
|
-
useRef as
|
|
6870
|
+
useRef as useRef6,
|
|
6657
6871
|
useEffect as useEffect6,
|
|
6658
|
-
useCallback as
|
|
6872
|
+
useCallback as useCallback6,
|
|
6659
6873
|
useMemo as useMemo9
|
|
6660
6874
|
} from "react";
|
|
6661
6875
|
|
|
@@ -6677,15 +6891,15 @@ var Input = React8.forwardRef(
|
|
|
6677
6891
|
Input.displayName = "Input";
|
|
6678
6892
|
|
|
6679
6893
|
// src/components/ui/DatePicker.tsx
|
|
6680
|
-
import { useState as useState5, useCallback as
|
|
6894
|
+
import { useState as useState5, useCallback as useCallback5, useEffect as useEffect5, useRef as useRef5 } from "react";
|
|
6681
6895
|
import { format as format3, isValid, parse, addDays, addMonths as addMonths2, addYears, subMonths as subMonths2, subYears, subDays } from "date-fns";
|
|
6682
6896
|
|
|
6683
6897
|
// src/components/ui/Calendar.tsx
|
|
6684
6898
|
import {
|
|
6685
6899
|
useState as useState4,
|
|
6686
|
-
useRef as
|
|
6900
|
+
useRef as useRef4,
|
|
6687
6901
|
useEffect as useEffect4,
|
|
6688
|
-
useCallback as
|
|
6902
|
+
useCallback as useCallback4,
|
|
6689
6903
|
useMemo as useMemo8
|
|
6690
6904
|
} from "react";
|
|
6691
6905
|
import {
|
|
@@ -6719,7 +6933,7 @@ var Calendar = ({
|
|
|
6719
6933
|
disabled = false,
|
|
6720
6934
|
isWeekend: isWeekendProp
|
|
6721
6935
|
}) => {
|
|
6722
|
-
const scrollRef =
|
|
6936
|
+
const scrollRef = useRef4(null);
|
|
6723
6937
|
const initialMonth = useMemo8(
|
|
6724
6938
|
() => startOfMonth(initialDate ?? selected ?? /* @__PURE__ */ new Date()),
|
|
6725
6939
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
@@ -6730,7 +6944,7 @@ var Calendar = ({
|
|
|
6730
6944
|
initialMonth,
|
|
6731
6945
|
addMonths(initialMonth, 1)
|
|
6732
6946
|
]);
|
|
6733
|
-
const loadMoreMonths =
|
|
6947
|
+
const loadMoreMonths = useCallback4((direction) => {
|
|
6734
6948
|
setMonths((prev) => {
|
|
6735
6949
|
if (direction === "up") {
|
|
6736
6950
|
return [subMonths(prev[0], 1), ...prev];
|
|
@@ -6766,7 +6980,7 @@ var Calendar = ({
|
|
|
6766
6980
|
el.scrollIntoView({ behavior: "auto", block: "start" });
|
|
6767
6981
|
}
|
|
6768
6982
|
}, []);
|
|
6769
|
-
const renderMonth =
|
|
6983
|
+
const renderMonth = useCallback4(
|
|
6770
6984
|
(month) => {
|
|
6771
6985
|
const firstDay = startOfMonth(month);
|
|
6772
6986
|
const totalDays = getDaysInMonth(month);
|
|
@@ -6865,9 +7079,9 @@ var DatePicker = ({
|
|
|
6865
7079
|
const [open, setOpen] = useState5(false);
|
|
6866
7080
|
const [inputValue, setInputValue] = useState5("");
|
|
6867
7081
|
const [draftDate, setDraftDate] = useState5(void 0);
|
|
6868
|
-
const dateInputRef =
|
|
6869
|
-
const segIdxRef =
|
|
6870
|
-
const charPosRef =
|
|
7082
|
+
const dateInputRef = useRef5(null);
|
|
7083
|
+
const segIdxRef = useRef5(0);
|
|
7084
|
+
const charPosRef = useRef5(0);
|
|
6871
7085
|
const selectedDate = (() => {
|
|
6872
7086
|
if (!value) return void 0;
|
|
6873
7087
|
const d = /* @__PURE__ */ new Date(value + "T00:00:00Z");
|
|
@@ -6887,7 +7101,7 @@ var DatePicker = ({
|
|
|
6887
7101
|
setDraftDate(void 0);
|
|
6888
7102
|
}
|
|
6889
7103
|
}, [value]);
|
|
6890
|
-
const selectSegByIdx =
|
|
7104
|
+
const selectSegByIdx = useCallback5((idx) => {
|
|
6891
7105
|
if (!dateInputRef.current) return;
|
|
6892
7106
|
const seg = segments[idx] ?? segments[0];
|
|
6893
7107
|
dateInputRef.current.setSelectionRange(seg.start, seg.end);
|
|
@@ -6920,18 +7134,18 @@ var DatePicker = ({
|
|
|
6920
7134
|
selectSegByIdx(segIdxRef.current);
|
|
6921
7135
|
}, 0);
|
|
6922
7136
|
};
|
|
6923
|
-
const handleShiftButtonMouseDown =
|
|
7137
|
+
const handleShiftButtonMouseDown = useCallback5(
|
|
6924
7138
|
(e) => {
|
|
6925
7139
|
e.preventDefault();
|
|
6926
7140
|
},
|
|
6927
7141
|
[]
|
|
6928
7142
|
);
|
|
6929
|
-
const updateFromDate =
|
|
7143
|
+
const updateFromDate = useCallback5((newDate) => {
|
|
6930
7144
|
if (!isValid(newDate)) return;
|
|
6931
7145
|
setInputValue(formatUTCDate(newDate, "dd.MM.yy"));
|
|
6932
7146
|
setDraftDate(newDate);
|
|
6933
7147
|
}, []);
|
|
6934
|
-
const commitDate =
|
|
7148
|
+
const commitDate = useCallback5((dateToCommit) => {
|
|
6935
7149
|
const nextDate = dateToCommit ?? draftDate ?? selectedDate;
|
|
6936
7150
|
if (!nextDate || !isValid(nextDate)) return;
|
|
6937
7151
|
const iso = [
|
|
@@ -6942,7 +7156,7 @@ var DatePicker = ({
|
|
|
6942
7156
|
if (iso === value) return;
|
|
6943
7157
|
onChange?.(iso);
|
|
6944
7158
|
}, [draftDate, onChange, selectedDate, value]);
|
|
6945
|
-
const handleCalendarSelect =
|
|
7159
|
+
const handleCalendarSelect = useCallback5(
|
|
6946
7160
|
(day) => {
|
|
6947
7161
|
const normalizedDay = businessDays && isWeekend3 && isWeekend3(day) ? snapToBusinessDay(day, 1, isWeekend3) : day;
|
|
6948
7162
|
updateFromDate(normalizedDay);
|
|
@@ -6951,7 +7165,7 @@ var DatePicker = ({
|
|
|
6951
7165
|
},
|
|
6952
7166
|
[businessDays, commitDate, isWeekend3, updateFromDate]
|
|
6953
7167
|
);
|
|
6954
|
-
const handleDayShift =
|
|
7168
|
+
const handleDayShift = useCallback5(
|
|
6955
7169
|
(delta) => {
|
|
6956
7170
|
const base = activeDate ?? /* @__PURE__ */ new Date();
|
|
6957
7171
|
if (businessDays && isWeekend3) {
|
|
@@ -6962,7 +7176,7 @@ var DatePicker = ({
|
|
|
6962
7176
|
},
|
|
6963
7177
|
[activeDate, updateFromDate, businessDays, isWeekend3]
|
|
6964
7178
|
);
|
|
6965
|
-
const handleTriggerKeyDown =
|
|
7179
|
+
const handleTriggerKeyDown = useCallback5((e) => {
|
|
6966
7180
|
if (disabled) return;
|
|
6967
7181
|
if (e.key === "ArrowUp") {
|
|
6968
7182
|
e.preventDefault();
|
|
@@ -6976,7 +7190,7 @@ var DatePicker = ({
|
|
|
6976
7190
|
handleDayShift(-1);
|
|
6977
7191
|
}
|
|
6978
7192
|
}, [disabled, handleDayShift]);
|
|
6979
|
-
const handleKeyDown =
|
|
7193
|
+
const handleKeyDown = useCallback5((e) => {
|
|
6980
7194
|
if (!dateInputRef.current) return;
|
|
6981
7195
|
const { value: inputVal } = dateInputRef.current;
|
|
6982
7196
|
const segIdx = segIdxRef.current;
|
|
@@ -7077,7 +7291,7 @@ var DatePicker = ({
|
|
|
7077
7291
|
}
|
|
7078
7292
|
}
|
|
7079
7293
|
}, [activeDate, businessDays, commitDate, isWeekend3, selectSegByIdx, updateFromDate]);
|
|
7080
|
-
const handleOpenChange =
|
|
7294
|
+
const handleOpenChange = useCallback5((nextOpen) => {
|
|
7081
7295
|
if (!nextOpen && open) {
|
|
7082
7296
|
commitDate();
|
|
7083
7297
|
}
|
|
@@ -7513,7 +7727,7 @@ var DepChip = ({
|
|
|
7513
7727
|
onChipSelect?.(null);
|
|
7514
7728
|
}
|
|
7515
7729
|
};
|
|
7516
|
-
const handleOpenChange =
|
|
7730
|
+
const handleOpenChange = useCallback6(
|
|
7517
7731
|
(open) => {
|
|
7518
7732
|
setPopoverOpen(open);
|
|
7519
7733
|
},
|
|
@@ -7525,7 +7739,7 @@ var DepChip = ({
|
|
|
7525
7739
|
onChipSelectClear();
|
|
7526
7740
|
setPopoverOpen(false);
|
|
7527
7741
|
};
|
|
7528
|
-
const handleLagChange =
|
|
7742
|
+
const handleLagChange = useCallback6(
|
|
7529
7743
|
(newLag) => {
|
|
7530
7744
|
if (!onTasksChange || !allTasks) return;
|
|
7531
7745
|
const taskById = new Map(allTasks.map((t) => [t.id, t]));
|
|
@@ -7585,7 +7799,7 @@ var DepChip = ({
|
|
|
7585
7799
|
},
|
|
7586
7800
|
[dep, task, allTasks, onTasksChange, businessDays, weekendPredicate]
|
|
7587
7801
|
);
|
|
7588
|
-
const handleInputCommit =
|
|
7802
|
+
const handleInputCommit = useCallback6(
|
|
7589
7803
|
(raw) => {
|
|
7590
7804
|
if (raw === "") {
|
|
7591
7805
|
handleLagChange(0);
|
|
@@ -7901,7 +8115,7 @@ var TaskListRow = React11.memo(
|
|
|
7901
8115
|
})
|
|
7902
8116
|
);
|
|
7903
8117
|
}, [resolvedColumns]);
|
|
7904
|
-
const getColumnStyle =
|
|
8118
|
+
const getColumnStyle = useCallback6((columnId, fallbackWidth) => {
|
|
7905
8119
|
return columnWidthStyleMap.get(columnId) ?? {
|
|
7906
8120
|
width: fallbackWidth,
|
|
7907
8121
|
minWidth: fallbackWidth,
|
|
@@ -7912,26 +8126,26 @@ var TaskListRow = React11.memo(
|
|
|
7912
8126
|
const normalizedTask = useMemo9(() => normalizeTaskDatesForType(task), [task]);
|
|
7913
8127
|
const isMilestone = useMemo9(() => isMilestoneTask(normalizedTask), [normalizedTask]);
|
|
7914
8128
|
const [nameValue, setNameValue] = useState6("");
|
|
7915
|
-
const nameInputRef =
|
|
8129
|
+
const nameInputRef = useRef6(null);
|
|
7916
8130
|
const [durationValue, setDurationValue] = useState6(
|
|
7917
8131
|
() => getInclusiveDurationDays(normalizedTask.startDate, normalizedTask.endDate)
|
|
7918
8132
|
);
|
|
7919
|
-
const durationInputRef =
|
|
7920
|
-
const dependencySearchInputRef =
|
|
7921
|
-
const dependencySearchListRef =
|
|
8133
|
+
const durationInputRef = useRef6(null);
|
|
8134
|
+
const dependencySearchInputRef = useRef6(null);
|
|
8135
|
+
const dependencySearchListRef = useRef6(null);
|
|
7922
8136
|
const [progressValue, setProgressValue] = useState6(0);
|
|
7923
|
-
const progressInputRef =
|
|
8137
|
+
const progressInputRef = useRef6(null);
|
|
7924
8138
|
const [overflowOpen, setOverflowOpen] = useState6(false);
|
|
7925
8139
|
const [contextMenuOpen, setContextMenuOpen] = useState6(false);
|
|
7926
8140
|
const [colorMenuOpen, setColorMenuOpen] = useState6(false);
|
|
7927
|
-
const nameConfirmedRef =
|
|
7928
|
-
const durationConfirmedRef =
|
|
7929
|
-
const progressConfirmedRef =
|
|
7930
|
-
const autoEditedForRef =
|
|
7931
|
-
const editTriggerRef =
|
|
8141
|
+
const nameConfirmedRef = useRef6(false);
|
|
8142
|
+
const durationConfirmedRef = useRef6(false);
|
|
8143
|
+
const progressConfirmedRef = useRef6(false);
|
|
8144
|
+
const autoEditedForRef = useRef6(null);
|
|
8145
|
+
const editTriggerRef = useRef6(
|
|
7932
8146
|
"doubleclick"
|
|
7933
8147
|
);
|
|
7934
|
-
const rowRef =
|
|
8148
|
+
const rowRef = useRef6(null);
|
|
7935
8149
|
const isSelected = selectedTaskId === task.id;
|
|
7936
8150
|
const isParent = useMemo9(
|
|
7937
8151
|
() => isTaskParent(task.id, allTasks),
|
|
@@ -7945,13 +8159,13 @@ var TaskListRow = React11.memo(
|
|
|
7945
8159
|
() => createCustomDayPredicate({ customDays, isWeekend: isWeekend3 }),
|
|
7946
8160
|
[customDays, isWeekend3]
|
|
7947
8161
|
);
|
|
7948
|
-
const getDuration =
|
|
8162
|
+
const getDuration = useCallback6(
|
|
7949
8163
|
(start, end) => {
|
|
7950
8164
|
return businessDays ? getBusinessDaysCount(start, end, weekendPredicate) : getInclusiveDurationDays(start, end);
|
|
7951
8165
|
},
|
|
7952
8166
|
[businessDays, weekendPredicate]
|
|
7953
8167
|
);
|
|
7954
|
-
const getEndDate =
|
|
8168
|
+
const getEndDate = useCallback6(
|
|
7955
8169
|
(start, duration) => {
|
|
7956
8170
|
return businessDays ? addBusinessDays(start, duration, weekendPredicate).toISOString().split("T")[0] : getEndDateFromDuration(start, duration);
|
|
7957
8171
|
},
|
|
@@ -7961,7 +8175,7 @@ var TaskListRow = React11.memo(
|
|
|
7961
8175
|
const [compositeIconMode, setCompositeIconMode] = useState6(
|
|
7962
8176
|
() => isCollapsed ? "composite" : "down"
|
|
7963
8177
|
);
|
|
7964
|
-
const compositeIconModeRef =
|
|
8178
|
+
const compositeIconModeRef = useRef6(compositeIconMode);
|
|
7965
8179
|
const [compositeIconAnimation, setCompositeIconAnimation] = useState6(null);
|
|
7966
8180
|
const [compositeIconAnimationPhase, setCompositeIconAnimationPhase] = useState6(null);
|
|
7967
8181
|
useEffect6(() => {
|
|
@@ -7987,7 +8201,7 @@ var TaskListRow = React11.memo(
|
|
|
7987
8201
|
window.clearTimeout(finishTimeoutId);
|
|
7988
8202
|
};
|
|
7989
8203
|
}, [isCollapsed]);
|
|
7990
|
-
const getHierarchyLineColor =
|
|
8204
|
+
const getHierarchyLineColor = useCallback6((columnDepth) => {
|
|
7991
8205
|
return columnDepth % 2 === 0 ? "#93c5fd" : "var(--gantt-hierarchy-line-color)";
|
|
7992
8206
|
}, []);
|
|
7993
8207
|
const isPicking = selectingPredecessorFor != null;
|
|
@@ -8085,7 +8299,7 @@ var TaskListRow = React11.memo(
|
|
|
8085
8299
|
setEditingColumnId("name");
|
|
8086
8300
|
}
|
|
8087
8301
|
}, [editingTaskId, task.id, disableTaskNameEditing]);
|
|
8088
|
-
const handleNameClick =
|
|
8302
|
+
const handleNameClick = useCallback6(
|
|
8089
8303
|
(e) => {
|
|
8090
8304
|
e.stopPropagation();
|
|
8091
8305
|
onRowClick?.(task.id);
|
|
@@ -8093,7 +8307,7 @@ var TaskListRow = React11.memo(
|
|
|
8093
8307
|
},
|
|
8094
8308
|
[task.id, onRowClick, onScrollToTask]
|
|
8095
8309
|
);
|
|
8096
|
-
const handleNameDoubleClick =
|
|
8310
|
+
const handleNameDoubleClick = useCallback6(
|
|
8097
8311
|
(e) => {
|
|
8098
8312
|
if (task.composite) return;
|
|
8099
8313
|
if (disableTaskNameEditing) return;
|
|
@@ -8105,7 +8319,7 @@ var TaskListRow = React11.memo(
|
|
|
8105
8319
|
},
|
|
8106
8320
|
[task.name, task.composite, disableTaskNameEditing]
|
|
8107
8321
|
);
|
|
8108
|
-
const handleRowKeyDown =
|
|
8322
|
+
const handleRowKeyDown = useCallback6(
|
|
8109
8323
|
(e) => {
|
|
8110
8324
|
if (editingProgress) return;
|
|
8111
8325
|
if (!editingName && !disableTaskNameEditing && e.key === "F2") {
|
|
@@ -8119,7 +8333,7 @@ var TaskListRow = React11.memo(
|
|
|
8119
8333
|
},
|
|
8120
8334
|
[editingName, disableTaskNameEditing, task.name]
|
|
8121
8335
|
);
|
|
8122
|
-
const handleNameSave =
|
|
8336
|
+
const handleNameSave = useCallback6(() => {
|
|
8123
8337
|
if (nameConfirmedRef.current) {
|
|
8124
8338
|
nameConfirmedRef.current = false;
|
|
8125
8339
|
return;
|
|
@@ -8129,10 +8343,10 @@ var TaskListRow = React11.memo(
|
|
|
8129
8343
|
}
|
|
8130
8344
|
setEditingColumnId(null);
|
|
8131
8345
|
}, [nameValue, task, onTasksChange]);
|
|
8132
|
-
const handleNameCancel =
|
|
8346
|
+
const handleNameCancel = useCallback6(() => {
|
|
8133
8347
|
setEditingColumnId(null);
|
|
8134
8348
|
}, []);
|
|
8135
|
-
const handleNameKeyDown =
|
|
8349
|
+
const handleNameKeyDown = useCallback6(
|
|
8136
8350
|
(e) => {
|
|
8137
8351
|
if (e.key === "Enter") {
|
|
8138
8352
|
nameConfirmedRef.current = true;
|
|
@@ -8146,7 +8360,7 @@ var TaskListRow = React11.memo(
|
|
|
8146
8360
|
},
|
|
8147
8361
|
[nameValue, task, onTasksChange, handleNameCancel]
|
|
8148
8362
|
);
|
|
8149
|
-
const handleDurationClick =
|
|
8363
|
+
const handleDurationClick = useCallback6(
|
|
8150
8364
|
(e) => {
|
|
8151
8365
|
if (task.locked) return;
|
|
8152
8366
|
e.stopPropagation();
|
|
@@ -8158,11 +8372,11 @@ var TaskListRow = React11.memo(
|
|
|
8158
8372
|
},
|
|
8159
8373
|
[task.locked, normalizedTask.startDate, normalizedTask.endDate, getDuration, isMilestone]
|
|
8160
8374
|
);
|
|
8161
|
-
const applyDurationChange =
|
|
8375
|
+
const applyDurationChange = useCallback6((nextDuration) => {
|
|
8162
8376
|
const normalizedDuration = Math.max(0, Math.round(nextDuration) || 0);
|
|
8163
8377
|
setDurationValue(normalizedDuration);
|
|
8164
8378
|
}, []);
|
|
8165
|
-
const emitDurationChange =
|
|
8379
|
+
const emitDurationChange = useCallback6((rounded) => {
|
|
8166
8380
|
if (onDurationChange) {
|
|
8167
8381
|
onDurationChange(
|
|
8168
8382
|
isMilestone && rounded > 0 ? { ...task, type: "task" } : !isMilestone && rounded === 0 ? { ...task, type: "milestone", endDate: task.startDate } : task,
|
|
@@ -8184,7 +8398,7 @@ var TaskListRow = React11.memo(
|
|
|
8184
8398
|
]);
|
|
8185
8399
|
}
|
|
8186
8400
|
}, [getEndDate, isMilestone, onDurationChange, onTasksChange, task]);
|
|
8187
|
-
const handleDurationSave =
|
|
8401
|
+
const handleDurationSave = useCallback6(() => {
|
|
8188
8402
|
if (durationConfirmedRef.current) {
|
|
8189
8403
|
durationConfirmedRef.current = false;
|
|
8190
8404
|
return;
|
|
@@ -8193,17 +8407,17 @@ var TaskListRow = React11.memo(
|
|
|
8193
8407
|
emitDurationChange(rounded);
|
|
8194
8408
|
setEditingColumnId(null);
|
|
8195
8409
|
}, [durationValue, emitDurationChange]);
|
|
8196
|
-
const handleDurationCancel =
|
|
8410
|
+
const handleDurationCancel = useCallback6(() => {
|
|
8197
8411
|
setDurationValue(isMilestone ? 0 : getDuration(normalizedTask.startDate, normalizedTask.endDate));
|
|
8198
8412
|
setEditingColumnId(null);
|
|
8199
8413
|
}, [normalizedTask.startDate, normalizedTask.endDate, getDuration, isMilestone]);
|
|
8200
|
-
const handleDurationAdjust =
|
|
8414
|
+
const handleDurationAdjust = useCallback6(
|
|
8201
8415
|
(delta) => {
|
|
8202
8416
|
applyDurationChange(durationValue + delta);
|
|
8203
8417
|
},
|
|
8204
8418
|
[applyDurationChange, durationValue]
|
|
8205
8419
|
);
|
|
8206
|
-
const handleDurationKeyDown =
|
|
8420
|
+
const handleDurationKeyDown = useCallback6(
|
|
8207
8421
|
(e) => {
|
|
8208
8422
|
e.stopPropagation();
|
|
8209
8423
|
if (e.key === "Enter") {
|
|
@@ -8217,7 +8431,7 @@ var TaskListRow = React11.memo(
|
|
|
8217
8431
|
},
|
|
8218
8432
|
[durationValue, emitDurationChange, handleDurationCancel]
|
|
8219
8433
|
);
|
|
8220
|
-
const handleProgressClick =
|
|
8434
|
+
const handleProgressClick = useCallback6(
|
|
8221
8435
|
(e) => {
|
|
8222
8436
|
if (task.locked) return;
|
|
8223
8437
|
e.stopPropagation();
|
|
@@ -8227,7 +8441,7 @@ var TaskListRow = React11.memo(
|
|
|
8227
8441
|
},
|
|
8228
8442
|
[task.progress, task.locked]
|
|
8229
8443
|
);
|
|
8230
|
-
const handleProgressSave =
|
|
8444
|
+
const handleProgressSave = useCallback6(() => {
|
|
8231
8445
|
if (progressConfirmedRef.current) {
|
|
8232
8446
|
progressConfirmedRef.current = false;
|
|
8233
8447
|
return;
|
|
@@ -8236,15 +8450,15 @@ var TaskListRow = React11.memo(
|
|
|
8236
8450
|
onTasksChange?.(cascadeTaskProgress({ ...task, progress: clampedValue }, allTasks));
|
|
8237
8451
|
setEditingColumnId(null);
|
|
8238
8452
|
}, [progressValue, task, onTasksChange, allTasks]);
|
|
8239
|
-
const handleProgressCancel =
|
|
8453
|
+
const handleProgressCancel = useCallback6(() => {
|
|
8240
8454
|
setEditingColumnId(null);
|
|
8241
8455
|
}, []);
|
|
8242
|
-
const handleProgressAdjust =
|
|
8456
|
+
const handleProgressAdjust = useCallback6((delta) => {
|
|
8243
8457
|
setProgressValue(
|
|
8244
8458
|
(current) => Math.max(0, Math.min(100, current + delta))
|
|
8245
8459
|
);
|
|
8246
8460
|
}, []);
|
|
8247
|
-
const handleProgressKeyDown =
|
|
8461
|
+
const handleProgressKeyDown = useCallback6(
|
|
8248
8462
|
(e) => {
|
|
8249
8463
|
e.stopPropagation();
|
|
8250
8464
|
if (e.key === "Enter") {
|
|
@@ -8273,7 +8487,7 @@ var TaskListRow = React11.memo(
|
|
|
8273
8487
|
durationInputRef.current.select();
|
|
8274
8488
|
}
|
|
8275
8489
|
}, [editingDuration]);
|
|
8276
|
-
const emitMilestoneDateChange =
|
|
8490
|
+
const emitMilestoneDateChange = useCallback6((nextDateISO) => {
|
|
8277
8491
|
const alignedDate = businessDays ? alignToWorkingDay(/* @__PURE__ */ new Date(`${nextDateISO}T00:00:00.000Z`), 1, weekendPredicate) : /* @__PURE__ */ new Date(`${nextDateISO}T00:00:00.000Z`);
|
|
8278
8492
|
const clampedRange = clampTaskRangeForIncomingFS(
|
|
8279
8493
|
task,
|
|
@@ -8306,7 +8520,7 @@ var TaskListRow = React11.memo(
|
|
|
8306
8520
|
}
|
|
8307
8521
|
]);
|
|
8308
8522
|
}, [task, onTasksChange, allTasks, businessDays, weekendPredicate]);
|
|
8309
|
-
const handleStartDateChange =
|
|
8523
|
+
const handleStartDateChange = useCallback6(
|
|
8310
8524
|
(newDateISO) => {
|
|
8311
8525
|
if (!newDateISO) return;
|
|
8312
8526
|
if (isMilestone) {
|
|
@@ -8359,7 +8573,7 @@ var TaskListRow = React11.memo(
|
|
|
8359
8573
|
},
|
|
8360
8574
|
[task, onTasksChange, businessDays, getDuration, allTasks, weekendPredicate, isMilestone, emitMilestoneDateChange, taskDateChangeMode]
|
|
8361
8575
|
);
|
|
8362
|
-
const handleEndDateChange =
|
|
8576
|
+
const handleEndDateChange = useCallback6(
|
|
8363
8577
|
(newDateISO) => {
|
|
8364
8578
|
if (!newDateISO) return;
|
|
8365
8579
|
if (isMilestone) {
|
|
@@ -8423,41 +8637,41 @@ var TaskListRow = React11.memo(
|
|
|
8423
8637
|
),
|
|
8424
8638
|
/* @__PURE__ */ jsx15("span", { children: "\u0421\u043E\u0445\u0440\u0430\u043D\u044F\u0442\u044C \u0434\u043B\u0438\u0442\u0435\u043B\u044C\u043D\u043E\u0441\u0442\u044C" })
|
|
8425
8639
|
] }) : null;
|
|
8426
|
-
const handleRowClickInternal =
|
|
8640
|
+
const handleRowClickInternal = useCallback6(() => {
|
|
8427
8641
|
onRowClick?.(task.id);
|
|
8428
8642
|
}, [task.id, onRowClick]);
|
|
8429
|
-
const handleNumberClick =
|
|
8643
|
+
const handleNumberClick = useCallback6(
|
|
8430
8644
|
(e) => {
|
|
8431
8645
|
e.stopPropagation();
|
|
8432
8646
|
onRowClick?.(task.id);
|
|
8433
8647
|
},
|
|
8434
8648
|
[task.id, onRowClick]
|
|
8435
8649
|
);
|
|
8436
|
-
const handleToggleCollapse =
|
|
8650
|
+
const handleToggleCollapse = useCallback6(
|
|
8437
8651
|
(e) => {
|
|
8438
8652
|
e.stopPropagation();
|
|
8439
8653
|
onToggleCollapse?.(task.id);
|
|
8440
8654
|
},
|
|
8441
8655
|
[task.id, onToggleCollapse]
|
|
8442
8656
|
);
|
|
8443
|
-
const handlePromote =
|
|
8657
|
+
const handlePromote = useCallback6(
|
|
8444
8658
|
(e) => {
|
|
8445
8659
|
e.stopPropagation();
|
|
8446
8660
|
onPromoteTask?.(task.id);
|
|
8447
8661
|
},
|
|
8448
8662
|
[task.id, onPromoteTask]
|
|
8449
8663
|
);
|
|
8450
|
-
const handleDemote =
|
|
8664
|
+
const handleDemote = useCallback6(
|
|
8451
8665
|
(e) => {
|
|
8452
8666
|
e.stopPropagation();
|
|
8453
8667
|
onDemoteTask?.(task.id, "");
|
|
8454
8668
|
},
|
|
8455
8669
|
[task.id, onDemoteTask]
|
|
8456
8670
|
);
|
|
8457
|
-
const closeColorMenu =
|
|
8671
|
+
const closeColorMenu = useCallback6(() => {
|
|
8458
8672
|
setColorMenuOpen(false);
|
|
8459
8673
|
}, []);
|
|
8460
|
-
const handleApplyColor =
|
|
8674
|
+
const handleApplyColor = useCallback6(
|
|
8461
8675
|
(color) => {
|
|
8462
8676
|
if (!onTasksChange) return;
|
|
8463
8677
|
const descendantIds = new Set(
|
|
@@ -8473,7 +8687,7 @@ var TaskListRow = React11.memo(
|
|
|
8473
8687
|
},
|
|
8474
8688
|
[allTasks, closeColorMenu, isParent, onTasksChange, task]
|
|
8475
8689
|
);
|
|
8476
|
-
const handleUngroup =
|
|
8690
|
+
const handleUngroup = useCallback6(
|
|
8477
8691
|
(e) => {
|
|
8478
8692
|
e.stopPropagation();
|
|
8479
8693
|
setContextMenuOpen(false);
|
|
@@ -8494,7 +8708,7 @@ var TaskListRow = React11.memo(
|
|
|
8494
8708
|
[taskListMenuCommands, task, isParent, isMilestoneRow]
|
|
8495
8709
|
);
|
|
8496
8710
|
const hasContextMenu = !hideTaskListRowActions && (visibleCustomMenuCommands.length > 0 || !!onDuplicateTask || !!onDelete || !!onTasksChange || isParent && !!onUngroupTask);
|
|
8497
|
-
const handleCustomMenuCommandClick =
|
|
8711
|
+
const handleCustomMenuCommandClick = useCallback6(
|
|
8498
8712
|
(command) => (e) => {
|
|
8499
8713
|
e.stopPropagation();
|
|
8500
8714
|
if (command.closeOnSelect !== false) {
|
|
@@ -8505,14 +8719,14 @@ var TaskListRow = React11.memo(
|
|
|
8505
8719
|
},
|
|
8506
8720
|
[closeColorMenu, task]
|
|
8507
8721
|
);
|
|
8508
|
-
const handleAddClick =
|
|
8722
|
+
const handleAddClick = useCallback6(
|
|
8509
8723
|
(e) => {
|
|
8510
8724
|
e.stopPropagation();
|
|
8511
8725
|
onSetSelectingPredecessorFor?.(task.id);
|
|
8512
8726
|
},
|
|
8513
8727
|
[task.id, onSetSelectingPredecessorFor]
|
|
8514
8728
|
);
|
|
8515
|
-
const handlePredecessorPick =
|
|
8729
|
+
const handlePredecessorPick = useCallback6(
|
|
8516
8730
|
(e) => {
|
|
8517
8731
|
e.stopPropagation();
|
|
8518
8732
|
if (!isPicking || isSourceRow) return;
|
|
@@ -8533,14 +8747,14 @@ var TaskListRow = React11.memo(
|
|
|
8533
8747
|
onAddDependency
|
|
8534
8748
|
]
|
|
8535
8749
|
);
|
|
8536
|
-
const handleCancelPicking =
|
|
8750
|
+
const handleCancelPicking = useCallback6(
|
|
8537
8751
|
(e) => {
|
|
8538
8752
|
e.stopPropagation();
|
|
8539
8753
|
onSetSelectingPredecessorFor?.(null);
|
|
8540
8754
|
},
|
|
8541
8755
|
[onSetSelectingPredecessorFor]
|
|
8542
8756
|
);
|
|
8543
|
-
const handleSourceCellClick =
|
|
8757
|
+
const handleSourceCellClick = useCallback6(
|
|
8544
8758
|
(e) => {
|
|
8545
8759
|
if (e.target === e.currentTarget) {
|
|
8546
8760
|
handleCancelPicking(e);
|
|
@@ -8548,7 +8762,7 @@ var TaskListRow = React11.memo(
|
|
|
8548
8762
|
},
|
|
8549
8763
|
[handleCancelPicking]
|
|
8550
8764
|
);
|
|
8551
|
-
const handleSearchPick =
|
|
8765
|
+
const handleSearchPick = useCallback6(
|
|
8552
8766
|
(pickedTaskId) => {
|
|
8553
8767
|
if (!activeLinkType) return;
|
|
8554
8768
|
if (dependencyPickMode === "predecessor") {
|
|
@@ -8559,7 +8773,7 @@ var TaskListRow = React11.memo(
|
|
|
8559
8773
|
},
|
|
8560
8774
|
[activeLinkType, dependencyPickMode, onAddDependency, task.id]
|
|
8561
8775
|
);
|
|
8562
|
-
const handleSearchRemove =
|
|
8776
|
+
const handleSearchRemove = useCallback6(
|
|
8563
8777
|
(pickedTaskId) => {
|
|
8564
8778
|
const matchingTypes = dependencyPickMode === "predecessor" ? (task.dependencies ?? []).filter((dep) => dep.taskId === pickedTaskId).map((dep) => dep.type) : (allTasks.find((candidate) => candidate.id === pickedTaskId)?.dependencies ?? []).filter((dep) => dep.taskId === task.id).map((dep) => dep.type);
|
|
8565
8779
|
for (const linkType of matchingTypes) {
|
|
@@ -9526,7 +9740,7 @@ var TaskListRow = React11.memo(
|
|
|
9526
9740
|
progress: progressCell,
|
|
9527
9741
|
dependencies: dependenciesCell
|
|
9528
9742
|
};
|
|
9529
|
-
const focusCustomCell =
|
|
9743
|
+
const focusCustomCell = useCallback6((taskId, columnId) => {
|
|
9530
9744
|
const overlay = rowRef.current?.closest(".gantt-tl-overlay");
|
|
9531
9745
|
if (!overlay) {
|
|
9532
9746
|
return;
|
|
@@ -9535,7 +9749,7 @@ var TaskListRow = React11.memo(
|
|
|
9535
9749
|
const nextCell = overlay.querySelector(selector);
|
|
9536
9750
|
nextCell?.focus();
|
|
9537
9751
|
}, []);
|
|
9538
|
-
const moveActiveCustomCell =
|
|
9752
|
+
const moveActiveCustomCell = useCallback6((columnId, direction) => {
|
|
9539
9753
|
const overlay = rowRef.current?.closest(".gantt-tl-overlay");
|
|
9540
9754
|
if (!overlay || !resolvedColumns) {
|
|
9541
9755
|
return;
|
|
@@ -9739,7 +9953,7 @@ var TaskListRow = React11.memo(
|
|
|
9739
9953
|
TaskListRow.displayName = "TaskListRow";
|
|
9740
9954
|
|
|
9741
9955
|
// src/components/TaskList/NewTaskRow.tsx
|
|
9742
|
-
import { useState as useState7, useRef as
|
|
9956
|
+
import { useState as useState7, useRef as useRef7, useEffect as useEffect7 } from "react";
|
|
9743
9957
|
import { jsx as jsx16, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
9744
9958
|
var NewTaskRow = ({
|
|
9745
9959
|
rowHeight,
|
|
@@ -9748,8 +9962,8 @@ var NewTaskRow = ({
|
|
|
9748
9962
|
nestingDepth = 0
|
|
9749
9963
|
}) => {
|
|
9750
9964
|
const [nameValue, setNameValue] = useState7("");
|
|
9751
|
-
const inputRef =
|
|
9752
|
-
const confirmedRef =
|
|
9965
|
+
const inputRef = useRef7(null);
|
|
9966
|
+
const confirmedRef = useRef7(false);
|
|
9753
9967
|
const inputInnerPadding = 4;
|
|
9754
9968
|
const levelOffset = nestingDepth > 0 ? nestingDepth * 20 + 8 : 0;
|
|
9755
9969
|
useEffect7(() => {
|
|
@@ -9805,7 +10019,7 @@ var NewTaskRow = ({
|
|
|
9805
10019
|
};
|
|
9806
10020
|
|
|
9807
10021
|
// src/components/GenerationSkeleton/GenerationSkeleton.tsx
|
|
9808
|
-
import { useRef as
|
|
10022
|
+
import { useRef as useRef8 } from "react";
|
|
9809
10023
|
import { Fragment as Fragment5, jsx as jsx17 } from "react/jsx-runtime";
|
|
9810
10024
|
var MAX_SKELETON_ROWS = 200;
|
|
9811
10025
|
var SHIMMER_DURATION_MS = 1450;
|
|
@@ -9830,8 +10044,8 @@ var GenerationSkeletonRows = ({
|
|
|
9830
10044
|
chartStartJitterDays = 0
|
|
9831
10045
|
}) => {
|
|
9832
10046
|
const safeCount = clampCount(count);
|
|
9833
|
-
const previousCountRef =
|
|
9834
|
-
const shimmerDelayRef =
|
|
10047
|
+
const previousCountRef = useRef8(null);
|
|
10048
|
+
const shimmerDelayRef = useRef8("0ms");
|
|
9835
10049
|
if (previousCountRef.current !== safeCount) {
|
|
9836
10050
|
previousCountRef.current = safeCount;
|
|
9837
10051
|
shimmerDelayRef.current = `-${Date.now() % SHIMMER_DURATION_MS}ms`;
|
|
@@ -10102,7 +10316,7 @@ var SelectAllCheckbox = ({
|
|
|
10102
10316
|
indeterminate,
|
|
10103
10317
|
onChange
|
|
10104
10318
|
}) => {
|
|
10105
|
-
const ref =
|
|
10319
|
+
const ref = useRef9(null);
|
|
10106
10320
|
useEffect8(() => {
|
|
10107
10321
|
if (ref.current) {
|
|
10108
10322
|
ref.current.indeterminate = indeterminate;
|
|
@@ -10188,8 +10402,8 @@ var TaskList = ({
|
|
|
10188
10402
|
const [activeCustomCell, setActiveCustomCell] = useState8(null);
|
|
10189
10403
|
const [columnWidthOverrides, setColumnWidthOverrides] = useState8(() => normalizeColumnWidthMap(taskListColumnWidths));
|
|
10190
10404
|
const [isColumnResizeMode, setIsColumnResizeMode] = useState8(false);
|
|
10191
|
-
const columnResizeHeaderRef =
|
|
10192
|
-
const resizeStateRef =
|
|
10405
|
+
const columnResizeHeaderRef = useRef9(null);
|
|
10406
|
+
const resizeStateRef = useRef9(null);
|
|
10193
10407
|
const effectiveSelectedTaskIds = selectedTaskIds ?? internalSelectedTaskIds;
|
|
10194
10408
|
useEffect8(() => {
|
|
10195
10409
|
if (!isColumnResizeMode) {
|
|
@@ -10207,7 +10421,7 @@ var TaskList = ({
|
|
|
10207
10421
|
document.removeEventListener("pointerdown", handleOutsidePointerDown);
|
|
10208
10422
|
};
|
|
10209
10423
|
}, [isColumnResizeMode]);
|
|
10210
|
-
const emitSelectedTaskIdsChange =
|
|
10424
|
+
const emitSelectedTaskIdsChange = useCallback7((nextSelectedTaskIds) => {
|
|
10211
10425
|
if (!selectedTaskIds) {
|
|
10212
10426
|
setInternalSelectedTaskIds(nextSelectedTaskIds);
|
|
10213
10427
|
}
|
|
@@ -10215,7 +10429,7 @@ var TaskList = ({
|
|
|
10215
10429
|
}, [onSelectedTaskIdsChange, selectedTaskIds]);
|
|
10216
10430
|
const [internalCollapsedParentIds, setInternalCollapsedParentIds] = useState8(/* @__PURE__ */ new Set());
|
|
10217
10431
|
const collapsedParentIds = externalCollapsedParentIds ?? internalCollapsedParentIds;
|
|
10218
|
-
const handleToggleCollapse = externalOnToggleCollapse ??
|
|
10432
|
+
const handleToggleCollapse = externalOnToggleCollapse ?? useCallback7((parentId) => {
|
|
10219
10433
|
setInternalCollapsedParentIds((prev) => {
|
|
10220
10434
|
const next = new Set(prev);
|
|
10221
10435
|
if (next.has(parentId)) {
|
|
@@ -10286,7 +10500,7 @@ var TaskList = ({
|
|
|
10286
10500
|
);
|
|
10287
10501
|
const areAllVisibleTasksSelected = visibleTaskIds.length > 0 && selectedVisibleTaskCount === visibleTaskIds.length;
|
|
10288
10502
|
const areSomeVisibleTasksSelected = selectedVisibleTaskCount > 0 && !areAllVisibleTasksSelected;
|
|
10289
|
-
const handleToggleTaskSelection =
|
|
10503
|
+
const handleToggleTaskSelection = useCallback7((taskId, checked) => {
|
|
10290
10504
|
const nextSelectedTaskIds = new Set(effectiveSelectedTaskIds);
|
|
10291
10505
|
if (checked) {
|
|
10292
10506
|
nextSelectedTaskIds.add(taskId);
|
|
@@ -10295,7 +10509,7 @@ var TaskList = ({
|
|
|
10295
10509
|
}
|
|
10296
10510
|
emitSelectedTaskIdsChange(nextSelectedTaskIds);
|
|
10297
10511
|
}, [effectiveSelectedTaskIds, emitSelectedTaskIdsChange]);
|
|
10298
|
-
const handleToggleAllVisibleTaskSelection =
|
|
10512
|
+
const handleToggleAllVisibleTaskSelection = useCallback7((checked) => {
|
|
10299
10513
|
const nextSelectedTaskIds = new Set(effectiveSelectedTaskIds);
|
|
10300
10514
|
for (const taskId of visibleTaskIds) {
|
|
10301
10515
|
if (checked) {
|
|
@@ -10376,7 +10590,7 @@ var TaskList = ({
|
|
|
10376
10590
|
}
|
|
10377
10591
|
return map;
|
|
10378
10592
|
}, [tasks, visibleTasks]);
|
|
10379
|
-
const handleRowClick =
|
|
10593
|
+
const handleRowClick = useCallback7((taskId) => {
|
|
10380
10594
|
onTaskSelect?.(taskId);
|
|
10381
10595
|
}, [onTaskSelect]);
|
|
10382
10596
|
const [activeLinkType, setActiveLinkType] = useState8("FS");
|
|
@@ -10384,14 +10598,14 @@ var TaskList = ({
|
|
|
10384
10598
|
const [dependencyPickMode, setDependencyPickMode] = useState8("successor");
|
|
10385
10599
|
const [typeMenuOpen, setTypeMenuOpen] = useState8(false);
|
|
10386
10600
|
const [dependencyError, setDependencyError] = useState8(null);
|
|
10387
|
-
const overlayRef =
|
|
10601
|
+
const overlayRef = useRef9(null);
|
|
10388
10602
|
const [selectedChip, setSelectedChip] = useState8(controlledSelectedChip ? { ...controlledSelectedChip, linkType: controlledSelectedChip.linkType } : null);
|
|
10389
10603
|
useEffect8(() => {
|
|
10390
10604
|
if (controlledSelectedChip !== void 0) {
|
|
10391
10605
|
setSelectedChip(controlledSelectedChip ? { ...controlledSelectedChip, linkType: controlledSelectedChip.linkType } : null);
|
|
10392
10606
|
}
|
|
10393
10607
|
}, [controlledSelectedChip]);
|
|
10394
|
-
const handleChipSelect =
|
|
10608
|
+
const handleChipSelect = useCallback7((chip) => {
|
|
10395
10609
|
setSelectedChip(chip);
|
|
10396
10610
|
onSelectedChipChange?.(chip);
|
|
10397
10611
|
}, [onSelectedChipChange]);
|
|
@@ -10490,7 +10704,7 @@ var TaskList = ({
|
|
|
10490
10704
|
document.removeEventListener("mouseup", handleCanvasMouseUp, true);
|
|
10491
10705
|
};
|
|
10492
10706
|
}, [selectingPredecessorFor, selectedChip, selectedTaskId, activeCustomCell, onTaskSelect, onSelectedChipChange]);
|
|
10493
|
-
const handleAddDependency =
|
|
10707
|
+
const handleAddDependency = useCallback7((successorTaskId, predecessorTaskId, linkType) => {
|
|
10494
10708
|
if (successorTaskId === predecessorTaskId) return;
|
|
10495
10709
|
if (areTasksHierarchicallyRelated(successorTaskId, predecessorTaskId, tasks)) {
|
|
10496
10710
|
setDependencyError("\u0421\u0432\u044F\u0437\u0438 \u043C\u0435\u0436\u0434\u0443 \u0440\u043E\u0434\u0438\u0442\u0435\u043B\u0435\u043C \u0438 \u043F\u043E\u0442\u043E\u043C\u043A\u043E\u043C \u0437\u0430\u043F\u0440\u0435\u0449\u0435\u043D\u044B");
|
|
@@ -10569,7 +10783,7 @@ var TaskList = ({
|
|
|
10569
10783
|
}
|
|
10570
10784
|
setSelectingPredecessorFor(null);
|
|
10571
10785
|
}, [tasks, onTasksChange]);
|
|
10572
|
-
const handleRemoveDependency =
|
|
10786
|
+
const handleRemoveDependency = useCallback7((taskId, predecessorTaskId, linkType) => {
|
|
10573
10787
|
const task = tasks.find((t) => t.id === taskId);
|
|
10574
10788
|
if (!task) return;
|
|
10575
10789
|
const updatedDeps = (task.dependencies ?? []).filter(
|
|
@@ -10582,16 +10796,16 @@ var TaskList = ({
|
|
|
10582
10796
|
const [draggingIndex, setDraggingIndex] = useState8(null);
|
|
10583
10797
|
const [dragOverTarget, setDragOverTarget] = useState8(null);
|
|
10584
10798
|
const [isBeforeFirstDropZoneActive, setIsBeforeFirstDropZoneActive] = useState8(false);
|
|
10585
|
-
const dragOriginIndexRef =
|
|
10586
|
-
const dragTaskIdRef =
|
|
10587
|
-
const clearDragState =
|
|
10799
|
+
const dragOriginIndexRef = useRef9(null);
|
|
10800
|
+
const dragTaskIdRef = useRef9(null);
|
|
10801
|
+
const clearDragState = useCallback7(() => {
|
|
10588
10802
|
setDraggingIndex(null);
|
|
10589
10803
|
setDragOverTarget(null);
|
|
10590
10804
|
setIsBeforeFirstDropZoneActive(false);
|
|
10591
10805
|
dragOriginIndexRef.current = null;
|
|
10592
10806
|
dragTaskIdRef.current = null;
|
|
10593
10807
|
}, []);
|
|
10594
|
-
const isValidParentDrop =
|
|
10808
|
+
const isValidParentDrop = useCallback7((draggedTaskId, dropIndex) => {
|
|
10595
10809
|
if (!isTaskParent(draggedTaskId, tasks)) {
|
|
10596
10810
|
return true;
|
|
10597
10811
|
}
|
|
@@ -10609,13 +10823,13 @@ var TaskList = ({
|
|
|
10609
10823
|
}
|
|
10610
10824
|
return true;
|
|
10611
10825
|
}, [tasks, visibleTasks, orderedTasks]);
|
|
10612
|
-
const handleDragStart =
|
|
10826
|
+
const handleDragStart = useCallback7((index, e) => {
|
|
10613
10827
|
e.dataTransfer.effectAllowed = "move";
|
|
10614
10828
|
setDraggingIndex(index);
|
|
10615
10829
|
dragOriginIndexRef.current = index;
|
|
10616
10830
|
dragTaskIdRef.current = visibleTasks[index]?.id ?? null;
|
|
10617
10831
|
}, [visibleTasks]);
|
|
10618
|
-
const normalizeDropTarget =
|
|
10832
|
+
const normalizeDropTarget = useCallback7((movedTaskId, target) => {
|
|
10619
10833
|
if (target.placement !== "before" || target.index <= 0 || target.index >= visibleTasks.length) {
|
|
10620
10834
|
return target;
|
|
10621
10835
|
}
|
|
@@ -10638,7 +10852,7 @@ var TaskList = ({
|
|
|
10638
10852
|
}
|
|
10639
10853
|
return target;
|
|
10640
10854
|
}, [orderedTasks, visibleTasks]);
|
|
10641
|
-
const handleDragOver =
|
|
10855
|
+
const handleDragOver = useCallback7((index, e, forcedPlacement) => {
|
|
10642
10856
|
e.preventDefault();
|
|
10643
10857
|
const draggedTaskId = dragTaskIdRef.current;
|
|
10644
10858
|
if (!draggedTaskId) return;
|
|
@@ -10690,7 +10904,7 @@ var TaskList = ({
|
|
|
10690
10904
|
isDirectChildDrop: normalizedTarget.placement === "after" && reorderPlan.inferredParentId === targetTask.id
|
|
10691
10905
|
});
|
|
10692
10906
|
}, [isValidParentDrop, normalizeDropTarget, orderedTasks, visibleTasks]);
|
|
10693
|
-
const handleDrop =
|
|
10907
|
+
const handleDrop = useCallback7((dropIndex, e, forcedPlacement) => {
|
|
10694
10908
|
e.preventDefault();
|
|
10695
10909
|
const originVisibleIndex = dragOriginIndexRef.current;
|
|
10696
10910
|
const movedTaskId = dragTaskIdRef.current;
|
|
@@ -10757,7 +10971,7 @@ var TaskList = ({
|
|
|
10757
10971
|
onTaskSelect?.(moved.id);
|
|
10758
10972
|
clearDragState();
|
|
10759
10973
|
}, [orderedTasks, visibleTasks, onReorder, onTaskSelect, isValidParentDrop, clearDragState, normalizeDropTarget]);
|
|
10760
|
-
const handleBeforeFirstDragOver =
|
|
10974
|
+
const handleBeforeFirstDragOver = useCallback7((e) => {
|
|
10761
10975
|
const draggedTaskId = dragTaskIdRef.current;
|
|
10762
10976
|
const firstTask = visibleTasks[0];
|
|
10763
10977
|
const descendantIds = draggedTaskId ? new Set(getAllDescendants2(draggedTaskId, orderedTasks).map((task) => task.id)) : /* @__PURE__ */ new Set();
|
|
@@ -10765,11 +10979,11 @@ var TaskList = ({
|
|
|
10765
10979
|
setIsBeforeFirstDropZoneActive(isValidBeforeFirstDrop);
|
|
10766
10980
|
handleDragOver(0, e, "before");
|
|
10767
10981
|
}, [handleDragOver, isValidParentDrop, orderedTasks, visibleTasks]);
|
|
10768
|
-
const handleDragEnd =
|
|
10982
|
+
const handleDragEnd = useCallback7(() => {
|
|
10769
10983
|
clearDragState();
|
|
10770
10984
|
}, [clearDragState]);
|
|
10771
10985
|
const shouldShowBeforeFirstDropZone = !reorderDisabled && visibleTasks.length > 0 && draggingIndex !== null && draggingIndex > 0;
|
|
10772
|
-
const handleConfirmNewTask =
|
|
10986
|
+
const handleConfirmNewTask = useCallback7((name) => {
|
|
10773
10987
|
const range = buildDefaultTaskDateRange(getTodayISODate(), {
|
|
10774
10988
|
businessDays,
|
|
10775
10989
|
defaultTaskDurationDays,
|
|
@@ -10784,8 +10998,8 @@ var TaskList = ({
|
|
|
10784
10998
|
onAdd?.(newTask);
|
|
10785
10999
|
setIsCreating(false);
|
|
10786
11000
|
}, [businessDays, defaultTaskDurationDays, onAdd, weekendPredicate]);
|
|
10787
|
-
const handleCancelNewTask =
|
|
10788
|
-
const findInsertAfterTaskId =
|
|
11001
|
+
const handleCancelNewTask = useCallback7(() => setIsCreating(false), []);
|
|
11002
|
+
const findInsertAfterTaskId = useCallback7((anchorTaskId) => {
|
|
10789
11003
|
const anchorIndex = orderedTasks.findIndex((task) => task.id === anchorTaskId);
|
|
10790
11004
|
if (anchorIndex === -1) {
|
|
10791
11005
|
return anchorTaskId;
|
|
@@ -10835,7 +11049,7 @@ var TaskList = ({
|
|
|
10835
11049
|
[pendingInsertDisplayTaskId, visibleTasks]
|
|
10836
11050
|
);
|
|
10837
11051
|
const hasVisiblePendingInsert = pendingInsertRowIndex >= 0;
|
|
10838
|
-
const handleStartInsertAfter =
|
|
11052
|
+
const handleStartInsertAfter = useCallback7((taskId, newTask) => {
|
|
10839
11053
|
const anchorTask = orderedTasks.find((task) => task.id === taskId);
|
|
10840
11054
|
if (!anchorTask) {
|
|
10841
11055
|
return;
|
|
@@ -10850,7 +11064,7 @@ var TaskList = ({
|
|
|
10850
11064
|
nestingDepth: nestingDepthMap.get(taskId) ?? 0
|
|
10851
11065
|
});
|
|
10852
11066
|
}, [findInsertAfterTaskId, nestingDepthMap, orderedTasks]);
|
|
10853
|
-
const handleConfirmInsertedTask =
|
|
11067
|
+
const handleConfirmInsertedTask = useCallback7((name) => {
|
|
10854
11068
|
if (!pendingInsert) {
|
|
10855
11069
|
return;
|
|
10856
11070
|
}
|
|
@@ -10864,7 +11078,7 @@ var TaskList = ({
|
|
|
10864
11078
|
onInsertAfter?.(pendingInsert.insertAfterTaskId, newTask);
|
|
10865
11079
|
setPendingInsert(null);
|
|
10866
11080
|
}, [onInsertAfter, pendingInsert]);
|
|
10867
|
-
const handleCancelInsertedTask =
|
|
11081
|
+
const handleCancelInsertedTask = useCallback7(() => setPendingInsert(null), []);
|
|
10868
11082
|
function getTaskDepth(task, tasks2) {
|
|
10869
11083
|
if (!task) return 0;
|
|
10870
11084
|
let depth = 0;
|
|
@@ -10877,7 +11091,7 @@ var TaskList = ({
|
|
|
10877
11091
|
}
|
|
10878
11092
|
return depth;
|
|
10879
11093
|
}
|
|
10880
|
-
const handleDemoteWrapper =
|
|
11094
|
+
const handleDemoteWrapper = useCallback7((taskId, _newParentId) => {
|
|
10881
11095
|
const taskIndex = visibleTasks.findIndex((t) => t.id === taskId);
|
|
10882
11096
|
const currentTask = visibleTasks[taskIndex];
|
|
10883
11097
|
const currentDepth = getTaskDepth(currentTask, orderedTasks);
|
|
@@ -10911,7 +11125,7 @@ var TaskList = ({
|
|
|
10911
11125
|
];
|
|
10912
11126
|
onReorder?.(updatedTasks, taskId, newSectionTask.id);
|
|
10913
11127
|
}, [visibleTasks, orderedTasks, onDemoteTask, onReorder]);
|
|
10914
|
-
const handleDuplicateTask =
|
|
11128
|
+
const handleDuplicateTask = useCallback7((taskId) => {
|
|
10915
11129
|
const duplicatedTasks = duplicateTaskSubtree(taskId, orderedTasks);
|
|
10916
11130
|
onReorder?.(duplicatedTasks);
|
|
10917
11131
|
}, [orderedTasks, onReorder]);
|
|
@@ -10961,7 +11175,7 @@ var TaskList = ({
|
|
|
10961
11175
|
const requestedTaskListWidth = taskListWidth ?? Math.min(MIN_TASK_LIST_WIDTH, resolvedColumnWidthTotal);
|
|
10962
11176
|
const effectiveTaskListWidth = Math.max(requestedTaskListWidth, resolvedColumnWidthTotal);
|
|
10963
11177
|
const tableHeaderHeight = headerHeight + 1;
|
|
10964
|
-
const updateColumnWidth =
|
|
11178
|
+
const updateColumnWidth = useCallback7((columnId, width) => {
|
|
10965
11179
|
setColumnWidthOverrides((prev) => {
|
|
10966
11180
|
if (prev[columnId] === width) {
|
|
10967
11181
|
return prev;
|
|
@@ -11047,7 +11261,7 @@ var TaskList = ({
|
|
|
11047
11261
|
document.body.style.removeProperty("touch-action");
|
|
11048
11262
|
};
|
|
11049
11263
|
}, [resolvedColumns, updateColumnWidth]);
|
|
11050
|
-
const startColumnResize =
|
|
11264
|
+
const startColumnResize = useCallback7((columnId, event) => {
|
|
11051
11265
|
if (resizeStateRef.current) {
|
|
11052
11266
|
return;
|
|
11053
11267
|
}
|
|
@@ -11074,7 +11288,7 @@ var TaskList = ({
|
|
|
11074
11288
|
document.body.style.userSelect = "none";
|
|
11075
11289
|
document.body.style.touchAction = "none";
|
|
11076
11290
|
}, [resolvedColumns]);
|
|
11077
|
-
const renderResizeHandle =
|
|
11291
|
+
const renderResizeHandle = useCallback7((columnId) => /* @__PURE__ */ jsx18(
|
|
11078
11292
|
"button",
|
|
11079
11293
|
{
|
|
11080
11294
|
type: "button",
|
|
@@ -11431,7 +11645,7 @@ var TaskList = ({
|
|
|
11431
11645
|
};
|
|
11432
11646
|
|
|
11433
11647
|
// src/components/ResourceTimelineChart/ResourceTimelineChart.tsx
|
|
11434
|
-
import React15, { useCallback as
|
|
11648
|
+
import React15, { useCallback as useCallback9, useEffect as useEffect10, useMemo as useMemo11, useRef as useRef11, useState as useState10 } from "react";
|
|
11435
11649
|
|
|
11436
11650
|
// src/utils/resourceTimelineLayout.ts
|
|
11437
11651
|
var isInvalidDate = (date) => Number.isNaN(date.getTime());
|
|
@@ -11633,7 +11847,7 @@ var layoutResourceTimelineItems = (resources, options) => {
|
|
|
11633
11847
|
};
|
|
11634
11848
|
|
|
11635
11849
|
// src/hooks/useResourceItemDrag.ts
|
|
11636
|
-
import { useCallback as
|
|
11850
|
+
import { useCallback as useCallback8, useEffect as useEffect9, useRef as useRef10, useState as useState9 } from "react";
|
|
11637
11851
|
var RESOURCE_CURSOR_STYLE_ID = "gantt-resource-global-drag-cursor-style";
|
|
11638
11852
|
function ensureResourceGlobalCursorStyle() {
|
|
11639
11853
|
if (typeof document === "undefined") return;
|
|
@@ -11745,10 +11959,10 @@ var useResourceItemDrag = ({
|
|
|
11745
11959
|
weekendPredicate,
|
|
11746
11960
|
onResourceItemMove
|
|
11747
11961
|
}) => {
|
|
11748
|
-
const activeDragRef =
|
|
11749
|
-
const rowsRef =
|
|
11750
|
-
const onResourceItemMoveRef =
|
|
11751
|
-
const rafRef =
|
|
11962
|
+
const activeDragRef = useRef10(null);
|
|
11963
|
+
const rowsRef = useRef10(rows);
|
|
11964
|
+
const onResourceItemMoveRef = useRef10(onResourceItemMove);
|
|
11965
|
+
const rafRef = useRef10(null);
|
|
11752
11966
|
const [preview, setPreview] = useState9(null);
|
|
11753
11967
|
useEffect9(() => {
|
|
11754
11968
|
rowsRef.current = rows;
|
|
@@ -11756,13 +11970,13 @@ var useResourceItemDrag = ({
|
|
|
11756
11970
|
useEffect9(() => {
|
|
11757
11971
|
onResourceItemMoveRef.current = onResourceItemMove;
|
|
11758
11972
|
}, [onResourceItemMove]);
|
|
11759
|
-
const clearRaf =
|
|
11973
|
+
const clearRaf = useCallback8(() => {
|
|
11760
11974
|
if (rafRef.current !== null) {
|
|
11761
11975
|
cancelAnimationFrame(rafRef.current);
|
|
11762
11976
|
rafRef.current = null;
|
|
11763
11977
|
}
|
|
11764
11978
|
}, []);
|
|
11765
|
-
const cancelDrag2 =
|
|
11979
|
+
const cancelDrag2 = useCallback8(() => {
|
|
11766
11980
|
clearRaf();
|
|
11767
11981
|
clearResourceGlobalCursor();
|
|
11768
11982
|
activeDragRef.current = null;
|
|
@@ -11841,7 +12055,7 @@ var useResourceItemDrag = ({
|
|
|
11841
12055
|
cancelDrag2();
|
|
11842
12056
|
};
|
|
11843
12057
|
}, [cancelDrag2, clearRaf, disableResourceReassignment, gridElementRef]);
|
|
11844
|
-
const startDrag =
|
|
12058
|
+
const startDrag = useCallback8((event, layoutItem) => {
|
|
11845
12059
|
if (readonly || layoutItem.item.locked || event.button !== 0) {
|
|
11846
12060
|
return;
|
|
11847
12061
|
}
|
|
@@ -12106,8 +12320,8 @@ var ResourceHeader = ({
|
|
|
12106
12320
|
const [scopeMenuOpen, setScopeMenuOpen] = useState10(false);
|
|
12107
12321
|
const [editingName, setEditingName] = useState10(false);
|
|
12108
12322
|
const [nameValue, setNameValue] = useState10(resource.name);
|
|
12109
|
-
const nameInputRef =
|
|
12110
|
-
const nameConfirmedRef =
|
|
12323
|
+
const nameInputRef = useRef11(null);
|
|
12324
|
+
const nameConfirmedRef = useRef11(false);
|
|
12111
12325
|
const visibleCommands = useMemo11(
|
|
12112
12326
|
() => menuCommands.filter((command) => command.isVisible?.(resource) ?? true),
|
|
12113
12327
|
[menuCommands, resource]
|
|
@@ -12117,7 +12331,7 @@ var ResourceHeader = ({
|
|
|
12117
12331
|
const scope = resource.scope ?? "Project";
|
|
12118
12332
|
const scopeLabel = RESOURCE_SCOPE_LABELS[scope] ?? scope;
|
|
12119
12333
|
const isInactive = isInactiveResourceStatus(resource.status);
|
|
12120
|
-
const applyResourcePatch =
|
|
12334
|
+
const applyResourcePatch = useCallback9((patch) => {
|
|
12121
12335
|
onResourceChange?.({ ...resource, ...patch });
|
|
12122
12336
|
}, [onResourceChange, resource]);
|
|
12123
12337
|
useEffect10(() => {
|
|
@@ -12138,7 +12352,7 @@ var ResourceHeader = ({
|
|
|
12138
12352
|
}
|
|
12139
12353
|
command.onSelect(resource);
|
|
12140
12354
|
};
|
|
12141
|
-
const handleNameDoubleClick =
|
|
12355
|
+
const handleNameDoubleClick = useCallback9((event) => {
|
|
12142
12356
|
if (!onResourceChange) {
|
|
12143
12357
|
return;
|
|
12144
12358
|
}
|
|
@@ -12147,7 +12361,7 @@ var ResourceHeader = ({
|
|
|
12147
12361
|
setNameValue(resource.name);
|
|
12148
12362
|
setEditingName(true);
|
|
12149
12363
|
}, [onResourceChange, resource.name]);
|
|
12150
|
-
const handleNameSave =
|
|
12364
|
+
const handleNameSave = useCallback9(() => {
|
|
12151
12365
|
if (nameConfirmedRef.current) {
|
|
12152
12366
|
nameConfirmedRef.current = false;
|
|
12153
12367
|
return;
|
|
@@ -12158,11 +12372,11 @@ var ResourceHeader = ({
|
|
|
12158
12372
|
}
|
|
12159
12373
|
setEditingName(false);
|
|
12160
12374
|
}, [applyResourcePatch, nameValue, resource.name]);
|
|
12161
|
-
const handleNameCancel =
|
|
12375
|
+
const handleNameCancel = useCallback9(() => {
|
|
12162
12376
|
setNameValue(resource.name);
|
|
12163
12377
|
setEditingName(false);
|
|
12164
12378
|
}, [resource.name]);
|
|
12165
|
-
const handleNameKeyDown =
|
|
12379
|
+
const handleNameKeyDown = useCallback9((event) => {
|
|
12166
12380
|
if (event.key === "Enter") {
|
|
12167
12381
|
nameConfirmedRef.current = true;
|
|
12168
12382
|
const nextName = nameValue.trim();
|
|
@@ -12367,8 +12581,8 @@ var ResourceHeader = ({
|
|
|
12367
12581
|
};
|
|
12368
12582
|
var NewResourceRow = ({ height, onConfirm, onCancel, columnTemplate }) => {
|
|
12369
12583
|
const [nameValue, setNameValue] = useState10("");
|
|
12370
|
-
const inputRef =
|
|
12371
|
-
const confirmedRef =
|
|
12584
|
+
const inputRef = useRef11(null);
|
|
12585
|
+
const confirmedRef = useRef11(false);
|
|
12372
12586
|
useEffect10(() => {
|
|
12373
12587
|
inputRef.current?.focus();
|
|
12374
12588
|
inputRef.current?.select();
|
|
@@ -12454,13 +12668,13 @@ function ResourceTimelineChart({
|
|
|
12454
12668
|
resourceTableColumnWidths,
|
|
12455
12669
|
onResourceTableColumnWidthsChange
|
|
12456
12670
|
}) {
|
|
12457
|
-
const scrollContainerRef =
|
|
12458
|
-
const gridRef =
|
|
12459
|
-
const panStateRef =
|
|
12460
|
-
const resourceColumnResizeRef =
|
|
12461
|
-
const conflictNavigationIndexRef =
|
|
12462
|
-
const resourceNavigationIndexRef =
|
|
12463
|
-
const conflictHighlightTimeoutRef =
|
|
12671
|
+
const scrollContainerRef = useRef11(null);
|
|
12672
|
+
const gridRef = useRef11(null);
|
|
12673
|
+
const panStateRef = useRef11(null);
|
|
12674
|
+
const resourceColumnResizeRef = useRef11(null);
|
|
12675
|
+
const conflictNavigationIndexRef = useRef11(/* @__PURE__ */ new Map());
|
|
12676
|
+
const resourceNavigationIndexRef = useRef11(/* @__PURE__ */ new Map());
|
|
12677
|
+
const conflictHighlightTimeoutRef = useRef11(null);
|
|
12464
12678
|
const [isCreatingResource, setIsCreatingResource] = useState10(false);
|
|
12465
12679
|
const [creatingResourceGroupType, setCreatingResourceGroupType] = useState10(null);
|
|
12466
12680
|
const [activeConflictItemId, setActiveConflictItemId] = useState10(null);
|
|
@@ -12534,7 +12748,7 @@ function ResourceTimelineChart({
|
|
|
12534
12748
|
const canAddResource = enableAddResource && Boolean(onAddResource);
|
|
12535
12749
|
const resourceAddRowHeight = laneHeight + DEFAULT_RESOURCE_ROW_GAP;
|
|
12536
12750
|
const [collapsedResourceGroups, setCollapsedResourceGroups] = useState10(/* @__PURE__ */ new Set());
|
|
12537
|
-
const updateResourceColumnWidth =
|
|
12751
|
+
const updateResourceColumnWidth = useCallback9((columnId, width) => {
|
|
12538
12752
|
setResourceColumnWidthOverrides((prev) => {
|
|
12539
12753
|
if (prev[columnId] === width) {
|
|
12540
12754
|
return prev;
|
|
@@ -12573,7 +12787,7 @@ function ResourceTimelineChart({
|
|
|
12573
12787
|
document.body.style.removeProperty("user-select");
|
|
12574
12788
|
};
|
|
12575
12789
|
}, [updateResourceColumnWidth]);
|
|
12576
|
-
const startResourceColumnResize =
|
|
12790
|
+
const startResourceColumnResize = useCallback9((columnId, event) => {
|
|
12577
12791
|
const width = resolvedResourceColumnWidths[columnId];
|
|
12578
12792
|
if (typeof width !== "number") {
|
|
12579
12793
|
return;
|
|
@@ -12588,7 +12802,7 @@ function ResourceTimelineChart({
|
|
|
12588
12802
|
document.body.style.cursor = "col-resize";
|
|
12589
12803
|
document.body.style.userSelect = "none";
|
|
12590
12804
|
}, [resolvedResourceColumnWidths]);
|
|
12591
|
-
const renderResizeHandle =
|
|
12805
|
+
const renderResizeHandle = useCallback9((columnId) => /* @__PURE__ */ jsx19(
|
|
12592
12806
|
"button",
|
|
12593
12807
|
{
|
|
12594
12808
|
type: "button",
|
|
@@ -12602,7 +12816,7 @@ function ResourceTimelineChart({
|
|
|
12602
12816
|
}
|
|
12603
12817
|
}
|
|
12604
12818
|
), [startResourceColumnResize]);
|
|
12605
|
-
const toggleResourceGroupCollapsed =
|
|
12819
|
+
const toggleResourceGroupCollapsed = useCallback9((groupKey) => {
|
|
12606
12820
|
setCollapsedResourceGroups((prev) => {
|
|
12607
12821
|
const next = new Set(prev);
|
|
12608
12822
|
if (next.has(groupKey)) {
|
|
@@ -12728,7 +12942,7 @@ function ResourceTimelineChart({
|
|
|
12728
12942
|
}, [displayLayout.items]);
|
|
12729
12943
|
const displayTotalHeight = displayLayout.totalHeight + (canAddResource ? resourceAddRowHeight : 0);
|
|
12730
12944
|
const timelineHeaderHeight = headerHeight + 1;
|
|
12731
|
-
const handleConfirmNewResource =
|
|
12945
|
+
const handleConfirmNewResource = useCallback9((name) => {
|
|
12732
12946
|
onAddResource?.({
|
|
12733
12947
|
id: crypto.randomUUID(),
|
|
12734
12948
|
name,
|
|
@@ -12739,7 +12953,7 @@ function ResourceTimelineChart({
|
|
|
12739
12953
|
setIsCreatingResource(false);
|
|
12740
12954
|
setCreatingResourceGroupType(null);
|
|
12741
12955
|
}, [creatingResourceGroupType, onAddResource]);
|
|
12742
|
-
const handleStartAddResourceToGroup =
|
|
12956
|
+
const handleStartAddResourceToGroup = useCallback9((type) => {
|
|
12743
12957
|
setIsCreatingResource(false);
|
|
12744
12958
|
setCreatingResourceGroupType(type);
|
|
12745
12959
|
setCollapsedResourceGroups((prev) => {
|
|
@@ -12751,11 +12965,11 @@ function ResourceTimelineChart({
|
|
|
12751
12965
|
return next;
|
|
12752
12966
|
});
|
|
12753
12967
|
}, []);
|
|
12754
|
-
const handleCancelNewResource =
|
|
12968
|
+
const handleCancelNewResource = useCallback9(() => {
|
|
12755
12969
|
setIsCreatingResource(false);
|
|
12756
12970
|
setCreatingResourceGroupType(null);
|
|
12757
12971
|
}, []);
|
|
12758
|
-
const handleConflictBadgeClick =
|
|
12972
|
+
const handleConflictBadgeClick = useCallback9((resourceId) => {
|
|
12759
12973
|
const conflictItems = conflictItemsByResourceId.get(resourceId) ?? [];
|
|
12760
12974
|
if (conflictItems.length === 0) {
|
|
12761
12975
|
return;
|
|
@@ -12780,7 +12994,7 @@ function ResourceTimelineChart({
|
|
|
12780
12994
|
conflictHighlightTimeoutRef.current = null;
|
|
12781
12995
|
}, 1600);
|
|
12782
12996
|
}, [conflictItemsByResourceId, dayWidth, laneHeight]);
|
|
12783
|
-
const handleResourceNameClick =
|
|
12997
|
+
const handleResourceNameClick = useCallback9((resourceId) => {
|
|
12784
12998
|
const resourceItems = itemsByResourceId.get(resourceId) ?? [];
|
|
12785
12999
|
if (resourceItems.length === 0) {
|
|
12786
13000
|
return;
|
|
@@ -12825,7 +13039,7 @@ function ResourceTimelineChart({
|
|
|
12825
13039
|
container.removeEventListener("scroll", updateShadow);
|
|
12826
13040
|
};
|
|
12827
13041
|
}, []);
|
|
12828
|
-
const handlePanStart =
|
|
13042
|
+
const handlePanStart = useCallback9((event) => {
|
|
12829
13043
|
if (event.button !== 0) {
|
|
12830
13044
|
return;
|
|
12831
13045
|
}
|
|
@@ -13312,7 +13526,7 @@ function ResourceTimelineChart({
|
|
|
13312
13526
|
}
|
|
13313
13527
|
|
|
13314
13528
|
// src/components/TableMatrix/TableMatrix.tsx
|
|
13315
|
-
import { useLayoutEffect, useMemo as useMemo12, useRef as
|
|
13529
|
+
import { useLayoutEffect, useMemo as useMemo12, useRef as useRef12, useState as useState11 } from "react";
|
|
13316
13530
|
import { jsx as jsx20, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
13317
13531
|
var AUTO_COLUMN_MIN_WIDTH = 72;
|
|
13318
13532
|
var AUTO_COLUMN_MAX_WIDTH = 180;
|
|
@@ -13379,7 +13593,7 @@ function TableMatrix({
|
|
|
13379
13593
|
filterMode = "highlight",
|
|
13380
13594
|
visibleRowIndices
|
|
13381
13595
|
}) {
|
|
13382
|
-
const measureRef =
|
|
13596
|
+
const measureRef = useRef12(null);
|
|
13383
13597
|
const [measuredAutoWidths, setMeasuredAutoWidths] = useState11([]);
|
|
13384
13598
|
const hasAutoWidthColumns = useMemo12(
|
|
13385
13599
|
() => columns.some((column) => typeof column.width !== "number"),
|
|
@@ -13680,7 +13894,7 @@ function TableMatrix({
|
|
|
13680
13894
|
}
|
|
13681
13895
|
|
|
13682
13896
|
// src/components/PlanFactMatrix/PlanFactMatrix.tsx
|
|
13683
|
-
import React17, { useCallback as
|
|
13897
|
+
import React17, { useCallback as useCallback10, useEffect as useEffect11, useMemo as useMemo13, useRef as useRef13, useState as useState12 } from "react";
|
|
13684
13898
|
import { jsx as jsx21, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
13685
13899
|
var DAY_MS6 = 24 * 60 * 60 * 1e3;
|
|
13686
13900
|
function joinClasses2(...values) {
|
|
@@ -13773,7 +13987,7 @@ function PlanFactCellEditor({
|
|
|
13773
13987
|
onCancel
|
|
13774
13988
|
}) {
|
|
13775
13989
|
const [draft, setDraft] = useState12(startValue ?? (value === void 0 ? "" : String(value)));
|
|
13776
|
-
const inputRef =
|
|
13990
|
+
const inputRef = useRef13(null);
|
|
13777
13991
|
useEffect11(() => {
|
|
13778
13992
|
inputRef.current?.focus();
|
|
13779
13993
|
if (startValue === void 0) {
|
|
@@ -13782,7 +13996,7 @@ function PlanFactCellEditor({
|
|
|
13782
13996
|
inputRef.current?.setSelectionRange(startValue.length, startValue.length);
|
|
13783
13997
|
}
|
|
13784
13998
|
}, [startValue]);
|
|
13785
|
-
const commit =
|
|
13999
|
+
const commit = useCallback10(() => {
|
|
13786
14000
|
const parsed = parseNumberInput(draft);
|
|
13787
14001
|
if (parsed === null) {
|
|
13788
14002
|
onCancel();
|
|
@@ -14132,13 +14346,13 @@ function PlanFactMatrix({
|
|
|
14132
14346
|
const [selectedRange, setSelectedRange] = useState12(null);
|
|
14133
14347
|
const [fillRange, setFillRange] = useState12(null);
|
|
14134
14348
|
const [overflowTooltip, setOverflowTooltip] = useState12(null);
|
|
14135
|
-
const isSelectingRef =
|
|
14136
|
-
const isFillDraggingRef =
|
|
14137
|
-
const didDragSelectRef =
|
|
14138
|
-
const pendingHoverCellRef =
|
|
14139
|
-
const hoverFrameRef =
|
|
14140
|
-
const rootRef =
|
|
14141
|
-
const bodyRef =
|
|
14349
|
+
const isSelectingRef = useRef13(false);
|
|
14350
|
+
const isFillDraggingRef = useRef13(false);
|
|
14351
|
+
const didDragSelectRef = useRef13(false);
|
|
14352
|
+
const pendingHoverCellRef = useRef13(null);
|
|
14353
|
+
const hoverFrameRef = useRef13(null);
|
|
14354
|
+
const rootRef = useRef13(null);
|
|
14355
|
+
const bodyRef = useRef13(null);
|
|
14142
14356
|
const totalWidth = dateRange.length * dayWidth;
|
|
14143
14357
|
const subrowHeight = rowHeight / 2;
|
|
14144
14358
|
const renderedRowIndices = useMemo13(
|
|
@@ -14187,7 +14401,7 @@ function PlanFactMatrix({
|
|
|
14187
14401
|
}
|
|
14188
14402
|
return rangeByTaskId;
|
|
14189
14403
|
}, [dateRange.length, dateRangeStartMs, tasks]);
|
|
14190
|
-
const focusCell =
|
|
14404
|
+
const focusCell = useCallback10((cell) => {
|
|
14191
14405
|
window.requestAnimationFrame(() => {
|
|
14192
14406
|
const selector = [
|
|
14193
14407
|
`[data-plan-fact-task-id="${escapeAttributeValue(cell.taskId)}"]`,
|
|
@@ -14197,7 +14411,7 @@ function PlanFactMatrix({
|
|
|
14197
14411
|
bodyRef.current?.querySelector(selector)?.focus();
|
|
14198
14412
|
});
|
|
14199
14413
|
}, []);
|
|
14200
|
-
const clearSelection =
|
|
14414
|
+
const clearSelection = useCallback10(() => {
|
|
14201
14415
|
if (hoverFrameRef.current !== null) {
|
|
14202
14416
|
window.cancelAnimationFrame(hoverFrameRef.current);
|
|
14203
14417
|
hoverFrameRef.current = null;
|
|
@@ -14212,10 +14426,10 @@ function PlanFactMatrix({
|
|
|
14212
14426
|
setFillRange(null);
|
|
14213
14427
|
setOverflowTooltip(null);
|
|
14214
14428
|
}, []);
|
|
14215
|
-
const hideOverflowTooltip =
|
|
14429
|
+
const hideOverflowTooltip = useCallback10(() => {
|
|
14216
14430
|
setOverflowTooltip(null);
|
|
14217
14431
|
}, []);
|
|
14218
|
-
const flushPendingHoverCell =
|
|
14432
|
+
const flushPendingHoverCell = useCallback10(() => {
|
|
14219
14433
|
hoverFrameRef.current = null;
|
|
14220
14434
|
const currentCell = pendingHoverCellRef.current;
|
|
14221
14435
|
if (!currentCell) return;
|
|
@@ -14233,12 +14447,12 @@ function PlanFactMatrix({
|
|
|
14233
14447
|
}));
|
|
14234
14448
|
onTaskSelect?.(currentCell.taskId);
|
|
14235
14449
|
}, [onTaskSelect, selectedRange]);
|
|
14236
|
-
const queueHoverCellUpdate =
|
|
14450
|
+
const queueHoverCellUpdate = useCallback10((cell) => {
|
|
14237
14451
|
pendingHoverCellRef.current = cell;
|
|
14238
14452
|
if (hoverFrameRef.current !== null) return;
|
|
14239
14453
|
hoverFrameRef.current = window.requestAnimationFrame(flushPendingHoverCell);
|
|
14240
14454
|
}, [flushPendingHoverCell]);
|
|
14241
|
-
const showOverflowTooltip =
|
|
14455
|
+
const showOverflowTooltip = useCallback10((target, label, force = false) => {
|
|
14242
14456
|
if (!rootRef.current || !label) return;
|
|
14243
14457
|
if (!force && target.scrollWidth <= target.clientWidth) {
|
|
14244
14458
|
setOverflowTooltip(null);
|
|
@@ -14252,12 +14466,12 @@ function PlanFactMatrix({
|
|
|
14252
14466
|
top: targetRect.top - rootRect.top
|
|
14253
14467
|
});
|
|
14254
14468
|
}, []);
|
|
14255
|
-
const selectSingleCell =
|
|
14469
|
+
const selectSingleCell = useCallback10((cell) => {
|
|
14256
14470
|
setActiveCell(cell);
|
|
14257
14471
|
setSelectedRange({ anchor: cell, focus: cell });
|
|
14258
14472
|
setFillRange(null);
|
|
14259
14473
|
}, []);
|
|
14260
|
-
const getRangeBounds =
|
|
14474
|
+
const getRangeBounds = useCallback10((range) => {
|
|
14261
14475
|
const anchorTaskIndex = taskIndexById.get(range.anchor.taskId);
|
|
14262
14476
|
const focusTaskIndex = taskIndexById.get(range.focus.taskId);
|
|
14263
14477
|
if (anchorTaskIndex === void 0 || focusTaskIndex === void 0) {
|
|
@@ -14281,7 +14495,7 @@ function PlanFactMatrix({
|
|
|
14281
14495
|
() => renderedRange ? getRangeBounds(renderedRange) : null,
|
|
14282
14496
|
[getRangeBounds, renderedRange]
|
|
14283
14497
|
);
|
|
14284
|
-
const getCellFromPosition =
|
|
14498
|
+
const getCellFromPosition = useCallback10((subrowIndex, dateIndex) => {
|
|
14285
14499
|
const task = tasks[Math.floor(subrowIndex / 2)];
|
|
14286
14500
|
if (!task) return null;
|
|
14287
14501
|
return {
|
|
@@ -14290,7 +14504,7 @@ function PlanFactMatrix({
|
|
|
14290
14504
|
kind: subrowIndex % 2 === 0 ? "plan" : "fact"
|
|
14291
14505
|
};
|
|
14292
14506
|
}, [tasks]);
|
|
14293
|
-
const isCellInRange =
|
|
14507
|
+
const isCellInRange = useCallback10((cell, range) => {
|
|
14294
14508
|
const bounds = getRangeBounds(range);
|
|
14295
14509
|
if (!bounds) return false;
|
|
14296
14510
|
const cellTaskIndex = taskIndexById.get(cell.taskId);
|
|
@@ -14300,7 +14514,7 @@ function PlanFactMatrix({
|
|
|
14300
14514
|
const cellSubrowIndex = getSubrowIndex(cellTaskIndex, cell.kind);
|
|
14301
14515
|
return cell.dateIndex >= bounds.fromDateIndex && cell.dateIndex <= bounds.toDateIndex && cellSubrowIndex >= bounds.fromSubrowIndex && cellSubrowIndex <= bounds.toSubrowIndex;
|
|
14302
14516
|
}, [getRangeBounds, taskIndexById]);
|
|
14303
|
-
const commitCell =
|
|
14517
|
+
const commitCell = useCallback10((task, dateIndex, kind, value) => {
|
|
14304
14518
|
const dateKey = dateKeys[dateIndex];
|
|
14305
14519
|
const source = kind === "plan" ? task.planByDate : task.factByDate;
|
|
14306
14520
|
const nextValues = { ...source ?? {} };
|
|
@@ -14322,7 +14536,7 @@ function PlanFactMatrix({
|
|
|
14322
14536
|
value
|
|
14323
14537
|
});
|
|
14324
14538
|
}, [dateKeys, dateRange, onCellCommit, onTasksChange]);
|
|
14325
|
-
const commitRangeCells =
|
|
14539
|
+
const commitRangeCells = useCallback10((bounds, value, mode) => {
|
|
14326
14540
|
const changedTasksById = /* @__PURE__ */ new Map();
|
|
14327
14541
|
for (let subrowIndex = bounds.fromSubrowIndex; subrowIndex <= bounds.toSubrowIndex; subrowIndex += 1) {
|
|
14328
14542
|
const task = tasks[Math.floor(subrowIndex / 2)];
|
|
@@ -14369,7 +14583,7 @@ function PlanFactMatrix({
|
|
|
14369
14583
|
onTasksChange?.(changedTasks);
|
|
14370
14584
|
}
|
|
14371
14585
|
}, [dateKeys, onTasksChange, parentTaskIds, tasks]);
|
|
14372
|
-
const clearSelectedCells =
|
|
14586
|
+
const clearSelectedCells = useCallback10(() => {
|
|
14373
14587
|
const activeRange = fillRange ?? selectedRange;
|
|
14374
14588
|
if (!activeRange) {
|
|
14375
14589
|
if (!activeCell) return;
|
|
@@ -14383,7 +14597,7 @@ function PlanFactMatrix({
|
|
|
14383
14597
|
commitRangeCells(bounds, void 0, "clear");
|
|
14384
14598
|
}
|
|
14385
14599
|
}, [activeCell, commitCell, commitRangeCells, fillRange, getRangeBounds, parentTaskIds, selectedRange, taskById]);
|
|
14386
|
-
const commitSelectedCells =
|
|
14600
|
+
const commitSelectedCells = useCallback10((value) => {
|
|
14387
14601
|
const activeRange = fillRange ?? selectedRange;
|
|
14388
14602
|
if (!activeRange) {
|
|
14389
14603
|
if (!activeCell) return;
|
|
@@ -14397,13 +14611,13 @@ function PlanFactMatrix({
|
|
|
14397
14611
|
commitRangeCells(bounds, value, "set");
|
|
14398
14612
|
}
|
|
14399
14613
|
}, [activeCell, commitCell, commitRangeCells, fillRange, getRangeBounds, parentTaskIds, selectedRange, taskById]);
|
|
14400
|
-
const getCellValue =
|
|
14614
|
+
const getCellValue = useCallback10((cell) => {
|
|
14401
14615
|
const task = taskById.get(cell.taskId);
|
|
14402
14616
|
if (!task) return void 0;
|
|
14403
14617
|
const dateKey = dateKeys[cell.dateIndex];
|
|
14404
14618
|
return cell.kind === "plan" ? task.planByDate?.[dateKey] : task.factByDate?.[dateKey];
|
|
14405
14619
|
}, [dateKeys, taskById]);
|
|
14406
|
-
const applyFillRange =
|
|
14620
|
+
const applyFillRange = useCallback10((nextFillRange) => {
|
|
14407
14621
|
const targetRange = nextFillRange ?? fillRange;
|
|
14408
14622
|
if (!selectedRange || !targetRange) return;
|
|
14409
14623
|
const sourceBounds = getRangeBounds(selectedRange);
|
|
@@ -14476,7 +14690,7 @@ function PlanFactMatrix({
|
|
|
14476
14690
|
selectedRange,
|
|
14477
14691
|
taskById
|
|
14478
14692
|
]);
|
|
14479
|
-
const moveActiveCell =
|
|
14693
|
+
const moveActiveCell = useCallback10((cell, direction) => {
|
|
14480
14694
|
const taskIndex = tasks.findIndex((task) => task.id === cell.taskId);
|
|
14481
14695
|
if (taskIndex < 0) return;
|
|
14482
14696
|
let nextCell = { ...cell };
|
|
@@ -14508,7 +14722,7 @@ function PlanFactMatrix({
|
|
|
14508
14722
|
onTaskSelect?.(nextCell.taskId);
|
|
14509
14723
|
focusCell(nextCell);
|
|
14510
14724
|
}, [dateRange.length, focusCell, onTaskSelect, parentTaskIds, tasks]);
|
|
14511
|
-
const extendSelectedRange =
|
|
14725
|
+
const extendSelectedRange = useCallback10((cell, direction) => {
|
|
14512
14726
|
const taskIndex = tasks.findIndex((task) => task.id === cell.taskId);
|
|
14513
14727
|
if (taskIndex < 0) return;
|
|
14514
14728
|
let nextCell = { ...cell };
|
|
@@ -15303,17 +15517,6 @@ function TaskGanttChartInner(props, ref) {
|
|
|
15303
15517
|
onTaskDateChangeModeChange: externalOnTaskDateChangeModeChange,
|
|
15304
15518
|
printDependencyLabels = false
|
|
15305
15519
|
} = props;
|
|
15306
|
-
const resolvedActivityDependencies = useMemo14(() => {
|
|
15307
|
-
if (activityDependencies !== void 0) return activityDependencies;
|
|
15308
|
-
return tasks.flatMap((task) => (task.activities ?? []).slice(1).map((successor, index) => ({
|
|
15309
|
-
predecessorTaskId: task.id,
|
|
15310
|
-
predecessorActivityId: task.activities[index].id,
|
|
15311
|
-
successorTaskId: task.id,
|
|
15312
|
-
successorActivityId: successor.id,
|
|
15313
|
-
type: "FS",
|
|
15314
|
-
lag: successor.lag ?? 0
|
|
15315
|
-
})));
|
|
15316
|
-
}, [tasks, activityDependencies]);
|
|
15317
15520
|
const dayWidth = !isTableMatrixMode ? props.dayWidth ?? 40 : 40;
|
|
15318
15521
|
const criticalPathMode = !isTableMatrixMode && !isPlanFactMode ? props.criticalPathMode : void 0;
|
|
15319
15522
|
const onSubtreeScaleResult = !isTableMatrixMode && !isPlanFactMode ? props.onSubtreeScaleResult : void 0;
|
|
@@ -15327,17 +15530,17 @@ function TaskGanttChartInner(props, ref) {
|
|
|
15327
15530
|
const onMatrixCellClick = isTableMatrixMode ? props.onMatrixCellClick : void 0;
|
|
15328
15531
|
const matrixDateOverlay = isTableMatrixMode ? props.matrixDateOverlay : void 0;
|
|
15329
15532
|
const onPlanFactCellCommit = isPlanFactMode ? props.onPlanFactCellCommit : void 0;
|
|
15330
|
-
const containerRef =
|
|
15331
|
-
const scrollContainerRef =
|
|
15332
|
-
const scrollContentRef =
|
|
15333
|
-
const clearSelectedTaskTimeoutRef =
|
|
15334
|
-
const hasAutoScrolledToTodayRef =
|
|
15335
|
-
const previewPositionStoreRef =
|
|
15336
|
-
const activityPreviewStoreRef =
|
|
15337
|
-
const activityBlockStoreRef =
|
|
15338
|
-
const activityDragOwnerRef =
|
|
15339
|
-
const activityActivationStoreRef =
|
|
15340
|
-
const renderedTaskIdsRef =
|
|
15533
|
+
const containerRef = useRef14(null);
|
|
15534
|
+
const scrollContainerRef = useRef14(null);
|
|
15535
|
+
const scrollContentRef = useRef14(null);
|
|
15536
|
+
const clearSelectedTaskTimeoutRef = useRef14(null);
|
|
15537
|
+
const hasAutoScrolledToTodayRef = useRef14(false);
|
|
15538
|
+
const previewPositionStoreRef = useRef14(null);
|
|
15539
|
+
const activityPreviewStoreRef = useRef14(null);
|
|
15540
|
+
const activityBlockStoreRef = useRef14(null);
|
|
15541
|
+
const activityDragOwnerRef = useRef14(null);
|
|
15542
|
+
const activityActivationStoreRef = useRef14(null);
|
|
15543
|
+
const renderedTaskIdsRef = useRef14(/* @__PURE__ */ new Set());
|
|
15341
15544
|
if (previewPositionStoreRef.current === null) {
|
|
15342
15545
|
previewPositionStoreRef.current = createTaskPreviewPositionStore();
|
|
15343
15546
|
}
|
|
@@ -15373,10 +15576,10 @@ function TaskGanttChartInner(props, ref) {
|
|
|
15373
15576
|
const [planFactDateWindow, setPlanFactDateWindow] = useState13({ start: 0, end: 0 });
|
|
15374
15577
|
const [selectedChip, setSelectedChip] = useState13(null);
|
|
15375
15578
|
const [dependencyCreationDrag, setDependencyCreationDrag] = useState13(null);
|
|
15376
|
-
const dependencyCreationRef =
|
|
15579
|
+
const dependencyCreationRef = useRef14(null);
|
|
15377
15580
|
const [dependencyCreationError, setDependencyCreationError] = useState13(null);
|
|
15378
15581
|
const [dependencyLineMenu, setDependencyLineMenu] = useState13(null);
|
|
15379
|
-
const getDependencyPortPoint =
|
|
15582
|
+
const getDependencyPortPoint = useCallback11((element, chartRect) => {
|
|
15380
15583
|
const rect = element.getBoundingClientRect();
|
|
15381
15584
|
const side = element.getAttribute("data-port-side");
|
|
15382
15585
|
return {
|
|
@@ -15390,13 +15593,13 @@ function TaskGanttChartInner(props, ref) {
|
|
|
15390
15593
|
y: rect.top + rect.height / 2 - chartRect.top
|
|
15391
15594
|
};
|
|
15392
15595
|
}, []);
|
|
15393
|
-
const getVisualDependencyType =
|
|
15596
|
+
const getVisualDependencyType = useCallback11((sourceSide, targetSide) => {
|
|
15394
15597
|
if (sourceSide === "right" && targetSide === "left") return "FS";
|
|
15395
15598
|
if (sourceSide === "left" && targetSide === "left") return "SS";
|
|
15396
15599
|
if (sourceSide === "right" && targetSide === "right") return "FF";
|
|
15397
15600
|
return "SF";
|
|
15398
15601
|
}, []);
|
|
15399
|
-
const handleDependencyPortPointerDown =
|
|
15602
|
+
const handleDependencyPortPointerDown = useCallback11((sourceId, sourceSide, event) => {
|
|
15400
15603
|
if (disableDependencyEditing || event.button !== 0) return;
|
|
15401
15604
|
const chartElement = event.currentTarget.closest(".gantt-taskArea");
|
|
15402
15605
|
if (!(chartElement instanceof HTMLElement)) return;
|
|
@@ -15514,7 +15717,7 @@ function TaskGanttChartInner(props, ref) {
|
|
|
15514
15717
|
document.removeEventListener("keydown", closeOnEscape);
|
|
15515
15718
|
};
|
|
15516
15719
|
}, [dependencyLineMenu]);
|
|
15517
|
-
const handleDependencyLineClick =
|
|
15720
|
+
const handleDependencyLineClick = useCallback11((dependency) => {
|
|
15518
15721
|
setSelectedChip({
|
|
15519
15722
|
predecessorId: dependency.predecessorId,
|
|
15520
15723
|
successorId: dependency.successorId,
|
|
@@ -15522,10 +15725,10 @@ function TaskGanttChartInner(props, ref) {
|
|
|
15522
15725
|
});
|
|
15523
15726
|
setDependencyLineMenu(dependency);
|
|
15524
15727
|
}, []);
|
|
15525
|
-
const handleDependencyLineClose =
|
|
15728
|
+
const handleDependencyLineClose = useCallback11(() => {
|
|
15526
15729
|
setDependencyLineMenu(null);
|
|
15527
15730
|
}, []);
|
|
15528
|
-
const handleDependencyLineDelete =
|
|
15731
|
+
const handleDependencyLineDelete = useCallback11(() => {
|
|
15529
15732
|
if (!dependencyLineMenu) return;
|
|
15530
15733
|
const successor = tasks.find((task) => task.id === dependencyLineMenu.successorId);
|
|
15531
15734
|
if (!successor) return;
|
|
@@ -15582,7 +15785,7 @@ function TaskGanttChartInner(props, ref) {
|
|
|
15582
15785
|
() => buildControlledScheduleIdentity(normalizedTasks),
|
|
15583
15786
|
[normalizedTasks]
|
|
15584
15787
|
);
|
|
15585
|
-
const previousControlledScheduleIdentityRef =
|
|
15788
|
+
const previousControlledScheduleIdentityRef = useRef14(null);
|
|
15586
15789
|
const controlledScheduleChanged = previousControlledScheduleIdentityRef.current !== null && previousControlledScheduleIdentityRef.current !== controlledScheduleIdentity;
|
|
15587
15790
|
const [previewTasksById, setPreviewTasksById] = useState13(/* @__PURE__ */ new Map());
|
|
15588
15791
|
const previewNormalizedTasks = useMemo14(() => {
|
|
@@ -15831,7 +16034,7 @@ function TaskGanttChartInner(props, ref) {
|
|
|
15831
16034
|
window.removeEventListener("resize", scheduleUpdate);
|
|
15832
16035
|
};
|
|
15833
16036
|
}, [dateRange.length, dayWidth, isPlanFactMode, showTaskList, taskListWidth, timelineHeaderHeight]);
|
|
15834
|
-
const scrollToToday =
|
|
16037
|
+
const scrollToToday = useCallback11(() => {
|
|
15835
16038
|
if (isTableMatrixMode) return;
|
|
15836
16039
|
const container = scrollContainerRef.current;
|
|
15837
16040
|
if (!container || dateRange.length === 0) return;
|
|
@@ -15843,7 +16046,7 @@ function TaskGanttChartInner(props, ref) {
|
|
|
15843
16046
|
const scrollLeft = Math.round(todayOffset + dayWidth / 2 - containerWidth * 0.3);
|
|
15844
16047
|
container.scrollTo({ left: Math.max(0, scrollLeft), behavior: "smooth" });
|
|
15845
16048
|
}, [dateRange, dayWidth, isTableMatrixMode]);
|
|
15846
|
-
const scrollToTask =
|
|
16049
|
+
const scrollToTask = useCallback11((taskId) => {
|
|
15847
16050
|
if (isTableMatrixMode) {
|
|
15848
16051
|
const container2 = scrollContainerRef.current;
|
|
15849
16052
|
if (!container2) return;
|
|
@@ -15870,7 +16073,7 @@ function TaskGanttChartInner(props, ref) {
|
|
|
15870
16073
|
const scrollLeft = Math.round(taskOffset - dayWidth * 2);
|
|
15871
16074
|
container.scrollTo({ left: Math.max(0, scrollLeft), behavior: "smooth" });
|
|
15872
16075
|
}, [dateRange, dayWidth, effectiveRowHeight, compositeRowLayout, isTableMatrixMode, tasks, visibleTasks]);
|
|
15873
|
-
const scrollToRow =
|
|
16076
|
+
const scrollToRow = useCallback11((taskId, options = {}) => {
|
|
15874
16077
|
const container = scrollContainerRef.current;
|
|
15875
16078
|
if (!container) return;
|
|
15876
16079
|
const task = tasks.find((t) => t.id === taskId);
|
|
@@ -15932,7 +16135,7 @@ function TaskGanttChartInner(props, ref) {
|
|
|
15932
16135
|
activityDragOwner.set(null);
|
|
15933
16136
|
activityActivationStore.setActiveKey(null);
|
|
15934
16137
|
}, [previewPositionStore, activityPreviewStore, activityBlockStore, activityDragOwner, activityActivationStore]);
|
|
15935
|
-
const handleTaskChange =
|
|
16138
|
+
const handleTaskChange = useCallback11((updatedTasks, durationEdit) => {
|
|
15936
16139
|
let updatedTask = updatedTasks[0];
|
|
15937
16140
|
if (!updatedTask) return;
|
|
15938
16141
|
const originalTask = normalizedTasks.find((t) => t.id === updatedTask.id);
|
|
@@ -16068,7 +16271,7 @@ function TaskGanttChartInner(props, ref) {
|
|
|
16068
16271
|
onTasksChange?.(cascadedTasks);
|
|
16069
16272
|
}
|
|
16070
16273
|
}, [tasks, normalizedTasks, onTasksChange, onScheduleIntent, disableConstraints, editingTaskId, businessDays, isCustomWeekend, onSubtreeScaleResult]);
|
|
16071
|
-
const handleTaskDurationChange =
|
|
16274
|
+
const handleTaskDurationChange = useCallback11((task, duration) => {
|
|
16072
16275
|
const updatedTask = {
|
|
16073
16276
|
...task,
|
|
16074
16277
|
endDate: task.type === "milestone" ? task.startDate : buildTaskRangeFromStart(
|
|
@@ -16080,7 +16283,7 @@ function TaskGanttChartInner(props, ref) {
|
|
|
16080
16283
|
};
|
|
16081
16284
|
handleTaskChange([updatedTask], { duration, anchor: "start" });
|
|
16082
16285
|
}, [businessDays, handleTaskChange, isCustomWeekend]);
|
|
16083
|
-
const handleDelete =
|
|
16286
|
+
const handleDelete = useCallback11((taskId) => {
|
|
16084
16287
|
const toDelete = /* @__PURE__ */ new Set([taskId]);
|
|
16085
16288
|
function collectDescendants(parentId) {
|
|
16086
16289
|
const children = getChildren(parentId, tasks);
|
|
@@ -16105,10 +16308,10 @@ function TaskGanttChartInner(props, ref) {
|
|
|
16105
16308
|
}
|
|
16106
16309
|
toDelete.forEach((id) => onDelete?.(id));
|
|
16107
16310
|
}, [tasks, onTasksChange, onDelete]);
|
|
16108
|
-
const handleInsertAfter =
|
|
16311
|
+
const handleInsertAfter = useCallback11((taskId, newTask) => {
|
|
16109
16312
|
onInsertAfter?.(taskId, newTask);
|
|
16110
16313
|
}, [onInsertAfter]);
|
|
16111
|
-
const handleReorder =
|
|
16314
|
+
const handleReorder = useCallback11((reorderedTasks, movedTaskId, inferredParentId) => {
|
|
16112
16315
|
let updated = reorderedTasks;
|
|
16113
16316
|
if (movedTaskId) {
|
|
16114
16317
|
updated = updated.map((t) => {
|
|
@@ -16140,7 +16343,7 @@ function TaskGanttChartInner(props, ref) {
|
|
|
16140
16343
|
}
|
|
16141
16344
|
return map;
|
|
16142
16345
|
}, [cascadeOverrides, controlledScheduleChanged, draggedTaskOverride]);
|
|
16143
|
-
const handleCascadeProgress =
|
|
16346
|
+
const handleCascadeProgress = useCallback11((overrides, previewTasks = []) => {
|
|
16144
16347
|
previewPositionStore.setPositions(overrides);
|
|
16145
16348
|
const renderedTaskIds = renderedTaskIdsRef.current;
|
|
16146
16349
|
const renderedOverrides = /* @__PURE__ */ new Map();
|
|
@@ -16220,7 +16423,7 @@ function TaskGanttChartInner(props, ref) {
|
|
|
16220
16423
|
}
|
|
16221
16424
|
}
|
|
16222
16425
|
return Array.from(indices).sort((left, right) => left - right);
|
|
16223
|
-
}, [compositeRowLayout, forceFullRenderForPrint, forcedRenderedTaskIds, scrollViewport, visibleTaskIndexMap, visibleTasks.length]);
|
|
16426
|
+
}, [compositeRowLayout, forceFullRenderForPrint, forcedRenderedTaskIds, scrollViewport.scrollTop, scrollViewport.viewportHeight, visibleTaskIndexMap, visibleTasks.length]);
|
|
16224
16427
|
const visiblePlanFactDateIndices = useMemo14(() => {
|
|
16225
16428
|
if (forceFullRenderForPrint) {
|
|
16226
16429
|
return void 0;
|
|
@@ -16249,22 +16452,22 @@ function TaskGanttChartInner(props, ref) {
|
|
|
16249
16452
|
() => new Set(renderedChartTasks.map(({ task }) => task.id)),
|
|
16250
16453
|
[renderedChartTasks]
|
|
16251
16454
|
);
|
|
16252
|
-
const handleCascade =
|
|
16455
|
+
const handleCascade = useCallback11((cascadedTasks) => {
|
|
16253
16456
|
if (!onScheduleIntent) {
|
|
16254
16457
|
onTasksChange?.(cascadedTasks);
|
|
16255
16458
|
}
|
|
16256
16459
|
}, [onScheduleIntent, onTasksChange]);
|
|
16257
|
-
const handleTaskSelect =
|
|
16460
|
+
const handleTaskSelect = useCallback11((taskId) => {
|
|
16258
16461
|
setSelectedTaskId(taskId);
|
|
16259
16462
|
}, []);
|
|
16260
|
-
const hoveredRowElementsRef =
|
|
16261
|
-
const clearHoveredRows =
|
|
16463
|
+
const hoveredRowElementsRef = useRef14([]);
|
|
16464
|
+
const clearHoveredRows = useCallback11(() => {
|
|
16262
16465
|
for (const element of hoveredRowElementsRef.current) {
|
|
16263
16466
|
element.classList.remove("gantt-tl-row-hovered", "gantt-tr-row-hovered", "gantt-mx-row-hovered", "gantt-pf-row-hovered");
|
|
16264
16467
|
}
|
|
16265
16468
|
hoveredRowElementsRef.current = [];
|
|
16266
16469
|
}, []);
|
|
16267
|
-
const applyHoveredRows =
|
|
16470
|
+
const applyHoveredRows = useCallback11((taskId) => {
|
|
16268
16471
|
const root = scrollContentRef.current;
|
|
16269
16472
|
if (!root) return;
|
|
16270
16473
|
clearHoveredRows();
|
|
@@ -16287,7 +16490,7 @@ function TaskGanttChartInner(props, ref) {
|
|
|
16287
16490
|
}
|
|
16288
16491
|
hoveredRowElementsRef.current = nextHoveredRows;
|
|
16289
16492
|
}, [clearHoveredRows]);
|
|
16290
|
-
const handleSharedRowHover =
|
|
16493
|
+
const handleSharedRowHover = useCallback11((event) => {
|
|
16291
16494
|
const target = event.target;
|
|
16292
16495
|
const row = target.closest("[data-gantt-task-row-id]");
|
|
16293
16496
|
const taskId = row?.dataset.ganttTaskRowId;
|
|
@@ -16317,7 +16520,7 @@ function TaskGanttChartInner(props, ref) {
|
|
|
16317
16520
|
return next;
|
|
16318
16521
|
});
|
|
16319
16522
|
});
|
|
16320
|
-
const lastCompositeBarToggleRef =
|
|
16523
|
+
const lastCompositeBarToggleRef = useRef14(null);
|
|
16321
16524
|
const handleCompositeBarToggle = (taskId, source) => {
|
|
16322
16525
|
const now = Date.now();
|
|
16323
16526
|
if (source === "click" && lastCompositeBarToggleRef.current?.source === "release" && lastCompositeBarToggleRef.current.id === taskId && now - lastCompositeBarToggleRef.current.time < 150) return;
|
|
@@ -16328,17 +16531,17 @@ function TaskGanttChartInner(props, ref) {
|
|
|
16328
16531
|
const taskIds = new Set(normalizedTasks.map((task) => task.id));
|
|
16329
16532
|
return new Set(normalizedTasks.map((task) => task.parentId).filter((parentId) => Boolean(parentId && taskIds.has(parentId))));
|
|
16330
16533
|
}, [normalizedTasks]);
|
|
16331
|
-
const handleCollapseAll =
|
|
16534
|
+
const handleCollapseAll = useCallback11(() => {
|
|
16332
16535
|
if (externalCollapsedParentIds) return;
|
|
16333
16536
|
setInternalCollapsedParentIds(allParentIds);
|
|
16334
16537
|
setExpandedCompositeIds(/* @__PURE__ */ new Set());
|
|
16335
16538
|
}, [allParentIds, externalCollapsedParentIds]);
|
|
16336
|
-
const handleExpandAll =
|
|
16539
|
+
const handleExpandAll = useCallback11(() => {
|
|
16337
16540
|
if (externalCollapsedParentIds) return;
|
|
16338
16541
|
setInternalCollapsedParentIds(/* @__PURE__ */ new Set());
|
|
16339
16542
|
setExpandedCompositeIds(new Set(normalizedTasks.filter((task) => task.composite).map((task) => task.id)));
|
|
16340
16543
|
}, [externalCollapsedParentIds, normalizedTasks]);
|
|
16341
|
-
const exportToPdf =
|
|
16544
|
+
const exportToPdf = useCallback11(async (options) => {
|
|
16342
16545
|
const sourceContainer = containerRef.current;
|
|
16343
16546
|
if (!sourceContainer || typeof window === "undefined" || typeof document === "undefined") {
|
|
16344
16547
|
return;
|
|
@@ -16411,7 +16614,7 @@ function TaskGanttChartInner(props, ref) {
|
|
|
16411
16614
|
}
|
|
16412
16615
|
return depth;
|
|
16413
16616
|
}
|
|
16414
|
-
const handlePromoteTask =
|
|
16617
|
+
const handlePromoteTask = useCallback11((taskId) => {
|
|
16415
16618
|
if (onPromoteTask) {
|
|
16416
16619
|
onPromoteTask(taskId);
|
|
16417
16620
|
return;
|
|
@@ -16443,7 +16646,7 @@ function TaskGanttChartInner(props, ref) {
|
|
|
16443
16646
|
]);
|
|
16444
16647
|
onTasksChange?.(reorderedTasks);
|
|
16445
16648
|
}, [tasks, onTasksChange, onPromoteTask]);
|
|
16446
|
-
const handleDemoteTask =
|
|
16649
|
+
const handleDemoteTask = useCallback11((taskId, newParentId) => {
|
|
16447
16650
|
if (onDemoteTask) {
|
|
16448
16651
|
onDemoteTask(taskId, newParentId);
|
|
16449
16652
|
return;
|
|
@@ -16484,7 +16687,7 @@ function TaskGanttChartInner(props, ref) {
|
|
|
16484
16687
|
};
|
|
16485
16688
|
onTasksChange?.([updatedDemotedTask]);
|
|
16486
16689
|
}, [tasks, onTasksChange, onDemoteTask]);
|
|
16487
|
-
const handleUngroupTask =
|
|
16690
|
+
const handleUngroupTask = useCallback11((taskId) => {
|
|
16488
16691
|
if (onUngroupTask) {
|
|
16489
16692
|
onUngroupTask(taskId);
|
|
16490
16693
|
return;
|
|
@@ -16509,8 +16712,8 @@ function TaskGanttChartInner(props, ref) {
|
|
|
16509
16712
|
onTasksChange?.(changedTasks);
|
|
16510
16713
|
}
|
|
16511
16714
|
}, [tasks, onTasksChange, onUngroupTask]);
|
|
16512
|
-
const panStateRef =
|
|
16513
|
-
const handlePanStart =
|
|
16715
|
+
const panStateRef = useRef14(null);
|
|
16716
|
+
const handlePanStart = useCallback11((e) => {
|
|
16514
16717
|
if (e.button !== 0) return;
|
|
16515
16718
|
const target = e.target;
|
|
16516
16719
|
if (!target.closest(".gantt-tr-activityBar")) {
|
|
@@ -16534,6 +16737,7 @@ function TaskGanttChartInner(props, ref) {
|
|
|
16534
16737
|
if (document.activeElement instanceof HTMLElement) {
|
|
16535
16738
|
document.activeElement.blur();
|
|
16536
16739
|
}
|
|
16740
|
+
container.setAttribute("data-panning", "true");
|
|
16537
16741
|
container.style.cursor = "grabbing";
|
|
16538
16742
|
e.preventDefault();
|
|
16539
16743
|
}, [activityActivationStore]);
|
|
@@ -16571,7 +16775,10 @@ function TaskGanttChartInner(props, ref) {
|
|
|
16571
16775
|
}
|
|
16572
16776
|
panStateRef.current = null;
|
|
16573
16777
|
const container = scrollContainerRef.current;
|
|
16574
|
-
if (container)
|
|
16778
|
+
if (container) {
|
|
16779
|
+
container.removeAttribute("data-panning");
|
|
16780
|
+
container.style.cursor = "";
|
|
16781
|
+
}
|
|
16575
16782
|
};
|
|
16576
16783
|
window.addEventListener("mousemove", handlePanMove);
|
|
16577
16784
|
window.addEventListener("mouseup", handlePanEnd);
|
|
@@ -16790,7 +16997,7 @@ function TaskGanttChartInner(props, ref) {
|
|
|
16790
16997
|
onHoverEnd: () => setActiveTimelineTooltip(null)
|
|
16791
16998
|
}
|
|
16792
16999
|
),
|
|
16793
|
-
showActivityLinks &&
|
|
17000
|
+
showActivityLinks && activityDependencies !== void 0 && /* @__PURE__ */ jsx22(ActivityDependencyLines, { tasks: previewVisibleTasks, renderedTaskIds: renderedTaskIdsRef.current, dependencies: activityDependencies, highlight: activityDependencyHighlight, monthStart, dayWidth, rowHeight: effectiveRowHeight, gridWidth: renderGridWidth, totalHeight: totalGridHeight, rowIndexByTaskId: visibleTaskIndexMap, rowTops: compositeRowLayout.tops, rowHeights: compositeRowLayout.heights, showLag: showActivityLag, previewStore: activityPreviewStore, horizontalWindow }),
|
|
16794
17001
|
/* @__PURE__ */ jsx22(
|
|
16795
17002
|
DependencyLines_default,
|
|
16796
17003
|
{
|
|
@@ -16933,10 +17140,10 @@ function TaskGanttChartInner(props, ref) {
|
|
|
16933
17140
|
activityActivationStore,
|
|
16934
17141
|
activityClickToDrag,
|
|
16935
17142
|
activityActivationMode,
|
|
16936
|
-
showActivityLinks:
|
|
17143
|
+
showActivityLinks: showActivityLinks && activityDependencies === void 0,
|
|
16937
17144
|
showActivityLag,
|
|
16938
17145
|
activityTooltip,
|
|
16939
|
-
horizontalWindow,
|
|
17146
|
+
horizontalWindow: forceFullRenderForPrint ? void 0 : horizontalWindow,
|
|
16940
17147
|
onCascadeProgress: handleCascadeProgress,
|
|
16941
17148
|
onCascade: handleCascade,
|
|
16942
17149
|
onScheduleIntent,
|