gantt-lib 0.135.8 → 0.136.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/README.md +22 -0
- package/dist/core/scheduling/index.d.mts +1 -1
- package/dist/core/scheduling/index.d.ts +1 -1
- package/dist/{index-DR8Q6-de.d.mts → index-D99kbU4p.d.mts} +5 -0
- package/dist/{index-DR8Q6-de.d.ts → index-D99kbU4p.d.ts} +5 -0
- package/dist/index.css.map +1 -1
- package/dist/index.d.mts +20 -3
- package/dist/index.d.ts +20 -3
- package/dist/index.js +480 -155
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +674 -351
- package/dist/index.mjs.map +1 -1
- package/dist/styles.css +248 -24
- 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 useMemo13, useCallback as useCallback10, useRef as
|
|
6
|
+
import { useMemo as useMemo13, useCallback as useCallback10, useRef as useRef13, useState as useState13, useEffect as useEffect11, useImperativeHandle, forwardRef } from "react";
|
|
7
7
|
|
|
8
8
|
// src/core/scheduling/dateMath.ts
|
|
9
9
|
var DAY_MS = 24 * 60 * 60 * 1e3;
|
|
@@ -3155,7 +3155,8 @@ var TimeScaleHeader = ({
|
|
|
3155
3155
|
var TimeScaleHeader_default = TimeScaleHeader;
|
|
3156
3156
|
|
|
3157
3157
|
// src/components/TaskRow/TaskRow.tsx
|
|
3158
|
-
import React2, { useCallback as useCallback2, useMemo as useMemo2, useSyncExternalStore } from "react";
|
|
3158
|
+
import React2, { useCallback as useCallback2, useEffect as useEffect2, useMemo as useMemo2, useRef as useRef2, useState as useState2, useSyncExternalStore } from "react";
|
|
3159
|
+
import { createPortal } from "react-dom";
|
|
3159
3160
|
|
|
3160
3161
|
// src/utils/geometry.ts
|
|
3161
3162
|
var getUTCDayDifference = (date1, date2) => {
|
|
@@ -3241,19 +3242,20 @@ var pixelsToDate = (pixels, monthStart, dayWidth) => {
|
|
|
3241
3242
|
var calculateGridWidth = (daysInMonth, dayWidth) => {
|
|
3242
3243
|
return Math.round(daysInMonth * dayWidth);
|
|
3243
3244
|
};
|
|
3245
|
+
var MIN_EDGE_ZONE_PX = 8;
|
|
3246
|
+
var MIN_MOVE_ZONE_PX = 16;
|
|
3244
3247
|
var detectEdgeZone = (clientX, taskBarElement, edgeZoneWidth = 12) => {
|
|
3245
3248
|
const rect = taskBarElement.getBoundingClientRect();
|
|
3246
3249
|
const relativeX = Math.round(clientX - rect.left);
|
|
3247
3250
|
const width = Math.round(rect.width);
|
|
3248
|
-
|
|
3249
|
-
|
|
3250
|
-
|
|
3251
|
-
|
|
3252
|
-
|
|
3253
|
-
if (relativeX >= 0 && relativeX <= edgeZoneWidth) {
|
|
3251
|
+
const effectiveZone = Math.max(
|
|
3252
|
+
MIN_EDGE_ZONE_PX,
|
|
3253
|
+
Math.min(edgeZoneWidth, (width - MIN_MOVE_ZONE_PX) / 2)
|
|
3254
|
+
);
|
|
3255
|
+
if (relativeX >= 0 && relativeX <= effectiveZone) {
|
|
3254
3256
|
return "left";
|
|
3255
3257
|
}
|
|
3256
|
-
if (relativeX >= width -
|
|
3258
|
+
if (relativeX >= width - effectiveZone && relativeX <= width) {
|
|
3257
3259
|
return "right";
|
|
3258
3260
|
}
|
|
3259
3261
|
return "move";
|
|
@@ -3873,8 +3875,7 @@ var useTaskDrag = (options) => {
|
|
|
3873
3875
|
locked = false,
|
|
3874
3876
|
disableTaskDrag = false,
|
|
3875
3877
|
businessDays = true,
|
|
3876
|
-
weekendPredicate
|
|
3877
|
-
viewMode = "day"
|
|
3878
|
+
weekendPredicate
|
|
3878
3879
|
} = options;
|
|
3879
3880
|
const rawHookTask = allTasks.find((t) => t.id === taskId);
|
|
3880
3881
|
const hookTask = rawHookTask ? normalizeTaskDatesForType(rawHookTask) : void 0;
|
|
@@ -4146,23 +4147,18 @@ var useTaskDrag = (options) => {
|
|
|
4146
4147
|
if (effectiveLocked) return;
|
|
4147
4148
|
const target = e.currentTarget;
|
|
4148
4149
|
const currentTask = allTasks.find((t) => t.id === taskId);
|
|
4149
|
-
const isSingleDayTask = !!currentTask && !isMilestoneTask(currentTask) && !isTaskParent(taskId, allTasks) && currentWidth <= dayWidth && viewMode === "day";
|
|
4150
4150
|
let mode = null;
|
|
4151
|
-
|
|
4152
|
-
|
|
4153
|
-
|
|
4154
|
-
|
|
4155
|
-
|
|
4156
|
-
|
|
4157
|
-
|
|
4158
|
-
|
|
4159
|
-
|
|
4160
|
-
|
|
4161
|
-
|
|
4162
|
-
case "move":
|
|
4163
|
-
mode = "move";
|
|
4164
|
-
break;
|
|
4165
|
-
}
|
|
4151
|
+
const edgeZone = detectEdgeZone(e.clientX, target, edgeZoneWidth);
|
|
4152
|
+
switch (edgeZone) {
|
|
4153
|
+
case "left":
|
|
4154
|
+
mode = "resize-left";
|
|
4155
|
+
break;
|
|
4156
|
+
case "right":
|
|
4157
|
+
mode = "resize-right";
|
|
4158
|
+
break;
|
|
4159
|
+
case "move":
|
|
4160
|
+
mode = "move";
|
|
4161
|
+
break;
|
|
4166
4162
|
}
|
|
4167
4163
|
if (mode === "resize-left" || mode === "resize-right") {
|
|
4168
4164
|
if (currentTask && isMilestoneTask(currentTask)) {
|
|
@@ -4212,7 +4208,7 @@ var useTaskDrag = (options) => {
|
|
|
4212
4208
|
cascadeContext: shouldBuildCascadeContext ? createCascadeContext(allTasks) : void 0,
|
|
4213
4209
|
scheduleIntentMode: Boolean(onScheduleIntent)
|
|
4214
4210
|
};
|
|
4215
|
-
}, [edgeZoneWidth, currentLeft, currentWidth, dayWidth, monthStart, taskId, onDragStateChange, handleProgress, handleComplete, handleCancel, allTasks, disableConstraints, deferCascadePreview, onCascadeProgress, onCascade, effectiveLocked
|
|
4211
|
+
}, [edgeZoneWidth, currentLeft, currentWidth, dayWidth, monthStart, taskId, onDragStateChange, handleProgress, handleComplete, handleCancel, allTasks, disableConstraints, deferCascadePreview, onCascadeProgress, onCascade, effectiveLocked]);
|
|
4216
4212
|
const handleMouseDown = useCallback((e) => {
|
|
4217
4213
|
startDrag(e);
|
|
4218
4214
|
}, [startDrag]);
|
|
@@ -4231,14 +4227,13 @@ var useTaskDrag = (options) => {
|
|
|
4231
4227
|
}
|
|
4232
4228
|
const target = e.currentTarget;
|
|
4233
4229
|
const currentTask = allTasks.find((t) => t.id === taskId);
|
|
4234
|
-
|
|
4235
|
-
if (isSingleDayTask || currentTask && isMilestoneTask(currentTask)) {
|
|
4230
|
+
if (currentTask && isMilestoneTask(currentTask)) {
|
|
4236
4231
|
setHoverCursor("grab");
|
|
4237
4232
|
return;
|
|
4238
4233
|
}
|
|
4239
4234
|
const edgeZone = detectEdgeZone(e.clientX, target, edgeZoneWidth);
|
|
4240
4235
|
setHoverCursor(edgeZone === "move" ? "grab" : "ew-resize");
|
|
4241
|
-
}, [disableTaskDrag, locked, isDragging, allTasks, taskId,
|
|
4236
|
+
}, [disableTaskDrag, locked, isDragging, allTasks, taskId, edgeZoneWidth]);
|
|
4242
4237
|
const handleMouseLeave = useCallback(() => {
|
|
4243
4238
|
setHoverCursor(disableTaskDrag ? "grab" : locked ? "not-allowed" : isDragging ? "grabbing" : "grab");
|
|
4244
4239
|
}, [disableTaskDrag, locked, isDragging]);
|
|
@@ -4269,12 +4264,35 @@ var useTaskDrag = (options) => {
|
|
|
4269
4264
|
|
|
4270
4265
|
// src/components/TaskRow/TaskRow.tsx
|
|
4271
4266
|
import { Fragment, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
4267
|
+
var formatCompositePreviewDate = (date) => {
|
|
4268
|
+
const month = new Intl.DateTimeFormat("ru-RU", { month: "short", timeZone: "UTC" }).format(date).replace(/\.$/, "");
|
|
4269
|
+
const yearSuffix = date.getUTCFullYear() === (/* @__PURE__ */ new Date()).getFullYear() ? "" : ` ${String(date.getUTCFullYear()).slice(-2)}`;
|
|
4270
|
+
return `${date.getUTCDate()} ${month}${yearSuffix}`;
|
|
4271
|
+
};
|
|
4272
4272
|
var arePropsEqual = (prevProps, nextProps) => {
|
|
4273
|
-
return prevProps.task.id === nextProps.task.id && prevProps.task.name === nextProps.task.name && prevProps.task.startDate === nextProps.task.startDate && prevProps.task.endDate === nextProps.task.endDate && prevProps.task.baselineStartDate === nextProps.task.baselineStartDate && prevProps.task.baselineEndDate === nextProps.task.baselineEndDate && prevProps.task.type === nextProps.task.type && prevProps.task.color === nextProps.task.color && prevProps.task.progress === nextProps.task.progress && prevProps.task.accepted === nextProps.task.accepted && prevProps.monthStart.getTime() === nextProps.monthStart.getTime() && prevProps.dayWidth === nextProps.dayWidth && prevProps.rowHeight === nextProps.rowHeight && prevProps.overridePosition?.left === nextProps.overridePosition?.left && prevProps.overridePosition?.width === nextProps.overridePosition?.width && prevProps.previewPositionStore === nextProps.previewPositionStore && prevProps.allTasks === nextProps.allTasks && prevProps.disableConstraints === nextProps.disableConstraints && prevProps.deferCascadePreview === nextProps.deferCascadePreview && prevProps.task.locked === nextProps.task.locked && prevProps.task.synced === nextProps.task.synced && prevProps.task.divider === nextProps.task.divider && prevProps.highlightExpiredTasks === nextProps.highlightExpiredTasks && prevProps.isCritical === nextProps.isCritical && prevProps.showBaseline === nextProps.showBaseline && prevProps.isFilterMatch === nextProps.isFilterMatch && prevProps.businessDays === nextProps.businessDays && prevProps.customDays === nextProps.customDays && prevProps.isWeekend === nextProps.isWeekend && prevProps.disableTaskDrag === nextProps.disableTaskDrag && prevProps.disableDependencyEditing === nextProps.disableDependencyEditing && prevProps.isDependencyDragActive === nextProps.isDependencyDragActive && prevProps.viewMode === nextProps.viewMode && prevProps.showTaskDateLabels === nextProps.showTaskDateLabels && prevProps.showTaskNames === nextProps.showTaskNames;
|
|
4273
|
+
return prevProps.task.id === nextProps.task.id && prevProps.task.name === nextProps.task.name && prevProps.task.startDate === nextProps.task.startDate && prevProps.task.endDate === nextProps.task.endDate && prevProps.task.baselineStartDate === nextProps.task.baselineStartDate && prevProps.task.baselineEndDate === nextProps.task.baselineEndDate && prevProps.task.type === nextProps.task.type && prevProps.task.color === nextProps.task.color && prevProps.task.progress === nextProps.task.progress && prevProps.task.accepted === nextProps.task.accepted && prevProps.monthStart.getTime() === nextProps.monthStart.getTime() && prevProps.dayWidth === nextProps.dayWidth && prevProps.rowHeight === nextProps.rowHeight && prevProps.overridePosition?.left === nextProps.overridePosition?.left && prevProps.overridePosition?.width === nextProps.overridePosition?.width && prevProps.previewPositionStore === nextProps.previewPositionStore && prevProps.allTasks === nextProps.allTasks && prevProps.disableConstraints === nextProps.disableConstraints && prevProps.deferCascadePreview === nextProps.deferCascadePreview && prevProps.task.locked === nextProps.task.locked && prevProps.task.synced === nextProps.task.synced && prevProps.task.divider === nextProps.task.divider && prevProps.highlightExpiredTasks === nextProps.highlightExpiredTasks && prevProps.isCritical === nextProps.isCritical && prevProps.showBaseline === nextProps.showBaseline && prevProps.onCompositeToggle === nextProps.onCompositeToggle && prevProps.compactDetail === nextProps.compactDetail && prevProps.compositeParentColor === nextProps.compositeParentColor && prevProps.compositeExpanded === nextProps.compositeExpanded && prevProps.isFilterMatch === nextProps.isFilterMatch && prevProps.businessDays === nextProps.businessDays && prevProps.customDays === nextProps.customDays && prevProps.isWeekend === nextProps.isWeekend && prevProps.disableTaskDrag === nextProps.disableTaskDrag && prevProps.disableDependencyEditing === nextProps.disableDependencyEditing && prevProps.isDependencyDragActive === nextProps.isDependencyDragActive && prevProps.viewMode === nextProps.viewMode && prevProps.showTaskDateLabels === nextProps.showTaskDateLabels && prevProps.showTaskNames === nextProps.showTaskNames;
|
|
4274
4274
|
};
|
|
4275
4275
|
var TaskRow = React2.memo(
|
|
4276
|
-
({ task, monthStart, dayWidth, rowHeight, onTasksChange, onScheduleIntent, onDragStateChange, rowIndex, allTasks, enableAutoSchedule, disableConstraints, deferCascadePreview = false, overridePosition, previewPositionStore, onCascadeProgress, onCascade, divider, highlightExpiredTasks, isCritical = false, showBaseline = false, isFilterMatch = false, businessDays, customDays, isWeekend: isWeekend3, disableTaskDrag = false, disableDependencyEditing = false, onDependencyPortPointerDown, isDependencyDragActive = false, viewMode = "day", showTaskDateLabels = true, showTaskNames = true }) => {
|
|
4276
|
+
({ task, monthStart, dayWidth, rowHeight, onTasksChange, onScheduleIntent, onDragStateChange, rowIndex, allTasks, enableAutoSchedule, disableConstraints, deferCascadePreview = false, overridePosition, previewPositionStore, onCascadeProgress, onCascade, divider, highlightExpiredTasks, isCritical = false, showBaseline = false, isFilterMatch = false, businessDays, customDays, isWeekend: isWeekend3, disableTaskDrag = false, disableDependencyEditing = false, onDependencyPortPointerDown, isDependencyDragActive = false, viewMode = "day", showTaskDateLabels = true, showTaskNames = true, onCompositeToggle, compactDetail = false, compositeParentColor, compositeExpanded = false }) => {
|
|
4277
4277
|
const defaultParentBarColor = "#782FC4";
|
|
4278
|
+
const [showCompositePreview, setShowCompositePreview] = useState2(false);
|
|
4279
|
+
const [compositePreviewPosition, setCompositePreviewPosition] = useState2(null);
|
|
4280
|
+
const pointerStart = useRef2(null);
|
|
4281
|
+
const suppressCompositeClick = useRef2(false);
|
|
4282
|
+
const compositeChildren = useMemo2(
|
|
4283
|
+
() => task.composite ? (allTasks ?? []).filter((child) => child.parentId === task.id) : [],
|
|
4284
|
+
[allTasks, task.composite, task.id]
|
|
4285
|
+
);
|
|
4286
|
+
useEffect2(() => {
|
|
4287
|
+
if (!showCompositePreview) return;
|
|
4288
|
+
const hide = () => setShowCompositePreview(false);
|
|
4289
|
+
window.addEventListener("scroll", hide, true);
|
|
4290
|
+
window.addEventListener("resize", hide);
|
|
4291
|
+
return () => {
|
|
4292
|
+
window.removeEventListener("scroll", hide, true);
|
|
4293
|
+
window.removeEventListener("resize", hide);
|
|
4294
|
+
};
|
|
4295
|
+
}, [showCompositePreview]);
|
|
4278
4296
|
const { divider: taskDivider } = task;
|
|
4279
4297
|
const normalizedTask = useMemo2(() => normalizeTaskDatesForType(task), [task]);
|
|
4280
4298
|
const milestone = useMemo2(() => isMilestoneTask(normalizedTask), [normalizedTask]);
|
|
@@ -4291,6 +4309,7 @@ var TaskRow = React2.memo(
|
|
|
4291
4309
|
const isParent = useMemo2(() => {
|
|
4292
4310
|
return allTasks ? isTaskParent(task.id, allTasks) : false;
|
|
4293
4311
|
}, [allTasks, task.id]);
|
|
4312
|
+
const isVisualParent = isParent && !task.composite;
|
|
4294
4313
|
const childCount = useMemo2(() => {
|
|
4295
4314
|
return allTasks ? getChildren(task.id, allTasks).length : 0;
|
|
4296
4315
|
}, [allTasks, task.id]);
|
|
@@ -4336,19 +4355,19 @@ var TaskRow = React2.memo(
|
|
|
4336
4355
|
if (isExpired) {
|
|
4337
4356
|
return "color-mix(in srgb, var(--gantt-expired-color) 40%, black)";
|
|
4338
4357
|
}
|
|
4339
|
-
const baseColor =
|
|
4358
|
+
const baseColor = isVisualParent ? task.color || defaultParentBarColor : task.color || "var(--gantt-task-bar-default-color)";
|
|
4340
4359
|
return `color-mix(in srgb, ${baseColor} 40%, black)`;
|
|
4341
|
-
}, [defaultParentBarColor, isCritical, isExpired,
|
|
4360
|
+
}, [defaultParentBarColor, isCritical, isExpired, isVisualParent, task.color]);
|
|
4342
4361
|
const barStyle = useMemo2(() => {
|
|
4343
4362
|
const parentBarColor = task.color || defaultParentBarColor;
|
|
4344
4363
|
if (isCritical && !isExpired) {
|
|
4345
4364
|
const c = criticalBarColor;
|
|
4346
|
-
if (
|
|
4365
|
+
if (isVisualParent) {
|
|
4347
4366
|
return { backgroundColor: c, "--gantt-parent-bar-color": c };
|
|
4348
4367
|
}
|
|
4349
4368
|
return { backgroundColor: c };
|
|
4350
4369
|
}
|
|
4351
|
-
if (
|
|
4370
|
+
if (isVisualParent) {
|
|
4352
4371
|
if (progressWidth >= 100) {
|
|
4353
4372
|
const c = isExpired ? "color-mix(in srgb, var(--gantt-expired-color) 40%, black)" : `color-mix(in srgb, ${parentBarColor} 40%, black)`;
|
|
4354
4373
|
return { backgroundColor: c, "--gantt-parent-bar-color": c };
|
|
@@ -4359,7 +4378,7 @@ var TaskRow = React2.memo(
|
|
|
4359
4378
|
return { backgroundColor: progressColor };
|
|
4360
4379
|
}
|
|
4361
4380
|
return { backgroundColor: barColor };
|
|
4362
|
-
}, [isCritical, defaultParentBarColor, isExpired,
|
|
4381
|
+
}, [isCritical, defaultParentBarColor, isExpired, isVisualParent, progressWidth, barColor, progressColor, task.color]);
|
|
4363
4382
|
const handleDragEnd = (result) => {
|
|
4364
4383
|
const updatedTask = {
|
|
4365
4384
|
...normalizedTask,
|
|
@@ -4433,6 +4452,25 @@ var TaskRow = React2.memo(
|
|
|
4433
4452
|
}, [displayLeft, dayWidth, milestoneGeometry.size]);
|
|
4434
4453
|
const visualLeft = milestone ? displayMilestoneGeometry.left : displayLeft;
|
|
4435
4454
|
const visualWidth = milestone ? displayMilestoneGeometry.size : displayWidth;
|
|
4455
|
+
const compositeSegments = useMemo2(() => {
|
|
4456
|
+
if (!task.composite || width <= 0) return [];
|
|
4457
|
+
const laneEnds = [];
|
|
4458
|
+
return compositeChildren.map((child) => {
|
|
4459
|
+
const segment = calculateTaskBar(parseUTCDate(child.startDate), parseUTCDate(child.endDate), monthStart, dayWidth);
|
|
4460
|
+
let lane = laneEnds.findIndex((end) => end <= segment.left);
|
|
4461
|
+
if (lane < 0) lane = laneEnds.length;
|
|
4462
|
+
laneEnds[lane] = segment.left + segment.width;
|
|
4463
|
+
return {
|
|
4464
|
+
id: child.id,
|
|
4465
|
+
name: child.name,
|
|
4466
|
+
left: (segment.left - left) / width * 100,
|
|
4467
|
+
width: segment.width / width * 100,
|
|
4468
|
+
lane
|
|
4469
|
+
};
|
|
4470
|
+
});
|
|
4471
|
+
}, [task.composite, compositeChildren, monthStart, dayWidth, left, width, displayLeft]);
|
|
4472
|
+
const compositeLaneCount = Math.max(1, ...compositeSegments.map((segment) => segment.lane + 1));
|
|
4473
|
+
const showCompositeSegments = task.composite && compositeSegments.length > 0 && visualWidth / compositeSegments.length >= 22;
|
|
4436
4474
|
const shouldRenderBaseline = showBaseline && baselineGeometry !== null;
|
|
4437
4475
|
const hasPreviewPosition = isDragging || effectiveOverridePosition !== void 0;
|
|
4438
4476
|
const currentStartDate = hasPreviewPosition ? pixelsToDate(displayLeft, monthStart, dayWidth) : taskStartDate;
|
|
@@ -4450,17 +4488,20 @@ var TaskRow = React2.memo(
|
|
|
4450
4488
|
if (lastDigit >= 2 && lastDigit <= 4) return `${count} \u0440\u0430\u0431\u043E\u0442\u044B`;
|
|
4451
4489
|
return `${count} \u0440\u0430\u0431\u043E\u0442`;
|
|
4452
4490
|
};
|
|
4453
|
-
const estimatedTextWidth =
|
|
4454
|
-
const showProgressInside = !milestone && progressWidth > 0 && displayWidth > estimatedTextWidth;
|
|
4455
|
-
const MIN_DURATION_WIDTH =
|
|
4456
|
-
const showDurationInside = !milestone && durationDays >= 2 && displayWidth > MIN_DURATION_WIDTH;
|
|
4491
|
+
const estimatedTextWidth = isVisualParent ? 120 : durationDays >= 10 ? 76 : 62;
|
|
4492
|
+
const showProgressInside = !milestone && progressWidth > 0 && displayWidth > (compactDetail ? 28 : estimatedTextWidth);
|
|
4493
|
+
const MIN_DURATION_WIDTH = isVisualParent ? 80 : task.composite ? 92 : 50;
|
|
4494
|
+
const showDurationInside = !compactDetail && !milestone && durationDays >= 2 && displayWidth > MIN_DURATION_WIDTH;
|
|
4457
4495
|
return /* @__PURE__ */ jsxs2(
|
|
4458
4496
|
"div",
|
|
4459
4497
|
{
|
|
4460
4498
|
"data-filter-match": isFilterMatch ? "true" : "false",
|
|
4461
4499
|
"data-gantt-task-row-id": task.id,
|
|
4462
|
-
className: `gantt-tr-row ${isFilterMatch ? "gantt-tr-row-filter-match" : ""}`,
|
|
4463
|
-
style: {
|
|
4500
|
+
className: `gantt-tr-row ${compactDetail ? "gantt-tr-row-compositeDetail" : ""} ${isFilterMatch ? "gantt-tr-row-filter-match" : ""}`,
|
|
4501
|
+
style: {
|
|
4502
|
+
height: `${rowHeight}px`,
|
|
4503
|
+
"--gantt-tr-composite-detail-color": compositeParentColor ?? "var(--gantt-task-bar-default-color, #8b5cf6)"
|
|
4504
|
+
},
|
|
4464
4505
|
children: [
|
|
4465
4506
|
taskDivider === "top" && /* @__PURE__ */ jsx2("div", { className: "gantt-tr-divider gantt-tr-divider-top" }),
|
|
4466
4507
|
/* @__PURE__ */ jsxs2("div", { className: "gantt-tr-taskContainer", children: [
|
|
@@ -4478,7 +4519,11 @@ var TaskRow = React2.memo(
|
|
|
4478
4519
|
"div",
|
|
4479
4520
|
{
|
|
4480
4521
|
"data-taskbar": true,
|
|
4481
|
-
|
|
4522
|
+
role: task.composite ? "button" : void 0,
|
|
4523
|
+
tabIndex: task.composite ? 0 : void 0,
|
|
4524
|
+
"aria-label": task.composite ? `${task.name}: ${compositeExpanded ? "\u0441\u0432\u0435\u0440\u043D\u0443\u0442\u044C" : "\u0440\u0430\u0441\u043A\u0440\u044B\u0442\u044C"} \u0434\u0435\u0442\u0430\u043B\u0438` : void 0,
|
|
4525
|
+
"aria-expanded": task.composite ? compositeExpanded : void 0,
|
|
4526
|
+
className: `gantt-tr-taskBar ${isDragging ? "gantt-tr-dragging" : ""} ${task.locked ? "gantt-tr-locked" : ""} ${task.synced === false ? "gantt-tr-unsynced" : ""} ${isVisualParent ? "gantt-tr-parentBar" : ""} ${task.composite ? "gantt-tr-compositeBar" : ""} ${milestone ? "gantt-tr-milestone" : ""} ${isCritical ? "gantt-tr-critical" : ""}`,
|
|
4482
4527
|
style: {
|
|
4483
4528
|
left: `${visualLeft}px`,
|
|
4484
4529
|
...barStyle,
|
|
@@ -4488,14 +4533,57 @@ var TaskRow = React2.memo(
|
|
|
4488
4533
|
padding: 0
|
|
4489
4534
|
} : {
|
|
4490
4535
|
width: `${visualWidth}px`,
|
|
4491
|
-
height:
|
|
4536
|
+
height: compactDetail ? "18px" : isVisualParent ? "var(--gantt-parent-bar-height, 14px)" : "var(--gantt-task-bar-height)"
|
|
4492
4537
|
},
|
|
4493
4538
|
cursor: dragHandleProps.style.cursor,
|
|
4494
4539
|
userSelect: dragHandleProps.style.userSelect
|
|
4495
4540
|
},
|
|
4496
4541
|
onMouseDown: dragHandleProps.onMouseDown,
|
|
4497
4542
|
onMouseMove: dragHandleProps.onMouseMove,
|
|
4498
|
-
onMouseLeave:
|
|
4543
|
+
onMouseLeave: () => {
|
|
4544
|
+
dragHandleProps.onMouseLeave();
|
|
4545
|
+
setShowCompositePreview(false);
|
|
4546
|
+
},
|
|
4547
|
+
onMouseEnter: task.composite ? (event) => {
|
|
4548
|
+
const rect = event.currentTarget.getBoundingClientRect();
|
|
4549
|
+
const previewWidth = 220;
|
|
4550
|
+
const previewHeight = Math.min(340, 68 + Math.min(compositeChildren.length, 12) * 20);
|
|
4551
|
+
setCompositePreviewPosition({
|
|
4552
|
+
left: Math.max(8, Math.min(rect.left, window.innerWidth - previewWidth - 8)),
|
|
4553
|
+
top: rect.bottom + previewHeight + 8 < window.innerHeight ? rect.bottom + 6 : Math.max(8, rect.top - previewHeight - 6)
|
|
4554
|
+
});
|
|
4555
|
+
setShowCompositePreview(true);
|
|
4556
|
+
} : void 0,
|
|
4557
|
+
onMouseDownCapture: task.composite ? (event) => {
|
|
4558
|
+
suppressCompositeClick.current = Boolean(event.target.closest(".gantt-tr-resizeHandle"));
|
|
4559
|
+
pointerStart.current = { x: event.clientX, y: event.clientY };
|
|
4560
|
+
} : void 0,
|
|
4561
|
+
onMouseMoveCapture: task.composite ? (event) => {
|
|
4562
|
+
const start = pointerStart.current;
|
|
4563
|
+
if (start && Math.hypot(event.clientX - start.x, event.clientY - start.y) >= 4) {
|
|
4564
|
+
suppressCompositeClick.current = true;
|
|
4565
|
+
}
|
|
4566
|
+
} : void 0,
|
|
4567
|
+
onMouseUpCapture: task.composite ? (event) => {
|
|
4568
|
+
const start = pointerStart.current;
|
|
4569
|
+
if (start && Math.hypot(event.clientX - start.x, event.clientY - start.y) >= 4) {
|
|
4570
|
+
suppressCompositeClick.current = true;
|
|
4571
|
+
}
|
|
4572
|
+
pointerStart.current = null;
|
|
4573
|
+
} : void 0,
|
|
4574
|
+
onClick: task.composite ? () => {
|
|
4575
|
+
if (!isDragging && !suppressCompositeClick.current) {
|
|
4576
|
+
setShowCompositePreview(false);
|
|
4577
|
+
onCompositeToggle?.("click");
|
|
4578
|
+
}
|
|
4579
|
+
suppressCompositeClick.current = false;
|
|
4580
|
+
} : void 0,
|
|
4581
|
+
onKeyDown: task.composite ? (event) => {
|
|
4582
|
+
if (event.key === "Enter" || event.key === " ") {
|
|
4583
|
+
event.preventDefault();
|
|
4584
|
+
onCompositeToggle?.("keyboard");
|
|
4585
|
+
}
|
|
4586
|
+
} : void 0,
|
|
4499
4587
|
children: [
|
|
4500
4588
|
!milestone && progressWidth > 0 && progressWidth < 100 && /* @__PURE__ */ jsx2(
|
|
4501
4589
|
"div",
|
|
@@ -4504,14 +4592,28 @@ var TaskRow = React2.memo(
|
|
|
4504
4592
|
style: {
|
|
4505
4593
|
width: `${progressWidth}%`,
|
|
4506
4594
|
backgroundColor: progressColor,
|
|
4507
|
-
...
|
|
4595
|
+
...isVisualParent && {
|
|
4508
4596
|
borderRadius: "var(--gantt-parent-bar-radius, 8px) 0 0 0"
|
|
4509
4597
|
}
|
|
4510
4598
|
}
|
|
4511
4599
|
}
|
|
4512
4600
|
),
|
|
4513
4601
|
!milestone && /* @__PURE__ */ jsx2("div", { className: "gantt-tr-resizeHandle gantt-tr-resizeHandleLeft" }),
|
|
4514
|
-
|
|
4602
|
+
showCompositeSegments && /* @__PURE__ */ jsx2("span", { className: "gantt-tr-compositeSegments", "aria-hidden": "true", children: compositeSegments.map((segment) => /* @__PURE__ */ jsx2(
|
|
4603
|
+
"span",
|
|
4604
|
+
{
|
|
4605
|
+
className: "gantt-tr-compositeSegment",
|
|
4606
|
+
style: {
|
|
4607
|
+
left: `${segment.left}%`,
|
|
4608
|
+
width: `${segment.width}%`,
|
|
4609
|
+
top: `${segment.lane / compositeLaneCount * 100}%`,
|
|
4610
|
+
height: `${100 / compositeLaneCount}%`
|
|
4611
|
+
}
|
|
4612
|
+
},
|
|
4613
|
+
segment.id
|
|
4614
|
+
)) }),
|
|
4615
|
+
task.composite && /* @__PURE__ */ jsx2("span", { className: "gantt-tr-compositeHoverChevron", "aria-hidden": "true", children: /* @__PURE__ */ jsx2("svg", { className: `gantt-tr-compositeChevron${compositeExpanded ? " gantt-tr-compositeChevron-open" : ""}`, viewBox: "0 0 20 20", children: /* @__PURE__ */ jsx2("path", { d: "m7 4 6 6-6 6", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) }) }),
|
|
4616
|
+
showDurationInside && /* @__PURE__ */ jsx2("span", { className: "gantt-tr-taskDuration", children: isVisualParent ? getChildCountLabel(childCount) : `${durationDays} \u0434` }),
|
|
4515
4617
|
progressWidth > 0 && showProgressInside && /* @__PURE__ */ jsxs2("span", { className: "gantt-tr-progressText", children: [
|
|
4516
4618
|
progressWidth,
|
|
4517
4619
|
"%"
|
|
@@ -4520,6 +4622,41 @@ var TaskRow = React2.memo(
|
|
|
4520
4622
|
]
|
|
4521
4623
|
}
|
|
4522
4624
|
),
|
|
4625
|
+
task.composite && showCompositePreview && compositePreviewPosition && compositeChildren.length > 0 && !isDragging && typeof document !== "undefined" && createPortal(
|
|
4626
|
+
/* @__PURE__ */ jsxs2(
|
|
4627
|
+
"div",
|
|
4628
|
+
{
|
|
4629
|
+
className: "gantt-tr-compositePreview",
|
|
4630
|
+
style: { left: `${compositePreviewPosition.left}px`, top: `${compositePreviewPosition.top}px` },
|
|
4631
|
+
role: "tooltip",
|
|
4632
|
+
children: [
|
|
4633
|
+
/* @__PURE__ */ jsxs2("div", { className: "gantt-tr-compositePreviewAxis", children: [
|
|
4634
|
+
/* @__PURE__ */ jsx2("span", { children: formatCompositePreviewDate(currentStartDate) }),
|
|
4635
|
+
/* @__PURE__ */ jsx2("span", { children: formatCompositePreviewDate(currentEndDate) })
|
|
4636
|
+
] }),
|
|
4637
|
+
compositeChildren.slice(0, 12).map((child) => /* @__PURE__ */ jsxs2("div", { className: "gantt-tr-compositePreviewRow", children: [
|
|
4638
|
+
/* @__PURE__ */ jsx2("span", { children: child.name }),
|
|
4639
|
+
/* @__PURE__ */ jsx2("span", { className: "gantt-tr-compositePreviewTrack", children: /* @__PURE__ */ jsx2(
|
|
4640
|
+
"span",
|
|
4641
|
+
{
|
|
4642
|
+
className: "gantt-tr-compositePreviewBar",
|
|
4643
|
+
style: {
|
|
4644
|
+
left: `${Math.max(0, (parseUTCDate(child.startDate).getTime() - taskStartDate.getTime()) / (taskEndDate.getTime() - taskStartDate.getTime() + 864e5) * 100)}%`,
|
|
4645
|
+
width: `${Math.max(2, (parseUTCDate(child.endDate).getTime() - parseUTCDate(child.startDate).getTime() + 864e5) / (taskEndDate.getTime() - taskStartDate.getTime() + 864e5) * 100)}%`,
|
|
4646
|
+
backgroundColor: barColor
|
|
4647
|
+
}
|
|
4648
|
+
}
|
|
4649
|
+
) })
|
|
4650
|
+
] }, child.id)),
|
|
4651
|
+
compositeChildren.length > 12 && /* @__PURE__ */ jsxs2("div", { children: [
|
|
4652
|
+
"+",
|
|
4653
|
+
compositeChildren.length - 12
|
|
4654
|
+
] })
|
|
4655
|
+
]
|
|
4656
|
+
}
|
|
4657
|
+
),
|
|
4658
|
+
document.body
|
|
4659
|
+
),
|
|
4523
4660
|
!disableDependencyEditing && onDependencyPortPointerDown && /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
4524
4661
|
/* @__PURE__ */ jsx2(
|
|
4525
4662
|
"button",
|
|
@@ -4528,8 +4665,8 @@ var TaskRow = React2.memo(
|
|
|
4528
4665
|
"data-gantt-dependency-port": true,
|
|
4529
4666
|
"data-task-id": task.id,
|
|
4530
4667
|
"data-port-side": "left",
|
|
4531
|
-
className: `gantt-tr-dependencyPort gantt-tr-dependencyPortLeft ${milestone ? "gantt-tr-dependencyPortMilestone" : ""} ${
|
|
4532
|
-
style: { left: `${visualLeft -
|
|
4668
|
+
className: `gantt-tr-dependencyPort gantt-tr-dependencyPortLeft ${milestone ? "gantt-tr-dependencyPortMilestone" : ""} ${isVisualParent ? "gantt-tr-dependencyPortParent" : ""} ${isDependencyDragActive ? "gantt-tr-dependencyPortDragActive" : ""}`,
|
|
4669
|
+
style: { left: `${visualLeft - 24}px` },
|
|
4533
4670
|
"aria-label": `\u041D\u0430\u0447\u0430\u0442\u044C \u0441\u0432\u044F\u0437\u044C \u043E\u0442 \u043B\u0435\u0432\u043E\u0433\u043E \u043A\u0440\u0430\u044F: ${task.name}`,
|
|
4534
4671
|
title: "\u041F\u043E\u0442\u044F\u043D\u0438\u0442\u0435 \u043A \u043A\u0440\u0430\u044E \u0434\u0440\u0443\u0433\u043E\u0439 \u043F\u043E\u043B\u043E\u0441\u044B, \u0447\u0442\u043E\u0431\u044B \u0441\u043E\u0437\u0434\u0430\u0442\u044C \u0441\u0432\u044F\u0437\u044C",
|
|
4535
4672
|
onPointerDown: (event) => onDependencyPortPointerDown(task.id, "left", event)
|
|
@@ -4542,7 +4679,7 @@ var TaskRow = React2.memo(
|
|
|
4542
4679
|
"data-gantt-dependency-port": true,
|
|
4543
4680
|
"data-task-id": task.id,
|
|
4544
4681
|
"data-port-side": "right",
|
|
4545
|
-
className: `gantt-tr-dependencyPort gantt-tr-dependencyPortRight ${milestone ? "gantt-tr-dependencyPortMilestone" : ""} ${
|
|
4682
|
+
className: `gantt-tr-dependencyPort gantt-tr-dependencyPortRight ${milestone ? "gantt-tr-dependencyPortMilestone" : ""} ${isVisualParent ? "gantt-tr-dependencyPortParent" : ""} ${isDependencyDragActive ? "gantt-tr-dependencyPortDragActive" : ""}`,
|
|
4546
4683
|
style: { left: `${visualLeft + visualWidth}px` },
|
|
4547
4684
|
"aria-label": `\u041D\u0430\u0447\u0430\u0442\u044C \u0441\u0432\u044F\u0437\u044C \u043E\u0442 \u043F\u0440\u0430\u0432\u043E\u0433\u043E \u043A\u0440\u0430\u044F: ${task.name}`,
|
|
4548
4685
|
title: "\u041F\u043E\u0442\u044F\u043D\u0438\u0442\u0435 \u043A \u043A\u0440\u0430\u044E \u0434\u0440\u0443\u0433\u043E\u0439 \u043F\u043E\u043B\u043E\u0441\u044B, \u0447\u0442\u043E\u0431\u044B \u0441\u043E\u0437\u0434\u0430\u0442\u044C \u0441\u0432\u044F\u0437\u044C",
|
|
@@ -4581,6 +4718,14 @@ var TaskRow = React2.memo(
|
|
|
4581
4718
|
children: /* @__PURE__ */ jsx2("path", { d: "M18 8h-1V6c0-2.76-2.24-5-5-5S7 3.24 7 6v2H6c-1.1 0-2 .9-2 2v10c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V10c0-1.1-.9-2-2-2zM12 17c-1.1 0-2-.9-2-2s.9-2 2-2 2 .9 2 2-.9 2-2 2zm3.1-9H8.9V6c0-1.71 1.39-3.1 3.1-3.1 1.71 0 3.1 1.39 3.1 3.1v2z" })
|
|
4582
4719
|
}
|
|
4583
4720
|
),
|
|
4721
|
+
!showDurationInside && !milestone && /* @__PURE__ */ jsx2(
|
|
4722
|
+
"span",
|
|
4723
|
+
{
|
|
4724
|
+
className: `gantt-tr-externalDuration gantt-tr-durationBeforeBar${compactDetail ? " gantt-tr-compositeDuration" : ""}`,
|
|
4725
|
+
style: { left: `${visualLeft - 46}px`, color: isParent ? task.color || defaultParentBarColor : barColor },
|
|
4726
|
+
children: isVisualParent ? getChildCountLabel(childCount) : `${durationDays} \u0434`
|
|
4727
|
+
}
|
|
4728
|
+
),
|
|
4584
4729
|
/* @__PURE__ */ jsxs2(
|
|
4585
4730
|
"div",
|
|
4586
4731
|
{
|
|
@@ -4590,7 +4735,6 @@ var TaskRow = React2.memo(
|
|
|
4590
4735
|
color: isParent ? task.color || defaultParentBarColor : barColor
|
|
4591
4736
|
},
|
|
4592
4737
|
children: [
|
|
4593
|
-
!showDurationInside && !milestone && /* @__PURE__ */ jsx2("span", { className: "gantt-tr-externalDuration", children: isParent ? getChildCountLabel(childCount) : `${durationDays} \u0434` }),
|
|
4594
4738
|
progressWidth > 0 && !showProgressInside && /* @__PURE__ */ jsxs2("span", { className: "gantt-tr-externalProgress", children: [
|
|
4595
4739
|
progressWidth,
|
|
4596
4740
|
"%"
|
|
@@ -4855,7 +4999,7 @@ var DragGuideLines = ({
|
|
|
4855
4999
|
var DragGuideLines_default = DragGuideLines;
|
|
4856
5000
|
|
|
4857
5001
|
// src/components/DependencyLines/DependencyLines.tsx
|
|
4858
|
-
import React6, { useMemo as useMemo6, useState as
|
|
5002
|
+
import React6, { useMemo as useMemo6, useState as useState3 } from "react";
|
|
4859
5003
|
import { jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
4860
5004
|
function isTaskHidden(taskId, collapsedParentIds, taskMap) {
|
|
4861
5005
|
const task = taskMap.get(taskId);
|
|
@@ -4894,6 +5038,8 @@ var DependencyLines = React6.memo(({
|
|
|
4894
5038
|
gridWidth,
|
|
4895
5039
|
totalHeight,
|
|
4896
5040
|
rowIndexByTaskId,
|
|
5041
|
+
rowTops,
|
|
5042
|
+
rowHeights,
|
|
4897
5043
|
dragOverrides,
|
|
4898
5044
|
selectedDep,
|
|
4899
5045
|
criticalTaskIds,
|
|
@@ -4901,7 +5047,7 @@ var DependencyLines = React6.memo(({
|
|
|
4901
5047
|
weekendPredicate,
|
|
4902
5048
|
onDependencyClick
|
|
4903
5049
|
}) => {
|
|
4904
|
-
const [hoveredLineId, setHoveredLineId] =
|
|
5050
|
+
const [hoveredLineId, setHoveredLineId] = useState3(null);
|
|
4905
5051
|
const tasksForPositions = allTasks ?? tasks;
|
|
4906
5052
|
const { taskPositions, taskIndices, hiddenTaskIds } = useMemo6(() => {
|
|
4907
5053
|
const positions = /* @__PURE__ */ new Map();
|
|
@@ -4917,7 +5063,8 @@ var DependencyLines = React6.memo(({
|
|
|
4917
5063
|
left: computed.left,
|
|
4918
5064
|
right: computed.right,
|
|
4919
5065
|
centerX: computed.centerX,
|
|
4920
|
-
rowTop: rowIndex * rowHeight,
|
|
5066
|
+
rowTop: rowTops?.[rowIndex] ?? rowIndex * rowHeight,
|
|
5067
|
+
rowHeight: rowHeights?.[rowIndex] ?? rowHeight,
|
|
4921
5068
|
isVirtual: false
|
|
4922
5069
|
});
|
|
4923
5070
|
});
|
|
@@ -4937,6 +5084,7 @@ var DependencyLines = React6.memo(({
|
|
|
4937
5084
|
right: computed.right,
|
|
4938
5085
|
centerX: computed.centerX,
|
|
4939
5086
|
rowTop: ancestorPosition.rowTop,
|
|
5087
|
+
rowHeight: ancestorPosition.rowHeight,
|
|
4940
5088
|
isVirtual: true
|
|
4941
5089
|
});
|
|
4942
5090
|
}
|
|
@@ -4950,18 +5098,19 @@ var DependencyLines = React6.memo(({
|
|
|
4950
5098
|
const override = dragOverrides?.get(task.id);
|
|
4951
5099
|
const computed = resolveTaskHorizontalGeometry(task, monthStart, dayWidth, override);
|
|
4952
5100
|
const rowIndex = rowIndexByTaskId?.get(task.id);
|
|
4953
|
-
const rowTop = rowIndex !== void 0 ? rowIndex * rowHeight : 0;
|
|
5101
|
+
const rowTop = rowIndex !== void 0 ? rowTops?.[rowIndex] ?? rowIndex * rowHeight : 0;
|
|
4954
5102
|
positions.set(task.id, {
|
|
4955
5103
|
left: computed.left,
|
|
4956
5104
|
right: computed.right,
|
|
4957
5105
|
centerX: computed.centerX,
|
|
4958
5106
|
rowTop,
|
|
5107
|
+
rowHeight: rowIndex !== void 0 ? rowHeights?.[rowIndex] ?? rowHeight : rowHeight,
|
|
4959
5108
|
isVirtual: false
|
|
4960
5109
|
});
|
|
4961
5110
|
}
|
|
4962
5111
|
}
|
|
4963
5112
|
return { taskPositions: positions, taskIndices: indices, hiddenTaskIds: hidden };
|
|
4964
|
-
}, [tasks, tasksForPositions, allTasks, collapsedParentIds, monthStart, dayWidth, rowHeight, dragOverrides, rowIndexByTaskId]);
|
|
5113
|
+
}, [tasks, tasksForPositions, allTasks, collapsedParentIds, monthStart, dayWidth, rowHeight, rowTops, rowHeights, dragOverrides, rowIndexByTaskId]);
|
|
4965
5114
|
const tasksForCycleDetection = allTasks ?? tasks;
|
|
4966
5115
|
const cycleInfo = useMemo6(() => {
|
|
4967
5116
|
const result = detectCycles(tasksForCycleDetection);
|
|
@@ -5003,7 +5152,9 @@ var DependencyLines = React6.memo(({
|
|
|
5003
5152
|
continue;
|
|
5004
5153
|
}
|
|
5005
5154
|
}
|
|
5006
|
-
|
|
5155
|
+
const predecessorVisibleId = predecessor.isVirtual ? findVisibleAncestor(taskMap.get(edge.predecessorId), collapsedParentIds, taskMap)?.id : edge.predecessorId;
|
|
5156
|
+
const successorVisibleId = successor.isVirtual ? findVisibleAncestor(taskMap.get(edge.successorId), collapsedParentIds, taskMap)?.id : edge.successorId;
|
|
5157
|
+
if (!renderedTaskIdSet.has(predecessorVisibleId ?? "") && !renderedTaskIdSet.has(successorVisibleId ?? "")) {
|
|
5007
5158
|
continue;
|
|
5008
5159
|
}
|
|
5009
5160
|
const isVirtual = predecessor.isVirtual || successor.isVirtual;
|
|
@@ -5017,9 +5168,9 @@ var DependencyLines = React6.memo(({
|
|
|
5017
5168
|
let toY;
|
|
5018
5169
|
if (reverseOrder) {
|
|
5019
5170
|
fromY = predecessor.rowTop + 10;
|
|
5020
|
-
toY = successor.rowTop + rowHeight - 6;
|
|
5171
|
+
toY = successor.rowTop + successor.rowHeight - 6;
|
|
5021
5172
|
} else {
|
|
5022
|
-
fromY = predecessor.rowTop + rowHeight - 10;
|
|
5173
|
+
fromY = predecessor.rowTop + predecessor.rowHeight - 10;
|
|
5023
5174
|
toY = successor.rowTop + 6;
|
|
5024
5175
|
}
|
|
5025
5176
|
let fromX = predecessorTask && isMilestoneTask(predecessorTask) ? predecessor.centerX : edge.type === "SS" || edge.type === "SF" ? predecessor.left : predecessor.right;
|
|
@@ -5246,18 +5397,18 @@ var LINK_TYPE_LABELS_RU = {
|
|
|
5246
5397
|
FF: "\u041E\u041E",
|
|
5247
5398
|
SF: "\u041D\u041E"
|
|
5248
5399
|
};
|
|
5400
|
+
var fmt = (n) => Math.round(n * 100) / 100;
|
|
5249
5401
|
function getPath(drag) {
|
|
5250
5402
|
const from = drag.source;
|
|
5251
5403
|
const to = drag.current;
|
|
5252
5404
|
const direction = to.y >= from.y ? 1 : -1;
|
|
5253
5405
|
const bend = Math.max(18, Math.abs(to.y - from.y) * 0.45);
|
|
5254
|
-
const middleX = Math.round((from.x + to.x) / 2);
|
|
5255
5406
|
if (Math.abs(to.y - from.y) < 2) {
|
|
5256
|
-
return `M ${
|
|
5407
|
+
return `M ${fmt(from.x)} ${fmt(from.y)} H ${fmt(to.x)}`;
|
|
5257
5408
|
}
|
|
5258
5409
|
return [
|
|
5259
|
-
`M ${
|
|
5260
|
-
`C ${
|
|
5410
|
+
`M ${fmt(from.x)} ${fmt(from.y)}`,
|
|
5411
|
+
`C ${fmt(from.x)} ${fmt(from.y + bend * direction)}, ${fmt(to.x)} ${fmt(to.y - bend * direction)}, ${fmt(to.x)} ${fmt(to.y)}`
|
|
5261
5412
|
].join(" ");
|
|
5262
5413
|
}
|
|
5263
5414
|
var DependencyCreationOverlay = ({ drag, width, height }) => {
|
|
@@ -5295,7 +5446,7 @@ var DependencyCreationOverlay = ({ drag, width, height }) => {
|
|
|
5295
5446
|
};
|
|
5296
5447
|
|
|
5297
5448
|
// src/components/TaskList/TaskList.tsx
|
|
5298
|
-
import React13, { useMemo as useMemo9, useCallback as useCallback6, useState as
|
|
5449
|
+
import React13, { useMemo as useMemo9, useCallback as useCallback6, useState as useState8, useEffect as useEffect7, useRef as useRef8 } from "react";
|
|
5299
5450
|
|
|
5300
5451
|
// src/utils/taskListReorder.ts
|
|
5301
5452
|
function getDescendantIds(taskId, tasks) {
|
|
@@ -5500,9 +5651,9 @@ var PopoverContent = ({
|
|
|
5500
5651
|
|
|
5501
5652
|
// src/components/TaskList/TaskListRow.tsx
|
|
5502
5653
|
import React10, {
|
|
5503
|
-
useState as
|
|
5504
|
-
useRef as
|
|
5505
|
-
useEffect as
|
|
5654
|
+
useState as useState6,
|
|
5655
|
+
useRef as useRef5,
|
|
5656
|
+
useEffect as useEffect5,
|
|
5506
5657
|
useCallback as useCallback5,
|
|
5507
5658
|
useMemo as useMemo8
|
|
5508
5659
|
} from "react";
|
|
@@ -5525,14 +5676,14 @@ var Input = React7.forwardRef(
|
|
|
5525
5676
|
Input.displayName = "Input";
|
|
5526
5677
|
|
|
5527
5678
|
// src/components/ui/DatePicker.tsx
|
|
5528
|
-
import { useState as
|
|
5679
|
+
import { useState as useState5, useCallback as useCallback4, useEffect as useEffect4, useRef as useRef4 } from "react";
|
|
5529
5680
|
import { format as format3, isValid, parse, addDays, addMonths as addMonths2, addYears, subMonths as subMonths2, subYears, subDays } from "date-fns";
|
|
5530
5681
|
|
|
5531
5682
|
// src/components/ui/Calendar.tsx
|
|
5532
5683
|
import {
|
|
5533
|
-
useState as
|
|
5534
|
-
useRef as
|
|
5535
|
-
useEffect as
|
|
5684
|
+
useState as useState4,
|
|
5685
|
+
useRef as useRef3,
|
|
5686
|
+
useEffect as useEffect3,
|
|
5536
5687
|
useCallback as useCallback3,
|
|
5537
5688
|
useMemo as useMemo7
|
|
5538
5689
|
} from "react";
|
|
@@ -5567,13 +5718,13 @@ var Calendar = ({
|
|
|
5567
5718
|
disabled = false,
|
|
5568
5719
|
isWeekend: isWeekendProp
|
|
5569
5720
|
}) => {
|
|
5570
|
-
const scrollRef =
|
|
5721
|
+
const scrollRef = useRef3(null);
|
|
5571
5722
|
const initialMonth = useMemo7(
|
|
5572
5723
|
() => startOfMonth(initialDate ?? selected ?? /* @__PURE__ */ new Date()),
|
|
5573
5724
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
5574
5725
|
[]
|
|
5575
5726
|
);
|
|
5576
|
-
const [months, setMonths] =
|
|
5727
|
+
const [months, setMonths] = useState4(() => [
|
|
5577
5728
|
subMonths(initialMonth, 1),
|
|
5578
5729
|
initialMonth,
|
|
5579
5730
|
addMonths(initialMonth, 1)
|
|
@@ -5587,7 +5738,7 @@ var Calendar = ({
|
|
|
5587
5738
|
}
|
|
5588
5739
|
});
|
|
5589
5740
|
}, []);
|
|
5590
|
-
|
|
5741
|
+
useEffect3(() => {
|
|
5591
5742
|
const container = scrollRef.current;
|
|
5592
5743
|
if (!container) return;
|
|
5593
5744
|
const handleScroll = () => {
|
|
@@ -5605,7 +5756,7 @@ var Calendar = ({
|
|
|
5605
5756
|
container.addEventListener("scroll", handleScroll);
|
|
5606
5757
|
return () => container.removeEventListener("scroll", handleScroll);
|
|
5607
5758
|
}, [loadMoreMonths]);
|
|
5608
|
-
|
|
5759
|
+
useEffect3(() => {
|
|
5609
5760
|
if (!scrollRef.current) return;
|
|
5610
5761
|
const target = selected ?? initialDate ?? /* @__PURE__ */ new Date();
|
|
5611
5762
|
const monthKey = format2(startOfMonth(target), "yyyy-MM");
|
|
@@ -5710,12 +5861,12 @@ var DatePicker = ({
|
|
|
5710
5861
|
businessDays = true,
|
|
5711
5862
|
footer
|
|
5712
5863
|
}) => {
|
|
5713
|
-
const [open, setOpen] =
|
|
5714
|
-
const [inputValue, setInputValue] =
|
|
5715
|
-
const [draftDate, setDraftDate] =
|
|
5716
|
-
const dateInputRef =
|
|
5717
|
-
const segIdxRef =
|
|
5718
|
-
const charPosRef =
|
|
5864
|
+
const [open, setOpen] = useState5(false);
|
|
5865
|
+
const [inputValue, setInputValue] = useState5("");
|
|
5866
|
+
const [draftDate, setDraftDate] = useState5(void 0);
|
|
5867
|
+
const dateInputRef = useRef4(null);
|
|
5868
|
+
const segIdxRef = useRef4(0);
|
|
5869
|
+
const charPosRef = useRef4(0);
|
|
5719
5870
|
const selectedDate = (() => {
|
|
5720
5871
|
if (!value) return void 0;
|
|
5721
5872
|
const d = /* @__PURE__ */ new Date(value + "T00:00:00Z");
|
|
@@ -5723,7 +5874,7 @@ var DatePicker = ({
|
|
|
5723
5874
|
})();
|
|
5724
5875
|
const activeDate = draftDate ?? selectedDate;
|
|
5725
5876
|
const displayValue = selectedDate ? formatUTCDate(selectedDate, displayFormat) : placeholder;
|
|
5726
|
-
|
|
5877
|
+
useEffect4(() => {
|
|
5727
5878
|
if (value) {
|
|
5728
5879
|
const d = /* @__PURE__ */ new Date(value + "T00:00:00Z");
|
|
5729
5880
|
if (isValid(d)) {
|
|
@@ -5740,7 +5891,7 @@ var DatePicker = ({
|
|
|
5740
5891
|
const seg = segments[idx] ?? segments[0];
|
|
5741
5892
|
dateInputRef.current.setSelectionRange(seg.start, seg.end);
|
|
5742
5893
|
}, []);
|
|
5743
|
-
|
|
5894
|
+
useEffect4(() => {
|
|
5744
5895
|
if (open) {
|
|
5745
5896
|
setTimeout(() => {
|
|
5746
5897
|
if (dateInputRef.current) {
|
|
@@ -6339,10 +6490,10 @@ var DepChip = ({
|
|
|
6339
6490
|
businessDays = true,
|
|
6340
6491
|
weekendPredicate
|
|
6341
6492
|
}) => {
|
|
6342
|
-
const [popoverOpen, setPopoverOpen] =
|
|
6493
|
+
const [popoverOpen, setPopoverOpen] = useState6(false);
|
|
6343
6494
|
const lagAbs = Math.abs(lag ?? 0);
|
|
6344
|
-
const [inputAbs, setInputAbs] =
|
|
6345
|
-
|
|
6495
|
+
const [inputAbs, setInputAbs] = useState6(lagAbs === 0 ? "" : String(lagAbs));
|
|
6496
|
+
useEffect5(() => {
|
|
6346
6497
|
const abs = Math.abs(lag ?? 0);
|
|
6347
6498
|
setInputAbs(abs === 0 ? "" : String(abs));
|
|
6348
6499
|
}, [lag]);
|
|
@@ -6721,13 +6872,14 @@ var TaskListRow = React10.memo(
|
|
|
6721
6872
|
taskListMenuCommands = [],
|
|
6722
6873
|
hideTaskListRowActions = false,
|
|
6723
6874
|
rowClassName,
|
|
6875
|
+
compositeParentColor,
|
|
6724
6876
|
getTaskListNamePrefixIcon,
|
|
6725
6877
|
taskDateChangeMode = "preserve-duration",
|
|
6726
6878
|
onTaskDateChangeModeChange,
|
|
6727
6879
|
printDependencyLabels = false
|
|
6728
6880
|
}) => {
|
|
6729
|
-
const [editingColumnId, setEditingColumnId] =
|
|
6730
|
-
const [editingColumnStartValue, setEditingColumnStartValue] =
|
|
6881
|
+
const [editingColumnId, setEditingColumnId] = useState6(null);
|
|
6882
|
+
const [editingColumnStartValue, setEditingColumnStartValue] = useState6(void 0);
|
|
6731
6883
|
const editingName = editingColumnId === "name";
|
|
6732
6884
|
const editingDuration = editingColumnId === "duration";
|
|
6733
6885
|
const editingProgress = editingColumnId === "progress";
|
|
@@ -6758,27 +6910,27 @@ var TaskListRow = React10.memo(
|
|
|
6758
6910
|
}, [columnWidthStyleMap]);
|
|
6759
6911
|
const normalizedTask = useMemo8(() => normalizeTaskDatesForType(task), [task]);
|
|
6760
6912
|
const isMilestone = useMemo8(() => isMilestoneTask(normalizedTask), [normalizedTask]);
|
|
6761
|
-
const [nameValue, setNameValue] =
|
|
6762
|
-
const nameInputRef =
|
|
6763
|
-
const [durationValue, setDurationValue] =
|
|
6913
|
+
const [nameValue, setNameValue] = useState6("");
|
|
6914
|
+
const nameInputRef = useRef5(null);
|
|
6915
|
+
const [durationValue, setDurationValue] = useState6(
|
|
6764
6916
|
() => getInclusiveDurationDays(normalizedTask.startDate, normalizedTask.endDate)
|
|
6765
6917
|
);
|
|
6766
|
-
const durationInputRef =
|
|
6767
|
-
const dependencySearchInputRef =
|
|
6768
|
-
const dependencySearchListRef =
|
|
6769
|
-
const [progressValue, setProgressValue] =
|
|
6770
|
-
const progressInputRef =
|
|
6771
|
-
const [overflowOpen, setOverflowOpen] =
|
|
6772
|
-
const [contextMenuOpen, setContextMenuOpen] =
|
|
6773
|
-
const [colorMenuOpen, setColorMenuOpen] =
|
|
6774
|
-
const nameConfirmedRef =
|
|
6775
|
-
const durationConfirmedRef =
|
|
6776
|
-
const progressConfirmedRef =
|
|
6777
|
-
const autoEditedForRef =
|
|
6778
|
-
const editTriggerRef =
|
|
6918
|
+
const durationInputRef = useRef5(null);
|
|
6919
|
+
const dependencySearchInputRef = useRef5(null);
|
|
6920
|
+
const dependencySearchListRef = useRef5(null);
|
|
6921
|
+
const [progressValue, setProgressValue] = useState6(0);
|
|
6922
|
+
const progressInputRef = useRef5(null);
|
|
6923
|
+
const [overflowOpen, setOverflowOpen] = useState6(false);
|
|
6924
|
+
const [contextMenuOpen, setContextMenuOpen] = useState6(false);
|
|
6925
|
+
const [colorMenuOpen, setColorMenuOpen] = useState6(false);
|
|
6926
|
+
const nameConfirmedRef = useRef5(false);
|
|
6927
|
+
const durationConfirmedRef = useRef5(false);
|
|
6928
|
+
const progressConfirmedRef = useRef5(false);
|
|
6929
|
+
const autoEditedForRef = useRef5(null);
|
|
6930
|
+
const editTriggerRef = useRef5(
|
|
6779
6931
|
"doubleclick"
|
|
6780
6932
|
);
|
|
6781
|
-
const rowRef =
|
|
6933
|
+
const rowRef = useRef5(null);
|
|
6782
6934
|
const isSelected = selectedTaskId === task.id;
|
|
6783
6935
|
const isParent = useMemo8(
|
|
6784
6936
|
() => isTaskParent(task.id, allTasks),
|
|
@@ -6805,13 +6957,42 @@ var TaskListRow = React10.memo(
|
|
|
6805
6957
|
[businessDays, weekendPredicate]
|
|
6806
6958
|
);
|
|
6807
6959
|
const isCollapsed = collapsedParentIds.has(task.id);
|
|
6960
|
+
const [compositeIconMode, setCompositeIconMode] = useState6(
|
|
6961
|
+
() => isCollapsed ? "composite" : "down"
|
|
6962
|
+
);
|
|
6963
|
+
const compositeIconModeRef = useRef5(compositeIconMode);
|
|
6964
|
+
const [compositeIconAnimation, setCompositeIconAnimation] = useState6(null);
|
|
6965
|
+
const [compositeIconAnimationPhase, setCompositeIconAnimationPhase] = useState6(null);
|
|
6966
|
+
useEffect5(() => {
|
|
6967
|
+
const nextMode = isCollapsed ? "composite" : "down";
|
|
6968
|
+
if (nextMode === compositeIconModeRef.current) {
|
|
6969
|
+
setCompositeIconAnimation(null);
|
|
6970
|
+
setCompositeIconAnimationPhase(null);
|
|
6971
|
+
return;
|
|
6972
|
+
}
|
|
6973
|
+
setCompositeIconAnimation(isCollapsed ? "closing" : "opening");
|
|
6974
|
+
setCompositeIconAnimationPhase("outgoing");
|
|
6975
|
+
const swapTimeoutId = window.setTimeout(() => {
|
|
6976
|
+
compositeIconModeRef.current = nextMode;
|
|
6977
|
+
setCompositeIconMode(nextMode);
|
|
6978
|
+
setCompositeIconAnimationPhase("incoming");
|
|
6979
|
+
}, 120);
|
|
6980
|
+
const finishTimeoutId = window.setTimeout(() => {
|
|
6981
|
+
setCompositeIconAnimation(null);
|
|
6982
|
+
setCompositeIconAnimationPhase(null);
|
|
6983
|
+
}, 240);
|
|
6984
|
+
return () => {
|
|
6985
|
+
window.clearTimeout(swapTimeoutId);
|
|
6986
|
+
window.clearTimeout(finishTimeoutId);
|
|
6987
|
+
};
|
|
6988
|
+
}, [isCollapsed]);
|
|
6808
6989
|
const getHierarchyLineColor = useCallback5((columnDepth) => {
|
|
6809
6990
|
return columnDepth % 2 === 0 ? "#93c5fd" : "var(--gantt-hierarchy-line-color)";
|
|
6810
6991
|
}, []);
|
|
6811
6992
|
const isPicking = selectingPredecessorFor != null;
|
|
6812
6993
|
const isSourceRow = isPicking && selectingPredecessorFor === task.id;
|
|
6813
|
-
const [dependencySearchQuery, setDependencySearchQuery] =
|
|
6814
|
-
const [highlightedDependencyIndex, setHighlightedDependencyIndex] =
|
|
6994
|
+
const [dependencySearchQuery, setDependencySearchQuery] = useState6("");
|
|
6995
|
+
const [highlightedDependencyIndex, setHighlightedDependencyIndex] = useState6(0);
|
|
6815
6996
|
const chips = useMemo8(() => {
|
|
6816
6997
|
const taskById = new Map((allTasks ?? []).map((t) => [t.id, t]));
|
|
6817
6998
|
return (task.dependencies ?? []).map((dep) => {
|
|
@@ -6848,7 +7029,7 @@ var TaskListRow = React10.memo(
|
|
|
6848
7029
|
taskNumberMap,
|
|
6849
7030
|
task.dependencies
|
|
6850
7031
|
]);
|
|
6851
|
-
|
|
7032
|
+
useEffect5(() => {
|
|
6852
7033
|
if (editingName && nameInputRef.current) {
|
|
6853
7034
|
nameInputRef.current.focus();
|
|
6854
7035
|
if (editTriggerRef.current === "keypress") {
|
|
@@ -6859,15 +7040,15 @@ var TaskListRow = React10.memo(
|
|
|
6859
7040
|
}
|
|
6860
7041
|
}
|
|
6861
7042
|
}, [editingName]);
|
|
6862
|
-
|
|
7043
|
+
useEffect5(() => {
|
|
6863
7044
|
if (!isSourceRow && dependencySearchQuery !== "") {
|
|
6864
7045
|
setDependencySearchQuery("");
|
|
6865
7046
|
}
|
|
6866
7047
|
}, [isSourceRow, dependencySearchQuery]);
|
|
6867
|
-
|
|
7048
|
+
useEffect5(() => {
|
|
6868
7049
|
setHighlightedDependencyIndex(0);
|
|
6869
7050
|
}, [dependencySearchQuery, isSourceRow, dependencyPickMode]);
|
|
6870
|
-
|
|
7051
|
+
useEffect5(() => {
|
|
6871
7052
|
if (dependencySearchCandidates.length === 0) {
|
|
6872
7053
|
setHighlightedDependencyIndex(0);
|
|
6873
7054
|
return;
|
|
@@ -6876,13 +7057,13 @@ var TaskListRow = React10.memo(
|
|
|
6876
7057
|
setHighlightedDependencyIndex(dependencySearchCandidates.length - 1);
|
|
6877
7058
|
}
|
|
6878
7059
|
}, [dependencySearchCandidates, highlightedDependencyIndex]);
|
|
6879
|
-
|
|
7060
|
+
useEffect5(() => {
|
|
6880
7061
|
if (isSourceRow && dependencySearchInputRef.current) {
|
|
6881
7062
|
dependencySearchInputRef.current.focus();
|
|
6882
7063
|
dependencySearchInputRef.current.select();
|
|
6883
7064
|
}
|
|
6884
7065
|
}, [isSourceRow, dependencyPickMode, activeLinkType]);
|
|
6885
|
-
|
|
7066
|
+
useEffect5(() => {
|
|
6886
7067
|
if (!isSourceRow || dependencySearchCandidates.length === 0) {
|
|
6887
7068
|
return;
|
|
6888
7069
|
}
|
|
@@ -6894,7 +7075,7 @@ var TaskListRow = React10.memo(
|
|
|
6894
7075
|
block: "nearest"
|
|
6895
7076
|
});
|
|
6896
7077
|
}, [isSourceRow, highlightedDependencyIndex, dependencySearchCandidates]);
|
|
6897
|
-
|
|
7078
|
+
useEffect5(() => {
|
|
6898
7079
|
if (editingTaskId === task.id && !disableTaskNameEditing && autoEditedForRef.current !== editingTaskId) {
|
|
6899
7080
|
autoEditedForRef.current = editingTaskId;
|
|
6900
7081
|
nameConfirmedRef.current = false;
|
|
@@ -6913,6 +7094,7 @@ var TaskListRow = React10.memo(
|
|
|
6913
7094
|
);
|
|
6914
7095
|
const handleNameDoubleClick = useCallback5(
|
|
6915
7096
|
(e) => {
|
|
7097
|
+
if (task.composite) return;
|
|
6916
7098
|
if (disableTaskNameEditing) return;
|
|
6917
7099
|
e.stopPropagation();
|
|
6918
7100
|
nameConfirmedRef.current = false;
|
|
@@ -6920,7 +7102,7 @@ var TaskListRow = React10.memo(
|
|
|
6920
7102
|
setNameValue(task.name);
|
|
6921
7103
|
setEditingColumnId("name");
|
|
6922
7104
|
},
|
|
6923
|
-
[task.name, disableTaskNameEditing]
|
|
7105
|
+
[task.name, task.composite, disableTaskNameEditing]
|
|
6924
7106
|
);
|
|
6925
7107
|
const handleRowKeyDown = useCallback5(
|
|
6926
7108
|
(e) => {
|
|
@@ -7075,16 +7257,16 @@ var TaskListRow = React10.memo(
|
|
|
7075
7257
|
},
|
|
7076
7258
|
[progressValue, task, onTasksChange, handleProgressCancel, allTasks]
|
|
7077
7259
|
);
|
|
7078
|
-
|
|
7260
|
+
useEffect5(() => {
|
|
7079
7261
|
if (editingProgress && progressInputRef.current) {
|
|
7080
7262
|
progressInputRef.current.focus();
|
|
7081
7263
|
progressInputRef.current.select();
|
|
7082
7264
|
}
|
|
7083
7265
|
}, [editingProgress]);
|
|
7084
|
-
|
|
7266
|
+
useEffect5(() => {
|
|
7085
7267
|
setDurationValue(getDuration(normalizedTask.startDate, normalizedTask.endDate));
|
|
7086
7268
|
}, [normalizedTask.startDate, normalizedTask.endDate, getDuration]);
|
|
7087
|
-
|
|
7269
|
+
useEffect5(() => {
|
|
7088
7270
|
if (editingDuration && durationInputRef.current) {
|
|
7089
7271
|
durationInputRef.current.focus();
|
|
7090
7272
|
durationInputRef.current.select();
|
|
@@ -7569,7 +7751,7 @@ var TaskListRow = React10.memo(
|
|
|
7569
7751
|
]
|
|
7570
7752
|
}
|
|
7571
7753
|
);
|
|
7572
|
-
const nameTriggerPaddingLeft = isParent ? `${nestingDepth * 20 + 28}px` : nestingDepth > 0 ? `${nestingDepth * 20 + 8}px` : void 0;
|
|
7754
|
+
const nameTriggerPaddingLeft = isParent && !task.composite ? `${nestingDepth * 20 + 28}px` : nestingDepth > 0 ? `${nestingDepth * 20 + 8}px` : void 0;
|
|
7573
7755
|
const nameInputPaddingLeft = nestingDepth > 0 ? `${nestingDepth * 20 + 8}px` : void 0;
|
|
7574
7756
|
const nestedDropIndicatorLeft = (() => {
|
|
7575
7757
|
const numberColumnWidth = resolvedColumns?.find((col) => col.id === "number")?.width ?? 40;
|
|
@@ -7667,36 +7849,35 @@ var TaskListRow = React10.memo(
|
|
|
7667
7849
|
}
|
|
7668
7850
|
)
|
|
7669
7851
|
] }),
|
|
7670
|
-
|
|
7671
|
-
|
|
7672
|
-
|
|
7673
|
-
|
|
7674
|
-
|
|
7675
|
-
|
|
7676
|
-
|
|
7677
|
-
|
|
7678
|
-
|
|
7679
|
-
|
|
7680
|
-
|
|
7681
|
-
|
|
7682
|
-
|
|
7683
|
-
}
|
|
7684
|
-
}
|
|
7685
|
-
),
|
|
7686
|
-
/* @__PURE__ */ jsx14(
|
|
7687
|
-
"button",
|
|
7688
|
-
{
|
|
7689
|
-
type: "button",
|
|
7690
|
-
className: `gantt-tl-collapse-btn ${isCollapsed ? "gantt-tl-collapse-btn-collapsed" : ""}`,
|
|
7691
|
-
onClick: handleToggleCollapse,
|
|
7692
|
-
style: { left: `${nestingDepth * 20 + 1}px` },
|
|
7693
|
-
"aria-label": isCollapsed ? "Expand children" : "Collapse children",
|
|
7694
|
-
children: /* @__PURE__ */ jsx14(ChevronRightIcon, {})
|
|
7852
|
+
task.composite && !isFilterHideMode && !isCollapsed && !editingName && /* @__PURE__ */ jsx14(
|
|
7853
|
+
"span",
|
|
7854
|
+
{
|
|
7855
|
+
"data-testid": "gantt-tl-parent-connector-tail",
|
|
7856
|
+
style: {
|
|
7857
|
+
position: "absolute",
|
|
7858
|
+
left: `${nestingDepth * 20 + 9}px`,
|
|
7859
|
+
top: `${rowHeight / 2 + 7}px`,
|
|
7860
|
+
height: `${rowHeight / 2 - 7}px`,
|
|
7861
|
+
width: "1.5px",
|
|
7862
|
+
background: getHierarchyLineColor(nestingDepth),
|
|
7863
|
+
borderRadius: "1px",
|
|
7864
|
+
pointerEvents: "none"
|
|
7695
7865
|
}
|
|
7696
|
-
|
|
7697
|
-
|
|
7866
|
+
}
|
|
7867
|
+
),
|
|
7868
|
+
isParent && !task.composite && !editingName && /* @__PURE__ */ jsx14(Fragment3, { children: /* @__PURE__ */ jsx14(
|
|
7869
|
+
"button",
|
|
7870
|
+
{
|
|
7871
|
+
type: "button",
|
|
7872
|
+
className: `gantt-tl-collapse-btn ${isCollapsed ? "gantt-tl-collapse-btn-collapsed" : ""}`,
|
|
7873
|
+
onClick: handleToggleCollapse,
|
|
7874
|
+
style: { left: `${nestingDepth * 20 - 2}px` },
|
|
7875
|
+
"aria-label": isCollapsed ? "Expand children" : "Collapse children",
|
|
7876
|
+
children: /* @__PURE__ */ jsx14(ChevronRightIcon, {})
|
|
7877
|
+
}
|
|
7878
|
+
) })
|
|
7698
7879
|
] }),
|
|
7699
|
-
!isChild && isParent && !editingName && /* @__PURE__ */ jsxs10(Fragment3, { children: [
|
|
7880
|
+
!isChild && isParent && !task.composite && !editingName && /* @__PURE__ */ jsxs10(Fragment3, { children: [
|
|
7700
7881
|
!isFilterHideMode && !isCollapsed && /* @__PURE__ */ jsx14(
|
|
7701
7882
|
"span",
|
|
7702
7883
|
{
|
|
@@ -7719,7 +7900,7 @@ var TaskListRow = React10.memo(
|
|
|
7719
7900
|
type: "button",
|
|
7720
7901
|
className: `gantt-tl-collapse-btn ${isCollapsed ? "gantt-tl-collapse-btn-collapsed" : ""}`,
|
|
7721
7902
|
onClick: handleToggleCollapse,
|
|
7722
|
-
style: { left: `${nestingDepth * 20
|
|
7903
|
+
style: { left: `${nestingDepth * 20 - 2}px` },
|
|
7723
7904
|
"aria-label": isCollapsed ? "Expand children" : "Collapse children",
|
|
7724
7905
|
children: /* @__PURE__ */ jsx14(ChevronRightIcon, {})
|
|
7725
7906
|
}
|
|
@@ -7738,27 +7919,57 @@ var TaskListRow = React10.memo(
|
|
|
7738
7919
|
style: { paddingLeft: nameInputPaddingLeft },
|
|
7739
7920
|
onClick: (e) => e.stopPropagation()
|
|
7740
7921
|
}
|
|
7741
|
-
) : /* @__PURE__ */ jsxs10(
|
|
7742
|
-
|
|
7743
|
-
|
|
7744
|
-
|
|
7745
|
-
|
|
7746
|
-
"gantt-tl-
|
|
7747
|
-
|
|
7748
|
-
|
|
7749
|
-
|
|
7750
|
-
|
|
7751
|
-
|
|
7752
|
-
|
|
7753
|
-
|
|
7754
|
-
|
|
7755
|
-
|
|
7756
|
-
|
|
7757
|
-
|
|
7758
|
-
|
|
7759
|
-
|
|
7760
|
-
|
|
7761
|
-
|
|
7922
|
+
) : /* @__PURE__ */ jsxs10(Fragment3, { children: [
|
|
7923
|
+
task.composite && /* @__PURE__ */ jsx14(
|
|
7924
|
+
"button",
|
|
7925
|
+
{
|
|
7926
|
+
type: "button",
|
|
7927
|
+
className: "gantt-tl-compositeToggle",
|
|
7928
|
+
onClick: handleToggleCollapse,
|
|
7929
|
+
style: { left: `${nestingDepth * 20 - 3}px` },
|
|
7930
|
+
"aria-label": isCollapsed ? `\u0420\u0430\u0441\u043A\u0440\u044B\u0442\u044C ${task.name}` : `\u0421\u0432\u0435\u0440\u043D\u0443\u0442\u044C ${task.name}`,
|
|
7931
|
+
"aria-expanded": !isCollapsed,
|
|
7932
|
+
title: isCollapsed ? "\u0420\u0430\u0441\u043A\u0440\u044B\u0442\u044C \u044D\u0442\u0430\u0436\u0438" : "\u0421\u0432\u0435\u0440\u043D\u0443\u0442\u044C \u044D\u0442\u0430\u0436\u0438",
|
|
7933
|
+
children: /* @__PURE__ */ jsx14(
|
|
7934
|
+
"svg",
|
|
7935
|
+
{
|
|
7936
|
+
className: compositeIconAnimation && compositeIconAnimationPhase ? `gantt-tl-compositeGlyph-${compositeIconMode}-${compositeIconAnimation}-${compositeIconAnimationPhase}` : void 0,
|
|
7937
|
+
viewBox: "0 0 24 24",
|
|
7938
|
+
fill: "none",
|
|
7939
|
+
stroke: "currentColor",
|
|
7940
|
+
strokeWidth: "2",
|
|
7941
|
+
strokeLinecap: "round",
|
|
7942
|
+
strokeLinejoin: "round",
|
|
7943
|
+
"aria-hidden": "true",
|
|
7944
|
+
children: compositeIconMode === "composite" ? /* @__PURE__ */ jsxs10(Fragment3, { children: [
|
|
7945
|
+
/* @__PURE__ */ jsx14("path", { d: "M21 5H11" }),
|
|
7946
|
+
/* @__PURE__ */ jsx14("path", { d: "M21 12H11" }),
|
|
7947
|
+
/* @__PURE__ */ jsx14("path", { d: "M21 19H11" }),
|
|
7948
|
+
/* @__PURE__ */ jsx14("path", { d: "m3 8 4 4-4 4" })
|
|
7949
|
+
] }) : /* @__PURE__ */ jsx14("path", { d: "m6 9 6 6 6-6" })
|
|
7950
|
+
}
|
|
7951
|
+
)
|
|
7952
|
+
}
|
|
7953
|
+
),
|
|
7954
|
+
/* @__PURE__ */ jsxs10(
|
|
7955
|
+
"button",
|
|
7956
|
+
{
|
|
7957
|
+
type: "button",
|
|
7958
|
+
className: `gantt-tl-name-trigger${disableTaskNameEditing ? " gantt-tl-name-locked" : ""}`,
|
|
7959
|
+
title: task.name,
|
|
7960
|
+
onClick: handleNameClick,
|
|
7961
|
+
onDoubleClick: handleNameDoubleClick,
|
|
7962
|
+
style: {
|
|
7963
|
+
paddingLeft: task.composite ? `${nestingDepth * 20 + 30}px` : nameTriggerPaddingLeft,
|
|
7964
|
+
paddingRight: task.color ? "20px" : void 0
|
|
7965
|
+
},
|
|
7966
|
+
children: [
|
|
7967
|
+
taskListNamePrefixIcon ? /* @__PURE__ */ jsx14("span", { className: "gantt-tl-name-trigger-icon", "aria-hidden": "true", children: taskListNamePrefixIcon }) : null,
|
|
7968
|
+
/* @__PURE__ */ jsx14("span", { className: "gantt-tl-name-trigger-text", children: task.name })
|
|
7969
|
+
]
|
|
7970
|
+
}
|
|
7971
|
+
)
|
|
7972
|
+
] }),
|
|
7762
7973
|
!editingName && task.color && /* @__PURE__ */ jsx14(
|
|
7763
7974
|
"span",
|
|
7764
7975
|
{
|
|
@@ -8375,8 +8586,9 @@ var TaskListRow = React10.memo(
|
|
|
8375
8586
|
isDragOver && isNestedDropTarget ? "gantt-tl-row-drag-over-nested" : "",
|
|
8376
8587
|
isDragOver && isDirectChildDropTarget ? "gantt-tl-row-drag-over-direct-child" : "",
|
|
8377
8588
|
isChild ? "gantt-tl-row-child" : "",
|
|
8378
|
-
isParent ? "gantt-tl-row-parent" : "",
|
|
8379
|
-
|
|
8589
|
+
isParent && !task.composite ? "gantt-tl-row-parent" : "",
|
|
8590
|
+
task.composite ? "gantt-tl-row-composite" : "",
|
|
8591
|
+
isParent && !task.composite && fillParentRow ? "gantt-tl-row-parent-filled" : "",
|
|
8380
8592
|
`gantt-tl-row-level-${rowFillLevel}`,
|
|
8381
8593
|
isTotalRow ? "gantt-tl-row-total" : "",
|
|
8382
8594
|
rowClassName ?? ""
|
|
@@ -8384,6 +8596,7 @@ var TaskListRow = React10.memo(
|
|
|
8384
8596
|
style: {
|
|
8385
8597
|
height: `${rowHeight}px`,
|
|
8386
8598
|
position: "relative",
|
|
8599
|
+
"--gantt-tl-composite-detail-color": compositeParentColor ?? "var(--gantt-task-bar-default-color, #8b5cf6)",
|
|
8387
8600
|
"--gantt-tl-nested-drop-left": nestedDropIndicatorLeft,
|
|
8388
8601
|
"--gantt-tl-nested-inside-drop-left": nestedInsideDropIndicatorLeft
|
|
8389
8602
|
},
|
|
@@ -8525,7 +8738,7 @@ var TaskListRow = React10.memo(
|
|
|
8525
8738
|
TaskListRow.displayName = "TaskListRow";
|
|
8526
8739
|
|
|
8527
8740
|
// src/components/TaskList/NewTaskRow.tsx
|
|
8528
|
-
import { useState as
|
|
8741
|
+
import { useState as useState7, useRef as useRef6, useEffect as useEffect6 } from "react";
|
|
8529
8742
|
import { jsx as jsx15, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
8530
8743
|
var NewTaskRow = ({
|
|
8531
8744
|
rowHeight,
|
|
@@ -8533,12 +8746,12 @@ var NewTaskRow = ({
|
|
|
8533
8746
|
onCancel,
|
|
8534
8747
|
nestingDepth = 0
|
|
8535
8748
|
}) => {
|
|
8536
|
-
const [nameValue, setNameValue] =
|
|
8537
|
-
const inputRef =
|
|
8538
|
-
const confirmedRef =
|
|
8749
|
+
const [nameValue, setNameValue] = useState7("");
|
|
8750
|
+
const inputRef = useRef6(null);
|
|
8751
|
+
const confirmedRef = useRef6(false);
|
|
8539
8752
|
const inputInnerPadding = 4;
|
|
8540
8753
|
const levelOffset = nestingDepth > 0 ? nestingDepth * 20 + 8 : 0;
|
|
8541
|
-
|
|
8754
|
+
useEffect6(() => {
|
|
8542
8755
|
if (inputRef.current) {
|
|
8543
8756
|
inputRef.current.focus();
|
|
8544
8757
|
inputRef.current.select();
|
|
@@ -8591,7 +8804,7 @@ var NewTaskRow = ({
|
|
|
8591
8804
|
};
|
|
8592
8805
|
|
|
8593
8806
|
// src/components/GenerationSkeleton/GenerationSkeleton.tsx
|
|
8594
|
-
import { useRef as
|
|
8807
|
+
import { useRef as useRef7 } from "react";
|
|
8595
8808
|
import { Fragment as Fragment4, jsx as jsx16 } from "react/jsx-runtime";
|
|
8596
8809
|
var MAX_SKELETON_ROWS = 200;
|
|
8597
8810
|
var SHIMMER_DURATION_MS = 1450;
|
|
@@ -8609,14 +8822,15 @@ var GenerationSkeletonRows = ({
|
|
|
8609
8822
|
rowHeight,
|
|
8610
8823
|
variant,
|
|
8611
8824
|
startIndex = 0,
|
|
8825
|
+
startTop,
|
|
8612
8826
|
taskListLayout,
|
|
8613
8827
|
chartDayWidth = 40,
|
|
8614
8828
|
chartStartDayOffset = 0,
|
|
8615
8829
|
chartStartJitterDays = 0
|
|
8616
8830
|
}) => {
|
|
8617
8831
|
const safeCount = clampCount(count);
|
|
8618
|
-
const previousCountRef =
|
|
8619
|
-
const shimmerDelayRef =
|
|
8832
|
+
const previousCountRef = useRef7(null);
|
|
8833
|
+
const shimmerDelayRef = useRef7("0ms");
|
|
8620
8834
|
if (previousCountRef.current !== safeCount) {
|
|
8621
8835
|
previousCountRef.current = safeCount;
|
|
8622
8836
|
shimmerDelayRef.current = `-${Date.now() % SHIMMER_DURATION_MS}ms`;
|
|
@@ -8649,7 +8863,7 @@ var GenerationSkeletonRows = ({
|
|
|
8649
8863
|
"div",
|
|
8650
8864
|
{
|
|
8651
8865
|
className: "gantt-generation-skeleton-row",
|
|
8652
|
-
style: { top: `${
|
|
8866
|
+
style: { top: `${(startTop ?? startIndex * rowHeight) + index * rowHeight}px`, height: `${rowHeight}px` },
|
|
8653
8867
|
children: variant === "task-list" ? /* @__PURE__ */ jsx16(Fragment4, { children: /* @__PURE__ */ jsx16("span", { className: `gantt-generation-skeleton-label ${shortShape ? "gantt-generation-skeleton-label-short" : ""} ${mediumShape ? "gantt-generation-skeleton-label-medium" : ""}` }) }) : /* @__PURE__ */ jsx16("span", { className: `gantt-generation-skeleton-bar ${parentShape ? "gantt-generation-skeleton-bar-parent" : ""} ${shortShape ? "gantt-generation-skeleton-bar-short" : ""}`, style: chartBarStyle })
|
|
8654
8868
|
},
|
|
8655
8869
|
rowIndex
|
|
@@ -8887,8 +9101,8 @@ var SelectAllCheckbox = ({
|
|
|
8887
9101
|
indeterminate,
|
|
8888
9102
|
onChange
|
|
8889
9103
|
}) => {
|
|
8890
|
-
const ref =
|
|
8891
|
-
|
|
9104
|
+
const ref = useRef8(null);
|
|
9105
|
+
useEffect7(() => {
|
|
8892
9106
|
if (ref.current) {
|
|
8893
9107
|
ref.current.indeterminate = indeterminate;
|
|
8894
9108
|
}
|
|
@@ -8909,6 +9123,8 @@ var SelectAllCheckbox = ({
|
|
|
8909
9123
|
var TaskList = ({
|
|
8910
9124
|
tasks,
|
|
8911
9125
|
rowHeight,
|
|
9126
|
+
rowTops,
|
|
9127
|
+
rowHeights,
|
|
8912
9128
|
headerHeight,
|
|
8913
9129
|
taskListWidth,
|
|
8914
9130
|
onTasksChange,
|
|
@@ -8967,14 +9183,14 @@ var TaskList = ({
|
|
|
8967
9183
|
skeletonRowCount = 0
|
|
8968
9184
|
}) => {
|
|
8969
9185
|
const reorderDisabled = disableTaskListReorder || disableTaskDrag;
|
|
8970
|
-
const [internalSelectedTaskIds, setInternalSelectedTaskIds] =
|
|
8971
|
-
const [activeCustomCell, setActiveCustomCell] =
|
|
8972
|
-
const [columnWidthOverrides, setColumnWidthOverrides] =
|
|
8973
|
-
const [isColumnResizeMode, setIsColumnResizeMode] =
|
|
8974
|
-
const columnResizeHeaderRef =
|
|
8975
|
-
const resizeStateRef =
|
|
9186
|
+
const [internalSelectedTaskIds, setInternalSelectedTaskIds] = useState8(/* @__PURE__ */ new Set());
|
|
9187
|
+
const [activeCustomCell, setActiveCustomCell] = useState8(null);
|
|
9188
|
+
const [columnWidthOverrides, setColumnWidthOverrides] = useState8(() => normalizeColumnWidthMap(taskListColumnWidths));
|
|
9189
|
+
const [isColumnResizeMode, setIsColumnResizeMode] = useState8(false);
|
|
9190
|
+
const columnResizeHeaderRef = useRef8(null);
|
|
9191
|
+
const resizeStateRef = useRef8(null);
|
|
8976
9192
|
const effectiveSelectedTaskIds = selectedTaskIds ?? internalSelectedTaskIds;
|
|
8977
|
-
|
|
9193
|
+
useEffect7(() => {
|
|
8978
9194
|
if (!isColumnResizeMode) {
|
|
8979
9195
|
return;
|
|
8980
9196
|
}
|
|
@@ -8996,7 +9212,7 @@ var TaskList = ({
|
|
|
8996
9212
|
}
|
|
8997
9213
|
onSelectedTaskIdsChange?.(nextSelectedTaskIds);
|
|
8998
9214
|
}, [onSelectedTaskIdsChange, selectedTaskIds]);
|
|
8999
|
-
const [internalCollapsedParentIds, setInternalCollapsedParentIds] =
|
|
9215
|
+
const [internalCollapsedParentIds, setInternalCollapsedParentIds] = useState8(/* @__PURE__ */ new Set());
|
|
9000
9216
|
const collapsedParentIds = externalCollapsedParentIds ?? internalCollapsedParentIds;
|
|
9001
9217
|
const handleToggleCollapse = externalOnToggleCollapse ?? useCallback6((parentId) => {
|
|
9002
9218
|
setInternalCollapsedParentIds((prev) => {
|
|
@@ -9036,14 +9252,22 @@ var TaskList = ({
|
|
|
9036
9252
|
return tasks2;
|
|
9037
9253
|
}, [orderedTasks, collapsedParentIds, filterMode, filteredTaskIds, isFilterActive, criticalPathMode, criticalTaskIds]);
|
|
9038
9254
|
const totalHeight = useMemo9(
|
|
9039
|
-
() => (visibleTasks.length + Math.max(0, Math.floor(skeletonRowCount))
|
|
9040
|
-
[rowHeight, skeletonRowCount, visibleTasks.length]
|
|
9255
|
+
() => (rowTops && rowHeights && visibleTasks.length > 0 ? rowTops[visibleTasks.length - 1] + rowHeights[visibleTasks.length - 1] : visibleTasks.length * rowHeight) + Math.max(0, Math.floor(skeletonRowCount)) * rowHeight,
|
|
9256
|
+
[rowHeight, rowTops, rowHeights, skeletonRowCount, visibleTasks.length]
|
|
9041
9257
|
);
|
|
9042
9258
|
const visibleTaskNumberMap = useMemo9(
|
|
9043
9259
|
() => Object.fromEntries(buildTaskNumberMap(visibleTasks)),
|
|
9044
9260
|
[visibleTasks]
|
|
9045
9261
|
);
|
|
9046
9262
|
const visibleTaskIds = useMemo9(() => visibleTasks.map((task) => task.id), [visibleTasks]);
|
|
9263
|
+
const compositeParentIds = useMemo9(
|
|
9264
|
+
() => new Set(tasks.filter((task) => task.composite).map((task) => task.id)),
|
|
9265
|
+
[tasks]
|
|
9266
|
+
);
|
|
9267
|
+
const compositeParentsById = useMemo9(
|
|
9268
|
+
() => new Map(tasks.filter((task) => task.composite).map((task) => [task.id, task])),
|
|
9269
|
+
[tasks]
|
|
9270
|
+
);
|
|
9047
9271
|
const renderedVisibleRowIndices = useMemo9(
|
|
9048
9272
|
() => visibleRowIndices ?? visibleTasks.map((_, index) => index),
|
|
9049
9273
|
[visibleRowIndices, visibleTasks]
|
|
@@ -9154,14 +9378,14 @@ var TaskList = ({
|
|
|
9154
9378
|
const handleRowClick = useCallback6((taskId) => {
|
|
9155
9379
|
onTaskSelect?.(taskId);
|
|
9156
9380
|
}, [onTaskSelect]);
|
|
9157
|
-
const [activeLinkType, setActiveLinkType] =
|
|
9158
|
-
const [selectingPredecessorFor, setSelectingPredecessorFor] =
|
|
9159
|
-
const [dependencyPickMode, setDependencyPickMode] =
|
|
9160
|
-
const [typeMenuOpen, setTypeMenuOpen] =
|
|
9161
|
-
const [dependencyError, setDependencyError] =
|
|
9162
|
-
const overlayRef =
|
|
9163
|
-
const [selectedChip, setSelectedChip] =
|
|
9164
|
-
|
|
9381
|
+
const [activeLinkType, setActiveLinkType] = useState8("FS");
|
|
9382
|
+
const [selectingPredecessorFor, setSelectingPredecessorFor] = useState8(null);
|
|
9383
|
+
const [dependencyPickMode, setDependencyPickMode] = useState8("successor");
|
|
9384
|
+
const [typeMenuOpen, setTypeMenuOpen] = useState8(false);
|
|
9385
|
+
const [dependencyError, setDependencyError] = useState8(null);
|
|
9386
|
+
const overlayRef = useRef8(null);
|
|
9387
|
+
const [selectedChip, setSelectedChip] = useState8(controlledSelectedChip ? { ...controlledSelectedChip, linkType: controlledSelectedChip.linkType } : null);
|
|
9388
|
+
useEffect7(() => {
|
|
9165
9389
|
if (controlledSelectedChip !== void 0) {
|
|
9166
9390
|
setSelectedChip(controlledSelectedChip ? { ...controlledSelectedChip, linkType: controlledSelectedChip.linkType } : null);
|
|
9167
9391
|
}
|
|
@@ -9170,7 +9394,7 @@ var TaskList = ({
|
|
|
9170
9394
|
setSelectedChip(chip);
|
|
9171
9395
|
onSelectedChipChange?.(chip);
|
|
9172
9396
|
}, [onSelectedChipChange]);
|
|
9173
|
-
|
|
9397
|
+
useEffect7(() => {
|
|
9174
9398
|
if (!selectingPredecessorFor && !selectedChip && !selectedTaskId && !activeCustomCell) return;
|
|
9175
9399
|
const pendingCanvasMouseDownRef = {
|
|
9176
9400
|
container: null,
|
|
@@ -9352,13 +9576,13 @@ var TaskList = ({
|
|
|
9352
9576
|
);
|
|
9353
9577
|
onTasksChange?.([{ ...task, dependencies: updatedDeps }]);
|
|
9354
9578
|
}, [tasks, onTasksChange]);
|
|
9355
|
-
const [isCreating, setIsCreating] =
|
|
9356
|
-
const [pendingInsert, setPendingInsert] =
|
|
9357
|
-
const [draggingIndex, setDraggingIndex] =
|
|
9358
|
-
const [dragOverTarget, setDragOverTarget] =
|
|
9359
|
-
const [isBeforeFirstDropZoneActive, setIsBeforeFirstDropZoneActive] =
|
|
9360
|
-
const dragOriginIndexRef =
|
|
9361
|
-
const dragTaskIdRef =
|
|
9579
|
+
const [isCreating, setIsCreating] = useState8(false);
|
|
9580
|
+
const [pendingInsert, setPendingInsert] = useState8(null);
|
|
9581
|
+
const [draggingIndex, setDraggingIndex] = useState8(null);
|
|
9582
|
+
const [dragOverTarget, setDragOverTarget] = useState8(null);
|
|
9583
|
+
const [isBeforeFirstDropZoneActive, setIsBeforeFirstDropZoneActive] = useState8(false);
|
|
9584
|
+
const dragOriginIndexRef = useRef8(null);
|
|
9585
|
+
const dragTaskIdRef = useRef8(null);
|
|
9362
9586
|
const clearDragState = useCallback6(() => {
|
|
9363
9587
|
setDraggingIndex(null);
|
|
9364
9588
|
setDragOverTarget(null);
|
|
@@ -9694,7 +9918,7 @@ var TaskList = ({
|
|
|
9694
9918
|
() => createBuiltInColumns({ businessDays, enableTaskMultiSelect }),
|
|
9695
9919
|
[businessDays, enableTaskMultiSelect]
|
|
9696
9920
|
);
|
|
9697
|
-
|
|
9921
|
+
useEffect7(() => {
|
|
9698
9922
|
setColumnWidthOverrides(normalizeColumnWidthMap(taskListColumnWidths));
|
|
9699
9923
|
}, [taskListColumnWidths]);
|
|
9700
9924
|
const resolvedColumns = useMemo9(
|
|
@@ -9746,7 +9970,7 @@ var TaskList = ({
|
|
|
9746
9970
|
return next;
|
|
9747
9971
|
});
|
|
9748
9972
|
}, [onTaskListColumnWidthsChange]);
|
|
9749
|
-
|
|
9973
|
+
useEffect7(() => {
|
|
9750
9974
|
const updateResizedColumn = (clientX) => {
|
|
9751
9975
|
const resizeState = resizeStateRef.current;
|
|
9752
9976
|
if (!resizeState) {
|
|
@@ -10035,7 +10259,7 @@ var TaskList = ({
|
|
|
10035
10259
|
renderedVisibleTasks.map(({ task, index }) => {
|
|
10036
10260
|
const previousVisibleTask = index > 0 ? visibleTasks[index - 1] : void 0;
|
|
10037
10261
|
const canDemoteTask = index === 0 || !task.parentId || previousVisibleTask?.id !== task.parentId;
|
|
10038
|
-
const topOffset = index * rowHeight + (hasVisiblePendingInsert && index > pendingInsertRowIndex ? rowHeight : 0);
|
|
10262
|
+
const topOffset = (rowTops?.[index] ?? index * rowHeight) + (hasVisiblePendingInsert && index > pendingInsertRowIndex ? rowHeight : 0);
|
|
10039
10263
|
return /* @__PURE__ */ jsx17(
|
|
10040
10264
|
"div",
|
|
10041
10265
|
{
|
|
@@ -10052,7 +10276,7 @@ var TaskList = ({
|
|
|
10052
10276
|
rowIndex: index,
|
|
10053
10277
|
taskNumber: originalTaskNumberMap[task.id] || "",
|
|
10054
10278
|
taskNumberMap: originalTaskNumberMap,
|
|
10055
|
-
rowHeight,
|
|
10279
|
+
rowHeight: rowHeights?.[index] ?? rowHeight,
|
|
10056
10280
|
onTasksChange,
|
|
10057
10281
|
onDurationChange,
|
|
10058
10282
|
selectedTaskId,
|
|
@@ -10109,7 +10333,8 @@ var TaskList = ({
|
|
|
10109
10333
|
onActiveCustomCellChange: setActiveCustomCell,
|
|
10110
10334
|
taskListMenuCommands,
|
|
10111
10335
|
hideTaskListRowActions,
|
|
10112
|
-
rowClassName: getTaskListRowClassName?.(task),
|
|
10336
|
+
rowClassName: [task.parentId && compositeParentIds.has(task.parentId) ? "gantt-tl-row-composite-detail" : "", getTaskListRowClassName?.(task)].filter(Boolean).join(" "),
|
|
10337
|
+
compositeParentColor: task.parentId ? compositeParentsById.get(task.parentId)?.color : void 0,
|
|
10113
10338
|
getTaskListNamePrefixIcon,
|
|
10114
10339
|
taskDateChangeMode,
|
|
10115
10340
|
onTaskDateChangeModeChange,
|
|
@@ -10125,7 +10350,7 @@ var TaskList = ({
|
|
|
10125
10350
|
{
|
|
10126
10351
|
style: {
|
|
10127
10352
|
position: "absolute",
|
|
10128
|
-
top: `${(pendingInsertRowIndex + 1) * rowHeight}px`,
|
|
10353
|
+
top: `${rowTops?.[pendingInsertRowIndex + 1] ?? (pendingInsertRowIndex + 1) * rowHeight}px`,
|
|
10129
10354
|
left: 0,
|
|
10130
10355
|
right: 0
|
|
10131
10356
|
},
|
|
@@ -10147,6 +10372,7 @@ var TaskList = ({
|
|
|
10147
10372
|
rowHeight,
|
|
10148
10373
|
variant: "task-list",
|
|
10149
10374
|
startIndex: visibleTasks.length,
|
|
10375
|
+
startTop: totalHeight - Math.max(0, Math.floor(skeletonRowCount)) * rowHeight,
|
|
10150
10376
|
taskListLayout: generationSkeletonTaskListLayout
|
|
10151
10377
|
}
|
|
10152
10378
|
)
|
|
@@ -10200,7 +10426,7 @@ var TaskList = ({
|
|
|
10200
10426
|
};
|
|
10201
10427
|
|
|
10202
10428
|
// src/components/ResourceTimelineChart/ResourceTimelineChart.tsx
|
|
10203
|
-
import React14, { useCallback as useCallback8, useEffect as
|
|
10429
|
+
import React14, { useCallback as useCallback8, useEffect as useEffect9, useMemo as useMemo10, useRef as useRef10, useState as useState10 } from "react";
|
|
10204
10430
|
|
|
10205
10431
|
// src/utils/resourceTimelineLayout.ts
|
|
10206
10432
|
var isInvalidDate = (date) => Number.isNaN(date.getTime());
|
|
@@ -10402,7 +10628,7 @@ var layoutResourceTimelineItems = (resources, options) => {
|
|
|
10402
10628
|
};
|
|
10403
10629
|
|
|
10404
10630
|
// src/hooks/useResourceItemDrag.ts
|
|
10405
|
-
import { useCallback as useCallback7, useEffect as
|
|
10631
|
+
import { useCallback as useCallback7, useEffect as useEffect8, useRef as useRef9, useState as useState9 } from "react";
|
|
10406
10632
|
var RESOURCE_CURSOR_STYLE_ID = "gantt-resource-global-drag-cursor-style";
|
|
10407
10633
|
function ensureResourceGlobalCursorStyle() {
|
|
10408
10634
|
if (typeof document === "undefined") return;
|
|
@@ -10514,15 +10740,15 @@ var useResourceItemDrag = ({
|
|
|
10514
10740
|
weekendPredicate,
|
|
10515
10741
|
onResourceItemMove
|
|
10516
10742
|
}) => {
|
|
10517
|
-
const activeDragRef =
|
|
10518
|
-
const rowsRef =
|
|
10519
|
-
const onResourceItemMoveRef =
|
|
10520
|
-
const rafRef =
|
|
10521
|
-
const [preview, setPreview] =
|
|
10522
|
-
|
|
10743
|
+
const activeDragRef = useRef9(null);
|
|
10744
|
+
const rowsRef = useRef9(rows);
|
|
10745
|
+
const onResourceItemMoveRef = useRef9(onResourceItemMove);
|
|
10746
|
+
const rafRef = useRef9(null);
|
|
10747
|
+
const [preview, setPreview] = useState9(null);
|
|
10748
|
+
useEffect8(() => {
|
|
10523
10749
|
rowsRef.current = rows;
|
|
10524
10750
|
}, [rows]);
|
|
10525
|
-
|
|
10751
|
+
useEffect8(() => {
|
|
10526
10752
|
onResourceItemMoveRef.current = onResourceItemMove;
|
|
10527
10753
|
}, [onResourceItemMove]);
|
|
10528
10754
|
const clearRaf = useCallback7(() => {
|
|
@@ -10537,7 +10763,7 @@ var useResourceItemDrag = ({
|
|
|
10537
10763
|
activeDragRef.current = null;
|
|
10538
10764
|
setPreview(null);
|
|
10539
10765
|
}, [clearRaf]);
|
|
10540
|
-
|
|
10766
|
+
useEffect8(() => {
|
|
10541
10767
|
const handleMouseMove = (event) => {
|
|
10542
10768
|
const activeDrag = activeDragRef.current;
|
|
10543
10769
|
if (!activeDrag || rafRef.current !== null) {
|
|
@@ -10870,13 +11096,13 @@ var ResourceHeader = ({
|
|
|
10870
11096
|
onConflictBadgeClick,
|
|
10871
11097
|
columnTemplate
|
|
10872
11098
|
}) => {
|
|
10873
|
-
const [menuOpen, setMenuOpen] =
|
|
10874
|
-
const [typeMenuOpen, setTypeMenuOpen] =
|
|
10875
|
-
const [scopeMenuOpen, setScopeMenuOpen] =
|
|
10876
|
-
const [editingName, setEditingName] =
|
|
10877
|
-
const [nameValue, setNameValue] =
|
|
10878
|
-
const nameInputRef =
|
|
10879
|
-
const nameConfirmedRef =
|
|
11099
|
+
const [menuOpen, setMenuOpen] = useState10(false);
|
|
11100
|
+
const [typeMenuOpen, setTypeMenuOpen] = useState10(false);
|
|
11101
|
+
const [scopeMenuOpen, setScopeMenuOpen] = useState10(false);
|
|
11102
|
+
const [editingName, setEditingName] = useState10(false);
|
|
11103
|
+
const [nameValue, setNameValue] = useState10(resource.name);
|
|
11104
|
+
const nameInputRef = useRef10(null);
|
|
11105
|
+
const nameConfirmedRef = useRef10(false);
|
|
10880
11106
|
const visibleCommands = useMemo10(
|
|
10881
11107
|
() => menuCommands.filter((command) => command.isVisible?.(resource) ?? true),
|
|
10882
11108
|
[menuCommands, resource]
|
|
@@ -10889,12 +11115,12 @@ var ResourceHeader = ({
|
|
|
10889
11115
|
const applyResourcePatch = useCallback8((patch) => {
|
|
10890
11116
|
onResourceChange?.({ ...resource, ...patch });
|
|
10891
11117
|
}, [onResourceChange, resource]);
|
|
10892
|
-
|
|
11118
|
+
useEffect9(() => {
|
|
10893
11119
|
if (!editingName) {
|
|
10894
11120
|
setNameValue(resource.name);
|
|
10895
11121
|
}
|
|
10896
11122
|
}, [editingName, resource.name]);
|
|
10897
|
-
|
|
11123
|
+
useEffect9(() => {
|
|
10898
11124
|
if (editingName && nameInputRef.current) {
|
|
10899
11125
|
nameInputRef.current.focus();
|
|
10900
11126
|
nameInputRef.current.select();
|
|
@@ -11135,10 +11361,10 @@ var ResourceHeader = ({
|
|
|
11135
11361
|
);
|
|
11136
11362
|
};
|
|
11137
11363
|
var NewResourceRow = ({ height, onConfirm, onCancel, columnTemplate }) => {
|
|
11138
|
-
const [nameValue, setNameValue] =
|
|
11139
|
-
const inputRef =
|
|
11140
|
-
const confirmedRef =
|
|
11141
|
-
|
|
11364
|
+
const [nameValue, setNameValue] = useState10("");
|
|
11365
|
+
const inputRef = useRef10(null);
|
|
11366
|
+
const confirmedRef = useRef10(false);
|
|
11367
|
+
useEffect9(() => {
|
|
11142
11368
|
inputRef.current?.focus();
|
|
11143
11369
|
inputRef.current?.select();
|
|
11144
11370
|
}, []);
|
|
@@ -11223,18 +11449,18 @@ function ResourceTimelineChart({
|
|
|
11223
11449
|
resourceTableColumnWidths,
|
|
11224
11450
|
onResourceTableColumnWidthsChange
|
|
11225
11451
|
}) {
|
|
11226
|
-
const scrollContainerRef =
|
|
11227
|
-
const gridRef =
|
|
11228
|
-
const panStateRef =
|
|
11229
|
-
const resourceColumnResizeRef =
|
|
11230
|
-
const conflictNavigationIndexRef =
|
|
11231
|
-
const resourceNavigationIndexRef =
|
|
11232
|
-
const conflictHighlightTimeoutRef =
|
|
11233
|
-
const [isCreatingResource, setIsCreatingResource] =
|
|
11234
|
-
const [creatingResourceGroupType, setCreatingResourceGroupType] =
|
|
11235
|
-
const [activeConflictItemId, setActiveConflictItemId] =
|
|
11236
|
-
const [resourceColumnHasRightShadow, setResourceColumnHasRightShadow] =
|
|
11237
|
-
const [resourceColumnWidthOverrides, setResourceColumnWidthOverrides] =
|
|
11452
|
+
const scrollContainerRef = useRef10(null);
|
|
11453
|
+
const gridRef = useRef10(null);
|
|
11454
|
+
const panStateRef = useRef10(null);
|
|
11455
|
+
const resourceColumnResizeRef = useRef10(null);
|
|
11456
|
+
const conflictNavigationIndexRef = useRef10(/* @__PURE__ */ new Map());
|
|
11457
|
+
const resourceNavigationIndexRef = useRef10(/* @__PURE__ */ new Map());
|
|
11458
|
+
const conflictHighlightTimeoutRef = useRef10(null);
|
|
11459
|
+
const [isCreatingResource, setIsCreatingResource] = useState10(false);
|
|
11460
|
+
const [creatingResourceGroupType, setCreatingResourceGroupType] = useState10(null);
|
|
11461
|
+
const [activeConflictItemId, setActiveConflictItemId] = useState10(null);
|
|
11462
|
+
const [resourceColumnHasRightShadow, setResourceColumnHasRightShadow] = useState10(false);
|
|
11463
|
+
const [resourceColumnWidthOverrides, setResourceColumnWidthOverrides] = useState10(() => normalizeResourceColumnWidthMap(resourceTableColumnWidths));
|
|
11238
11464
|
const validItems = useMemo10(() => collectValidItems(resources), [resources]);
|
|
11239
11465
|
const dateRange = useMemo10(() => getMultiMonthDays(validItems), [validItems]);
|
|
11240
11466
|
const monthStart = useMemo10(() => {
|
|
@@ -11246,7 +11472,7 @@ function ResourceTimelineChart({
|
|
|
11246
11472
|
[customDays, isWeekend3]
|
|
11247
11473
|
);
|
|
11248
11474
|
const gridWidth = useMemo10(() => Math.round(dateRange.length * dayWidth), [dateRange.length, dayWidth]);
|
|
11249
|
-
|
|
11475
|
+
useEffect9(() => {
|
|
11250
11476
|
setResourceColumnWidthOverrides(normalizeResourceColumnWidthMap(resourceTableColumnWidths));
|
|
11251
11477
|
}, [resourceTableColumnWidths]);
|
|
11252
11478
|
const resolvedResourceColumnWidths = useMemo10(
|
|
@@ -11302,7 +11528,7 @@ function ResourceTimelineChart({
|
|
|
11302
11528
|
);
|
|
11303
11529
|
const canAddResource = enableAddResource && Boolean(onAddResource);
|
|
11304
11530
|
const resourceAddRowHeight = laneHeight + DEFAULT_RESOURCE_ROW_GAP;
|
|
11305
|
-
const [collapsedResourceGroups, setCollapsedResourceGroups] =
|
|
11531
|
+
const [collapsedResourceGroups, setCollapsedResourceGroups] = useState10(/* @__PURE__ */ new Set());
|
|
11306
11532
|
const updateResourceColumnWidth = useCallback8((columnId, width) => {
|
|
11307
11533
|
setResourceColumnWidthOverrides((prev) => {
|
|
11308
11534
|
if (prev[columnId] === width) {
|
|
@@ -11313,7 +11539,7 @@ function ResourceTimelineChart({
|
|
|
11313
11539
|
return next;
|
|
11314
11540
|
});
|
|
11315
11541
|
}, [onResourceTableColumnWidthsChange]);
|
|
11316
|
-
|
|
11542
|
+
useEffect9(() => {
|
|
11317
11543
|
const handleMouseMove = (event) => {
|
|
11318
11544
|
const resizeState = resourceColumnResizeRef.current;
|
|
11319
11545
|
if (!resizeState) {
|
|
@@ -11582,7 +11808,7 @@ function ResourceTimelineChart({
|
|
|
11582
11808
|
weekendPredicate,
|
|
11583
11809
|
onResourceItemMove
|
|
11584
11810
|
});
|
|
11585
|
-
|
|
11811
|
+
useEffect9(() => {
|
|
11586
11812
|
const container = scrollContainerRef.current;
|
|
11587
11813
|
if (!container) return;
|
|
11588
11814
|
const updateShadow = () => {
|
|
@@ -11622,7 +11848,7 @@ function ResourceTimelineChart({
|
|
|
11622
11848
|
container.style.cursor = "grabbing";
|
|
11623
11849
|
event.preventDefault();
|
|
11624
11850
|
}, []);
|
|
11625
|
-
|
|
11851
|
+
useEffect9(() => {
|
|
11626
11852
|
const handlePanMove = (event) => {
|
|
11627
11853
|
const pan = panStateRef.current;
|
|
11628
11854
|
const container = scrollContainerRef.current;
|
|
@@ -11651,7 +11877,7 @@ function ResourceTimelineChart({
|
|
|
11651
11877
|
window.removeEventListener("mouseup", handlePanEnd);
|
|
11652
11878
|
};
|
|
11653
11879
|
}, [allowVerticalPan]);
|
|
11654
|
-
|
|
11880
|
+
useEffect9(() => {
|
|
11655
11881
|
const nextNavigation = /* @__PURE__ */ new Map();
|
|
11656
11882
|
for (const [resourceId, resourceItems] of itemsByResourceId.entries()) {
|
|
11657
11883
|
if (resourceItems.length === 0) {
|
|
@@ -11661,7 +11887,7 @@ function ResourceTimelineChart({
|
|
|
11661
11887
|
}
|
|
11662
11888
|
resourceNavigationIndexRef.current = nextNavigation;
|
|
11663
11889
|
}, [itemsByResourceId]);
|
|
11664
|
-
|
|
11890
|
+
useEffect9(() => {
|
|
11665
11891
|
return () => {
|
|
11666
11892
|
if (conflictHighlightTimeoutRef.current) {
|
|
11667
11893
|
window.clearTimeout(conflictHighlightTimeoutRef.current);
|
|
@@ -12081,7 +12307,7 @@ function ResourceTimelineChart({
|
|
|
12081
12307
|
}
|
|
12082
12308
|
|
|
12083
12309
|
// src/components/TableMatrix/TableMatrix.tsx
|
|
12084
|
-
import { useLayoutEffect, useMemo as useMemo11, useRef as
|
|
12310
|
+
import { useLayoutEffect, useMemo as useMemo11, useRef as useRef11, useState as useState11 } from "react";
|
|
12085
12311
|
import { jsx as jsx19, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
12086
12312
|
var AUTO_COLUMN_MIN_WIDTH = 72;
|
|
12087
12313
|
var AUTO_COLUMN_MAX_WIDTH = 180;
|
|
@@ -12148,8 +12374,8 @@ function TableMatrix({
|
|
|
12148
12374
|
filterMode = "highlight",
|
|
12149
12375
|
visibleRowIndices
|
|
12150
12376
|
}) {
|
|
12151
|
-
const measureRef =
|
|
12152
|
-
const [measuredAutoWidths, setMeasuredAutoWidths] =
|
|
12377
|
+
const measureRef = useRef11(null);
|
|
12378
|
+
const [measuredAutoWidths, setMeasuredAutoWidths] = useState11([]);
|
|
12153
12379
|
const hasAutoWidthColumns = useMemo11(
|
|
12154
12380
|
() => columns.some((column) => typeof column.width !== "number"),
|
|
12155
12381
|
[columns]
|
|
@@ -12449,7 +12675,7 @@ function TableMatrix({
|
|
|
12449
12675
|
}
|
|
12450
12676
|
|
|
12451
12677
|
// src/components/PlanFactMatrix/PlanFactMatrix.tsx
|
|
12452
|
-
import React16, { useCallback as useCallback9, useEffect as
|
|
12678
|
+
import React16, { useCallback as useCallback9, useEffect as useEffect10, useMemo as useMemo12, useRef as useRef12, useState as useState12 } from "react";
|
|
12453
12679
|
import { jsx as jsx20, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
12454
12680
|
var DAY_MS5 = 24 * 60 * 60 * 1e3;
|
|
12455
12681
|
function joinClasses2(...values) {
|
|
@@ -12541,9 +12767,9 @@ function PlanFactCellEditor({
|
|
|
12541
12767
|
onCommitRange,
|
|
12542
12768
|
onCancel
|
|
12543
12769
|
}) {
|
|
12544
|
-
const [draft, setDraft] =
|
|
12545
|
-
const inputRef =
|
|
12546
|
-
|
|
12770
|
+
const [draft, setDraft] = useState12(startValue ?? (value === void 0 ? "" : String(value)));
|
|
12771
|
+
const inputRef = useRef12(null);
|
|
12772
|
+
useEffect10(() => {
|
|
12547
12773
|
inputRef.current?.focus();
|
|
12548
12774
|
if (startValue === void 0) {
|
|
12549
12775
|
inputRef.current?.select();
|
|
@@ -12896,18 +13122,18 @@ function PlanFactMatrix({
|
|
|
12896
13122
|
todayDateIndex,
|
|
12897
13123
|
isCustomWeekend
|
|
12898
13124
|
}) {
|
|
12899
|
-
const [activeCell, setActiveCell] =
|
|
12900
|
-
const [editingCell, setEditingCell] =
|
|
12901
|
-
const [selectedRange, setSelectedRange] =
|
|
12902
|
-
const [fillRange, setFillRange] =
|
|
12903
|
-
const [overflowTooltip, setOverflowTooltip] =
|
|
12904
|
-
const isSelectingRef =
|
|
12905
|
-
const isFillDraggingRef =
|
|
12906
|
-
const didDragSelectRef =
|
|
12907
|
-
const pendingHoverCellRef =
|
|
12908
|
-
const hoverFrameRef =
|
|
12909
|
-
const rootRef =
|
|
12910
|
-
const bodyRef =
|
|
13125
|
+
const [activeCell, setActiveCell] = useState12(null);
|
|
13126
|
+
const [editingCell, setEditingCell] = useState12(null);
|
|
13127
|
+
const [selectedRange, setSelectedRange] = useState12(null);
|
|
13128
|
+
const [fillRange, setFillRange] = useState12(null);
|
|
13129
|
+
const [overflowTooltip, setOverflowTooltip] = useState12(null);
|
|
13130
|
+
const isSelectingRef = useRef12(false);
|
|
13131
|
+
const isFillDraggingRef = useRef12(false);
|
|
13132
|
+
const didDragSelectRef = useRef12(false);
|
|
13133
|
+
const pendingHoverCellRef = useRef12(null);
|
|
13134
|
+
const hoverFrameRef = useRef12(null);
|
|
13135
|
+
const rootRef = useRef12(null);
|
|
13136
|
+
const bodyRef = useRef12(null);
|
|
12911
13137
|
const totalWidth = dateRange.length * dayWidth;
|
|
12912
13138
|
const subrowHeight = rowHeight / 2;
|
|
12913
13139
|
const renderedRowIndices = useMemo12(
|
|
@@ -13313,7 +13539,7 @@ function PlanFactMatrix({
|
|
|
13313
13539
|
onTaskSelect?.(nextCell.taskId);
|
|
13314
13540
|
focusCell(selectedRange?.anchor ?? cell);
|
|
13315
13541
|
}, [dateRange.length, focusCell, onTaskSelect, parentTaskIds, selectedRange, tasks]);
|
|
13316
|
-
|
|
13542
|
+
useEffect10(() => {
|
|
13317
13543
|
const endSelection = () => {
|
|
13318
13544
|
let pendingFillRange = null;
|
|
13319
13545
|
if (hoverFrameRef.current !== null) {
|
|
@@ -13336,12 +13562,12 @@ function PlanFactMatrix({
|
|
|
13336
13562
|
window.removeEventListener("mouseup", endSelection);
|
|
13337
13563
|
};
|
|
13338
13564
|
}, [applyFillRange, flushPendingHoverCell]);
|
|
13339
|
-
|
|
13565
|
+
useEffect10(() => () => {
|
|
13340
13566
|
if (hoverFrameRef.current !== null) {
|
|
13341
13567
|
window.cancelAnimationFrame(hoverFrameRef.current);
|
|
13342
13568
|
}
|
|
13343
13569
|
}, []);
|
|
13344
|
-
|
|
13570
|
+
useEffect10(() => {
|
|
13345
13571
|
const handleKeyDown = (event) => {
|
|
13346
13572
|
if (event.key !== "Escape") return;
|
|
13347
13573
|
clearSelection();
|
|
@@ -14144,39 +14370,43 @@ function TaskGanttChartInner(props, ref) {
|
|
|
14144
14370
|
const onMatrixCellClick = isTableMatrixMode ? props.onMatrixCellClick : void 0;
|
|
14145
14371
|
const matrixDateOverlay = isTableMatrixMode ? props.matrixDateOverlay : void 0;
|
|
14146
14372
|
const onPlanFactCellCommit = isPlanFactMode ? props.onPlanFactCellCommit : void 0;
|
|
14147
|
-
const containerRef =
|
|
14148
|
-
const scrollContainerRef =
|
|
14149
|
-
const scrollContentRef =
|
|
14150
|
-
const clearSelectedTaskTimeoutRef =
|
|
14151
|
-
const hasAutoScrolledToTodayRef =
|
|
14152
|
-
const previewPositionStoreRef =
|
|
14153
|
-
const renderedTaskIdsRef =
|
|
14373
|
+
const containerRef = useRef13(null);
|
|
14374
|
+
const scrollContainerRef = useRef13(null);
|
|
14375
|
+
const scrollContentRef = useRef13(null);
|
|
14376
|
+
const clearSelectedTaskTimeoutRef = useRef13(null);
|
|
14377
|
+
const hasAutoScrolledToTodayRef = useRef13(false);
|
|
14378
|
+
const previewPositionStoreRef = useRef13(null);
|
|
14379
|
+
const renderedTaskIdsRef = useRef13(/* @__PURE__ */ new Set());
|
|
14154
14380
|
if (previewPositionStoreRef.current === null) {
|
|
14155
14381
|
previewPositionStoreRef.current = createTaskPreviewPositionStore();
|
|
14156
14382
|
}
|
|
14157
14383
|
const previewPositionStore = previewPositionStoreRef.current;
|
|
14158
|
-
const [selectedTaskId, setSelectedTaskId] =
|
|
14159
|
-
const [taskListHasRightShadow, setTaskListHasRightShadow] =
|
|
14160
|
-
const [internalTaskDateChangeMode, setInternalTaskDateChangeMode] =
|
|
14161
|
-
const [scrollViewport, setScrollViewport] =
|
|
14384
|
+
const [selectedTaskId, setSelectedTaskId] = useState13(null);
|
|
14385
|
+
const [taskListHasRightShadow, setTaskListHasRightShadow] = useState13(false);
|
|
14386
|
+
const [internalTaskDateChangeMode, setInternalTaskDateChangeMode] = useState13("preserve-duration");
|
|
14387
|
+
const [scrollViewport, setScrollViewport] = useState13(() => ({
|
|
14162
14388
|
scrollTop: 0,
|
|
14163
14389
|
viewportHeight: getInitialScrollViewportHeight(containerHeight, headerHeight + 1)
|
|
14164
14390
|
}));
|
|
14165
|
-
const [forceFullRenderForPrint, setForceFullRenderForPrint] =
|
|
14166
|
-
const [planFactDateWindow, setPlanFactDateWindow] =
|
|
14167
|
-
const [selectedChip, setSelectedChip] =
|
|
14168
|
-
const [dependencyCreationDrag, setDependencyCreationDrag] =
|
|
14169
|
-
const dependencyCreationRef =
|
|
14170
|
-
const [dependencyCreationError, setDependencyCreationError] =
|
|
14171
|
-
const [dependencyLineMenu, setDependencyLineMenu] =
|
|
14391
|
+
const [forceFullRenderForPrint, setForceFullRenderForPrint] = useState13(false);
|
|
14392
|
+
const [planFactDateWindow, setPlanFactDateWindow] = useState13({ start: 0, end: 0 });
|
|
14393
|
+
const [selectedChip, setSelectedChip] = useState13(null);
|
|
14394
|
+
const [dependencyCreationDrag, setDependencyCreationDrag] = useState13(null);
|
|
14395
|
+
const dependencyCreationRef = useRef13(null);
|
|
14396
|
+
const [dependencyCreationError, setDependencyCreationError] = useState13(null);
|
|
14397
|
+
const [dependencyLineMenu, setDependencyLineMenu] = useState13(null);
|
|
14172
14398
|
const getDependencyPortPoint = useCallback10((element, chartRect) => {
|
|
14173
14399
|
const rect = element.getBoundingClientRect();
|
|
14174
14400
|
const side = element.getAttribute("data-port-side");
|
|
14175
14401
|
return {
|
|
14176
|
-
//
|
|
14177
|
-
//
|
|
14178
|
-
|
|
14179
|
-
|
|
14402
|
+
// Anchor the preview at the port dot's center so the dragged polyline
|
|
14403
|
+
// ends exactly on the link handle. The dot core is 8px and sits 4px
|
|
14404
|
+
// inside the 24px zone from the bar side (see TaskRow.css), which puts
|
|
14405
|
+
// its center 8px off the button edge adjacent to the bar. No rounding:
|
|
14406
|
+
// the CSS ball centers at a fractional position, and a rounded SVG
|
|
14407
|
+
// coordinate landed ~1px off it.
|
|
14408
|
+
x: (side === "left" ? rect.right - 8 : rect.left + 8) - chartRect.left,
|
|
14409
|
+
y: rect.top + rect.height / 2 - chartRect.top
|
|
14180
14410
|
};
|
|
14181
14411
|
}, []);
|
|
14182
14412
|
const getVisualDependencyType = useCallback10((sourceSide, targetSide) => {
|
|
@@ -14198,7 +14428,7 @@ function TaskGanttChartInner(props, ref) {
|
|
|
14198
14428
|
dependencyCreationRef.current = nextDrag;
|
|
14199
14429
|
setDependencyCreationDrag(nextDrag);
|
|
14200
14430
|
}, [disableDependencyEditing, getDependencyPortPoint]);
|
|
14201
|
-
|
|
14431
|
+
useEffect11(() => {
|
|
14202
14432
|
if (!dependencyCreationDrag) return;
|
|
14203
14433
|
const handlePointerMove = (event) => {
|
|
14204
14434
|
const activeDrag = dependencyCreationRef.current;
|
|
@@ -14282,12 +14512,12 @@ function TaskGanttChartInner(props, ref) {
|
|
|
14282
14512
|
document.removeEventListener("keydown", handleKeyDown);
|
|
14283
14513
|
};
|
|
14284
14514
|
}, [businessDays, customDays, dependencyCreationDrag !== null, getDependencyPortPoint, getVisualDependencyType, isWeekend3, onTasksChange, tasks]);
|
|
14285
|
-
|
|
14515
|
+
useEffect11(() => {
|
|
14286
14516
|
if (!dependencyCreationError) return;
|
|
14287
14517
|
const timeout = window.setTimeout(() => setDependencyCreationError(null), 3e3);
|
|
14288
14518
|
return () => window.clearTimeout(timeout);
|
|
14289
14519
|
}, [dependencyCreationError]);
|
|
14290
|
-
|
|
14520
|
+
useEffect11(() => {
|
|
14291
14521
|
if (!dependencyLineMenu) return;
|
|
14292
14522
|
const closeMenu = (event) => {
|
|
14293
14523
|
const target = event.target;
|
|
@@ -14325,10 +14555,10 @@ function TaskGanttChartInner(props, ref) {
|
|
|
14325
14555
|
setSelectedChip(null);
|
|
14326
14556
|
setDependencyLineMenu(null);
|
|
14327
14557
|
}, [dependencyLineMenu, onTasksChange, tasks]);
|
|
14328
|
-
const [activeTimelineTooltip, setActiveTimelineTooltip] =
|
|
14329
|
-
const [internalCollapsedParentIds, setInternalCollapsedParentIds] =
|
|
14330
|
-
const
|
|
14331
|
-
const [editingTaskId, setEditingTaskId] =
|
|
14558
|
+
const [activeTimelineTooltip, setActiveTimelineTooltip] = useState13(null);
|
|
14559
|
+
const [internalCollapsedParentIds, setInternalCollapsedParentIds] = useState13(/* @__PURE__ */ new Set());
|
|
14560
|
+
const [expandedCompositeIds, setExpandedCompositeIds] = useState13(/* @__PURE__ */ new Set());
|
|
14561
|
+
const [editingTaskId, setEditingTaskId] = useState13(null);
|
|
14332
14562
|
const taskDateChangeMode = externalTaskDateChangeMode ?? internalTaskDateChangeMode;
|
|
14333
14563
|
const handleTaskDateChangeMode = externalOnTaskDateChangeModeChange ?? setInternalTaskDateChangeMode;
|
|
14334
14564
|
const resolvedRowContentLines = isPlanFactMode ? Math.max(2, Math.floor(rowContentLines)) : Math.max(1, Math.floor(rowContentLines));
|
|
@@ -14337,14 +14567,43 @@ function TaskGanttChartInner(props, ref) {
|
|
|
14337
14567
|
() => Math.max(rowHeight, 10 + resolvedRowContentLines * 18),
|
|
14338
14568
|
[resolvedRowContentLines, rowHeight]
|
|
14339
14569
|
);
|
|
14340
|
-
const normalizedTasks = useMemo13(() =>
|
|
14570
|
+
const normalizedTasks = useMemo13(() => {
|
|
14571
|
+
const ordered = normalizeHierarchyTasks(tasks);
|
|
14572
|
+
const ranges = /* @__PURE__ */ new Map();
|
|
14573
|
+
for (const task of ordered) {
|
|
14574
|
+
if (!task.parentId) continue;
|
|
14575
|
+
const start = parseUTCDate(task.startDate).getTime();
|
|
14576
|
+
const end = parseUTCDate(task.endDate).getTime();
|
|
14577
|
+
const range = ranges.get(task.parentId);
|
|
14578
|
+
ranges.set(task.parentId, {
|
|
14579
|
+
start: Math.min(range?.start ?? start, start),
|
|
14580
|
+
end: Math.max(range?.end ?? end, end)
|
|
14581
|
+
});
|
|
14582
|
+
}
|
|
14583
|
+
return ordered.map((task) => {
|
|
14584
|
+
const range = task.composite ? ranges.get(task.id) : void 0;
|
|
14585
|
+
return range ? {
|
|
14586
|
+
...task,
|
|
14587
|
+
startDate: new Date(range.start).toISOString().slice(0, 10),
|
|
14588
|
+
endDate: new Date(range.end).toISOString().slice(0, 10)
|
|
14589
|
+
} : task;
|
|
14590
|
+
});
|
|
14591
|
+
}, [tasks]);
|
|
14592
|
+
const collapsedParentIds = useMemo13(() => {
|
|
14593
|
+
if (externalCollapsedParentIds) return externalCollapsedParentIds;
|
|
14594
|
+
const ids = new Set(internalCollapsedParentIds);
|
|
14595
|
+
for (const task of normalizedTasks) {
|
|
14596
|
+
if (task.composite && !expandedCompositeIds.has(task.id)) ids.add(task.id);
|
|
14597
|
+
}
|
|
14598
|
+
return ids;
|
|
14599
|
+
}, [externalCollapsedParentIds, internalCollapsedParentIds, normalizedTasks, expandedCompositeIds]);
|
|
14341
14600
|
const controlledScheduleIdentity = useMemo13(
|
|
14342
14601
|
() => buildControlledScheduleIdentity(normalizedTasks),
|
|
14343
14602
|
[normalizedTasks]
|
|
14344
14603
|
);
|
|
14345
|
-
const previousControlledScheduleIdentityRef =
|
|
14604
|
+
const previousControlledScheduleIdentityRef = useRef13(null);
|
|
14346
14605
|
const controlledScheduleChanged = previousControlledScheduleIdentityRef.current !== null && previousControlledScheduleIdentityRef.current !== controlledScheduleIdentity;
|
|
14347
|
-
const [previewTasksById, setPreviewTasksById] =
|
|
14606
|
+
const [previewTasksById, setPreviewTasksById] = useState13(/* @__PURE__ */ new Map());
|
|
14348
14607
|
const previewNormalizedTasks = useMemo13(() => {
|
|
14349
14608
|
if (controlledScheduleChanged || previewTasksById.size === 0) return normalizedTasks;
|
|
14350
14609
|
return normalizedTasks.map((task) => previewTasksById.get(task.id) ?? task);
|
|
@@ -14384,8 +14643,8 @@ function TaskGanttChartInner(props, ref) {
|
|
|
14384
14643
|
},
|
|
14385
14644
|
[dateRangeTasks, explicitDateRange, isPlanFactMode]
|
|
14386
14645
|
);
|
|
14387
|
-
const [validationResult, setValidationResult] =
|
|
14388
|
-
const [cascadeOverrides, setCascadeOverrides] =
|
|
14646
|
+
const [validationResult, setValidationResult] = useState13(null);
|
|
14647
|
+
const [cascadeOverrides, setCascadeOverrides] = useState13(/* @__PURE__ */ new Map());
|
|
14389
14648
|
const gridWidth = useMemo13(
|
|
14390
14649
|
() => Math.round(dateRange.length * dayWidth),
|
|
14391
14650
|
[dateRange.length, dayWidth]
|
|
@@ -14417,6 +14676,23 @@ function TaskGanttChartInner(props, ref) {
|
|
|
14417
14676
|
}
|
|
14418
14677
|
return tasks2;
|
|
14419
14678
|
}, [normalizedTasks, collapsedParentIds, filterMode, taskFilter, criticalPathMode, criticalTaskIds]);
|
|
14679
|
+
const compositeRowLayout = useMemo13(() => {
|
|
14680
|
+
const compositeIds = new Set(normalizedTasks.filter((task) => task.composite).map((task) => task.id));
|
|
14681
|
+
const tops = [];
|
|
14682
|
+
const heights = [];
|
|
14683
|
+
let top = 0;
|
|
14684
|
+
for (const task of visibleTasks) {
|
|
14685
|
+
tops.push(top);
|
|
14686
|
+
const height = task.parentId && compositeIds.has(task.parentId) ? Math.min(effectiveRowHeight, 22) : effectiveRowHeight;
|
|
14687
|
+
heights.push(height);
|
|
14688
|
+
top += height;
|
|
14689
|
+
}
|
|
14690
|
+
return { tops, heights, totalHeight: top };
|
|
14691
|
+
}, [normalizedTasks, visibleTasks, effectiveRowHeight]);
|
|
14692
|
+
const compositeParentsById = useMemo13(
|
|
14693
|
+
() => new Map(normalizedTasks.filter((task) => task.composite).map((task) => [task.id, task])),
|
|
14694
|
+
[normalizedTasks]
|
|
14695
|
+
);
|
|
14420
14696
|
const matchedTaskIds = useMemo13(() => {
|
|
14421
14697
|
if (!taskFilter) return /* @__PURE__ */ new Set();
|
|
14422
14698
|
return new Set(visibleTasks.filter(taskFilter).map((task) => task.id));
|
|
@@ -14438,8 +14714,8 @@ function TaskGanttChartInner(props, ref) {
|
|
|
14438
14714
|
return mergedHighlightedTaskIds;
|
|
14439
14715
|
}, [filterMode, highlightedTaskIds, matchedTaskIds, criticalPathMode, criticalTaskIds]);
|
|
14440
14716
|
const totalGridHeight = useMemo13(
|
|
14441
|
-
() =>
|
|
14442
|
-
[effectiveRowHeight, skeletonRowCount
|
|
14717
|
+
() => compositeRowLayout.totalHeight + Math.max(0, Math.floor(skeletonRowCount)) * effectiveRowHeight,
|
|
14718
|
+
[compositeRowLayout.totalHeight, effectiveRowHeight, skeletonRowCount]
|
|
14443
14719
|
);
|
|
14444
14720
|
const timelineHeaderHeight = headerHeight + 1;
|
|
14445
14721
|
const tableBodyMinHeight = useMemo13(() => {
|
|
@@ -14477,7 +14753,7 @@ function TaskGanttChartInner(props, ref) {
|
|
|
14477
14753
|
return markerDate >= rangeStartMs && markerDate <= rangeEndMs;
|
|
14478
14754
|
});
|
|
14479
14755
|
}, [dateRange, isTableMatrixMode, timelineMarkers]);
|
|
14480
|
-
|
|
14756
|
+
useEffect11(() => {
|
|
14481
14757
|
if (isTableMatrixMode) return;
|
|
14482
14758
|
if (hasAutoScrolledToTodayRef.current) return;
|
|
14483
14759
|
const container = scrollContainerRef.current;
|
|
@@ -14491,7 +14767,7 @@ function TaskGanttChartInner(props, ref) {
|
|
|
14491
14767
|
container.scrollLeft = Math.max(0, scrollLeft);
|
|
14492
14768
|
hasAutoScrolledToTodayRef.current = true;
|
|
14493
14769
|
}, [dateRange, dayWidth, isTableMatrixMode]);
|
|
14494
|
-
|
|
14770
|
+
useEffect11(() => {
|
|
14495
14771
|
const container = scrollContainerRef.current;
|
|
14496
14772
|
if (!container) return;
|
|
14497
14773
|
let frameId = null;
|
|
@@ -14566,7 +14842,7 @@ function TaskGanttChartInner(props, ref) {
|
|
|
14566
14842
|
const rowIndex = visibleTasks.findIndex((visibleTask) => visibleTask.id === taskId);
|
|
14567
14843
|
if (rowIndex === -1) return;
|
|
14568
14844
|
const paddedRowIndex = Math.max(0, rowIndex - SCROLL_TO_ROW_CONTEXT_ROWS);
|
|
14569
|
-
container2.scrollTo({ top: Math.max(0,
|
|
14845
|
+
container2.scrollTo({ top: Math.max(0, compositeRowLayout.tops[paddedRowIndex] ?? 0), behavior: "smooth" });
|
|
14570
14846
|
setSelectedTaskId(taskId);
|
|
14571
14847
|
return;
|
|
14572
14848
|
}
|
|
@@ -14585,7 +14861,7 @@ function TaskGanttChartInner(props, ref) {
|
|
|
14585
14861
|
const taskOffset = taskIndex * dayWidth;
|
|
14586
14862
|
const scrollLeft = Math.round(taskOffset - dayWidth * 2);
|
|
14587
14863
|
container.scrollTo({ left: Math.max(0, scrollLeft), behavior: "smooth" });
|
|
14588
|
-
}, [dateRange, dayWidth, effectiveRowHeight, isTableMatrixMode, tasks, visibleTasks]);
|
|
14864
|
+
}, [dateRange, dayWidth, effectiveRowHeight, compositeRowLayout, isTableMatrixMode, tasks, visibleTasks]);
|
|
14589
14865
|
const scrollToRow = useCallback10((taskId, options = {}) => {
|
|
14590
14866
|
const container = scrollContainerRef.current;
|
|
14591
14867
|
if (!container) return;
|
|
@@ -14594,7 +14870,7 @@ function TaskGanttChartInner(props, ref) {
|
|
|
14594
14870
|
const rowIndex = visibleTasks.findIndex((visibleTask) => visibleTask.id === task.id);
|
|
14595
14871
|
if (rowIndex === -1) return;
|
|
14596
14872
|
const paddedRowIndex = Math.max(0, rowIndex - SCROLL_TO_ROW_CONTEXT_ROWS);
|
|
14597
|
-
const scrollTop = Math.max(0,
|
|
14873
|
+
const scrollTop = Math.max(0, compositeRowLayout.tops[paddedRowIndex] ?? 0);
|
|
14598
14874
|
const {
|
|
14599
14875
|
select = true,
|
|
14600
14876
|
behavior = "smooth",
|
|
@@ -14614,10 +14890,10 @@ function TaskGanttChartInner(props, ref) {
|
|
|
14614
14890
|
}
|
|
14615
14891
|
}
|
|
14616
14892
|
container.scrollTo({ top: scrollTop, behavior });
|
|
14617
|
-
}, [effectiveRowHeight, tasks, visibleTasks]);
|
|
14618
|
-
const [dragGuideLines, setDragGuideLines] =
|
|
14619
|
-
const [draggedTaskOverride, setDraggedTaskOverride] =
|
|
14620
|
-
|
|
14893
|
+
}, [effectiveRowHeight, compositeRowLayout, tasks, visibleTasks]);
|
|
14894
|
+
const [dragGuideLines, setDragGuideLines] = useState13(null);
|
|
14895
|
+
const [draggedTaskOverride, setDraggedTaskOverride] = useState13(null);
|
|
14896
|
+
useEffect11(() => {
|
|
14621
14897
|
const previousIdentity = previousControlledScheduleIdentityRef.current;
|
|
14622
14898
|
previousControlledScheduleIdentityRef.current = controlledScheduleIdentity;
|
|
14623
14899
|
if (previousIdentity === null || previousIdentity === controlledScheduleIdentity) {
|
|
@@ -14629,21 +14905,21 @@ function TaskGanttChartInner(props, ref) {
|
|
|
14629
14905
|
setDraggedTaskOverride((current) => current === null ? current : null);
|
|
14630
14906
|
setDragGuideLines((current) => current === null ? current : null);
|
|
14631
14907
|
}, [controlledScheduleIdentity, previewPositionStore]);
|
|
14632
|
-
|
|
14908
|
+
useEffect11(() => {
|
|
14633
14909
|
const result = validateDependencies(tasks);
|
|
14634
14910
|
setValidationResult(result);
|
|
14635
14911
|
onValidateDependencies?.(result);
|
|
14636
14912
|
}, [tasks, onValidateDependencies]);
|
|
14637
|
-
|
|
14913
|
+
useEffect11(() => () => {
|
|
14638
14914
|
if (clearSelectedTaskTimeoutRef.current !== null) {
|
|
14639
14915
|
window.clearTimeout(clearSelectedTaskTimeoutRef.current);
|
|
14640
14916
|
}
|
|
14641
14917
|
previewPositionStore.clear();
|
|
14642
14918
|
}, [previewPositionStore]);
|
|
14643
14919
|
const handleTaskChange = useCallback10((updatedTasks, durationEdit) => {
|
|
14644
|
-
|
|
14920
|
+
let updatedTask = updatedTasks[0];
|
|
14645
14921
|
if (!updatedTask) return;
|
|
14646
|
-
const originalTask =
|
|
14922
|
+
const originalTask = normalizedTasks.find((t) => t.id === updatedTask.id);
|
|
14647
14923
|
if (!originalTask) {
|
|
14648
14924
|
onTasksChange?.(updatedTasks);
|
|
14649
14925
|
if (editingTaskId === updatedTask.id) {
|
|
@@ -14656,6 +14932,8 @@ function TaskGanttChartInner(props, ref) {
|
|
|
14656
14932
|
const newStart = new Date(updatedTask.startDate);
|
|
14657
14933
|
const newEnd = new Date(updatedTask.endDate);
|
|
14658
14934
|
const datesChanged = origStart.getTime() !== newStart.getTime() || origEnd.getTime() !== newEnd.getTime();
|
|
14935
|
+
const isCompositeDetail = datesChanged && tasks.some((task) => task.id === updatedTask.parentId && task.composite);
|
|
14936
|
+
if (isCompositeDetail) updatedTask = { ...updatedTask, synced: false };
|
|
14659
14937
|
if (!datesChanged) {
|
|
14660
14938
|
if (updatedTasks.length > 1) {
|
|
14661
14939
|
onTasksChange?.(updatedTasks);
|
|
@@ -14717,7 +14995,7 @@ function TaskGanttChartInner(props, ref) {
|
|
|
14717
14995
|
}
|
|
14718
14996
|
return;
|
|
14719
14997
|
}
|
|
14720
|
-
const movedParentCascade = disableConstraints ? [updatedTask] : universalCascade(updatedTask, newStart, newEnd,
|
|
14998
|
+
const movedParentCascade = disableConstraints && !originalTask.composite ? [updatedTask] : universalCascade(updatedTask, newStart, newEnd, normalizedTasks, businessDays, isCustomWeekend);
|
|
14721
14999
|
if (onScheduleIntent) {
|
|
14722
15000
|
onScheduleIntent({
|
|
14723
15001
|
type: "move_task",
|
|
@@ -14741,7 +15019,8 @@ function TaskGanttChartInner(props, ref) {
|
|
|
14741
15019
|
taskId: updatedTask.id,
|
|
14742
15020
|
duration: durationEdit.duration,
|
|
14743
15021
|
anchor: durationEdit.anchor,
|
|
14744
|
-
taskType: updatedTask.type ?? "task"
|
|
15022
|
+
taskType: updatedTask.type ?? "task",
|
|
15023
|
+
...isCompositeDetail ? { localOverride: true } : {}
|
|
14745
15024
|
});
|
|
14746
15025
|
} else {
|
|
14747
15026
|
onTasksChange?.(cascadedTasks);
|
|
@@ -14753,7 +15032,8 @@ function TaskGanttChartInner(props, ref) {
|
|
|
14753
15032
|
onScheduleIntent({
|
|
14754
15033
|
type: "move_task",
|
|
14755
15034
|
taskId: updatedTask.id,
|
|
14756
|
-
startDate: newStart.toISOString().split("T")[0]
|
|
15035
|
+
startDate: newStart.toISOString().split("T")[0],
|
|
15036
|
+
...isCompositeDetail ? { localOverride: true } : {}
|
|
14757
15037
|
});
|
|
14758
15038
|
} else {
|
|
14759
15039
|
const anchor = startChanged ? "end" : "start";
|
|
@@ -14761,13 +15041,14 @@ function TaskGanttChartInner(props, ref) {
|
|
|
14761
15041
|
type: "resize_task",
|
|
14762
15042
|
taskId: updatedTask.id,
|
|
14763
15043
|
anchor,
|
|
14764
|
-
date: (startChanged ? newStart : newEnd).toISOString().split("T")[0]
|
|
15044
|
+
date: (startChanged ? newStart : newEnd).toISOString().split("T")[0],
|
|
15045
|
+
...isCompositeDetail ? { localOverride: true } : {}
|
|
14765
15046
|
});
|
|
14766
15047
|
}
|
|
14767
15048
|
} else {
|
|
14768
15049
|
onTasksChange?.(cascadedTasks);
|
|
14769
15050
|
}
|
|
14770
|
-
}, [tasks, onTasksChange, onScheduleIntent, disableConstraints, editingTaskId, businessDays, isCustomWeekend, onSubtreeScaleResult]);
|
|
15051
|
+
}, [tasks, normalizedTasks, onTasksChange, onScheduleIntent, disableConstraints, editingTaskId, businessDays, isCustomWeekend, onSubtreeScaleResult]);
|
|
14771
15052
|
const handleTaskDurationChange = useCallback10((task, duration) => {
|
|
14772
15053
|
const updatedTask = {
|
|
14773
15054
|
...task,
|
|
@@ -14881,12 +15162,25 @@ function TaskGanttChartInner(props, ref) {
|
|
|
14881
15162
|
if (scrollViewport.viewportHeight <= 0) {
|
|
14882
15163
|
return Array.from({ length: totalTasks }, (_, index) => index);
|
|
14883
15164
|
}
|
|
14884
|
-
|
|
14885
|
-
|
|
14886
|
-
|
|
14887
|
-
|
|
14888
|
-
|
|
14889
|
-
|
|
15165
|
+
let low = 0;
|
|
15166
|
+
let high = totalTasks;
|
|
15167
|
+
while (low < high) {
|
|
15168
|
+
const middle = low + high >>> 1;
|
|
15169
|
+
if (compositeRowLayout.tops[middle] + compositeRowLayout.heights[middle] < scrollViewport.scrollTop) low = middle + 1;
|
|
15170
|
+
else high = middle;
|
|
15171
|
+
}
|
|
15172
|
+
const first = Math.min(low, totalTasks - 1);
|
|
15173
|
+
const viewportBottom = scrollViewport.scrollTop + scrollViewport.viewportHeight;
|
|
15174
|
+
low = first;
|
|
15175
|
+
high = totalTasks;
|
|
15176
|
+
while (low < high) {
|
|
15177
|
+
const middle = low + high >>> 1;
|
|
15178
|
+
if (compositeRowLayout.tops[middle] < viewportBottom) low = middle + 1;
|
|
15179
|
+
else high = middle;
|
|
15180
|
+
}
|
|
15181
|
+
const last = Math.min(low, totalTasks - 1);
|
|
15182
|
+
const rangeStart = Math.max(0, first - TASK_ROW_OVERSCAN);
|
|
15183
|
+
const rangeEnd = Math.min(totalTasks - 1, last + TASK_ROW_OVERSCAN);
|
|
14890
15184
|
const indices = /* @__PURE__ */ new Set();
|
|
14891
15185
|
for (let index = rangeStart; index <= rangeEnd; index += 1) {
|
|
14892
15186
|
indices.add(index);
|
|
@@ -14898,7 +15192,7 @@ function TaskGanttChartInner(props, ref) {
|
|
|
14898
15192
|
}
|
|
14899
15193
|
}
|
|
14900
15194
|
return Array.from(indices).sort((left, right) => left - right);
|
|
14901
|
-
}, [
|
|
15195
|
+
}, [compositeRowLayout, forceFullRenderForPrint, forcedRenderedTaskIds, scrollViewport, visibleTaskIndexMap, visibleTasks.length]);
|
|
14902
15196
|
const visiblePlanFactDateIndices = useMemo13(() => {
|
|
14903
15197
|
if (forceFullRenderForPrint) {
|
|
14904
15198
|
return void 0;
|
|
@@ -14935,7 +15229,7 @@ function TaskGanttChartInner(props, ref) {
|
|
|
14935
15229
|
const handleTaskSelect = useCallback10((taskId) => {
|
|
14936
15230
|
setSelectedTaskId(taskId);
|
|
14937
15231
|
}, []);
|
|
14938
|
-
const hoveredRowElementsRef =
|
|
15232
|
+
const hoveredRowElementsRef = useRef13([]);
|
|
14939
15233
|
const clearHoveredRows = useCallback10(() => {
|
|
14940
15234
|
for (const element of hoveredRowElementsRef.current) {
|
|
14941
15235
|
element.classList.remove("gantt-tl-row-hovered", "gantt-tr-row-hovered", "gantt-mx-row-hovered", "gantt-pf-row-hovered");
|
|
@@ -14975,7 +15269,16 @@ function TaskGanttChartInner(props, ref) {
|
|
|
14975
15269
|
}
|
|
14976
15270
|
applyHoveredRows(taskId);
|
|
14977
15271
|
}, [applyHoveredRows]);
|
|
14978
|
-
const handleToggleCollapse = externalOnToggleCollapse ??
|
|
15272
|
+
const handleToggleCollapse = externalOnToggleCollapse ?? ((parentId) => {
|
|
15273
|
+
if (normalizedTasks.some((task) => task.id === parentId && task.composite)) {
|
|
15274
|
+
setExpandedCompositeIds((prev) => {
|
|
15275
|
+
const next = new Set(prev);
|
|
15276
|
+
if (next.has(parentId)) next.delete(parentId);
|
|
15277
|
+
else next.add(parentId);
|
|
15278
|
+
return next;
|
|
15279
|
+
});
|
|
15280
|
+
return;
|
|
15281
|
+
}
|
|
14979
15282
|
setInternalCollapsedParentIds((prev) => {
|
|
14980
15283
|
const next = new Set(prev);
|
|
14981
15284
|
if (next.has(parentId)) {
|
|
@@ -14985,7 +15288,14 @@ function TaskGanttChartInner(props, ref) {
|
|
|
14985
15288
|
}
|
|
14986
15289
|
return next;
|
|
14987
15290
|
});
|
|
14988
|
-
}
|
|
15291
|
+
});
|
|
15292
|
+
const lastCompositeBarToggleRef = useRef13(null);
|
|
15293
|
+
const handleCompositeBarToggle = (taskId, source) => {
|
|
15294
|
+
const now = Date.now();
|
|
15295
|
+
if (source === "click" && lastCompositeBarToggleRef.current?.source === "release" && lastCompositeBarToggleRef.current.id === taskId && now - lastCompositeBarToggleRef.current.time < 150) return;
|
|
15296
|
+
lastCompositeBarToggleRef.current = { id: taskId, time: now, source };
|
|
15297
|
+
handleToggleCollapse(taskId);
|
|
15298
|
+
};
|
|
14989
15299
|
const allParentIds = useMemo13(() => {
|
|
14990
15300
|
const taskIds = new Set(normalizedTasks.map((task) => task.id));
|
|
14991
15301
|
return new Set(normalizedTasks.map((task) => task.parentId).filter((parentId) => Boolean(parentId && taskIds.has(parentId))));
|
|
@@ -14993,11 +15303,13 @@ function TaskGanttChartInner(props, ref) {
|
|
|
14993
15303
|
const handleCollapseAll = useCallback10(() => {
|
|
14994
15304
|
if (externalCollapsedParentIds) return;
|
|
14995
15305
|
setInternalCollapsedParentIds(allParentIds);
|
|
15306
|
+
setExpandedCompositeIds(/* @__PURE__ */ new Set());
|
|
14996
15307
|
}, [allParentIds, externalCollapsedParentIds]);
|
|
14997
15308
|
const handleExpandAll = useCallback10(() => {
|
|
14998
15309
|
if (externalCollapsedParentIds) return;
|
|
14999
15310
|
setInternalCollapsedParentIds(/* @__PURE__ */ new Set());
|
|
15000
|
-
|
|
15311
|
+
setExpandedCompositeIds(new Set(normalizedTasks.filter((task) => task.composite).map((task) => task.id)));
|
|
15312
|
+
}, [externalCollapsedParentIds, normalizedTasks]);
|
|
15001
15313
|
const exportToPdf = useCallback10(async (options) => {
|
|
15002
15314
|
const sourceContainer = containerRef.current;
|
|
15003
15315
|
if (!sourceContainer || typeof window === "undefined" || typeof document === "undefined") {
|
|
@@ -15169,7 +15481,7 @@ function TaskGanttChartInner(props, ref) {
|
|
|
15169
15481
|
onTasksChange?.(changedTasks);
|
|
15170
15482
|
}
|
|
15171
15483
|
}, [tasks, onTasksChange, onUngroupTask]);
|
|
15172
|
-
const panStateRef =
|
|
15484
|
+
const panStateRef = useRef13(null);
|
|
15173
15485
|
const handlePanStart = useCallback10((e) => {
|
|
15174
15486
|
if (e.button !== 0) return;
|
|
15175
15487
|
const target = e.target;
|
|
@@ -15194,7 +15506,7 @@ function TaskGanttChartInner(props, ref) {
|
|
|
15194
15506
|
container.style.cursor = "grabbing";
|
|
15195
15507
|
e.preventDefault();
|
|
15196
15508
|
}, []);
|
|
15197
|
-
|
|
15509
|
+
useEffect11(() => {
|
|
15198
15510
|
const flushPanMove = () => {
|
|
15199
15511
|
const pan = panStateRef.current;
|
|
15200
15512
|
if (!pan?.active) return;
|
|
@@ -15262,6 +15574,8 @@ function TaskGanttChartInner(props, ref) {
|
|
|
15262
15574
|
{
|
|
15263
15575
|
tasks: normalizedTasks,
|
|
15264
15576
|
rowHeight: effectiveRowHeight,
|
|
15577
|
+
rowTops: compositeRowLayout.tops,
|
|
15578
|
+
rowHeights: compositeRowLayout.heights,
|
|
15265
15579
|
headerHeight,
|
|
15266
15580
|
taskListWidth,
|
|
15267
15581
|
onTasksChange: handleTaskChange,
|
|
@@ -15456,6 +15770,8 @@ function TaskGanttChartInner(props, ref) {
|
|
|
15456
15770
|
gridWidth: renderGridWidth,
|
|
15457
15771
|
totalHeight: totalGridHeight,
|
|
15458
15772
|
rowIndexByTaskId: visibleTaskIndexMap,
|
|
15773
|
+
rowTops: compositeRowLayout.tops,
|
|
15774
|
+
rowHeights: compositeRowLayout.heights,
|
|
15459
15775
|
dragOverrides: dependencyOverrides,
|
|
15460
15776
|
selectedDep: selectedChip,
|
|
15461
15777
|
businessDays,
|
|
@@ -15542,10 +15858,10 @@ function TaskGanttChartInner(props, ref) {
|
|
|
15542
15858
|
{
|
|
15543
15859
|
style: {
|
|
15544
15860
|
position: "absolute",
|
|
15545
|
-
top: `${index
|
|
15861
|
+
top: `${compositeRowLayout.tops[index]}px`,
|
|
15546
15862
|
left: 0,
|
|
15547
15863
|
right: 0,
|
|
15548
|
-
height: `${
|
|
15864
|
+
height: `${compositeRowLayout.heights[index]}px`
|
|
15549
15865
|
},
|
|
15550
15866
|
children: /* @__PURE__ */ jsx21(
|
|
15551
15867
|
TaskRow_default,
|
|
@@ -15553,7 +15869,9 @@ function TaskGanttChartInner(props, ref) {
|
|
|
15553
15869
|
task,
|
|
15554
15870
|
monthStart,
|
|
15555
15871
|
dayWidth,
|
|
15556
|
-
rowHeight:
|
|
15872
|
+
rowHeight: compositeRowLayout.heights[index],
|
|
15873
|
+
compactDetail: compositeRowLayout.heights[index] < effectiveRowHeight,
|
|
15874
|
+
compositeParentColor: task.parentId ? compositeParentsById.get(task.parentId)?.color : void 0,
|
|
15557
15875
|
onTasksChange: handleTaskChange,
|
|
15558
15876
|
onDragStateChange: (state) => {
|
|
15559
15877
|
if (state.isDragging) {
|
|
@@ -15590,7 +15908,9 @@ function TaskGanttChartInner(props, ref) {
|
|
|
15590
15908
|
isDependencyDragActive: dependencyCreationDrag !== null,
|
|
15591
15909
|
viewMode,
|
|
15592
15910
|
showTaskDateLabels,
|
|
15593
|
-
showTaskNames
|
|
15911
|
+
showTaskNames,
|
|
15912
|
+
onCompositeToggle: task.composite ? (source) => handleCompositeBarToggle(task.id, source) : void 0,
|
|
15913
|
+
compositeExpanded: task.composite ? !collapsedParentIds.has(task.id) : void 0
|
|
15594
15914
|
}
|
|
15595
15915
|
)
|
|
15596
15916
|
},
|
|
@@ -15603,6 +15923,7 @@ function TaskGanttChartInner(props, ref) {
|
|
|
15603
15923
|
rowHeight: effectiveRowHeight,
|
|
15604
15924
|
variant: "chart",
|
|
15605
15925
|
startIndex: visibleTasks.length,
|
|
15926
|
+
startTop: compositeRowLayout.totalHeight,
|
|
15606
15927
|
chartDayWidth: dayWidth,
|
|
15607
15928
|
chartStartDayOffset: todayInRange ? Math.max(0, todayIndex + Math.floor(Number.isFinite(skeletonStartOffsetDays) ? skeletonStartOffsetDays : 0)) : 0,
|
|
15608
15929
|
chartStartJitterDays: skeletonStartJitterDays
|
|
@@ -15685,6 +16006,8 @@ export {
|
|
|
15685
16006
|
GenerationSkeleton_default as GenerationSkeletonRows,
|
|
15686
16007
|
GridBackground_default as GridBackground,
|
|
15687
16008
|
Input,
|
|
16009
|
+
MIN_EDGE_ZONE_PX,
|
|
16010
|
+
MIN_MOVE_ZONE_PX,
|
|
15688
16011
|
PlanFactMatrix,
|
|
15689
16012
|
Popover,
|
|
15690
16013
|
PopoverContent,
|