gantt-lib 0.0.4 → 0.0.6
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 +8 -0
- package/dist/index.css.map +1 -1
- package/dist/index.d.mts +280 -55
- package/dist/index.d.ts +280 -55
- package/dist/index.js +574 -69
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +564 -67
- package/dist/index.mjs.map +1 -1
- package/dist/styles.css +51 -13
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -37,27 +37,35 @@ __export(index_exports, {
|
|
|
37
37
|
TaskRow: () => TaskRow_default,
|
|
38
38
|
TimeScaleHeader: () => TimeScaleHeader_default,
|
|
39
39
|
TodayIndicator: () => TodayIndicator_default,
|
|
40
|
+
buildAdjacencyList: () => buildAdjacencyList,
|
|
41
|
+
calculateBezierPath: () => calculateBezierPath,
|
|
40
42
|
calculateGridLines: () => calculateGridLines,
|
|
41
43
|
calculateGridWidth: () => calculateGridWidth,
|
|
44
|
+
calculateOrthogonalPath: () => calculateOrthogonalPath,
|
|
45
|
+
calculateSuccessorDate: () => calculateSuccessorDate,
|
|
42
46
|
calculateTaskBar: () => calculateTaskBar,
|
|
43
47
|
calculateWeekendBlocks: () => calculateWeekendBlocks,
|
|
48
|
+
detectCycles: () => detectCycles,
|
|
44
49
|
detectEdgeZone: () => detectEdgeZone,
|
|
45
50
|
formatDateLabel: () => formatDateLabel,
|
|
51
|
+
getAllDependencyEdges: () => getAllDependencyEdges,
|
|
46
52
|
getCursorForPosition: () => getCursorForPosition,
|
|
47
53
|
getDayOffset: () => getDayOffset,
|
|
48
54
|
getMonthDays: () => getMonthDays,
|
|
49
55
|
getMonthSpans: () => getMonthSpans,
|
|
50
56
|
getMultiMonthDays: () => getMultiMonthDays,
|
|
57
|
+
getSuccessorChain: () => getSuccessorChain,
|
|
51
58
|
isToday: () => isToday,
|
|
52
59
|
isWeekend: () => isWeekend,
|
|
53
60
|
parseUTCDate: () => parseUTCDate,
|
|
54
61
|
pixelsToDate: () => pixelsToDate,
|
|
55
|
-
useTaskDrag: () => useTaskDrag
|
|
62
|
+
useTaskDrag: () => useTaskDrag,
|
|
63
|
+
validateDependencies: () => validateDependencies
|
|
56
64
|
});
|
|
57
65
|
module.exports = __toCommonJS(index_exports);
|
|
58
66
|
|
|
59
67
|
// src/components/GanttChart/GanttChart.tsx
|
|
60
|
-
var
|
|
68
|
+
var import_react7 = require("react");
|
|
61
69
|
|
|
62
70
|
// src/utils/dateUtils.ts
|
|
63
71
|
var parseUTCDate = (date) => {
|
|
@@ -198,6 +206,148 @@ var formatDateLabel = (date) => {
|
|
|
198
206
|
return `${day}.${month}`;
|
|
199
207
|
};
|
|
200
208
|
|
|
209
|
+
// src/utils/dependencyUtils.ts
|
|
210
|
+
function buildAdjacencyList(tasks) {
|
|
211
|
+
const taskMap = new Map(tasks.map((t) => [t.id, t]));
|
|
212
|
+
const graph = /* @__PURE__ */ new Map();
|
|
213
|
+
for (const task of tasks) {
|
|
214
|
+
const successors = [];
|
|
215
|
+
for (const otherTask of tasks) {
|
|
216
|
+
if (otherTask.dependencies) {
|
|
217
|
+
for (const dep of otherTask.dependencies) {
|
|
218
|
+
if (dep.taskId === task.id) {
|
|
219
|
+
successors.push(otherTask.id);
|
|
220
|
+
break;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
graph.set(task.id, successors);
|
|
226
|
+
}
|
|
227
|
+
return graph;
|
|
228
|
+
}
|
|
229
|
+
function detectCycles(tasks) {
|
|
230
|
+
const graph = buildAdjacencyList(tasks);
|
|
231
|
+
const visiting = /* @__PURE__ */ new Set();
|
|
232
|
+
const visited = /* @__PURE__ */ new Set();
|
|
233
|
+
const path = [];
|
|
234
|
+
function dfs(taskId) {
|
|
235
|
+
if (visiting.has(taskId)) {
|
|
236
|
+
return true;
|
|
237
|
+
}
|
|
238
|
+
if (visited.has(taskId)) {
|
|
239
|
+
return false;
|
|
240
|
+
}
|
|
241
|
+
visiting.add(taskId);
|
|
242
|
+
path.push(taskId);
|
|
243
|
+
const successors = graph.get(taskId) || [];
|
|
244
|
+
for (const successor of successors) {
|
|
245
|
+
if (dfs(successor)) {
|
|
246
|
+
return true;
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
visiting.delete(taskId);
|
|
250
|
+
path.pop();
|
|
251
|
+
visited.add(taskId);
|
|
252
|
+
return false;
|
|
253
|
+
}
|
|
254
|
+
for (const task of tasks) {
|
|
255
|
+
if (dfs(task.id)) {
|
|
256
|
+
return { hasCycle: true, cyclePath: [...path] };
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
return { hasCycle: false };
|
|
260
|
+
}
|
|
261
|
+
function calculateSuccessorDate(predecessorStart, predecessorEnd, linkType, lag = 0) {
|
|
262
|
+
const baseDate = linkType.startsWith("F") ? predecessorEnd : predecessorStart;
|
|
263
|
+
const lagMs = lag * 24 * 60 * 60 * 1e3;
|
|
264
|
+
const resultDate = new Date(baseDate.getTime() + lagMs);
|
|
265
|
+
return resultDate;
|
|
266
|
+
}
|
|
267
|
+
function validateDependencies(tasks) {
|
|
268
|
+
const errors = [];
|
|
269
|
+
const taskIds = new Set(tasks.map((t) => t.id));
|
|
270
|
+
for (const task of tasks) {
|
|
271
|
+
if (task.dependencies) {
|
|
272
|
+
for (const dep of task.dependencies) {
|
|
273
|
+
if (!taskIds.has(dep.taskId)) {
|
|
274
|
+
errors.push({
|
|
275
|
+
type: "missing-task",
|
|
276
|
+
taskId: task.id,
|
|
277
|
+
message: `Dependency references non-existent task: ${dep.taskId}`,
|
|
278
|
+
relatedTaskIds: [dep.taskId]
|
|
279
|
+
});
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
const cycleResult = detectCycles(tasks);
|
|
285
|
+
if (cycleResult.hasCycle && cycleResult.cyclePath) {
|
|
286
|
+
errors.push({
|
|
287
|
+
type: "cycle",
|
|
288
|
+
taskId: cycleResult.cyclePath[0],
|
|
289
|
+
message: "Circular dependency detected",
|
|
290
|
+
relatedTaskIds: cycleResult.cyclePath
|
|
291
|
+
});
|
|
292
|
+
}
|
|
293
|
+
return {
|
|
294
|
+
isValid: errors.length === 0,
|
|
295
|
+
errors
|
|
296
|
+
};
|
|
297
|
+
}
|
|
298
|
+
function getSuccessorChain(draggedTaskId, allTasks) {
|
|
299
|
+
const successorMap = /* @__PURE__ */ new Map();
|
|
300
|
+
for (const task of allTasks) {
|
|
301
|
+
successorMap.set(task.id, []);
|
|
302
|
+
}
|
|
303
|
+
for (const task of allTasks) {
|
|
304
|
+
if (!task.dependencies) continue;
|
|
305
|
+
for (const dep of task.dependencies) {
|
|
306
|
+
if (dep.type === "FS") {
|
|
307
|
+
const list = successorMap.get(dep.taskId) ?? [];
|
|
308
|
+
list.push(task.id);
|
|
309
|
+
successorMap.set(dep.taskId, list);
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
const taskById = new Map(allTasks.map((t) => [t.id, t]));
|
|
314
|
+
const visited = /* @__PURE__ */ new Set();
|
|
315
|
+
const queue = [draggedTaskId];
|
|
316
|
+
const chain = [];
|
|
317
|
+
visited.add(draggedTaskId);
|
|
318
|
+
while (queue.length > 0) {
|
|
319
|
+
const current = queue.shift();
|
|
320
|
+
const successors = successorMap.get(current) ?? [];
|
|
321
|
+
for (const sid of successors) {
|
|
322
|
+
if (!visited.has(sid)) {
|
|
323
|
+
visited.add(sid);
|
|
324
|
+
const t = taskById.get(sid);
|
|
325
|
+
if (t) {
|
|
326
|
+
chain.push(t);
|
|
327
|
+
queue.push(sid);
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
return chain;
|
|
333
|
+
}
|
|
334
|
+
function getAllDependencyEdges(tasks) {
|
|
335
|
+
const edges = [];
|
|
336
|
+
for (const task of tasks) {
|
|
337
|
+
if (task.dependencies) {
|
|
338
|
+
for (const dep of task.dependencies) {
|
|
339
|
+
edges.push({
|
|
340
|
+
predecessorId: dep.taskId,
|
|
341
|
+
successorId: task.id,
|
|
342
|
+
type: dep.type,
|
|
343
|
+
lag: dep.lag ?? 0
|
|
344
|
+
});
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
return edges;
|
|
349
|
+
}
|
|
350
|
+
|
|
201
351
|
// src/components/TimeScaleHeader/TimeScaleHeader.tsx
|
|
202
352
|
var import_react = require("react");
|
|
203
353
|
var import_date_fns = require("date-fns");
|
|
@@ -361,6 +511,43 @@ var calculateWeekendBlocks = (dateRange, dayWidth) => {
|
|
|
361
511
|
}
|
|
362
512
|
return blocks;
|
|
363
513
|
};
|
|
514
|
+
var calculateBezierPath = (from, to) => {
|
|
515
|
+
const verticalDistance = Math.abs(to.y - from.y);
|
|
516
|
+
const cpOffset = Math.max(verticalDistance * 0.5, 20);
|
|
517
|
+
if (from.y === to.y) {
|
|
518
|
+
const arcHeight = 20;
|
|
519
|
+
const midX = (from.x + to.x) / 2;
|
|
520
|
+
return `M ${from.x} ${from.y} Q ${midX} ${from.y - arcHeight} ${to.x} ${to.y}`;
|
|
521
|
+
}
|
|
522
|
+
const cp1x = from.x;
|
|
523
|
+
const cp1y = from.y + (to.y > from.y ? cpOffset : -cpOffset);
|
|
524
|
+
const cp2x = to.x;
|
|
525
|
+
const cp2y = to.y - (to.y > from.y ? cpOffset : -cpOffset);
|
|
526
|
+
return `M ${Math.round(from.x)} ${Math.round(from.y)} C ${Math.round(cp1x)} ${Math.round(cp1y)}, ${Math.round(cp2x)} ${Math.round(cp2y)}, ${Math.round(to.x)} ${Math.round(to.y)}`;
|
|
527
|
+
};
|
|
528
|
+
var calculateOrthogonalPath = (from, to) => {
|
|
529
|
+
const fx = Math.round(from.x);
|
|
530
|
+
const fy = Math.round(from.y);
|
|
531
|
+
const tx = Math.round(to.x);
|
|
532
|
+
const ty = Math.round(to.y);
|
|
533
|
+
if (fy === ty) {
|
|
534
|
+
return `M ${fx} ${fy} H ${tx}`;
|
|
535
|
+
}
|
|
536
|
+
const C = 2;
|
|
537
|
+
const goingDown = ty > fy;
|
|
538
|
+
const goingRight = tx >= fx;
|
|
539
|
+
const dirY = goingDown ? 1 : -1;
|
|
540
|
+
const dirX = goingRight ? 1 : -1;
|
|
541
|
+
if (Math.abs(ty - fy) >= C && Math.abs(tx - fx) >= C) {
|
|
542
|
+
return [
|
|
543
|
+
`M ${fx} ${fy}`,
|
|
544
|
+
`H ${tx - dirX * C}`,
|
|
545
|
+
`L ${tx} ${fy + dirY * C}`,
|
|
546
|
+
`V ${ty}`
|
|
547
|
+
].join(" ");
|
|
548
|
+
}
|
|
549
|
+
return `M ${fx} ${fy} H ${tx} V ${ty}`;
|
|
550
|
+
};
|
|
364
551
|
|
|
365
552
|
// src/hooks/useTaskDrag.ts
|
|
366
553
|
var import_react2 = require("react");
|
|
@@ -372,8 +559,8 @@ function completeDrag() {
|
|
|
372
559
|
globalRafId = null;
|
|
373
560
|
}
|
|
374
561
|
if (globalActiveDrag) {
|
|
562
|
+
globalActiveDrag.onCascadeProgress?.(/* @__PURE__ */ new Map());
|
|
375
563
|
const { onComplete, currentLeft, currentWidth } = globalActiveDrag;
|
|
376
|
-
const drag = globalActiveDrag;
|
|
377
564
|
globalActiveDrag = null;
|
|
378
565
|
onComplete(currentLeft, currentWidth);
|
|
379
566
|
}
|
|
@@ -392,6 +579,27 @@ function cancelDrag() {
|
|
|
392
579
|
function snapToGrid(pixels, dayWidth) {
|
|
393
580
|
return Math.round(pixels / dayWidth) * dayWidth;
|
|
394
581
|
}
|
|
582
|
+
function recalculateIncomingLags(task, newStartDate, allTasks) {
|
|
583
|
+
if (!task.dependencies) return [];
|
|
584
|
+
const taskById = new Map(allTasks.map((t) => [t.id, t]));
|
|
585
|
+
return task.dependencies.map((dep) => {
|
|
586
|
+
if (dep.type !== "FS") return dep;
|
|
587
|
+
const predecessor = taskById.get(dep.taskId);
|
|
588
|
+
if (!predecessor) return dep;
|
|
589
|
+
const predEnd = new Date(predecessor.endDate);
|
|
590
|
+
const lagMs = Date.UTC(
|
|
591
|
+
newStartDate.getUTCFullYear(),
|
|
592
|
+
newStartDate.getUTCMonth(),
|
|
593
|
+
newStartDate.getUTCDate()
|
|
594
|
+
) - Date.UTC(
|
|
595
|
+
predEnd.getUTCFullYear(),
|
|
596
|
+
predEnd.getUTCMonth(),
|
|
597
|
+
predEnd.getUTCDate()
|
|
598
|
+
);
|
|
599
|
+
const lagDays = Math.round(lagMs / (24 * 60 * 60 * 1e3));
|
|
600
|
+
return { ...dep, lag: lagDays };
|
|
601
|
+
});
|
|
602
|
+
}
|
|
395
603
|
function handleGlobalMouseMove(e) {
|
|
396
604
|
if (!globalActiveDrag || globalRafId !== null) {
|
|
397
605
|
return;
|
|
@@ -401,7 +609,7 @@ function handleGlobalMouseMove(e) {
|
|
|
401
609
|
globalRafId = null;
|
|
402
610
|
return;
|
|
403
611
|
}
|
|
404
|
-
const { startX, initialLeft, initialWidth, mode, dayWidth, onProgress } = globalActiveDrag;
|
|
612
|
+
const { startX, initialLeft, initialWidth, mode, dayWidth, onProgress, allTasks } = globalActiveDrag;
|
|
405
613
|
const deltaX = e.clientX - startX;
|
|
406
614
|
let newLeft = initialLeft;
|
|
407
615
|
let newWidth = initialWidth;
|
|
@@ -420,6 +628,50 @@ function handleGlobalMouseMove(e) {
|
|
|
420
628
|
newWidth = Math.max(dayWidth, snappedWidth);
|
|
421
629
|
break;
|
|
422
630
|
}
|
|
631
|
+
if (mode === "move" && allTasks.length > 0 && !globalActiveDrag.disableConstraints) {
|
|
632
|
+
const currentTask = allTasks.find((t) => t.id === globalActiveDrag?.taskId);
|
|
633
|
+
if (currentTask && currentTask.dependencies && currentTask.dependencies.length > 0) {
|
|
634
|
+
let minAllowedLeft = 0;
|
|
635
|
+
for (const dep of currentTask.dependencies) {
|
|
636
|
+
if (dep.type !== "FS") continue;
|
|
637
|
+
const predecessor = globalActiveDrag.allTasks.find((t) => t.id === dep.taskId);
|
|
638
|
+
if (!predecessor) continue;
|
|
639
|
+
const predStart = new Date(predecessor.startDate);
|
|
640
|
+
const predStartOffset = Math.round(
|
|
641
|
+
(Date.UTC(predStart.getUTCFullYear(), predStart.getUTCMonth(), predStart.getUTCDate()) - Date.UTC(
|
|
642
|
+
globalActiveDrag.monthStart.getUTCFullYear(),
|
|
643
|
+
globalActiveDrag.monthStart.getUTCMonth(),
|
|
644
|
+
globalActiveDrag.monthStart.getUTCDate()
|
|
645
|
+
)) / (24 * 60 * 60 * 1e3)
|
|
646
|
+
);
|
|
647
|
+
const predStartLeft = Math.round(predStartOffset * globalActiveDrag.dayWidth);
|
|
648
|
+
minAllowedLeft = Math.max(minAllowedLeft, predStartLeft);
|
|
649
|
+
}
|
|
650
|
+
newLeft = Math.max(minAllowedLeft, newLeft);
|
|
651
|
+
}
|
|
652
|
+
}
|
|
653
|
+
if ((mode === "move" || mode === "resize-right") && !globalActiveDrag.disableConstraints && globalActiveDrag.cascadeChain.length > 0 && globalActiveDrag.onCascadeProgress) {
|
|
654
|
+
const deltaDays = mode === "resize-right" ? Math.round((newWidth - globalActiveDrag.initialWidth) / globalActiveDrag.dayWidth) : Math.round((newLeft - globalActiveDrag.initialLeft) / globalActiveDrag.dayWidth);
|
|
655
|
+
const overrides = /* @__PURE__ */ new Map();
|
|
656
|
+
for (const chainTask of globalActiveDrag.cascadeChain) {
|
|
657
|
+
const chainStart = new Date(chainTask.startDate);
|
|
658
|
+
const chainEnd = new Date(chainTask.endDate);
|
|
659
|
+
const chainStartOffset = Math.round(
|
|
660
|
+
(Date.UTC(chainStart.getUTCFullYear(), chainStart.getUTCMonth(), chainStart.getUTCDate()) - Date.UTC(
|
|
661
|
+
globalActiveDrag.monthStart.getUTCFullYear(),
|
|
662
|
+
globalActiveDrag.monthStart.getUTCMonth(),
|
|
663
|
+
globalActiveDrag.monthStart.getUTCDate()
|
|
664
|
+
)) / (24 * 60 * 60 * 1e3)
|
|
665
|
+
);
|
|
666
|
+
const chainDuration = Math.round(
|
|
667
|
+
(Date.UTC(chainEnd.getUTCFullYear(), chainEnd.getUTCMonth(), chainEnd.getUTCDate()) - Date.UTC(chainStart.getUTCFullYear(), chainStart.getUTCMonth(), chainStart.getUTCDate())) / (24 * 60 * 60 * 1e3)
|
|
668
|
+
);
|
|
669
|
+
const chainLeft = Math.round((chainStartOffset + deltaDays) * globalActiveDrag.dayWidth);
|
|
670
|
+
const chainWidth = Math.round((chainDuration + 1) * globalActiveDrag.dayWidth);
|
|
671
|
+
overrides.set(chainTask.id, { left: chainLeft, width: chainWidth });
|
|
672
|
+
}
|
|
673
|
+
globalActiveDrag.onCascadeProgress(overrides);
|
|
674
|
+
}
|
|
423
675
|
globalActiveDrag.currentLeft = newLeft;
|
|
424
676
|
globalActiveDrag.currentWidth = newWidth;
|
|
425
677
|
onProgress(newLeft, newWidth);
|
|
@@ -448,7 +700,13 @@ var useTaskDrag = (options) => {
|
|
|
448
700
|
dayWidth,
|
|
449
701
|
onDragEnd,
|
|
450
702
|
onDragStateChange,
|
|
451
|
-
edgeZoneWidth = 12
|
|
703
|
+
edgeZoneWidth = 12,
|
|
704
|
+
allTasks = [],
|
|
705
|
+
rowIndex,
|
|
706
|
+
enableAutoSchedule = false,
|
|
707
|
+
disableConstraints = false,
|
|
708
|
+
onCascadeProgress,
|
|
709
|
+
onCascade
|
|
452
710
|
} = options;
|
|
453
711
|
const isOwnerRef = (0, import_react2.useRef)(false);
|
|
454
712
|
const [isDragging, setIsDragging] = (0, import_react2.useState)(false);
|
|
@@ -518,14 +776,60 @@ var useTaskDrag = (options) => {
|
|
|
518
776
|
width: finalWidth
|
|
519
777
|
});
|
|
520
778
|
}
|
|
521
|
-
if (
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
779
|
+
if (wasOwner) {
|
|
780
|
+
if (!disableConstraints && onCascade && allTasks.length > 0) {
|
|
781
|
+
const chain = getSuccessorChain(taskId, allTasks);
|
|
782
|
+
if (chain.length > 0) {
|
|
783
|
+
const origEndMs = Date.UTC(
|
|
784
|
+
initialEndDate.getUTCFullYear(),
|
|
785
|
+
initialEndDate.getUTCMonth(),
|
|
786
|
+
initialEndDate.getUTCDate()
|
|
787
|
+
);
|
|
788
|
+
const newEndMs = Date.UTC(
|
|
789
|
+
newEndDate.getUTCFullYear(),
|
|
790
|
+
newEndDate.getUTCMonth(),
|
|
791
|
+
newEndDate.getUTCDate()
|
|
792
|
+
);
|
|
793
|
+
const deltaDays = Math.round((newEndMs - origEndMs) / (24 * 60 * 60 * 1e3));
|
|
794
|
+
const draggedTaskData = allTasks.find((t) => t.id === taskId);
|
|
795
|
+
const cascadedTasks = [
|
|
796
|
+
{
|
|
797
|
+
...draggedTaskData ?? { id: taskId, name: "", startDate: "", endDate: "" },
|
|
798
|
+
startDate: newStartDate.toISOString(),
|
|
799
|
+
endDate: newEndDate.toISOString(),
|
|
800
|
+
...draggedTaskData?.dependencies && {
|
|
801
|
+
dependencies: recalculateIncomingLags(draggedTaskData, newStartDate, allTasks)
|
|
802
|
+
}
|
|
803
|
+
},
|
|
804
|
+
...chain.map((chainTask) => {
|
|
805
|
+
const origStart = new Date(chainTask.startDate);
|
|
806
|
+
const origEnd = new Date(chainTask.endDate);
|
|
807
|
+
const newStart = new Date(Date.UTC(
|
|
808
|
+
origStart.getUTCFullYear(),
|
|
809
|
+
origStart.getUTCMonth(),
|
|
810
|
+
origStart.getUTCDate() + deltaDays
|
|
811
|
+
));
|
|
812
|
+
const newEnd = new Date(Date.UTC(
|
|
813
|
+
origEnd.getUTCFullYear(),
|
|
814
|
+
origEnd.getUTCMonth(),
|
|
815
|
+
origEnd.getUTCDate() + deltaDays
|
|
816
|
+
));
|
|
817
|
+
return { ...chainTask, startDate: newStart.toISOString(), endDate: newEnd.toISOString() };
|
|
818
|
+
})
|
|
819
|
+
];
|
|
820
|
+
onCascade(cascadedTasks);
|
|
821
|
+
return;
|
|
822
|
+
}
|
|
823
|
+
}
|
|
824
|
+
if (allTasks.length > 0 && onDragEnd) {
|
|
825
|
+
const currentTaskData = allTasks.find((t) => t.id === taskId);
|
|
826
|
+
const updatedDependencies = currentTaskData?.dependencies ? recalculateIncomingLags(currentTaskData, newStartDate, allTasks) : void 0;
|
|
827
|
+
onDragEnd({ id: taskId, startDate: newStartDate, endDate: newEndDate, updatedDependencies });
|
|
828
|
+
} else if (onDragEnd) {
|
|
829
|
+
onDragEnd({ id: taskId, startDate: newStartDate, endDate: newEndDate });
|
|
830
|
+
}
|
|
527
831
|
}
|
|
528
|
-
}, [dayWidth, monthStart, onDragEnd, onDragStateChange, taskId]);
|
|
832
|
+
}, [dayWidth, monthStart, onDragEnd, onDragStateChange, taskId, disableConstraints, onCascade, allTasks, initialStartDate, initialEndDate]);
|
|
529
833
|
const handleCancel = (0, import_react2.useCallback)(() => {
|
|
530
834
|
isOwnerRef.current = false;
|
|
531
835
|
setIsDragging(false);
|
|
@@ -592,9 +896,13 @@ var useTaskDrag = (options) => {
|
|
|
592
896
|
monthStart,
|
|
593
897
|
onProgress: handleProgress,
|
|
594
898
|
onComplete: handleComplete,
|
|
595
|
-
onCancel: handleCancel
|
|
899
|
+
onCancel: handleCancel,
|
|
900
|
+
allTasks,
|
|
901
|
+
disableConstraints,
|
|
902
|
+
cascadeChain: (mode === "move" || mode === "resize-right") && !disableConstraints ? getSuccessorChain(taskId, allTasks) : [],
|
|
903
|
+
onCascadeProgress
|
|
596
904
|
};
|
|
597
|
-
}, [edgeZoneWidth, currentLeft, currentWidth, dayWidth, monthStart, taskId, onDragStateChange, handleProgress, handleComplete, handleCancel]);
|
|
905
|
+
}, [edgeZoneWidth, currentLeft, currentWidth, dayWidth, monthStart, taskId, onDragStateChange, handleProgress, handleComplete, handleCancel, allTasks, disableConstraints, onCascadeProgress, onCascade]);
|
|
598
906
|
const getCursorStyle = (0, import_react2.useCallback)(() => {
|
|
599
907
|
if (isDragging) {
|
|
600
908
|
return "grabbing";
|
|
@@ -619,10 +927,10 @@ var useTaskDrag = (options) => {
|
|
|
619
927
|
// src/components/TaskRow/TaskRow.tsx
|
|
620
928
|
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
621
929
|
var arePropsEqual = (prevProps, nextProps) => {
|
|
622
|
-
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.color === nextProps.task.color && prevProps.monthStart.getTime() === nextProps.monthStart.getTime() && prevProps.dayWidth === nextProps.dayWidth && prevProps.rowHeight === nextProps.rowHeight;
|
|
930
|
+
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.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.allTasks === nextProps.allTasks && prevProps.disableConstraints === nextProps.disableConstraints;
|
|
623
931
|
};
|
|
624
932
|
var TaskRow = import_react3.default.memo(
|
|
625
|
-
({ task, monthStart, dayWidth, rowHeight, onChange, onDragStateChange }) => {
|
|
933
|
+
({ task, monthStart, dayWidth, rowHeight, onChange, onDragStateChange, rowIndex, allTasks, enableAutoSchedule, disableConstraints, overridePosition, onCascadeProgress, onCascade }) => {
|
|
626
934
|
const taskStartDate = (0, import_react3.useMemo)(() => parseUTCDate(task.startDate), [task.startDate]);
|
|
627
935
|
const taskEndDate = (0, import_react3.useMemo)(() => parseUTCDate(task.endDate), [task.endDate]);
|
|
628
936
|
const { left, width } = (0, import_react3.useMemo)(
|
|
@@ -630,11 +938,22 @@ var TaskRow = import_react3.default.memo(
|
|
|
630
938
|
[taskStartDate, taskEndDate, monthStart, dayWidth]
|
|
631
939
|
);
|
|
632
940
|
const barColor = task.color || "var(--gantt-task-bar-default-color)";
|
|
941
|
+
const progressWidth = (0, import_react3.useMemo)(() => {
|
|
942
|
+
if (task.progress === void 0 || task.progress <= 0) return 0;
|
|
943
|
+
return Math.min(100, Math.max(0, Math.round(task.progress)));
|
|
944
|
+
}, [task.progress]);
|
|
945
|
+
const progressColor = (0, import_react3.useMemo)(() => {
|
|
946
|
+
if (progressWidth === 100) {
|
|
947
|
+
return task.accepted ? "var(--gantt-progress-accepted, #22c55e)" : "var(--gantt-progress-completed, #fbbf24)";
|
|
948
|
+
}
|
|
949
|
+
return task.color ? `color-mix(in srgb, ${task.color} 40%, black)` : "var(--gantt-progress-color, rgba(0, 0, 0, 0.2))";
|
|
950
|
+
}, [progressWidth, task.accepted, task.color]);
|
|
633
951
|
const handleDragEnd = (result) => {
|
|
634
952
|
const updatedTask = {
|
|
635
953
|
...task,
|
|
636
954
|
startDate: result.startDate.toISOString(),
|
|
637
|
-
endDate: result.endDate.toISOString()
|
|
955
|
+
endDate: result.endDate.toISOString(),
|
|
956
|
+
...result.updatedDependencies !== void 0 && { dependencies: result.updatedDependencies }
|
|
638
957
|
};
|
|
639
958
|
onChange?.(updatedTask);
|
|
640
959
|
};
|
|
@@ -652,10 +971,16 @@ var TaskRow = import_react3.default.memo(
|
|
|
652
971
|
dayWidth,
|
|
653
972
|
onDragEnd: handleDragEnd,
|
|
654
973
|
onDragStateChange,
|
|
655
|
-
edgeZoneWidth: 20
|
|
974
|
+
edgeZoneWidth: 20,
|
|
975
|
+
allTasks,
|
|
976
|
+
rowIndex,
|
|
977
|
+
enableAutoSchedule,
|
|
978
|
+
disableConstraints,
|
|
979
|
+
onCascadeProgress,
|
|
980
|
+
onCascade
|
|
656
981
|
});
|
|
657
|
-
const displayLeft = isDragging ? currentLeft : left;
|
|
658
|
-
const displayWidth = isDragging ? currentWidth : width;
|
|
982
|
+
const displayLeft = overridePosition?.left ?? (isDragging ? currentLeft : left);
|
|
983
|
+
const displayWidth = overridePosition?.width ?? (isDragging ? currentWidth : width);
|
|
659
984
|
const currentStartDate = isDragging ? pixelsToDate(displayLeft, monthStart, dayWidth) : taskStartDate;
|
|
660
985
|
const currentEndDate = isDragging ? pixelsToDate(displayLeft + displayWidth - dayWidth, monthStart, dayWidth) : taskEndDate;
|
|
661
986
|
const startDateLabel = formatDateLabel(currentStartDate);
|
|
@@ -663,16 +988,6 @@ var TaskRow = import_react3.default.memo(
|
|
|
663
988
|
const durationDays = Math.round(
|
|
664
989
|
(currentEndDate.getTime() - currentStartDate.getTime()) / (1e3 * 60 * 60 * 24)
|
|
665
990
|
) + 1;
|
|
666
|
-
const [isNameOverflow, setIsNameOverflow] = (0, import_react3.useState)(false);
|
|
667
|
-
const taskNameRef = (0, import_react3.useRef)(null);
|
|
668
|
-
(0, import_react3.useEffect)(() => {
|
|
669
|
-
const nameEl = taskNameRef.current;
|
|
670
|
-
if (nameEl) {
|
|
671
|
-
const reservedWidth = 120;
|
|
672
|
-
const availableWidth = displayWidth - reservedWidth;
|
|
673
|
-
setIsNameOverflow(nameEl.scrollWidth > availableWidth);
|
|
674
|
-
}
|
|
675
|
-
}, [displayWidth, task.name]);
|
|
676
991
|
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
677
992
|
"div",
|
|
678
993
|
{
|
|
@@ -694,22 +1009,21 @@ var TaskRow = import_react3.default.memo(
|
|
|
694
1009
|
},
|
|
695
1010
|
onMouseDown: dragHandleProps.onMouseDown,
|
|
696
1011
|
children: [
|
|
1012
|
+
progressWidth > 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
1013
|
+
"div",
|
|
1014
|
+
{
|
|
1015
|
+
className: "gantt-tr-progressBar",
|
|
1016
|
+
style: {
|
|
1017
|
+
width: `${progressWidth}%`,
|
|
1018
|
+
backgroundColor: progressColor
|
|
1019
|
+
}
|
|
1020
|
+
}
|
|
1021
|
+
),
|
|
697
1022
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "gantt-tr-resizeHandle gantt-tr-resizeHandleLeft" }),
|
|
698
1023
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "gantt-tr-taskDuration", children: [
|
|
699
1024
|
durationDays,
|
|
700
1025
|
" \u0434"
|
|
701
1026
|
] }),
|
|
702
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
703
|
-
"span",
|
|
704
|
-
{
|
|
705
|
-
ref: taskNameRef,
|
|
706
|
-
className: `gantt-tr-taskName ${isNameOverflow ? "gantt-tr-taskNameHidden" : ""}`,
|
|
707
|
-
children: [
|
|
708
|
-
"\u2014 ",
|
|
709
|
-
task.name
|
|
710
|
-
]
|
|
711
|
-
}
|
|
712
|
-
),
|
|
713
1027
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "gantt-tr-resizeHandle gantt-tr-resizeHandleRight" })
|
|
714
1028
|
]
|
|
715
1029
|
}
|
|
@@ -735,7 +1049,7 @@ var TaskRow = import_react3.default.memo(
|
|
|
735
1049
|
style: {
|
|
736
1050
|
left: `${displayLeft + displayWidth}px`
|
|
737
1051
|
},
|
|
738
|
-
children:
|
|
1052
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "gantt-tr-externalTaskName", children: task.name })
|
|
739
1053
|
}
|
|
740
1054
|
)
|
|
741
1055
|
] })
|
|
@@ -881,55 +1195,212 @@ var DragGuideLines = ({
|
|
|
881
1195
|
};
|
|
882
1196
|
var DragGuideLines_default = DragGuideLines;
|
|
883
1197
|
|
|
884
|
-
// src/components/
|
|
1198
|
+
// src/components/DependencyLines/DependencyLines.tsx
|
|
1199
|
+
var import_react6 = __toESM(require("react"));
|
|
885
1200
|
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
1201
|
+
var DependencyLines = import_react6.default.memo(({
|
|
1202
|
+
tasks,
|
|
1203
|
+
monthStart,
|
|
1204
|
+
dayWidth,
|
|
1205
|
+
rowHeight,
|
|
1206
|
+
gridWidth,
|
|
1207
|
+
dragOverrides
|
|
1208
|
+
}) => {
|
|
1209
|
+
const { taskPositions, taskIndices } = (0, import_react6.useMemo)(() => {
|
|
1210
|
+
const positions = /* @__PURE__ */ new Map();
|
|
1211
|
+
const indices = /* @__PURE__ */ new Map();
|
|
1212
|
+
tasks.forEach((task, index) => {
|
|
1213
|
+
const startDate = new Date(task.startDate);
|
|
1214
|
+
const endDate = new Date(task.endDate);
|
|
1215
|
+
const computed = calculateTaskBar(startDate, endDate, monthStart, dayWidth);
|
|
1216
|
+
const override = dragOverrides?.get(task.id);
|
|
1217
|
+
const resolvedLeft = override?.left ?? computed.left;
|
|
1218
|
+
const resolvedWidth = override?.width ?? computed.width;
|
|
1219
|
+
indices.set(task.id, index);
|
|
1220
|
+
positions.set(task.id, {
|
|
1221
|
+
left: resolvedLeft + 10,
|
|
1222
|
+
right: resolvedLeft + resolvedWidth,
|
|
1223
|
+
rowTop: index * rowHeight
|
|
1224
|
+
});
|
|
1225
|
+
});
|
|
1226
|
+
return { taskPositions: positions, taskIndices: indices };
|
|
1227
|
+
}, [tasks, monthStart, dayWidth, rowHeight, dragOverrides]);
|
|
1228
|
+
const cycleInfo = (0, import_react6.useMemo)(() => {
|
|
1229
|
+
const result = detectCycles(tasks);
|
|
1230
|
+
const cycleTaskIds = new Set(result.cyclePath || []);
|
|
1231
|
+
return cycleTaskIds;
|
|
1232
|
+
}, [tasks]);
|
|
1233
|
+
const lines = (0, import_react6.useMemo)(() => {
|
|
1234
|
+
const edges = getAllDependencyEdges(tasks);
|
|
1235
|
+
const lines2 = [];
|
|
1236
|
+
for (const edge of edges) {
|
|
1237
|
+
const predecessor = taskPositions.get(edge.predecessorId);
|
|
1238
|
+
const successor = taskPositions.get(edge.successorId);
|
|
1239
|
+
const predecessorIndex = taskIndices.get(edge.predecessorId);
|
|
1240
|
+
const successorIndex = taskIndices.get(edge.successorId);
|
|
1241
|
+
if (!predecessor || !successor || predecessorIndex === void 0 || successorIndex === void 0) {
|
|
1242
|
+
continue;
|
|
1243
|
+
}
|
|
1244
|
+
const reverseOrder = predecessorIndex > successorIndex;
|
|
1245
|
+
let fromY;
|
|
1246
|
+
let toY;
|
|
1247
|
+
if (reverseOrder) {
|
|
1248
|
+
fromY = predecessor.rowTop + 10;
|
|
1249
|
+
toY = successor.rowTop + rowHeight - 6;
|
|
1250
|
+
} else {
|
|
1251
|
+
fromY = predecessor.rowTop + rowHeight - 10;
|
|
1252
|
+
toY = successor.rowTop + 6;
|
|
1253
|
+
}
|
|
1254
|
+
const from = { x: predecessor.right, y: fromY };
|
|
1255
|
+
const to = { x: successor.left, y: toY };
|
|
1256
|
+
const path = calculateOrthogonalPath(from, to);
|
|
1257
|
+
const hasCycle = cycleInfo.has(edge.predecessorId) || cycleInfo.has(edge.successorId);
|
|
1258
|
+
lines2.push({
|
|
1259
|
+
id: `${edge.predecessorId}-${edge.successorId}`,
|
|
1260
|
+
path,
|
|
1261
|
+
hasCycle
|
|
1262
|
+
});
|
|
1263
|
+
}
|
|
1264
|
+
return lines2;
|
|
1265
|
+
}, [tasks, taskPositions, taskIndices, cycleInfo]);
|
|
1266
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
|
1267
|
+
"svg",
|
|
1268
|
+
{
|
|
1269
|
+
className: "gantt-dependencies-svg",
|
|
1270
|
+
width: gridWidth,
|
|
1271
|
+
height: tasks.length * rowHeight,
|
|
1272
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
1273
|
+
children: [
|
|
1274
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("defs", { children: [
|
|
1275
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1276
|
+
"marker",
|
|
1277
|
+
{
|
|
1278
|
+
id: "arrowhead",
|
|
1279
|
+
markerWidth: "8",
|
|
1280
|
+
markerHeight: "6",
|
|
1281
|
+
markerUnits: "userSpaceOnUse",
|
|
1282
|
+
refX: "7",
|
|
1283
|
+
refY: "3",
|
|
1284
|
+
orient: "auto",
|
|
1285
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1286
|
+
"polygon",
|
|
1287
|
+
{
|
|
1288
|
+
points: "0 0, 8 3, 0 6",
|
|
1289
|
+
fill: "var(--gantt-dependency-line-color, #666666)"
|
|
1290
|
+
}
|
|
1291
|
+
)
|
|
1292
|
+
}
|
|
1293
|
+
),
|
|
1294
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1295
|
+
"marker",
|
|
1296
|
+
{
|
|
1297
|
+
id: "arrowhead-cycle",
|
|
1298
|
+
markerWidth: "8",
|
|
1299
|
+
markerHeight: "6",
|
|
1300
|
+
markerUnits: "userSpaceOnUse",
|
|
1301
|
+
refX: "7",
|
|
1302
|
+
refY: "3",
|
|
1303
|
+
orient: "auto",
|
|
1304
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1305
|
+
"polygon",
|
|
1306
|
+
{
|
|
1307
|
+
points: "0 0, 8 3, 0 6",
|
|
1308
|
+
fill: "var(--gantt-dependency-cycle-color, #ef4444)"
|
|
1309
|
+
}
|
|
1310
|
+
)
|
|
1311
|
+
}
|
|
1312
|
+
)
|
|
1313
|
+
] }),
|
|
1314
|
+
lines.map(({ id, path, hasCycle }) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1315
|
+
"path",
|
|
1316
|
+
{
|
|
1317
|
+
d: path,
|
|
1318
|
+
className: hasCycle ? "gantt-dependency-path gantt-dependency-cycle" : "gantt-dependency-path",
|
|
1319
|
+
markerEnd: hasCycle ? "url(#arrowhead-cycle)" : "url(#arrowhead)"
|
|
1320
|
+
},
|
|
1321
|
+
id
|
|
1322
|
+
))
|
|
1323
|
+
]
|
|
1324
|
+
}
|
|
1325
|
+
);
|
|
1326
|
+
});
|
|
1327
|
+
DependencyLines.displayName = "DependencyLines";
|
|
1328
|
+
var DependencyLines_default = DependencyLines;
|
|
1329
|
+
|
|
1330
|
+
// src/components/GanttChart/GanttChart.tsx
|
|
1331
|
+
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
886
1332
|
var GanttChart = ({
|
|
887
1333
|
tasks,
|
|
888
1334
|
dayWidth = 40,
|
|
889
1335
|
rowHeight = 40,
|
|
890
1336
|
headerHeight = 40,
|
|
891
1337
|
containerHeight = 600,
|
|
892
|
-
onChange
|
|
1338
|
+
onChange,
|
|
1339
|
+
onValidateDependencies,
|
|
1340
|
+
enableAutoSchedule,
|
|
1341
|
+
disableConstraints,
|
|
1342
|
+
onCascade
|
|
893
1343
|
}) => {
|
|
894
|
-
const scrollContainerRef = (0,
|
|
895
|
-
const dateRange = (0,
|
|
896
|
-
const
|
|
1344
|
+
const scrollContainerRef = (0, import_react7.useRef)(null);
|
|
1345
|
+
const dateRange = (0, import_react7.useMemo)(() => getMultiMonthDays(tasks), [tasks]);
|
|
1346
|
+
const [validationResult, setValidationResult] = (0, import_react7.useState)(null);
|
|
1347
|
+
const [cascadeOverrides, setCascadeOverrides] = (0, import_react7.useState)(/* @__PURE__ */ new Map());
|
|
1348
|
+
const gridWidth = (0, import_react7.useMemo)(
|
|
897
1349
|
() => Math.round(dateRange.length * dayWidth),
|
|
898
1350
|
[dateRange.length, dayWidth]
|
|
899
1351
|
);
|
|
900
|
-
const totalGridHeight = (0,
|
|
1352
|
+
const totalGridHeight = (0, import_react7.useMemo)(
|
|
901
1353
|
() => tasks.length * rowHeight,
|
|
902
1354
|
[tasks.length, rowHeight]
|
|
903
1355
|
);
|
|
904
|
-
const monthStart = (0,
|
|
1356
|
+
const monthStart = (0, import_react7.useMemo)(() => {
|
|
905
1357
|
if (dateRange.length === 0) {
|
|
906
1358
|
return new Date(Date.UTC((/* @__PURE__ */ new Date()).getUTCFullYear(), (/* @__PURE__ */ new Date()).getUTCMonth(), 1));
|
|
907
1359
|
}
|
|
908
1360
|
const firstDay = dateRange[0];
|
|
909
1361
|
return new Date(Date.UTC(firstDay.getUTCFullYear(), firstDay.getUTCMonth(), 1));
|
|
910
1362
|
}, [dateRange]);
|
|
911
|
-
const todayInRange = (0,
|
|
1363
|
+
const todayInRange = (0, import_react7.useMemo)(() => {
|
|
912
1364
|
const now = /* @__PURE__ */ new Date();
|
|
913
1365
|
const today = new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate()));
|
|
914
1366
|
return dateRange.some((day) => day.getTime() === today.getTime());
|
|
915
1367
|
}, [dateRange]);
|
|
916
|
-
const [dragGuideLines, setDragGuideLines] = (0,
|
|
917
|
-
const
|
|
1368
|
+
const [dragGuideLines, setDragGuideLines] = (0, import_react7.useState)(null);
|
|
1369
|
+
const [draggedTaskOverride, setDraggedTaskOverride] = (0, import_react7.useState)(null);
|
|
1370
|
+
(0, import_react7.useEffect)(() => {
|
|
1371
|
+
const result = validateDependencies(tasks);
|
|
1372
|
+
setValidationResult(result);
|
|
1373
|
+
onValidateDependencies?.(result);
|
|
1374
|
+
}, [tasks, onValidateDependencies]);
|
|
1375
|
+
const handleTaskChange = (0, import_react7.useCallback)((updatedTask) => {
|
|
918
1376
|
onChange?.(
|
|
919
1377
|
(currentTasks) => currentTasks.map(
|
|
920
1378
|
(t) => t.id === updatedTask.id ? updatedTask : t
|
|
921
1379
|
)
|
|
922
1380
|
);
|
|
923
1381
|
}, [onChange]);
|
|
924
|
-
const
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
1382
|
+
const dependencyOverrides = (0, import_react7.useMemo)(() => {
|
|
1383
|
+
const map = new Map(cascadeOverrides);
|
|
1384
|
+
if (draggedTaskOverride) {
|
|
1385
|
+
map.set(draggedTaskOverride.taskId, {
|
|
1386
|
+
left: draggedTaskOverride.left,
|
|
1387
|
+
width: draggedTaskOverride.width
|
|
1388
|
+
});
|
|
929
1389
|
}
|
|
1390
|
+
return map;
|
|
1391
|
+
}, [cascadeOverrides, draggedTaskOverride]);
|
|
1392
|
+
const handleCascadeProgress = (0, import_react7.useCallback)((overrides) => {
|
|
1393
|
+
setCascadeOverrides(new Map(overrides));
|
|
930
1394
|
}, []);
|
|
931
|
-
const
|
|
932
|
-
|
|
1395
|
+
const handleCascade = (0, import_react7.useCallback)((cascadedTasks) => {
|
|
1396
|
+
onChange?.((currentTasks) => {
|
|
1397
|
+
const cascadeMap = new Map(cascadedTasks.map((t) => [t.id, t]));
|
|
1398
|
+
return currentTasks.map((t) => cascadeMap.get(t.id) ?? t);
|
|
1399
|
+
});
|
|
1400
|
+
onCascade?.(cascadedTasks);
|
|
1401
|
+
}, [onChange, onCascade]);
|
|
1402
|
+
const panStateRef = (0, import_react7.useRef)(null);
|
|
1403
|
+
const handlePanStart = (0, import_react7.useCallback)((e) => {
|
|
933
1404
|
if (e.button !== 0) return;
|
|
934
1405
|
const target = e.target;
|
|
935
1406
|
if (target.closest("[data-taskbar]")) return;
|
|
@@ -945,7 +1416,7 @@ var GanttChart = ({
|
|
|
945
1416
|
container.style.cursor = "grabbing";
|
|
946
1417
|
e.preventDefault();
|
|
947
1418
|
}, []);
|
|
948
|
-
(0,
|
|
1419
|
+
(0, import_react7.useEffect)(() => {
|
|
949
1420
|
const handlePanMove = (e) => {
|
|
950
1421
|
const pan = panStateRef.current;
|
|
951
1422
|
if (!pan?.active) return;
|
|
@@ -967,7 +1438,7 @@ var GanttChart = ({
|
|
|
967
1438
|
window.removeEventListener("mouseup", handlePanEnd);
|
|
968
1439
|
};
|
|
969
1440
|
}, []);
|
|
970
|
-
return /* @__PURE__ */ (0,
|
|
1441
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "gantt-container", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
|
|
971
1442
|
"div",
|
|
972
1443
|
{
|
|
973
1444
|
ref: scrollContainerRef,
|
|
@@ -975,7 +1446,7 @@ var GanttChart = ({
|
|
|
975
1446
|
style: { height: `${containerHeight}px`, cursor: "grab" },
|
|
976
1447
|
onMouseDown: handlePanStart,
|
|
977
1448
|
children: [
|
|
978
|
-
/* @__PURE__ */ (0,
|
|
1449
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "gantt-stickyHeader", style: { width: `${gridWidth}px` }, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
979
1450
|
TimeScaleHeader_default,
|
|
980
1451
|
{
|
|
981
1452
|
days: dateRange,
|
|
@@ -983,7 +1454,7 @@ var GanttChart = ({
|
|
|
983
1454
|
headerHeight
|
|
984
1455
|
}
|
|
985
1456
|
) }),
|
|
986
|
-
/* @__PURE__ */ (0,
|
|
1457
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
|
|
987
1458
|
"div",
|
|
988
1459
|
{
|
|
989
1460
|
className: "gantt-taskArea",
|
|
@@ -992,7 +1463,7 @@ var GanttChart = ({
|
|
|
992
1463
|
width: `${gridWidth}px`
|
|
993
1464
|
},
|
|
994
1465
|
children: [
|
|
995
|
-
/* @__PURE__ */ (0,
|
|
1466
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
996
1467
|
GridBackground_default,
|
|
997
1468
|
{
|
|
998
1469
|
dateRange,
|
|
@@ -1000,8 +1471,19 @@ var GanttChart = ({
|
|
|
1000
1471
|
totalHeight: totalGridHeight
|
|
1001
1472
|
}
|
|
1002
1473
|
),
|
|
1003
|
-
todayInRange && /* @__PURE__ */ (0,
|
|
1004
|
-
|
|
1474
|
+
todayInRange && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(TodayIndicator_default, { monthStart, dayWidth }),
|
|
1475
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1476
|
+
DependencyLines_default,
|
|
1477
|
+
{
|
|
1478
|
+
tasks,
|
|
1479
|
+
monthStart,
|
|
1480
|
+
dayWidth,
|
|
1481
|
+
rowHeight,
|
|
1482
|
+
gridWidth,
|
|
1483
|
+
dragOverrides: dependencyOverrides
|
|
1484
|
+
}
|
|
1485
|
+
),
|
|
1486
|
+
dragGuideLines && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1005
1487
|
DragGuideLines_default,
|
|
1006
1488
|
{
|
|
1007
1489
|
isDragging: dragGuideLines.isDragging,
|
|
@@ -1011,7 +1493,7 @@ var GanttChart = ({
|
|
|
1011
1493
|
totalHeight: totalGridHeight
|
|
1012
1494
|
}
|
|
1013
1495
|
),
|
|
1014
|
-
tasks.map((task) => /* @__PURE__ */ (0,
|
|
1496
|
+
tasks.map((task, index) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1015
1497
|
TaskRow_default,
|
|
1016
1498
|
{
|
|
1017
1499
|
task,
|
|
@@ -1019,7 +1501,22 @@ var GanttChart = ({
|
|
|
1019
1501
|
dayWidth,
|
|
1020
1502
|
rowHeight,
|
|
1021
1503
|
onChange: handleTaskChange,
|
|
1022
|
-
onDragStateChange:
|
|
1504
|
+
onDragStateChange: (state) => {
|
|
1505
|
+
if (state.isDragging) {
|
|
1506
|
+
setDragGuideLines(state);
|
|
1507
|
+
setDraggedTaskOverride({ taskId: task.id, left: state.left, width: state.width });
|
|
1508
|
+
} else {
|
|
1509
|
+
setDragGuideLines(null);
|
|
1510
|
+
setDraggedTaskOverride(null);
|
|
1511
|
+
}
|
|
1512
|
+
},
|
|
1513
|
+
rowIndex: index,
|
|
1514
|
+
allTasks: tasks,
|
|
1515
|
+
enableAutoSchedule: enableAutoSchedule ?? false,
|
|
1516
|
+
disableConstraints: disableConstraints ?? false,
|
|
1517
|
+
overridePosition: cascadeOverrides.get(task.id),
|
|
1518
|
+
onCascadeProgress: handleCascadeProgress,
|
|
1519
|
+
onCascade: handleCascade
|
|
1023
1520
|
},
|
|
1024
1521
|
task.id
|
|
1025
1522
|
))
|
|
@@ -1038,21 +1535,29 @@ var GanttChart = ({
|
|
|
1038
1535
|
TaskRow,
|
|
1039
1536
|
TimeScaleHeader,
|
|
1040
1537
|
TodayIndicator,
|
|
1538
|
+
buildAdjacencyList,
|
|
1539
|
+
calculateBezierPath,
|
|
1041
1540
|
calculateGridLines,
|
|
1042
1541
|
calculateGridWidth,
|
|
1542
|
+
calculateOrthogonalPath,
|
|
1543
|
+
calculateSuccessorDate,
|
|
1043
1544
|
calculateTaskBar,
|
|
1044
1545
|
calculateWeekendBlocks,
|
|
1546
|
+
detectCycles,
|
|
1045
1547
|
detectEdgeZone,
|
|
1046
1548
|
formatDateLabel,
|
|
1549
|
+
getAllDependencyEdges,
|
|
1047
1550
|
getCursorForPosition,
|
|
1048
1551
|
getDayOffset,
|
|
1049
1552
|
getMonthDays,
|
|
1050
1553
|
getMonthSpans,
|
|
1051
1554
|
getMultiMonthDays,
|
|
1555
|
+
getSuccessorChain,
|
|
1052
1556
|
isToday,
|
|
1053
1557
|
isWeekend,
|
|
1054
1558
|
parseUTCDate,
|
|
1055
1559
|
pixelsToDate,
|
|
1056
|
-
useTaskDrag
|
|
1560
|
+
useTaskDrag,
|
|
1561
|
+
validateDependencies
|
|
1057
1562
|
});
|
|
1058
1563
|
//# sourceMappingURL=index.js.map
|