gantt-lib 0.74.0 → 0.75.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 +49 -0
- package/dist/core/scheduling/index.d.mts +2 -1
- package/dist/core/scheduling/index.d.ts +2 -1
- package/dist/{index-BLFB_fez.d.mts → index-B2Hmdkey.d.mts} +42 -1
- package/dist/{index-BLFB_fez.d.ts → index-B2Hmdkey.d.ts} +42 -1
- package/dist/index.css.map +1 -1
- package/dist/index.d.mts +50 -5
- package/dist/index.d.ts +50 -5
- package/dist/index.js +602 -69
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +598 -67
- package/dist/index.mjs.map +1 -1
- package/dist/styles.css +120 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -515,6 +515,7 @@ __export(index_exports, {
|
|
|
515
515
|
Popover: () => Popover,
|
|
516
516
|
PopoverContent: () => PopoverContent,
|
|
517
517
|
PopoverTrigger: () => PopoverTrigger,
|
|
518
|
+
ResourceTimelineChart: () => ResourceTimelineChart,
|
|
518
519
|
TaskList: () => TaskList,
|
|
519
520
|
TaskRow: () => TaskRow_default,
|
|
520
521
|
TimeScaleHeader: () => TimeScaleHeader_default,
|
|
@@ -578,6 +579,7 @@ __export(index_exports, {
|
|
|
578
579
|
isTaskParent: () => isTaskParent,
|
|
579
580
|
isToday: () => isToday,
|
|
580
581
|
isWeekend: () => isWeekend,
|
|
582
|
+
layoutResourceTimelineItems: () => layoutResourceTimelineItems,
|
|
581
583
|
moveTaskRange: () => moveTaskRange,
|
|
582
584
|
moveTaskWithCascade: () => moveTaskWithCascade,
|
|
583
585
|
nameContains: () => nameContains,
|
|
@@ -610,7 +612,7 @@ __export(index_exports, {
|
|
|
610
612
|
module.exports = __toCommonJS(index_exports);
|
|
611
613
|
|
|
612
614
|
// src/components/GanttChart/GanttChart.tsx
|
|
613
|
-
var
|
|
615
|
+
var import_react15 = require("react");
|
|
614
616
|
init_dateUtils();
|
|
615
617
|
|
|
616
618
|
// src/core/scheduling/index.ts
|
|
@@ -7357,6 +7359,522 @@ var TaskList = ({
|
|
|
7357
7359
|
);
|
|
7358
7360
|
};
|
|
7359
7361
|
|
|
7362
|
+
// src/components/ResourceTimelineChart/ResourceTimelineChart.tsx
|
|
7363
|
+
var import_react14 = require("react");
|
|
7364
|
+
init_dateUtils();
|
|
7365
|
+
|
|
7366
|
+
// src/utils/resourceTimelineLayout.ts
|
|
7367
|
+
init_dateUtils();
|
|
7368
|
+
var isInvalidDate = (date) => Number.isNaN(date.getTime());
|
|
7369
|
+
var getUTCDayNumber = (date) => {
|
|
7370
|
+
return Math.floor(Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate()) / 864e5);
|
|
7371
|
+
};
|
|
7372
|
+
var compareParsedItems = (a, b) => {
|
|
7373
|
+
const startDiff = getUTCDayNumber(a.startDate) - getUTCDayNumber(b.startDate);
|
|
7374
|
+
if (startDiff !== 0) {
|
|
7375
|
+
return startDiff;
|
|
7376
|
+
}
|
|
7377
|
+
const endDiff = getUTCDayNumber(a.endDate) - getUTCDayNumber(b.endDate);
|
|
7378
|
+
if (endDiff !== 0) {
|
|
7379
|
+
return endDiff;
|
|
7380
|
+
}
|
|
7381
|
+
return a.item.id.localeCompare(b.item.id);
|
|
7382
|
+
};
|
|
7383
|
+
var layoutResourceTimelineItems = (resources, options) => {
|
|
7384
|
+
const rows = [];
|
|
7385
|
+
const items = [];
|
|
7386
|
+
const diagnostics = [];
|
|
7387
|
+
let currentTop = 0;
|
|
7388
|
+
for (const resource of resources) {
|
|
7389
|
+
const parsedItems = [];
|
|
7390
|
+
for (const item of resource.items) {
|
|
7391
|
+
try {
|
|
7392
|
+
const startDate = parseUTCDate(item.startDate);
|
|
7393
|
+
const endDate = parseUTCDate(item.endDate);
|
|
7394
|
+
if (isInvalidDate(startDate) || isInvalidDate(endDate)) {
|
|
7395
|
+
throw new Error("Invalid date");
|
|
7396
|
+
}
|
|
7397
|
+
parsedItems.push({ item, startDate, endDate });
|
|
7398
|
+
} catch {
|
|
7399
|
+
diagnostics.push({
|
|
7400
|
+
itemId: item.id,
|
|
7401
|
+
resourceId: resource.id,
|
|
7402
|
+
reason: "invalid-date"
|
|
7403
|
+
});
|
|
7404
|
+
}
|
|
7405
|
+
}
|
|
7406
|
+
parsedItems.sort(compareParsedItems);
|
|
7407
|
+
const laneEndDays = [];
|
|
7408
|
+
const laidOutItems = [];
|
|
7409
|
+
for (const parsed of parsedItems) {
|
|
7410
|
+
const startDay = getUTCDayNumber(parsed.startDate);
|
|
7411
|
+
const endDay = getUTCDayNumber(parsed.endDate);
|
|
7412
|
+
let laneIndex = laneEndDays.findIndex((laneEndDay) => laneEndDay < startDay);
|
|
7413
|
+
if (laneIndex === -1) {
|
|
7414
|
+
laneIndex = laneEndDays.length;
|
|
7415
|
+
laneEndDays.push(endDay);
|
|
7416
|
+
} else {
|
|
7417
|
+
laneEndDays[laneIndex] = endDay;
|
|
7418
|
+
}
|
|
7419
|
+
const { left, width } = calculateTaskBar(parsed.startDate, parsed.endDate, options.monthStart, options.dayWidth);
|
|
7420
|
+
laidOutItems.push({
|
|
7421
|
+
item: parsed.item,
|
|
7422
|
+
itemId: parsed.item.id,
|
|
7423
|
+
resourceId: resource.id,
|
|
7424
|
+
laneIndex,
|
|
7425
|
+
left,
|
|
7426
|
+
width,
|
|
7427
|
+
resourceRowTop: currentTop,
|
|
7428
|
+
resourceRowHeight: 0,
|
|
7429
|
+
top: currentTop + laneIndex * options.laneHeight,
|
|
7430
|
+
height: options.laneHeight,
|
|
7431
|
+
startDate: parsed.startDate,
|
|
7432
|
+
endDate: parsed.endDate
|
|
7433
|
+
});
|
|
7434
|
+
}
|
|
7435
|
+
const laneCount = Math.max(1, laneEndDays.length);
|
|
7436
|
+
const resourceRowHeight = laneCount * options.laneHeight;
|
|
7437
|
+
const row = {
|
|
7438
|
+
resource,
|
|
7439
|
+
resourceId: resource.id,
|
|
7440
|
+
laneCount,
|
|
7441
|
+
resourceRowTop: currentTop,
|
|
7442
|
+
resourceRowHeight
|
|
7443
|
+
};
|
|
7444
|
+
rows.push(row);
|
|
7445
|
+
items.push(...laidOutItems.map((item) => ({
|
|
7446
|
+
...item,
|
|
7447
|
+
resourceRowHeight
|
|
7448
|
+
})));
|
|
7449
|
+
currentTop += resourceRowHeight;
|
|
7450
|
+
}
|
|
7451
|
+
return {
|
|
7452
|
+
rows,
|
|
7453
|
+
items,
|
|
7454
|
+
diagnostics,
|
|
7455
|
+
totalHeight: currentTop
|
|
7456
|
+
};
|
|
7457
|
+
};
|
|
7458
|
+
|
|
7459
|
+
// src/hooks/useResourceItemDrag.ts
|
|
7460
|
+
var import_react13 = require("react");
|
|
7461
|
+
var snapToDay = (pixels, dayWidth) => {
|
|
7462
|
+
return Math.round(pixels / dayWidth) * dayWidth;
|
|
7463
|
+
};
|
|
7464
|
+
var addUTCDays = (date, days) => {
|
|
7465
|
+
return new Date(Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate() + days));
|
|
7466
|
+
};
|
|
7467
|
+
var resolveTargetResource = (rows, clientY, gridTop) => {
|
|
7468
|
+
const localY = clientY - gridTop;
|
|
7469
|
+
return rows.find(
|
|
7470
|
+
(row) => localY >= row.resourceRowTop && localY < row.resourceRowTop + row.resourceRowHeight
|
|
7471
|
+
)?.resource ?? null;
|
|
7472
|
+
};
|
|
7473
|
+
var useResourceItemDrag = ({
|
|
7474
|
+
dayWidth,
|
|
7475
|
+
rows,
|
|
7476
|
+
gridElementRef,
|
|
7477
|
+
readonly,
|
|
7478
|
+
disableResourceReassignment,
|
|
7479
|
+
onResourceItemMove
|
|
7480
|
+
}) => {
|
|
7481
|
+
const activeDragRef = (0, import_react13.useRef)(null);
|
|
7482
|
+
const rowsRef = (0, import_react13.useRef)(rows);
|
|
7483
|
+
const onResourceItemMoveRef = (0, import_react13.useRef)(onResourceItemMove);
|
|
7484
|
+
const rafRef = (0, import_react13.useRef)(null);
|
|
7485
|
+
const [preview, setPreview] = (0, import_react13.useState)(null);
|
|
7486
|
+
(0, import_react13.useEffect)(() => {
|
|
7487
|
+
rowsRef.current = rows;
|
|
7488
|
+
}, [rows]);
|
|
7489
|
+
(0, import_react13.useEffect)(() => {
|
|
7490
|
+
onResourceItemMoveRef.current = onResourceItemMove;
|
|
7491
|
+
}, [onResourceItemMove]);
|
|
7492
|
+
const clearRaf = (0, import_react13.useCallback)(() => {
|
|
7493
|
+
if (rafRef.current !== null) {
|
|
7494
|
+
cancelAnimationFrame(rafRef.current);
|
|
7495
|
+
rafRef.current = null;
|
|
7496
|
+
}
|
|
7497
|
+
}, []);
|
|
7498
|
+
const cancelDrag2 = (0, import_react13.useCallback)(() => {
|
|
7499
|
+
clearRaf();
|
|
7500
|
+
activeDragRef.current = null;
|
|
7501
|
+
setPreview(null);
|
|
7502
|
+
}, [clearRaf]);
|
|
7503
|
+
(0, import_react13.useEffect)(() => {
|
|
7504
|
+
const handleMouseMove = (event) => {
|
|
7505
|
+
const activeDrag = activeDragRef.current;
|
|
7506
|
+
if (!activeDrag || rafRef.current !== null) {
|
|
7507
|
+
return;
|
|
7508
|
+
}
|
|
7509
|
+
rafRef.current = requestAnimationFrame(() => {
|
|
7510
|
+
rafRef.current = null;
|
|
7511
|
+
const latestDrag = activeDragRef.current;
|
|
7512
|
+
if (!latestDrag) {
|
|
7513
|
+
return;
|
|
7514
|
+
}
|
|
7515
|
+
const nextLeft = latestDrag.initialLeft + snapToDay(event.clientX - latestDrag.startX, latestDrag.dayWidth);
|
|
7516
|
+
const nextTop = disableResourceReassignment ? latestDrag.initialTop : latestDrag.initialTop + (event.clientY - latestDrag.startY);
|
|
7517
|
+
latestDrag.currentLeft = nextLeft;
|
|
7518
|
+
latestDrag.currentTop = nextTop;
|
|
7519
|
+
setPreview({
|
|
7520
|
+
itemId: latestDrag.itemId,
|
|
7521
|
+
left: nextLeft,
|
|
7522
|
+
top: nextTop
|
|
7523
|
+
});
|
|
7524
|
+
});
|
|
7525
|
+
};
|
|
7526
|
+
const handleMouseUp = (event) => {
|
|
7527
|
+
const activeDrag = activeDragRef.current;
|
|
7528
|
+
if (!activeDrag) {
|
|
7529
|
+
return;
|
|
7530
|
+
}
|
|
7531
|
+
clearRaf();
|
|
7532
|
+
activeDragRef.current = null;
|
|
7533
|
+
setPreview(null);
|
|
7534
|
+
const gridTop = gridElementRef?.current?.getBoundingClientRect().top ?? 0;
|
|
7535
|
+
const targetResource = disableResourceReassignment ? rowsRef.current.find((row) => row.resourceId === activeDrag.fromResourceId)?.resource ?? null : resolveTargetResource(rowsRef.current, event.clientY, gridTop);
|
|
7536
|
+
if (!targetResource) {
|
|
7537
|
+
return;
|
|
7538
|
+
}
|
|
7539
|
+
const dayDelta = Math.round((activeDrag.currentLeft - activeDrag.initialLeft) / activeDrag.dayWidth);
|
|
7540
|
+
onResourceItemMoveRef.current?.({
|
|
7541
|
+
item: activeDrag.item,
|
|
7542
|
+
itemId: activeDrag.itemId,
|
|
7543
|
+
fromResourceId: activeDrag.fromResourceId,
|
|
7544
|
+
toResourceId: targetResource.id,
|
|
7545
|
+
startDate: addUTCDays(activeDrag.startDate, dayDelta),
|
|
7546
|
+
endDate: addUTCDays(activeDrag.endDate, dayDelta)
|
|
7547
|
+
});
|
|
7548
|
+
};
|
|
7549
|
+
window.addEventListener("mousemove", handleMouseMove);
|
|
7550
|
+
window.addEventListener("mouseup", handleMouseUp);
|
|
7551
|
+
return () => {
|
|
7552
|
+
window.removeEventListener("mousemove", handleMouseMove);
|
|
7553
|
+
window.removeEventListener("mouseup", handleMouseUp);
|
|
7554
|
+
cancelDrag2();
|
|
7555
|
+
};
|
|
7556
|
+
}, [cancelDrag2, clearRaf, disableResourceReassignment, gridElementRef]);
|
|
7557
|
+
const startDrag = (0, import_react13.useCallback)((event, layoutItem) => {
|
|
7558
|
+
if (readonly || layoutItem.item.locked || event.button !== 0) {
|
|
7559
|
+
return;
|
|
7560
|
+
}
|
|
7561
|
+
event.preventDefault();
|
|
7562
|
+
activeDragRef.current = {
|
|
7563
|
+
item: layoutItem.item,
|
|
7564
|
+
itemId: layoutItem.itemId,
|
|
7565
|
+
fromResourceId: layoutItem.resourceId,
|
|
7566
|
+
startX: event.clientX,
|
|
7567
|
+
startY: event.clientY,
|
|
7568
|
+
initialLeft: layoutItem.left,
|
|
7569
|
+
initialTop: layoutItem.top,
|
|
7570
|
+
currentLeft: layoutItem.left,
|
|
7571
|
+
currentTop: layoutItem.top,
|
|
7572
|
+
dayWidth,
|
|
7573
|
+
startDate: layoutItem.startDate,
|
|
7574
|
+
endDate: layoutItem.endDate
|
|
7575
|
+
};
|
|
7576
|
+
setPreview({
|
|
7577
|
+
itemId: layoutItem.itemId,
|
|
7578
|
+
left: layoutItem.left,
|
|
7579
|
+
top: layoutItem.top
|
|
7580
|
+
});
|
|
7581
|
+
}, [dayWidth, readonly]);
|
|
7582
|
+
return {
|
|
7583
|
+
preview,
|
|
7584
|
+
startDrag,
|
|
7585
|
+
cancelDrag: cancelDrag2
|
|
7586
|
+
};
|
|
7587
|
+
};
|
|
7588
|
+
|
|
7589
|
+
// src/components/ResourceTimelineChart/ResourceTimelineChart.tsx
|
|
7590
|
+
var import_jsx_runtime15 = require("react/jsx-runtime");
|
|
7591
|
+
var DEFAULT_DAY_WIDTH = 40;
|
|
7592
|
+
var DEFAULT_HEADER_HEIGHT = 40;
|
|
7593
|
+
var DEFAULT_LANE_HEIGHT = 40;
|
|
7594
|
+
var DEFAULT_ROW_HEADER_WIDTH = 240;
|
|
7595
|
+
var ITEM_OUTER_VERTICAL_INSET = 2;
|
|
7596
|
+
var ITEM_INNER_VERTICAL_INSET = 1;
|
|
7597
|
+
var ITEM_HORIZONTAL_INSET = 1;
|
|
7598
|
+
var isValidDate = (date) => !Number.isNaN(date.getTime());
|
|
7599
|
+
var getResourceTimelineDays = (items) => {
|
|
7600
|
+
if (items.length === 0) {
|
|
7601
|
+
return getMonthDays(/* @__PURE__ */ new Date());
|
|
7602
|
+
}
|
|
7603
|
+
let minDate = null;
|
|
7604
|
+
let maxDate = null;
|
|
7605
|
+
for (const item of items) {
|
|
7606
|
+
const startDate = parseUTCDate(item.startDate);
|
|
7607
|
+
const endDate = parseUTCDate(item.endDate);
|
|
7608
|
+
if (!minDate || startDate.getTime() < minDate.getTime()) {
|
|
7609
|
+
minDate = startDate;
|
|
7610
|
+
}
|
|
7611
|
+
if (!maxDate || endDate.getTime() > maxDate.getTime()) {
|
|
7612
|
+
maxDate = endDate;
|
|
7613
|
+
}
|
|
7614
|
+
}
|
|
7615
|
+
if (!minDate || !maxDate) {
|
|
7616
|
+
return getMonthDays(/* @__PURE__ */ new Date());
|
|
7617
|
+
}
|
|
7618
|
+
const startOfMonth2 = new Date(Date.UTC(minDate.getUTCFullYear(), minDate.getUTCMonth(), 1));
|
|
7619
|
+
const endOfMonth = new Date(Date.UTC(maxDate.getUTCFullYear(), maxDate.getUTCMonth() + 1, 0));
|
|
7620
|
+
const days = [];
|
|
7621
|
+
const current = new Date(startOfMonth2);
|
|
7622
|
+
while (current.getTime() <= endOfMonth.getTime()) {
|
|
7623
|
+
days.push(new Date(Date.UTC(current.getUTCFullYear(), current.getUTCMonth(), current.getUTCDate())));
|
|
7624
|
+
current.setUTCDate(current.getUTCDate() + 1);
|
|
7625
|
+
}
|
|
7626
|
+
return days;
|
|
7627
|
+
};
|
|
7628
|
+
var collectValidItems = (resources) => {
|
|
7629
|
+
return resources.flatMap(
|
|
7630
|
+
(resource) => resource.items.flatMap((item) => {
|
|
7631
|
+
try {
|
|
7632
|
+
const startDate = parseUTCDate(item.startDate);
|
|
7633
|
+
const endDate = parseUTCDate(item.endDate);
|
|
7634
|
+
if (!isValidDate(startDate) || !isValidDate(endDate)) {
|
|
7635
|
+
return [];
|
|
7636
|
+
}
|
|
7637
|
+
return [{ startDate, endDate }];
|
|
7638
|
+
} catch {
|
|
7639
|
+
return [];
|
|
7640
|
+
}
|
|
7641
|
+
})
|
|
7642
|
+
);
|
|
7643
|
+
};
|
|
7644
|
+
var getVisualItemGeometry = (geometry, laneIndex, laneCount) => {
|
|
7645
|
+
const topInset = laneIndex === 0 ? ITEM_OUTER_VERTICAL_INSET : ITEM_INNER_VERTICAL_INSET;
|
|
7646
|
+
const bottomInset = laneIndex === laneCount - 1 ? ITEM_OUTER_VERTICAL_INSET : ITEM_INNER_VERTICAL_INSET;
|
|
7647
|
+
return {
|
|
7648
|
+
left: geometry.left + ITEM_HORIZONTAL_INSET,
|
|
7649
|
+
top: geometry.top + topInset,
|
|
7650
|
+
width: Math.max(0, geometry.width - ITEM_HORIZONTAL_INSET * 2),
|
|
7651
|
+
height: Math.max(0, geometry.height - topInset - bottomInset)
|
|
7652
|
+
};
|
|
7653
|
+
};
|
|
7654
|
+
function ResourceTimelineChart({
|
|
7655
|
+
resources,
|
|
7656
|
+
dayWidth = DEFAULT_DAY_WIDTH,
|
|
7657
|
+
rowHeaderWidth = DEFAULT_ROW_HEADER_WIDTH,
|
|
7658
|
+
laneHeight = DEFAULT_LANE_HEIGHT,
|
|
7659
|
+
headerHeight = DEFAULT_HEADER_HEIGHT,
|
|
7660
|
+
readonly,
|
|
7661
|
+
disableResourceReassignment,
|
|
7662
|
+
renderItem,
|
|
7663
|
+
getItemClassName,
|
|
7664
|
+
onResourceItemMove
|
|
7665
|
+
}) {
|
|
7666
|
+
const scrollContainerRef = (0, import_react14.useRef)(null);
|
|
7667
|
+
const gridRef = (0, import_react14.useRef)(null);
|
|
7668
|
+
const panStateRef = (0, import_react14.useRef)(null);
|
|
7669
|
+
const validItems = (0, import_react14.useMemo)(() => collectValidItems(resources), [resources]);
|
|
7670
|
+
const dateRange = (0, import_react14.useMemo)(() => {
|
|
7671
|
+
return getResourceTimelineDays(validItems);
|
|
7672
|
+
}, [validItems]);
|
|
7673
|
+
const monthStart = (0, import_react14.useMemo)(() => {
|
|
7674
|
+
const firstDay = dateRange[0] ?? /* @__PURE__ */ new Date();
|
|
7675
|
+
return new Date(Date.UTC(firstDay.getUTCFullYear(), firstDay.getUTCMonth(), 1));
|
|
7676
|
+
}, [dateRange]);
|
|
7677
|
+
const gridWidth = (0, import_react14.useMemo)(() => Math.round(dateRange.length * dayWidth), [dateRange.length, dayWidth]);
|
|
7678
|
+
const layout = (0, import_react14.useMemo)(
|
|
7679
|
+
() => layoutResourceTimelineItems(resources, { monthStart, dayWidth, laneHeight }),
|
|
7680
|
+
[resources, monthStart, dayWidth, laneHeight]
|
|
7681
|
+
);
|
|
7682
|
+
const todayInRange = (0, import_react14.useMemo)(() => {
|
|
7683
|
+
const now = /* @__PURE__ */ new Date();
|
|
7684
|
+
const today = new Date(Date.UTC(now.getFullYear(), now.getMonth(), now.getDate()));
|
|
7685
|
+
return dateRange.some((day) => day.getTime() === today.getTime());
|
|
7686
|
+
}, [dateRange]);
|
|
7687
|
+
const itemsByResourceId = (0, import_react14.useMemo)(() => {
|
|
7688
|
+
const map = /* @__PURE__ */ new Map();
|
|
7689
|
+
for (const item of layout.items) {
|
|
7690
|
+
const next = map.get(item.resourceId) ?? [];
|
|
7691
|
+
next.push(item);
|
|
7692
|
+
map.set(item.resourceId, next);
|
|
7693
|
+
}
|
|
7694
|
+
return map;
|
|
7695
|
+
}, [layout.items]);
|
|
7696
|
+
const { preview, startDrag } = useResourceItemDrag({
|
|
7697
|
+
dayWidth,
|
|
7698
|
+
rows: layout.rows,
|
|
7699
|
+
gridElementRef: gridRef,
|
|
7700
|
+
readonly,
|
|
7701
|
+
disableResourceReassignment,
|
|
7702
|
+
onResourceItemMove
|
|
7703
|
+
});
|
|
7704
|
+
const handlePanStart = (0, import_react14.useCallback)((event) => {
|
|
7705
|
+
if (event.button !== 0) {
|
|
7706
|
+
return;
|
|
7707
|
+
}
|
|
7708
|
+
const target = event.target;
|
|
7709
|
+
if (target.closest("[data-resource-item-id]")) {
|
|
7710
|
+
return;
|
|
7711
|
+
}
|
|
7712
|
+
if (target.closest("input, button, textarea, [contenteditable]")) {
|
|
7713
|
+
return;
|
|
7714
|
+
}
|
|
7715
|
+
const container = scrollContainerRef.current;
|
|
7716
|
+
if (!container) {
|
|
7717
|
+
return;
|
|
7718
|
+
}
|
|
7719
|
+
panStateRef.current = {
|
|
7720
|
+
active: true,
|
|
7721
|
+
startX: event.clientX,
|
|
7722
|
+
startY: event.clientY,
|
|
7723
|
+
scrollX: container.scrollLeft,
|
|
7724
|
+
scrollY: container.scrollTop
|
|
7725
|
+
};
|
|
7726
|
+
if (document.activeElement instanceof HTMLElement) {
|
|
7727
|
+
document.activeElement.blur();
|
|
7728
|
+
}
|
|
7729
|
+
container.style.cursor = "grabbing";
|
|
7730
|
+
event.preventDefault();
|
|
7731
|
+
}, []);
|
|
7732
|
+
(0, import_react14.useEffect)(() => {
|
|
7733
|
+
const handlePanMove = (event) => {
|
|
7734
|
+
const pan = panStateRef.current;
|
|
7735
|
+
const container = scrollContainerRef.current;
|
|
7736
|
+
if (!pan?.active || !container) {
|
|
7737
|
+
return;
|
|
7738
|
+
}
|
|
7739
|
+
container.scrollLeft = pan.scrollX - (event.clientX - pan.startX);
|
|
7740
|
+
container.scrollTop = pan.scrollY - (event.clientY - pan.startY);
|
|
7741
|
+
};
|
|
7742
|
+
const handlePanEnd = () => {
|
|
7743
|
+
if (!panStateRef.current?.active) {
|
|
7744
|
+
return;
|
|
7745
|
+
}
|
|
7746
|
+
panStateRef.current = null;
|
|
7747
|
+
const container = scrollContainerRef.current;
|
|
7748
|
+
if (container) {
|
|
7749
|
+
container.style.cursor = "";
|
|
7750
|
+
}
|
|
7751
|
+
};
|
|
7752
|
+
window.addEventListener("mousemove", handlePanMove);
|
|
7753
|
+
window.addEventListener("mouseup", handlePanEnd);
|
|
7754
|
+
return () => {
|
|
7755
|
+
window.removeEventListener("mousemove", handlePanMove);
|
|
7756
|
+
window.removeEventListener("mouseup", handlePanEnd);
|
|
7757
|
+
};
|
|
7758
|
+
}, []);
|
|
7759
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: "gantt-container gantt-resourceTimeline", children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
7760
|
+
"div",
|
|
7761
|
+
{
|
|
7762
|
+
ref: scrollContainerRef,
|
|
7763
|
+
className: "gantt-resourceTimeline-scrollContainer",
|
|
7764
|
+
style: { cursor: "grab" },
|
|
7765
|
+
onMouseDown: handlePanStart,
|
|
7766
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "gantt-resourceTimeline-scrollContent", children: [
|
|
7767
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
|
|
7768
|
+
"div",
|
|
7769
|
+
{
|
|
7770
|
+
className: "gantt-resourceTimeline-resourceColumn",
|
|
7771
|
+
style: { width: `${rowHeaderWidth}px`, minWidth: `${rowHeaderWidth}px` },
|
|
7772
|
+
children: [
|
|
7773
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
7774
|
+
"div",
|
|
7775
|
+
{
|
|
7776
|
+
className: "gantt-resourceTimeline-corner",
|
|
7777
|
+
style: { height: `${headerHeight}px` }
|
|
7778
|
+
}
|
|
7779
|
+
),
|
|
7780
|
+
layout.rows.map((row) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
7781
|
+
"div",
|
|
7782
|
+
{
|
|
7783
|
+
className: "gantt-resourceTimeline-resourceHeader",
|
|
7784
|
+
"data-resource-row-id": row.resourceId,
|
|
7785
|
+
style: { height: `${row.resourceRowHeight}px` },
|
|
7786
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "gantt-resourceTimeline-resourceName", children: row.resource.name })
|
|
7787
|
+
},
|
|
7788
|
+
row.resourceId
|
|
7789
|
+
))
|
|
7790
|
+
]
|
|
7791
|
+
}
|
|
7792
|
+
),
|
|
7793
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
|
|
7794
|
+
"div",
|
|
7795
|
+
{
|
|
7796
|
+
className: "gantt-resourceTimeline-chartSurface",
|
|
7797
|
+
style: { minWidth: `${gridWidth}px` },
|
|
7798
|
+
children: [
|
|
7799
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: "gantt-resourceTimeline-stickyHeader", style: { width: `${gridWidth}px` }, children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(TimeScaleHeader_default, { days: dateRange, dayWidth, headerHeight }) }),
|
|
7800
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
|
|
7801
|
+
"div",
|
|
7802
|
+
{
|
|
7803
|
+
ref: gridRef,
|
|
7804
|
+
className: "gantt-resourceTimeline-grid",
|
|
7805
|
+
style: { width: `${gridWidth}px`, height: `${layout.totalHeight}px` },
|
|
7806
|
+
children: [
|
|
7807
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(GridBackground_default, { dateRange, dayWidth, totalHeight: layout.totalHeight }),
|
|
7808
|
+
todayInRange && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(TodayIndicator_default, { monthStart, dayWidth }),
|
|
7809
|
+
layout.rows.map((row) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
7810
|
+
"div",
|
|
7811
|
+
{
|
|
7812
|
+
className: "gantt-resourceTimeline-row",
|
|
7813
|
+
"data-resource-row-id": row.resourceId,
|
|
7814
|
+
style: {
|
|
7815
|
+
top: `${row.resourceRowTop}px`,
|
|
7816
|
+
height: `${row.resourceRowHeight}px`
|
|
7817
|
+
}
|
|
7818
|
+
},
|
|
7819
|
+
row.resourceId
|
|
7820
|
+
)),
|
|
7821
|
+
Array.from(itemsByResourceId.values()).flatMap(
|
|
7822
|
+
(resourceItems) => resourceItems.map((layoutItem) => {
|
|
7823
|
+
const customClassName = getItemClassName?.(layoutItem.item);
|
|
7824
|
+
const className = [
|
|
7825
|
+
"gantt-resourceTimeline-item",
|
|
7826
|
+
preview?.itemId === layoutItem.itemId && "gantt-resourceTimeline-itemDragging",
|
|
7827
|
+
(readonly || layoutItem.item.locked) && "gantt-resourceTimeline-itemDisabled",
|
|
7828
|
+
customClassName
|
|
7829
|
+
].filter(Boolean).join(" ");
|
|
7830
|
+
const laneCount = Math.max(1, Math.round(layoutItem.resourceRowHeight / layoutItem.height));
|
|
7831
|
+
const previewStyle = preview?.itemId === layoutItem.itemId ? getVisualItemGeometry({
|
|
7832
|
+
left: preview.left,
|
|
7833
|
+
top: preview.top,
|
|
7834
|
+
width: layoutItem.width,
|
|
7835
|
+
height: layoutItem.height
|
|
7836
|
+
}, layoutItem.laneIndex, laneCount) : void 0;
|
|
7837
|
+
const itemGeometry = getVisualItemGeometry({
|
|
7838
|
+
left: layoutItem.left,
|
|
7839
|
+
top: layoutItem.top,
|
|
7840
|
+
width: layoutItem.width,
|
|
7841
|
+
height: layoutItem.height
|
|
7842
|
+
}, layoutItem.laneIndex, laneCount);
|
|
7843
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
7844
|
+
"div",
|
|
7845
|
+
{
|
|
7846
|
+
className,
|
|
7847
|
+
"data-resource-item-id": layoutItem.itemId,
|
|
7848
|
+
onMouseDown: (event) => startDrag(event, layoutItem),
|
|
7849
|
+
style: {
|
|
7850
|
+
left: `${itemGeometry.left}px`,
|
|
7851
|
+
top: `${itemGeometry.top}px`,
|
|
7852
|
+
...previewStyle,
|
|
7853
|
+
width: `${itemGeometry.width}px`,
|
|
7854
|
+
height: `${itemGeometry.height}px`,
|
|
7855
|
+
backgroundColor: layoutItem.item.color ?? "var(--gantt-task-bar-default-color, #3b82f6)"
|
|
7856
|
+
},
|
|
7857
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: "gantt-resourceTimeline-itemInner", children: renderItem ? renderItem(layoutItem.item) : /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_jsx_runtime15.Fragment, { children: [
|
|
7858
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "gantt-resourceTimeline-itemTitle", children: layoutItem.item.title }),
|
|
7859
|
+
layoutItem.item.subtitle && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "gantt-resourceTimeline-itemSubtitle", children: layoutItem.item.subtitle }),
|
|
7860
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "gantt-resourceTimeline-itemDates", children: formatDateRangeLabel(layoutItem.startDate, layoutItem.endDate) })
|
|
7861
|
+
] }) })
|
|
7862
|
+
},
|
|
7863
|
+
layoutItem.itemId
|
|
7864
|
+
);
|
|
7865
|
+
})
|
|
7866
|
+
)
|
|
7867
|
+
]
|
|
7868
|
+
}
|
|
7869
|
+
)
|
|
7870
|
+
]
|
|
7871
|
+
}
|
|
7872
|
+
)
|
|
7873
|
+
] })
|
|
7874
|
+
}
|
|
7875
|
+
) });
|
|
7876
|
+
}
|
|
7877
|
+
|
|
7360
7878
|
// src/components/GanttChart/print.ts
|
|
7361
7879
|
function getPrintDocumentTitle({
|
|
7362
7880
|
header,
|
|
@@ -7695,9 +8213,21 @@ async function printGanttChart({
|
|
|
7695
8213
|
}
|
|
7696
8214
|
|
|
7697
8215
|
// src/components/GanttChart/GanttChart.tsx
|
|
7698
|
-
var
|
|
8216
|
+
var import_jsx_runtime16 = require("react/jsx-runtime");
|
|
7699
8217
|
var SCROLL_TO_ROW_CONTEXT_ROWS = 2;
|
|
7700
8218
|
function GanttChartInner(props, ref) {
|
|
8219
|
+
if (props.mode === "resource-planner") {
|
|
8220
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(ResourceTimelineChart, { ...props });
|
|
8221
|
+
}
|
|
8222
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
8223
|
+
TaskGanttChart,
|
|
8224
|
+
{
|
|
8225
|
+
...props,
|
|
8226
|
+
ref
|
|
8227
|
+
}
|
|
8228
|
+
);
|
|
8229
|
+
}
|
|
8230
|
+
function TaskGanttChartInner(props, ref) {
|
|
7701
8231
|
const {
|
|
7702
8232
|
tasks,
|
|
7703
8233
|
dayWidth = 40,
|
|
@@ -7737,28 +8267,28 @@ function GanttChartInner(props, ref) {
|
|
|
7737
8267
|
additionalColumns,
|
|
7738
8268
|
taskListMenuCommands
|
|
7739
8269
|
} = props;
|
|
7740
|
-
const containerRef = (0,
|
|
7741
|
-
const scrollContainerRef = (0,
|
|
7742
|
-
const scrollContentRef = (0,
|
|
7743
|
-
const [selectedTaskId, setSelectedTaskId] = (0,
|
|
7744
|
-
const [taskListHasRightShadow, setTaskListHasRightShadow] = (0,
|
|
7745
|
-
const [selectedChip, setSelectedChip] = (0,
|
|
7746
|
-
const [internalCollapsedParentIds, setInternalCollapsedParentIds] = (0,
|
|
8270
|
+
const containerRef = (0, import_react15.useRef)(null);
|
|
8271
|
+
const scrollContainerRef = (0, import_react15.useRef)(null);
|
|
8272
|
+
const scrollContentRef = (0, import_react15.useRef)(null);
|
|
8273
|
+
const [selectedTaskId, setSelectedTaskId] = (0, import_react15.useState)(null);
|
|
8274
|
+
const [taskListHasRightShadow, setTaskListHasRightShadow] = (0, import_react15.useState)(false);
|
|
8275
|
+
const [selectedChip, setSelectedChip] = (0, import_react15.useState)(null);
|
|
8276
|
+
const [internalCollapsedParentIds, setInternalCollapsedParentIds] = (0, import_react15.useState)(/* @__PURE__ */ new Set());
|
|
7747
8277
|
const collapsedParentIds = externalCollapsedParentIds ?? internalCollapsedParentIds;
|
|
7748
|
-
const [editingTaskId, setEditingTaskId] = (0,
|
|
7749
|
-
const normalizedTasks = (0,
|
|
7750
|
-
const isCustomWeekend = (0,
|
|
8278
|
+
const [editingTaskId, setEditingTaskId] = (0, import_react15.useState)(null);
|
|
8279
|
+
const normalizedTasks = (0, import_react15.useMemo)(() => normalizeHierarchyTasks(tasks), [tasks]);
|
|
8280
|
+
const isCustomWeekend = (0, import_react15.useMemo)(
|
|
7751
8281
|
() => createCustomDayPredicate({ customDays, isWeekend: isWeekend3 }),
|
|
7752
8282
|
[customDays, isWeekend3]
|
|
7753
8283
|
);
|
|
7754
|
-
const dateRange = (0,
|
|
7755
|
-
const [validationResult, setValidationResult] = (0,
|
|
7756
|
-
const [cascadeOverrides, setCascadeOverrides] = (0,
|
|
7757
|
-
const gridWidth = (0,
|
|
8284
|
+
const dateRange = (0, import_react15.useMemo)(() => getMultiMonthDays(normalizedTasks), [normalizedTasks]);
|
|
8285
|
+
const [validationResult, setValidationResult] = (0, import_react15.useState)(null);
|
|
8286
|
+
const [cascadeOverrides, setCascadeOverrides] = (0, import_react15.useState)(/* @__PURE__ */ new Map());
|
|
8287
|
+
const gridWidth = (0, import_react15.useMemo)(
|
|
7758
8288
|
() => Math.round(dateRange.length * dayWidth),
|
|
7759
8289
|
[dateRange.length, dayWidth]
|
|
7760
8290
|
);
|
|
7761
|
-
const visibleTasks = (0,
|
|
8291
|
+
const visibleTasks = (0, import_react15.useMemo)(() => {
|
|
7762
8292
|
const parentMap = new Map(normalizedTasks.map((t) => [t.id, t.parentId]));
|
|
7763
8293
|
function isAnyAncestorCollapsed(parentId) {
|
|
7764
8294
|
let current = parentId;
|
|
@@ -7774,11 +8304,11 @@ function GanttChartInner(props, ref) {
|
|
|
7774
8304
|
}
|
|
7775
8305
|
return tasks2;
|
|
7776
8306
|
}, [normalizedTasks, collapsedParentIds, filterMode, taskFilter]);
|
|
7777
|
-
const matchedTaskIds = (0,
|
|
8307
|
+
const matchedTaskIds = (0, import_react15.useMemo)(() => {
|
|
7778
8308
|
if (!taskFilter) return /* @__PURE__ */ new Set();
|
|
7779
8309
|
return new Set(visibleTasks.filter(taskFilter).map((task) => task.id));
|
|
7780
8310
|
}, [visibleTasks, taskFilter]);
|
|
7781
|
-
const taskListHighlightedTaskIds = (0,
|
|
8311
|
+
const taskListHighlightedTaskIds = (0, import_react15.useMemo)(() => {
|
|
7782
8312
|
if (filterMode === "hide") {
|
|
7783
8313
|
return /* @__PURE__ */ new Set();
|
|
7784
8314
|
}
|
|
@@ -7789,23 +8319,23 @@ function GanttChartInner(props, ref) {
|
|
|
7789
8319
|
matchedTaskIds.forEach((taskId) => mergedHighlightedTaskIds.add(taskId));
|
|
7790
8320
|
return mergedHighlightedTaskIds;
|
|
7791
8321
|
}, [filterMode, highlightedTaskIds, matchedTaskIds]);
|
|
7792
|
-
const totalGridHeight = (0,
|
|
8322
|
+
const totalGridHeight = (0, import_react15.useMemo)(
|
|
7793
8323
|
() => visibleTasks.length * rowHeight,
|
|
7794
8324
|
[visibleTasks.length, rowHeight]
|
|
7795
8325
|
);
|
|
7796
|
-
const monthStart = (0,
|
|
8326
|
+
const monthStart = (0, import_react15.useMemo)(() => {
|
|
7797
8327
|
if (dateRange.length === 0) {
|
|
7798
8328
|
return new Date(Date.UTC((/* @__PURE__ */ new Date()).getUTCFullYear(), (/* @__PURE__ */ new Date()).getUTCMonth(), 1));
|
|
7799
8329
|
}
|
|
7800
8330
|
const firstDay = dateRange[0];
|
|
7801
8331
|
return new Date(Date.UTC(firstDay.getUTCFullYear(), firstDay.getUTCMonth(), 1));
|
|
7802
8332
|
}, [dateRange]);
|
|
7803
|
-
const todayInRange = (0,
|
|
8333
|
+
const todayInRange = (0, import_react15.useMemo)(() => {
|
|
7804
8334
|
const now = /* @__PURE__ */ new Date();
|
|
7805
8335
|
const today = new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate()));
|
|
7806
8336
|
return dateRange.some((day) => day.getTime() === today.getTime());
|
|
7807
8337
|
}, [dateRange]);
|
|
7808
|
-
(0,
|
|
8338
|
+
(0, import_react15.useEffect)(() => {
|
|
7809
8339
|
const container = scrollContainerRef.current;
|
|
7810
8340
|
if (!container || dateRange.length === 0) return;
|
|
7811
8341
|
const now = /* @__PURE__ */ new Date();
|
|
@@ -7817,7 +8347,7 @@ function GanttChartInner(props, ref) {
|
|
|
7817
8347
|
const scrollLeft = Math.round(todayOffset + dayWidth / 2 - containerWidth * 0.3);
|
|
7818
8348
|
container.scrollLeft = Math.max(0, scrollLeft);
|
|
7819
8349
|
}, []);
|
|
7820
|
-
(0,
|
|
8350
|
+
(0, import_react15.useEffect)(() => {
|
|
7821
8351
|
const container = scrollContainerRef.current;
|
|
7822
8352
|
if (!container) return;
|
|
7823
8353
|
const updateShadow = () => {
|
|
@@ -7829,7 +8359,7 @@ function GanttChartInner(props, ref) {
|
|
|
7829
8359
|
container.removeEventListener("scroll", updateShadow);
|
|
7830
8360
|
};
|
|
7831
8361
|
}, []);
|
|
7832
|
-
const scrollToToday = (0,
|
|
8362
|
+
const scrollToToday = (0, import_react15.useCallback)(() => {
|
|
7833
8363
|
const container = scrollContainerRef.current;
|
|
7834
8364
|
if (!container || dateRange.length === 0) return;
|
|
7835
8365
|
const now = /* @__PURE__ */ new Date();
|
|
@@ -7841,7 +8371,7 @@ function GanttChartInner(props, ref) {
|
|
|
7841
8371
|
const scrollLeft = Math.round(todayOffset + dayWidth / 2 - containerWidth * 0.3);
|
|
7842
8372
|
container.scrollTo({ left: Math.max(0, scrollLeft), behavior: "smooth" });
|
|
7843
8373
|
}, [dateRange, dayWidth]);
|
|
7844
|
-
const scrollToTask = (0,
|
|
8374
|
+
const scrollToTask = (0, import_react15.useCallback)((taskId) => {
|
|
7845
8375
|
const container = scrollContainerRef.current;
|
|
7846
8376
|
if (!container || dateRange.length === 0) return;
|
|
7847
8377
|
const task = tasks.find((t) => t.id === taskId);
|
|
@@ -7858,7 +8388,7 @@ function GanttChartInner(props, ref) {
|
|
|
7858
8388
|
const scrollLeft = Math.round(taskOffset - dayWidth * 2);
|
|
7859
8389
|
container.scrollTo({ left: Math.max(0, scrollLeft), behavior: "smooth" });
|
|
7860
8390
|
}, [tasks, dateRange, dayWidth]);
|
|
7861
|
-
const scrollToRow = (0,
|
|
8391
|
+
const scrollToRow = (0, import_react15.useCallback)((taskId) => {
|
|
7862
8392
|
const container = scrollContainerRef.current;
|
|
7863
8393
|
if (!container) return;
|
|
7864
8394
|
const task = tasks.find((t) => t.id === taskId);
|
|
@@ -7870,15 +8400,15 @@ function GanttChartInner(props, ref) {
|
|
|
7870
8400
|
setSelectedTaskId(taskId);
|
|
7871
8401
|
container.scrollTo({ top: scrollTop, behavior: "smooth" });
|
|
7872
8402
|
}, [tasks, visibleTasks, rowHeight]);
|
|
7873
|
-
const [dragGuideLines, setDragGuideLines] = (0,
|
|
7874
|
-
const [draggedTaskOverride, setDraggedTaskOverride] = (0,
|
|
7875
|
-
const [previewTasksById, setPreviewTasksById] = (0,
|
|
7876
|
-
(0,
|
|
8403
|
+
const [dragGuideLines, setDragGuideLines] = (0, import_react15.useState)(null);
|
|
8404
|
+
const [draggedTaskOverride, setDraggedTaskOverride] = (0, import_react15.useState)(null);
|
|
8405
|
+
const [previewTasksById, setPreviewTasksById] = (0, import_react15.useState)(/* @__PURE__ */ new Map());
|
|
8406
|
+
(0, import_react15.useEffect)(() => {
|
|
7877
8407
|
const result = validateDependencies(tasks);
|
|
7878
8408
|
setValidationResult(result);
|
|
7879
8409
|
onValidateDependencies?.(result);
|
|
7880
8410
|
}, [tasks, onValidateDependencies]);
|
|
7881
|
-
const handleTaskChange = (0,
|
|
8411
|
+
const handleTaskChange = (0, import_react15.useCallback)((updatedTasks) => {
|
|
7882
8412
|
const updatedTask = updatedTasks[0];
|
|
7883
8413
|
if (!updatedTask) return;
|
|
7884
8414
|
const originalTask = tasks.find((t) => t.id === updatedTask.id);
|
|
@@ -7924,7 +8454,7 @@ function GanttChartInner(props, ref) {
|
|
|
7924
8454
|
const cascadedTasks = disableConstraints ? [updatedTask] : universalCascade(updatedTask, newStart, newEnd, sourceTasks, businessDays, isCustomWeekend);
|
|
7925
8455
|
onTasksChange?.(cascadedTasks);
|
|
7926
8456
|
}, [tasks, onTasksChange, disableConstraints, editingTaskId, businessDays, isCustomWeekend]);
|
|
7927
|
-
const handleDelete = (0,
|
|
8457
|
+
const handleDelete = (0, import_react15.useCallback)((taskId) => {
|
|
7928
8458
|
const toDelete = /* @__PURE__ */ new Set([taskId]);
|
|
7929
8459
|
function collectDescendants(parentId) {
|
|
7930
8460
|
const children = getChildren(parentId, tasks);
|
|
@@ -7949,10 +8479,10 @@ function GanttChartInner(props, ref) {
|
|
|
7949
8479
|
}
|
|
7950
8480
|
toDelete.forEach((id) => onDelete?.(id));
|
|
7951
8481
|
}, [tasks, onTasksChange, onDelete]);
|
|
7952
|
-
const handleInsertAfter = (0,
|
|
8482
|
+
const handleInsertAfter = (0, import_react15.useCallback)((taskId, newTask) => {
|
|
7953
8483
|
onInsertAfter?.(taskId, newTask);
|
|
7954
8484
|
}, [onInsertAfter]);
|
|
7955
|
-
const handleReorder = (0,
|
|
8485
|
+
const handleReorder = (0, import_react15.useCallback)((reorderedTasks, movedTaskId, inferredParentId) => {
|
|
7956
8486
|
let updated = reorderedTasks;
|
|
7957
8487
|
if (movedTaskId) {
|
|
7958
8488
|
updated = updated.map((t) => {
|
|
@@ -7969,7 +8499,7 @@ function GanttChartInner(props, ref) {
|
|
|
7969
8499
|
}
|
|
7970
8500
|
onTasksChange?.(normalized);
|
|
7971
8501
|
}, [onTasksChange, onReorder]);
|
|
7972
|
-
const dependencyOverrides = (0,
|
|
8502
|
+
const dependencyOverrides = (0, import_react15.useMemo)(() => {
|
|
7973
8503
|
const map = new Map(cascadeOverrides);
|
|
7974
8504
|
if (draggedTaskOverride) {
|
|
7975
8505
|
map.set(draggedTaskOverride.taskId, {
|
|
@@ -7979,25 +8509,25 @@ function GanttChartInner(props, ref) {
|
|
|
7979
8509
|
}
|
|
7980
8510
|
return map;
|
|
7981
8511
|
}, [cascadeOverrides, draggedTaskOverride]);
|
|
7982
|
-
const handleCascadeProgress = (0,
|
|
8512
|
+
const handleCascadeProgress = (0, import_react15.useCallback)((overrides, previewTasks = []) => {
|
|
7983
8513
|
setCascadeOverrides(new Map(overrides));
|
|
7984
8514
|
setPreviewTasksById(new Map(previewTasks.map((task) => [task.id, task])));
|
|
7985
8515
|
}, []);
|
|
7986
|
-
const previewNormalizedTasks = (0,
|
|
8516
|
+
const previewNormalizedTasks = (0, import_react15.useMemo)(() => {
|
|
7987
8517
|
if (previewTasksById.size === 0) return normalizedTasks;
|
|
7988
8518
|
return normalizedTasks.map((task) => previewTasksById.get(task.id) ?? task);
|
|
7989
8519
|
}, [normalizedTasks, previewTasksById]);
|
|
7990
|
-
const previewVisibleTasks = (0,
|
|
8520
|
+
const previewVisibleTasks = (0, import_react15.useMemo)(() => {
|
|
7991
8521
|
if (previewTasksById.size === 0) return visibleTasks;
|
|
7992
8522
|
return visibleTasks.map((task) => previewTasksById.get(task.id) ?? task);
|
|
7993
8523
|
}, [visibleTasks, previewTasksById]);
|
|
7994
|
-
const handleCascade = (0,
|
|
8524
|
+
const handleCascade = (0, import_react15.useCallback)((cascadedTasks) => {
|
|
7995
8525
|
onTasksChange?.(cascadedTasks);
|
|
7996
8526
|
}, [tasks, onTasksChange]);
|
|
7997
|
-
const handleTaskSelect = (0,
|
|
8527
|
+
const handleTaskSelect = (0, import_react15.useCallback)((taskId) => {
|
|
7998
8528
|
setSelectedTaskId(taskId);
|
|
7999
8529
|
}, []);
|
|
8000
|
-
const handleToggleCollapse = externalOnToggleCollapse ?? (0,
|
|
8530
|
+
const handleToggleCollapse = externalOnToggleCollapse ?? (0, import_react15.useCallback)((parentId) => {
|
|
8001
8531
|
setInternalCollapsedParentIds((prev) => {
|
|
8002
8532
|
const next = new Set(prev);
|
|
8003
8533
|
if (next.has(parentId)) {
|
|
@@ -8008,20 +8538,20 @@ function GanttChartInner(props, ref) {
|
|
|
8008
8538
|
return next;
|
|
8009
8539
|
});
|
|
8010
8540
|
}, []);
|
|
8011
|
-
const allParentIds = (0,
|
|
8541
|
+
const allParentIds = (0, import_react15.useMemo)(() => {
|
|
8012
8542
|
return new Set(
|
|
8013
8543
|
normalizedTasks.filter((t) => isTaskParent(t.id, normalizedTasks)).map((t) => t.id)
|
|
8014
8544
|
);
|
|
8015
8545
|
}, [normalizedTasks]);
|
|
8016
|
-
const handleCollapseAll = (0,
|
|
8546
|
+
const handleCollapseAll = (0, import_react15.useCallback)(() => {
|
|
8017
8547
|
if (externalCollapsedParentIds) return;
|
|
8018
8548
|
setInternalCollapsedParentIds(allParentIds);
|
|
8019
8549
|
}, [allParentIds, externalCollapsedParentIds]);
|
|
8020
|
-
const handleExpandAll = (0,
|
|
8550
|
+
const handleExpandAll = (0, import_react15.useCallback)(() => {
|
|
8021
8551
|
if (externalCollapsedParentIds) return;
|
|
8022
8552
|
setInternalCollapsedParentIds(/* @__PURE__ */ new Set());
|
|
8023
8553
|
}, [externalCollapsedParentIds]);
|
|
8024
|
-
const exportToPdf = (0,
|
|
8554
|
+
const exportToPdf = (0, import_react15.useCallback)(async (options) => {
|
|
8025
8555
|
const sourceContainer = containerRef.current;
|
|
8026
8556
|
const sourceContent = scrollContentRef.current;
|
|
8027
8557
|
if (!sourceContainer || !sourceContent || typeof window === "undefined" || typeof document === "undefined") {
|
|
@@ -8057,7 +8587,7 @@ function GanttChartInner(props, ref) {
|
|
|
8057
8587
|
orientation: options?.orientation
|
|
8058
8588
|
});
|
|
8059
8589
|
}, [showTaskList, showChart]);
|
|
8060
|
-
(0,
|
|
8590
|
+
(0, import_react15.useImperativeHandle)(
|
|
8061
8591
|
ref,
|
|
8062
8592
|
() => ({
|
|
8063
8593
|
scrollToToday,
|
|
@@ -8080,7 +8610,7 @@ function GanttChartInner(props, ref) {
|
|
|
8080
8610
|
}
|
|
8081
8611
|
return depth;
|
|
8082
8612
|
}
|
|
8083
|
-
const handlePromoteTask = (0,
|
|
8613
|
+
const handlePromoteTask = (0, import_react15.useCallback)((taskId) => {
|
|
8084
8614
|
if (onPromoteTask) {
|
|
8085
8615
|
onPromoteTask(taskId);
|
|
8086
8616
|
return;
|
|
@@ -8110,7 +8640,7 @@ function GanttChartInner(props, ref) {
|
|
|
8110
8640
|
]);
|
|
8111
8641
|
onTasksChange?.(reorderedTasks);
|
|
8112
8642
|
}, [tasks, onTasksChange, onPromoteTask]);
|
|
8113
|
-
const handleDemoteTask = (0,
|
|
8643
|
+
const handleDemoteTask = (0, import_react15.useCallback)((taskId, newParentId) => {
|
|
8114
8644
|
if (onDemoteTask) {
|
|
8115
8645
|
onDemoteTask(taskId, newParentId);
|
|
8116
8646
|
return;
|
|
@@ -8151,7 +8681,7 @@ function GanttChartInner(props, ref) {
|
|
|
8151
8681
|
};
|
|
8152
8682
|
onTasksChange?.([updatedDemotedTask]);
|
|
8153
8683
|
}, [tasks, onTasksChange, onDemoteTask]);
|
|
8154
|
-
const handleUngroupTask = (0,
|
|
8684
|
+
const handleUngroupTask = (0, import_react15.useCallback)((taskId) => {
|
|
8155
8685
|
if (onUngroupTask) {
|
|
8156
8686
|
onUngroupTask(taskId);
|
|
8157
8687
|
return;
|
|
@@ -8178,8 +8708,8 @@ function GanttChartInner(props, ref) {
|
|
|
8178
8708
|
}
|
|
8179
8709
|
onDelete?.(taskId);
|
|
8180
8710
|
}, [tasks, onTasksChange, onDelete, onUngroupTask]);
|
|
8181
|
-
const panStateRef = (0,
|
|
8182
|
-
const handlePanStart = (0,
|
|
8711
|
+
const panStateRef = (0, import_react15.useRef)(null);
|
|
8712
|
+
const handlePanStart = (0, import_react15.useCallback)((e) => {
|
|
8183
8713
|
if (e.button !== 0) return;
|
|
8184
8714
|
const target = e.target;
|
|
8185
8715
|
if (target.closest("[data-taskbar]")) return;
|
|
@@ -8200,7 +8730,7 @@ function GanttChartInner(props, ref) {
|
|
|
8200
8730
|
container.style.cursor = "grabbing";
|
|
8201
8731
|
e.preventDefault();
|
|
8202
8732
|
}, []);
|
|
8203
|
-
(0,
|
|
8733
|
+
(0, import_react15.useEffect)(() => {
|
|
8204
8734
|
const handlePanMove = (e) => {
|
|
8205
8735
|
const pan = panStateRef.current;
|
|
8206
8736
|
if (!pan?.active) return;
|
|
@@ -8222,15 +8752,15 @@ function GanttChartInner(props, ref) {
|
|
|
8222
8752
|
window.removeEventListener("mouseup", handlePanEnd);
|
|
8223
8753
|
};
|
|
8224
8754
|
}, []);
|
|
8225
|
-
return /* @__PURE__ */ (0,
|
|
8755
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { ref: containerRef, className: "gantt-container", children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
8226
8756
|
"div",
|
|
8227
8757
|
{
|
|
8228
8758
|
ref: scrollContainerRef,
|
|
8229
8759
|
className: "gantt-scrollContainer",
|
|
8230
8760
|
style: { height: containerHeight ?? "auto", cursor: "grab" },
|
|
8231
8761
|
onMouseDown: handlePanStart,
|
|
8232
|
-
children: /* @__PURE__ */ (0,
|
|
8233
|
-
/* @__PURE__ */ (0,
|
|
8762
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { ref: scrollContentRef, className: "gantt-scrollContent", children: [
|
|
8763
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
8234
8764
|
TaskList,
|
|
8235
8765
|
{
|
|
8236
8766
|
tasks: normalizedTasks,
|
|
@@ -8268,13 +8798,13 @@ function GanttChartInner(props, ref) {
|
|
|
8268
8798
|
taskListMenuCommands
|
|
8269
8799
|
}
|
|
8270
8800
|
),
|
|
8271
|
-
/* @__PURE__ */ (0,
|
|
8801
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
|
|
8272
8802
|
"div",
|
|
8273
8803
|
{
|
|
8274
8804
|
className: showChart ? "gantt-chartSurface" : "gantt-chartSurface gantt-chart-hidden",
|
|
8275
8805
|
style: { minWidth: `${gridWidth}px`, flex: 1, display: showChart ? void 0 : "none" },
|
|
8276
8806
|
children: [
|
|
8277
|
-
/* @__PURE__ */ (0,
|
|
8807
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "gantt-stickyHeader", style: { width: `${gridWidth}px` }, children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
8278
8808
|
TimeScaleHeader_default,
|
|
8279
8809
|
{
|
|
8280
8810
|
days: dateRange,
|
|
@@ -8284,7 +8814,7 @@ function GanttChartInner(props, ref) {
|
|
|
8284
8814
|
isCustomWeekend
|
|
8285
8815
|
}
|
|
8286
8816
|
) }),
|
|
8287
|
-
/* @__PURE__ */ (0,
|
|
8817
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
|
|
8288
8818
|
"div",
|
|
8289
8819
|
{
|
|
8290
8820
|
className: "gantt-taskArea",
|
|
@@ -8293,7 +8823,7 @@ function GanttChartInner(props, ref) {
|
|
|
8293
8823
|
width: `${gridWidth}px`
|
|
8294
8824
|
},
|
|
8295
8825
|
children: [
|
|
8296
|
-
/* @__PURE__ */ (0,
|
|
8826
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
8297
8827
|
GridBackground_default,
|
|
8298
8828
|
{
|
|
8299
8829
|
dateRange,
|
|
@@ -8303,8 +8833,8 @@ function GanttChartInner(props, ref) {
|
|
|
8303
8833
|
isCustomWeekend
|
|
8304
8834
|
}
|
|
8305
8835
|
),
|
|
8306
|
-
todayInRange && /* @__PURE__ */ (0,
|
|
8307
|
-
/* @__PURE__ */ (0,
|
|
8836
|
+
todayInRange && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(TodayIndicator_default, { monthStart, dayWidth }),
|
|
8837
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
8308
8838
|
DependencyLines_default,
|
|
8309
8839
|
{
|
|
8310
8840
|
tasks: previewVisibleTasks,
|
|
@@ -8320,7 +8850,7 @@ function GanttChartInner(props, ref) {
|
|
|
8320
8850
|
weekendPredicate: isCustomWeekend
|
|
8321
8851
|
}
|
|
8322
8852
|
),
|
|
8323
|
-
dragGuideLines && /* @__PURE__ */ (0,
|
|
8853
|
+
dragGuideLines && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
8324
8854
|
DragGuideLines_default,
|
|
8325
8855
|
{
|
|
8326
8856
|
isDragging: dragGuideLines.isDragging,
|
|
@@ -8330,7 +8860,7 @@ function GanttChartInner(props, ref) {
|
|
|
8330
8860
|
totalHeight: totalGridHeight
|
|
8331
8861
|
}
|
|
8332
8862
|
),
|
|
8333
|
-
visibleTasks.map((task, index) => /* @__PURE__ */ (0,
|
|
8863
|
+
visibleTasks.map((task, index) => /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
8334
8864
|
TaskRow_default,
|
|
8335
8865
|
{
|
|
8336
8866
|
task,
|
|
@@ -8374,13 +8904,14 @@ function GanttChartInner(props, ref) {
|
|
|
8374
8904
|
}
|
|
8375
8905
|
) });
|
|
8376
8906
|
}
|
|
8377
|
-
var
|
|
8907
|
+
var TaskGanttChart = (0, import_react15.forwardRef)(TaskGanttChartInner);
|
|
8908
|
+
var GanttChart = (0, import_react15.forwardRef)(GanttChartInner);
|
|
8378
8909
|
GanttChart.displayName = "GanttChart";
|
|
8379
8910
|
|
|
8380
8911
|
// src/components/ui/Button.tsx
|
|
8381
|
-
var
|
|
8382
|
-
var
|
|
8383
|
-
var Button =
|
|
8912
|
+
var import_react16 = __toESM(require("react"));
|
|
8913
|
+
var import_jsx_runtime17 = require("react/jsx-runtime");
|
|
8914
|
+
var Button = import_react16.default.forwardRef(
|
|
8384
8915
|
({ className, variant = "default", size = "default", children, ...props }, ref) => {
|
|
8385
8916
|
const classes = [
|
|
8386
8917
|
"gantt-btn",
|
|
@@ -8388,7 +8919,7 @@ var Button = import_react14.default.forwardRef(
|
|
|
8388
8919
|
size !== "default" ? `gantt-btn-${size}` : "",
|
|
8389
8920
|
className || ""
|
|
8390
8921
|
].filter(Boolean).join(" ");
|
|
8391
|
-
return /* @__PURE__ */ (0,
|
|
8922
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("button", { ref, className: classes, ...props, children });
|
|
8392
8923
|
}
|
|
8393
8924
|
);
|
|
8394
8925
|
Button.displayName = "Button";
|
|
@@ -8434,6 +8965,7 @@ var nameContains = (substring, caseSensitive = false) => (task) => {
|
|
|
8434
8965
|
Popover,
|
|
8435
8966
|
PopoverContent,
|
|
8436
8967
|
PopoverTrigger,
|
|
8968
|
+
ResourceTimelineChart,
|
|
8437
8969
|
TaskList,
|
|
8438
8970
|
TaskRow,
|
|
8439
8971
|
TimeScaleHeader,
|
|
@@ -8497,6 +9029,7 @@ var nameContains = (substring, caseSensitive = false) => (task) => {
|
|
|
8497
9029
|
isTaskParent,
|
|
8498
9030
|
isToday,
|
|
8499
9031
|
isWeekend,
|
|
9032
|
+
layoutResourceTimelineItems,
|
|
8500
9033
|
moveTaskRange,
|
|
8501
9034
|
moveTaskWithCascade,
|
|
8502
9035
|
nameContains,
|