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.mjs
CHANGED
|
@@ -492,7 +492,7 @@ var init_dateUtils = __esm({
|
|
|
492
492
|
|
|
493
493
|
// src/components/GanttChart/GanttChart.tsx
|
|
494
494
|
init_dateUtils();
|
|
495
|
-
import { useMemo as
|
|
495
|
+
import { useMemo as useMemo10, useCallback as useCallback8, useRef as useRef9, useState as useState8, useEffect as useEffect9, useImperativeHandle, forwardRef } from "react";
|
|
496
496
|
|
|
497
497
|
// src/core/scheduling/index.ts
|
|
498
498
|
init_dateMath();
|
|
@@ -7262,6 +7262,522 @@ var TaskList = ({
|
|
|
7262
7262
|
);
|
|
7263
7263
|
};
|
|
7264
7264
|
|
|
7265
|
+
// src/components/ResourceTimelineChart/ResourceTimelineChart.tsx
|
|
7266
|
+
init_dateUtils();
|
|
7267
|
+
import { useCallback as useCallback7, useEffect as useEffect8, useMemo as useMemo9, useRef as useRef8 } from "react";
|
|
7268
|
+
|
|
7269
|
+
// src/utils/resourceTimelineLayout.ts
|
|
7270
|
+
init_dateUtils();
|
|
7271
|
+
var isInvalidDate = (date) => Number.isNaN(date.getTime());
|
|
7272
|
+
var getUTCDayNumber = (date) => {
|
|
7273
|
+
return Math.floor(Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate()) / 864e5);
|
|
7274
|
+
};
|
|
7275
|
+
var compareParsedItems = (a, b) => {
|
|
7276
|
+
const startDiff = getUTCDayNumber(a.startDate) - getUTCDayNumber(b.startDate);
|
|
7277
|
+
if (startDiff !== 0) {
|
|
7278
|
+
return startDiff;
|
|
7279
|
+
}
|
|
7280
|
+
const endDiff = getUTCDayNumber(a.endDate) - getUTCDayNumber(b.endDate);
|
|
7281
|
+
if (endDiff !== 0) {
|
|
7282
|
+
return endDiff;
|
|
7283
|
+
}
|
|
7284
|
+
return a.item.id.localeCompare(b.item.id);
|
|
7285
|
+
};
|
|
7286
|
+
var layoutResourceTimelineItems = (resources, options) => {
|
|
7287
|
+
const rows = [];
|
|
7288
|
+
const items = [];
|
|
7289
|
+
const diagnostics = [];
|
|
7290
|
+
let currentTop = 0;
|
|
7291
|
+
for (const resource of resources) {
|
|
7292
|
+
const parsedItems = [];
|
|
7293
|
+
for (const item of resource.items) {
|
|
7294
|
+
try {
|
|
7295
|
+
const startDate = parseUTCDate(item.startDate);
|
|
7296
|
+
const endDate = parseUTCDate(item.endDate);
|
|
7297
|
+
if (isInvalidDate(startDate) || isInvalidDate(endDate)) {
|
|
7298
|
+
throw new Error("Invalid date");
|
|
7299
|
+
}
|
|
7300
|
+
parsedItems.push({ item, startDate, endDate });
|
|
7301
|
+
} catch {
|
|
7302
|
+
diagnostics.push({
|
|
7303
|
+
itemId: item.id,
|
|
7304
|
+
resourceId: resource.id,
|
|
7305
|
+
reason: "invalid-date"
|
|
7306
|
+
});
|
|
7307
|
+
}
|
|
7308
|
+
}
|
|
7309
|
+
parsedItems.sort(compareParsedItems);
|
|
7310
|
+
const laneEndDays = [];
|
|
7311
|
+
const laidOutItems = [];
|
|
7312
|
+
for (const parsed of parsedItems) {
|
|
7313
|
+
const startDay = getUTCDayNumber(parsed.startDate);
|
|
7314
|
+
const endDay = getUTCDayNumber(parsed.endDate);
|
|
7315
|
+
let laneIndex = laneEndDays.findIndex((laneEndDay) => laneEndDay < startDay);
|
|
7316
|
+
if (laneIndex === -1) {
|
|
7317
|
+
laneIndex = laneEndDays.length;
|
|
7318
|
+
laneEndDays.push(endDay);
|
|
7319
|
+
} else {
|
|
7320
|
+
laneEndDays[laneIndex] = endDay;
|
|
7321
|
+
}
|
|
7322
|
+
const { left, width } = calculateTaskBar(parsed.startDate, parsed.endDate, options.monthStart, options.dayWidth);
|
|
7323
|
+
laidOutItems.push({
|
|
7324
|
+
item: parsed.item,
|
|
7325
|
+
itemId: parsed.item.id,
|
|
7326
|
+
resourceId: resource.id,
|
|
7327
|
+
laneIndex,
|
|
7328
|
+
left,
|
|
7329
|
+
width,
|
|
7330
|
+
resourceRowTop: currentTop,
|
|
7331
|
+
resourceRowHeight: 0,
|
|
7332
|
+
top: currentTop + laneIndex * options.laneHeight,
|
|
7333
|
+
height: options.laneHeight,
|
|
7334
|
+
startDate: parsed.startDate,
|
|
7335
|
+
endDate: parsed.endDate
|
|
7336
|
+
});
|
|
7337
|
+
}
|
|
7338
|
+
const laneCount = Math.max(1, laneEndDays.length);
|
|
7339
|
+
const resourceRowHeight = laneCount * options.laneHeight;
|
|
7340
|
+
const row = {
|
|
7341
|
+
resource,
|
|
7342
|
+
resourceId: resource.id,
|
|
7343
|
+
laneCount,
|
|
7344
|
+
resourceRowTop: currentTop,
|
|
7345
|
+
resourceRowHeight
|
|
7346
|
+
};
|
|
7347
|
+
rows.push(row);
|
|
7348
|
+
items.push(...laidOutItems.map((item) => ({
|
|
7349
|
+
...item,
|
|
7350
|
+
resourceRowHeight
|
|
7351
|
+
})));
|
|
7352
|
+
currentTop += resourceRowHeight;
|
|
7353
|
+
}
|
|
7354
|
+
return {
|
|
7355
|
+
rows,
|
|
7356
|
+
items,
|
|
7357
|
+
diagnostics,
|
|
7358
|
+
totalHeight: currentTop
|
|
7359
|
+
};
|
|
7360
|
+
};
|
|
7361
|
+
|
|
7362
|
+
// src/hooks/useResourceItemDrag.ts
|
|
7363
|
+
import { useCallback as useCallback6, useEffect as useEffect7, useRef as useRef7, useState as useState7 } from "react";
|
|
7364
|
+
var snapToDay = (pixels, dayWidth) => {
|
|
7365
|
+
return Math.round(pixels / dayWidth) * dayWidth;
|
|
7366
|
+
};
|
|
7367
|
+
var addUTCDays = (date, days) => {
|
|
7368
|
+
return new Date(Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate() + days));
|
|
7369
|
+
};
|
|
7370
|
+
var resolveTargetResource = (rows, clientY, gridTop) => {
|
|
7371
|
+
const localY = clientY - gridTop;
|
|
7372
|
+
return rows.find(
|
|
7373
|
+
(row) => localY >= row.resourceRowTop && localY < row.resourceRowTop + row.resourceRowHeight
|
|
7374
|
+
)?.resource ?? null;
|
|
7375
|
+
};
|
|
7376
|
+
var useResourceItemDrag = ({
|
|
7377
|
+
dayWidth,
|
|
7378
|
+
rows,
|
|
7379
|
+
gridElementRef,
|
|
7380
|
+
readonly,
|
|
7381
|
+
disableResourceReassignment,
|
|
7382
|
+
onResourceItemMove
|
|
7383
|
+
}) => {
|
|
7384
|
+
const activeDragRef = useRef7(null);
|
|
7385
|
+
const rowsRef = useRef7(rows);
|
|
7386
|
+
const onResourceItemMoveRef = useRef7(onResourceItemMove);
|
|
7387
|
+
const rafRef = useRef7(null);
|
|
7388
|
+
const [preview, setPreview] = useState7(null);
|
|
7389
|
+
useEffect7(() => {
|
|
7390
|
+
rowsRef.current = rows;
|
|
7391
|
+
}, [rows]);
|
|
7392
|
+
useEffect7(() => {
|
|
7393
|
+
onResourceItemMoveRef.current = onResourceItemMove;
|
|
7394
|
+
}, [onResourceItemMove]);
|
|
7395
|
+
const clearRaf = useCallback6(() => {
|
|
7396
|
+
if (rafRef.current !== null) {
|
|
7397
|
+
cancelAnimationFrame(rafRef.current);
|
|
7398
|
+
rafRef.current = null;
|
|
7399
|
+
}
|
|
7400
|
+
}, []);
|
|
7401
|
+
const cancelDrag2 = useCallback6(() => {
|
|
7402
|
+
clearRaf();
|
|
7403
|
+
activeDragRef.current = null;
|
|
7404
|
+
setPreview(null);
|
|
7405
|
+
}, [clearRaf]);
|
|
7406
|
+
useEffect7(() => {
|
|
7407
|
+
const handleMouseMove = (event) => {
|
|
7408
|
+
const activeDrag = activeDragRef.current;
|
|
7409
|
+
if (!activeDrag || rafRef.current !== null) {
|
|
7410
|
+
return;
|
|
7411
|
+
}
|
|
7412
|
+
rafRef.current = requestAnimationFrame(() => {
|
|
7413
|
+
rafRef.current = null;
|
|
7414
|
+
const latestDrag = activeDragRef.current;
|
|
7415
|
+
if (!latestDrag) {
|
|
7416
|
+
return;
|
|
7417
|
+
}
|
|
7418
|
+
const nextLeft = latestDrag.initialLeft + snapToDay(event.clientX - latestDrag.startX, latestDrag.dayWidth);
|
|
7419
|
+
const nextTop = disableResourceReassignment ? latestDrag.initialTop : latestDrag.initialTop + (event.clientY - latestDrag.startY);
|
|
7420
|
+
latestDrag.currentLeft = nextLeft;
|
|
7421
|
+
latestDrag.currentTop = nextTop;
|
|
7422
|
+
setPreview({
|
|
7423
|
+
itemId: latestDrag.itemId,
|
|
7424
|
+
left: nextLeft,
|
|
7425
|
+
top: nextTop
|
|
7426
|
+
});
|
|
7427
|
+
});
|
|
7428
|
+
};
|
|
7429
|
+
const handleMouseUp = (event) => {
|
|
7430
|
+
const activeDrag = activeDragRef.current;
|
|
7431
|
+
if (!activeDrag) {
|
|
7432
|
+
return;
|
|
7433
|
+
}
|
|
7434
|
+
clearRaf();
|
|
7435
|
+
activeDragRef.current = null;
|
|
7436
|
+
setPreview(null);
|
|
7437
|
+
const gridTop = gridElementRef?.current?.getBoundingClientRect().top ?? 0;
|
|
7438
|
+
const targetResource = disableResourceReassignment ? rowsRef.current.find((row) => row.resourceId === activeDrag.fromResourceId)?.resource ?? null : resolveTargetResource(rowsRef.current, event.clientY, gridTop);
|
|
7439
|
+
if (!targetResource) {
|
|
7440
|
+
return;
|
|
7441
|
+
}
|
|
7442
|
+
const dayDelta = Math.round((activeDrag.currentLeft - activeDrag.initialLeft) / activeDrag.dayWidth);
|
|
7443
|
+
onResourceItemMoveRef.current?.({
|
|
7444
|
+
item: activeDrag.item,
|
|
7445
|
+
itemId: activeDrag.itemId,
|
|
7446
|
+
fromResourceId: activeDrag.fromResourceId,
|
|
7447
|
+
toResourceId: targetResource.id,
|
|
7448
|
+
startDate: addUTCDays(activeDrag.startDate, dayDelta),
|
|
7449
|
+
endDate: addUTCDays(activeDrag.endDate, dayDelta)
|
|
7450
|
+
});
|
|
7451
|
+
};
|
|
7452
|
+
window.addEventListener("mousemove", handleMouseMove);
|
|
7453
|
+
window.addEventListener("mouseup", handleMouseUp);
|
|
7454
|
+
return () => {
|
|
7455
|
+
window.removeEventListener("mousemove", handleMouseMove);
|
|
7456
|
+
window.removeEventListener("mouseup", handleMouseUp);
|
|
7457
|
+
cancelDrag2();
|
|
7458
|
+
};
|
|
7459
|
+
}, [cancelDrag2, clearRaf, disableResourceReassignment, gridElementRef]);
|
|
7460
|
+
const startDrag = useCallback6((event, layoutItem) => {
|
|
7461
|
+
if (readonly || layoutItem.item.locked || event.button !== 0) {
|
|
7462
|
+
return;
|
|
7463
|
+
}
|
|
7464
|
+
event.preventDefault();
|
|
7465
|
+
activeDragRef.current = {
|
|
7466
|
+
item: layoutItem.item,
|
|
7467
|
+
itemId: layoutItem.itemId,
|
|
7468
|
+
fromResourceId: layoutItem.resourceId,
|
|
7469
|
+
startX: event.clientX,
|
|
7470
|
+
startY: event.clientY,
|
|
7471
|
+
initialLeft: layoutItem.left,
|
|
7472
|
+
initialTop: layoutItem.top,
|
|
7473
|
+
currentLeft: layoutItem.left,
|
|
7474
|
+
currentTop: layoutItem.top,
|
|
7475
|
+
dayWidth,
|
|
7476
|
+
startDate: layoutItem.startDate,
|
|
7477
|
+
endDate: layoutItem.endDate
|
|
7478
|
+
};
|
|
7479
|
+
setPreview({
|
|
7480
|
+
itemId: layoutItem.itemId,
|
|
7481
|
+
left: layoutItem.left,
|
|
7482
|
+
top: layoutItem.top
|
|
7483
|
+
});
|
|
7484
|
+
}, [dayWidth, readonly]);
|
|
7485
|
+
return {
|
|
7486
|
+
preview,
|
|
7487
|
+
startDrag,
|
|
7488
|
+
cancelDrag: cancelDrag2
|
|
7489
|
+
};
|
|
7490
|
+
};
|
|
7491
|
+
|
|
7492
|
+
// src/components/ResourceTimelineChart/ResourceTimelineChart.tsx
|
|
7493
|
+
import { Fragment as Fragment3, jsx as jsx15, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
7494
|
+
var DEFAULT_DAY_WIDTH = 40;
|
|
7495
|
+
var DEFAULT_HEADER_HEIGHT = 40;
|
|
7496
|
+
var DEFAULT_LANE_HEIGHT = 40;
|
|
7497
|
+
var DEFAULT_ROW_HEADER_WIDTH = 240;
|
|
7498
|
+
var ITEM_OUTER_VERTICAL_INSET = 2;
|
|
7499
|
+
var ITEM_INNER_VERTICAL_INSET = 1;
|
|
7500
|
+
var ITEM_HORIZONTAL_INSET = 1;
|
|
7501
|
+
var isValidDate = (date) => !Number.isNaN(date.getTime());
|
|
7502
|
+
var getResourceTimelineDays = (items) => {
|
|
7503
|
+
if (items.length === 0) {
|
|
7504
|
+
return getMonthDays(/* @__PURE__ */ new Date());
|
|
7505
|
+
}
|
|
7506
|
+
let minDate = null;
|
|
7507
|
+
let maxDate = null;
|
|
7508
|
+
for (const item of items) {
|
|
7509
|
+
const startDate = parseUTCDate(item.startDate);
|
|
7510
|
+
const endDate = parseUTCDate(item.endDate);
|
|
7511
|
+
if (!minDate || startDate.getTime() < minDate.getTime()) {
|
|
7512
|
+
minDate = startDate;
|
|
7513
|
+
}
|
|
7514
|
+
if (!maxDate || endDate.getTime() > maxDate.getTime()) {
|
|
7515
|
+
maxDate = endDate;
|
|
7516
|
+
}
|
|
7517
|
+
}
|
|
7518
|
+
if (!minDate || !maxDate) {
|
|
7519
|
+
return getMonthDays(/* @__PURE__ */ new Date());
|
|
7520
|
+
}
|
|
7521
|
+
const startOfMonth2 = new Date(Date.UTC(minDate.getUTCFullYear(), minDate.getUTCMonth(), 1));
|
|
7522
|
+
const endOfMonth = new Date(Date.UTC(maxDate.getUTCFullYear(), maxDate.getUTCMonth() + 1, 0));
|
|
7523
|
+
const days = [];
|
|
7524
|
+
const current = new Date(startOfMonth2);
|
|
7525
|
+
while (current.getTime() <= endOfMonth.getTime()) {
|
|
7526
|
+
days.push(new Date(Date.UTC(current.getUTCFullYear(), current.getUTCMonth(), current.getUTCDate())));
|
|
7527
|
+
current.setUTCDate(current.getUTCDate() + 1);
|
|
7528
|
+
}
|
|
7529
|
+
return days;
|
|
7530
|
+
};
|
|
7531
|
+
var collectValidItems = (resources) => {
|
|
7532
|
+
return resources.flatMap(
|
|
7533
|
+
(resource) => resource.items.flatMap((item) => {
|
|
7534
|
+
try {
|
|
7535
|
+
const startDate = parseUTCDate(item.startDate);
|
|
7536
|
+
const endDate = parseUTCDate(item.endDate);
|
|
7537
|
+
if (!isValidDate(startDate) || !isValidDate(endDate)) {
|
|
7538
|
+
return [];
|
|
7539
|
+
}
|
|
7540
|
+
return [{ startDate, endDate }];
|
|
7541
|
+
} catch {
|
|
7542
|
+
return [];
|
|
7543
|
+
}
|
|
7544
|
+
})
|
|
7545
|
+
);
|
|
7546
|
+
};
|
|
7547
|
+
var getVisualItemGeometry = (geometry, laneIndex, laneCount) => {
|
|
7548
|
+
const topInset = laneIndex === 0 ? ITEM_OUTER_VERTICAL_INSET : ITEM_INNER_VERTICAL_INSET;
|
|
7549
|
+
const bottomInset = laneIndex === laneCount - 1 ? ITEM_OUTER_VERTICAL_INSET : ITEM_INNER_VERTICAL_INSET;
|
|
7550
|
+
return {
|
|
7551
|
+
left: geometry.left + ITEM_HORIZONTAL_INSET,
|
|
7552
|
+
top: geometry.top + topInset,
|
|
7553
|
+
width: Math.max(0, geometry.width - ITEM_HORIZONTAL_INSET * 2),
|
|
7554
|
+
height: Math.max(0, geometry.height - topInset - bottomInset)
|
|
7555
|
+
};
|
|
7556
|
+
};
|
|
7557
|
+
function ResourceTimelineChart({
|
|
7558
|
+
resources,
|
|
7559
|
+
dayWidth = DEFAULT_DAY_WIDTH,
|
|
7560
|
+
rowHeaderWidth = DEFAULT_ROW_HEADER_WIDTH,
|
|
7561
|
+
laneHeight = DEFAULT_LANE_HEIGHT,
|
|
7562
|
+
headerHeight = DEFAULT_HEADER_HEIGHT,
|
|
7563
|
+
readonly,
|
|
7564
|
+
disableResourceReassignment,
|
|
7565
|
+
renderItem,
|
|
7566
|
+
getItemClassName,
|
|
7567
|
+
onResourceItemMove
|
|
7568
|
+
}) {
|
|
7569
|
+
const scrollContainerRef = useRef8(null);
|
|
7570
|
+
const gridRef = useRef8(null);
|
|
7571
|
+
const panStateRef = useRef8(null);
|
|
7572
|
+
const validItems = useMemo9(() => collectValidItems(resources), [resources]);
|
|
7573
|
+
const dateRange = useMemo9(() => {
|
|
7574
|
+
return getResourceTimelineDays(validItems);
|
|
7575
|
+
}, [validItems]);
|
|
7576
|
+
const monthStart = useMemo9(() => {
|
|
7577
|
+
const firstDay = dateRange[0] ?? /* @__PURE__ */ new Date();
|
|
7578
|
+
return new Date(Date.UTC(firstDay.getUTCFullYear(), firstDay.getUTCMonth(), 1));
|
|
7579
|
+
}, [dateRange]);
|
|
7580
|
+
const gridWidth = useMemo9(() => Math.round(dateRange.length * dayWidth), [dateRange.length, dayWidth]);
|
|
7581
|
+
const layout = useMemo9(
|
|
7582
|
+
() => layoutResourceTimelineItems(resources, { monthStart, dayWidth, laneHeight }),
|
|
7583
|
+
[resources, monthStart, dayWidth, laneHeight]
|
|
7584
|
+
);
|
|
7585
|
+
const todayInRange = useMemo9(() => {
|
|
7586
|
+
const now = /* @__PURE__ */ new Date();
|
|
7587
|
+
const today = new Date(Date.UTC(now.getFullYear(), now.getMonth(), now.getDate()));
|
|
7588
|
+
return dateRange.some((day) => day.getTime() === today.getTime());
|
|
7589
|
+
}, [dateRange]);
|
|
7590
|
+
const itemsByResourceId = useMemo9(() => {
|
|
7591
|
+
const map = /* @__PURE__ */ new Map();
|
|
7592
|
+
for (const item of layout.items) {
|
|
7593
|
+
const next = map.get(item.resourceId) ?? [];
|
|
7594
|
+
next.push(item);
|
|
7595
|
+
map.set(item.resourceId, next);
|
|
7596
|
+
}
|
|
7597
|
+
return map;
|
|
7598
|
+
}, [layout.items]);
|
|
7599
|
+
const { preview, startDrag } = useResourceItemDrag({
|
|
7600
|
+
dayWidth,
|
|
7601
|
+
rows: layout.rows,
|
|
7602
|
+
gridElementRef: gridRef,
|
|
7603
|
+
readonly,
|
|
7604
|
+
disableResourceReassignment,
|
|
7605
|
+
onResourceItemMove
|
|
7606
|
+
});
|
|
7607
|
+
const handlePanStart = useCallback7((event) => {
|
|
7608
|
+
if (event.button !== 0) {
|
|
7609
|
+
return;
|
|
7610
|
+
}
|
|
7611
|
+
const target = event.target;
|
|
7612
|
+
if (target.closest("[data-resource-item-id]")) {
|
|
7613
|
+
return;
|
|
7614
|
+
}
|
|
7615
|
+
if (target.closest("input, button, textarea, [contenteditable]")) {
|
|
7616
|
+
return;
|
|
7617
|
+
}
|
|
7618
|
+
const container = scrollContainerRef.current;
|
|
7619
|
+
if (!container) {
|
|
7620
|
+
return;
|
|
7621
|
+
}
|
|
7622
|
+
panStateRef.current = {
|
|
7623
|
+
active: true,
|
|
7624
|
+
startX: event.clientX,
|
|
7625
|
+
startY: event.clientY,
|
|
7626
|
+
scrollX: container.scrollLeft,
|
|
7627
|
+
scrollY: container.scrollTop
|
|
7628
|
+
};
|
|
7629
|
+
if (document.activeElement instanceof HTMLElement) {
|
|
7630
|
+
document.activeElement.blur();
|
|
7631
|
+
}
|
|
7632
|
+
container.style.cursor = "grabbing";
|
|
7633
|
+
event.preventDefault();
|
|
7634
|
+
}, []);
|
|
7635
|
+
useEffect8(() => {
|
|
7636
|
+
const handlePanMove = (event) => {
|
|
7637
|
+
const pan = panStateRef.current;
|
|
7638
|
+
const container = scrollContainerRef.current;
|
|
7639
|
+
if (!pan?.active || !container) {
|
|
7640
|
+
return;
|
|
7641
|
+
}
|
|
7642
|
+
container.scrollLeft = pan.scrollX - (event.clientX - pan.startX);
|
|
7643
|
+
container.scrollTop = pan.scrollY - (event.clientY - pan.startY);
|
|
7644
|
+
};
|
|
7645
|
+
const handlePanEnd = () => {
|
|
7646
|
+
if (!panStateRef.current?.active) {
|
|
7647
|
+
return;
|
|
7648
|
+
}
|
|
7649
|
+
panStateRef.current = null;
|
|
7650
|
+
const container = scrollContainerRef.current;
|
|
7651
|
+
if (container) {
|
|
7652
|
+
container.style.cursor = "";
|
|
7653
|
+
}
|
|
7654
|
+
};
|
|
7655
|
+
window.addEventListener("mousemove", handlePanMove);
|
|
7656
|
+
window.addEventListener("mouseup", handlePanEnd);
|
|
7657
|
+
return () => {
|
|
7658
|
+
window.removeEventListener("mousemove", handlePanMove);
|
|
7659
|
+
window.removeEventListener("mouseup", handlePanEnd);
|
|
7660
|
+
};
|
|
7661
|
+
}, []);
|
|
7662
|
+
return /* @__PURE__ */ jsx15("div", { className: "gantt-container gantt-resourceTimeline", children: /* @__PURE__ */ jsx15(
|
|
7663
|
+
"div",
|
|
7664
|
+
{
|
|
7665
|
+
ref: scrollContainerRef,
|
|
7666
|
+
className: "gantt-resourceTimeline-scrollContainer",
|
|
7667
|
+
style: { cursor: "grab" },
|
|
7668
|
+
onMouseDown: handlePanStart,
|
|
7669
|
+
children: /* @__PURE__ */ jsxs12("div", { className: "gantt-resourceTimeline-scrollContent", children: [
|
|
7670
|
+
/* @__PURE__ */ jsxs12(
|
|
7671
|
+
"div",
|
|
7672
|
+
{
|
|
7673
|
+
className: "gantt-resourceTimeline-resourceColumn",
|
|
7674
|
+
style: { width: `${rowHeaderWidth}px`, minWidth: `${rowHeaderWidth}px` },
|
|
7675
|
+
children: [
|
|
7676
|
+
/* @__PURE__ */ jsx15(
|
|
7677
|
+
"div",
|
|
7678
|
+
{
|
|
7679
|
+
className: "gantt-resourceTimeline-corner",
|
|
7680
|
+
style: { height: `${headerHeight}px` }
|
|
7681
|
+
}
|
|
7682
|
+
),
|
|
7683
|
+
layout.rows.map((row) => /* @__PURE__ */ jsx15(
|
|
7684
|
+
"div",
|
|
7685
|
+
{
|
|
7686
|
+
className: "gantt-resourceTimeline-resourceHeader",
|
|
7687
|
+
"data-resource-row-id": row.resourceId,
|
|
7688
|
+
style: { height: `${row.resourceRowHeight}px` },
|
|
7689
|
+
children: /* @__PURE__ */ jsx15("span", { className: "gantt-resourceTimeline-resourceName", children: row.resource.name })
|
|
7690
|
+
},
|
|
7691
|
+
row.resourceId
|
|
7692
|
+
))
|
|
7693
|
+
]
|
|
7694
|
+
}
|
|
7695
|
+
),
|
|
7696
|
+
/* @__PURE__ */ jsxs12(
|
|
7697
|
+
"div",
|
|
7698
|
+
{
|
|
7699
|
+
className: "gantt-resourceTimeline-chartSurface",
|
|
7700
|
+
style: { minWidth: `${gridWidth}px` },
|
|
7701
|
+
children: [
|
|
7702
|
+
/* @__PURE__ */ jsx15("div", { className: "gantt-resourceTimeline-stickyHeader", style: { width: `${gridWidth}px` }, children: /* @__PURE__ */ jsx15(TimeScaleHeader_default, { days: dateRange, dayWidth, headerHeight }) }),
|
|
7703
|
+
/* @__PURE__ */ jsxs12(
|
|
7704
|
+
"div",
|
|
7705
|
+
{
|
|
7706
|
+
ref: gridRef,
|
|
7707
|
+
className: "gantt-resourceTimeline-grid",
|
|
7708
|
+
style: { width: `${gridWidth}px`, height: `${layout.totalHeight}px` },
|
|
7709
|
+
children: [
|
|
7710
|
+
/* @__PURE__ */ jsx15(GridBackground_default, { dateRange, dayWidth, totalHeight: layout.totalHeight }),
|
|
7711
|
+
todayInRange && /* @__PURE__ */ jsx15(TodayIndicator_default, { monthStart, dayWidth }),
|
|
7712
|
+
layout.rows.map((row) => /* @__PURE__ */ jsx15(
|
|
7713
|
+
"div",
|
|
7714
|
+
{
|
|
7715
|
+
className: "gantt-resourceTimeline-row",
|
|
7716
|
+
"data-resource-row-id": row.resourceId,
|
|
7717
|
+
style: {
|
|
7718
|
+
top: `${row.resourceRowTop}px`,
|
|
7719
|
+
height: `${row.resourceRowHeight}px`
|
|
7720
|
+
}
|
|
7721
|
+
},
|
|
7722
|
+
row.resourceId
|
|
7723
|
+
)),
|
|
7724
|
+
Array.from(itemsByResourceId.values()).flatMap(
|
|
7725
|
+
(resourceItems) => resourceItems.map((layoutItem) => {
|
|
7726
|
+
const customClassName = getItemClassName?.(layoutItem.item);
|
|
7727
|
+
const className = [
|
|
7728
|
+
"gantt-resourceTimeline-item",
|
|
7729
|
+
preview?.itemId === layoutItem.itemId && "gantt-resourceTimeline-itemDragging",
|
|
7730
|
+
(readonly || layoutItem.item.locked) && "gantt-resourceTimeline-itemDisabled",
|
|
7731
|
+
customClassName
|
|
7732
|
+
].filter(Boolean).join(" ");
|
|
7733
|
+
const laneCount = Math.max(1, Math.round(layoutItem.resourceRowHeight / layoutItem.height));
|
|
7734
|
+
const previewStyle = preview?.itemId === layoutItem.itemId ? getVisualItemGeometry({
|
|
7735
|
+
left: preview.left,
|
|
7736
|
+
top: preview.top,
|
|
7737
|
+
width: layoutItem.width,
|
|
7738
|
+
height: layoutItem.height
|
|
7739
|
+
}, layoutItem.laneIndex, laneCount) : void 0;
|
|
7740
|
+
const itemGeometry = getVisualItemGeometry({
|
|
7741
|
+
left: layoutItem.left,
|
|
7742
|
+
top: layoutItem.top,
|
|
7743
|
+
width: layoutItem.width,
|
|
7744
|
+
height: layoutItem.height
|
|
7745
|
+
}, layoutItem.laneIndex, laneCount);
|
|
7746
|
+
return /* @__PURE__ */ jsx15(
|
|
7747
|
+
"div",
|
|
7748
|
+
{
|
|
7749
|
+
className,
|
|
7750
|
+
"data-resource-item-id": layoutItem.itemId,
|
|
7751
|
+
onMouseDown: (event) => startDrag(event, layoutItem),
|
|
7752
|
+
style: {
|
|
7753
|
+
left: `${itemGeometry.left}px`,
|
|
7754
|
+
top: `${itemGeometry.top}px`,
|
|
7755
|
+
...previewStyle,
|
|
7756
|
+
width: `${itemGeometry.width}px`,
|
|
7757
|
+
height: `${itemGeometry.height}px`,
|
|
7758
|
+
backgroundColor: layoutItem.item.color ?? "var(--gantt-task-bar-default-color, #3b82f6)"
|
|
7759
|
+
},
|
|
7760
|
+
children: /* @__PURE__ */ jsx15("div", { className: "gantt-resourceTimeline-itemInner", children: renderItem ? renderItem(layoutItem.item) : /* @__PURE__ */ jsxs12(Fragment3, { children: [
|
|
7761
|
+
/* @__PURE__ */ jsx15("span", { className: "gantt-resourceTimeline-itemTitle", children: layoutItem.item.title }),
|
|
7762
|
+
layoutItem.item.subtitle && /* @__PURE__ */ jsx15("span", { className: "gantt-resourceTimeline-itemSubtitle", children: layoutItem.item.subtitle }),
|
|
7763
|
+
/* @__PURE__ */ jsx15("span", { className: "gantt-resourceTimeline-itemDates", children: formatDateRangeLabel(layoutItem.startDate, layoutItem.endDate) })
|
|
7764
|
+
] }) })
|
|
7765
|
+
},
|
|
7766
|
+
layoutItem.itemId
|
|
7767
|
+
);
|
|
7768
|
+
})
|
|
7769
|
+
)
|
|
7770
|
+
]
|
|
7771
|
+
}
|
|
7772
|
+
)
|
|
7773
|
+
]
|
|
7774
|
+
}
|
|
7775
|
+
)
|
|
7776
|
+
] })
|
|
7777
|
+
}
|
|
7778
|
+
) });
|
|
7779
|
+
}
|
|
7780
|
+
|
|
7265
7781
|
// src/components/GanttChart/print.ts
|
|
7266
7782
|
function getPrintDocumentTitle({
|
|
7267
7783
|
header,
|
|
@@ -7600,9 +8116,21 @@ async function printGanttChart({
|
|
|
7600
8116
|
}
|
|
7601
8117
|
|
|
7602
8118
|
// src/components/GanttChart/GanttChart.tsx
|
|
7603
|
-
import { jsx as
|
|
8119
|
+
import { jsx as jsx16, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
7604
8120
|
var SCROLL_TO_ROW_CONTEXT_ROWS = 2;
|
|
7605
8121
|
function GanttChartInner(props, ref) {
|
|
8122
|
+
if (props.mode === "resource-planner") {
|
|
8123
|
+
return /* @__PURE__ */ jsx16(ResourceTimelineChart, { ...props });
|
|
8124
|
+
}
|
|
8125
|
+
return /* @__PURE__ */ jsx16(
|
|
8126
|
+
TaskGanttChart,
|
|
8127
|
+
{
|
|
8128
|
+
...props,
|
|
8129
|
+
ref
|
|
8130
|
+
}
|
|
8131
|
+
);
|
|
8132
|
+
}
|
|
8133
|
+
function TaskGanttChartInner(props, ref) {
|
|
7606
8134
|
const {
|
|
7607
8135
|
tasks,
|
|
7608
8136
|
dayWidth = 40,
|
|
@@ -7642,28 +8170,28 @@ function GanttChartInner(props, ref) {
|
|
|
7642
8170
|
additionalColumns,
|
|
7643
8171
|
taskListMenuCommands
|
|
7644
8172
|
} = props;
|
|
7645
|
-
const containerRef =
|
|
7646
|
-
const scrollContainerRef =
|
|
7647
|
-
const scrollContentRef =
|
|
7648
|
-
const [selectedTaskId, setSelectedTaskId] =
|
|
7649
|
-
const [taskListHasRightShadow, setTaskListHasRightShadow] =
|
|
7650
|
-
const [selectedChip, setSelectedChip] =
|
|
7651
|
-
const [internalCollapsedParentIds, setInternalCollapsedParentIds] =
|
|
8173
|
+
const containerRef = useRef9(null);
|
|
8174
|
+
const scrollContainerRef = useRef9(null);
|
|
8175
|
+
const scrollContentRef = useRef9(null);
|
|
8176
|
+
const [selectedTaskId, setSelectedTaskId] = useState8(null);
|
|
8177
|
+
const [taskListHasRightShadow, setTaskListHasRightShadow] = useState8(false);
|
|
8178
|
+
const [selectedChip, setSelectedChip] = useState8(null);
|
|
8179
|
+
const [internalCollapsedParentIds, setInternalCollapsedParentIds] = useState8(/* @__PURE__ */ new Set());
|
|
7652
8180
|
const collapsedParentIds = externalCollapsedParentIds ?? internalCollapsedParentIds;
|
|
7653
|
-
const [editingTaskId, setEditingTaskId] =
|
|
7654
|
-
const normalizedTasks =
|
|
7655
|
-
const isCustomWeekend =
|
|
8181
|
+
const [editingTaskId, setEditingTaskId] = useState8(null);
|
|
8182
|
+
const normalizedTasks = useMemo10(() => normalizeHierarchyTasks(tasks), [tasks]);
|
|
8183
|
+
const isCustomWeekend = useMemo10(
|
|
7656
8184
|
() => createCustomDayPredicate({ customDays, isWeekend: isWeekend3 }),
|
|
7657
8185
|
[customDays, isWeekend3]
|
|
7658
8186
|
);
|
|
7659
|
-
const dateRange =
|
|
7660
|
-
const [validationResult, setValidationResult] =
|
|
7661
|
-
const [cascadeOverrides, setCascadeOverrides] =
|
|
7662
|
-
const gridWidth =
|
|
8187
|
+
const dateRange = useMemo10(() => getMultiMonthDays(normalizedTasks), [normalizedTasks]);
|
|
8188
|
+
const [validationResult, setValidationResult] = useState8(null);
|
|
8189
|
+
const [cascadeOverrides, setCascadeOverrides] = useState8(/* @__PURE__ */ new Map());
|
|
8190
|
+
const gridWidth = useMemo10(
|
|
7663
8191
|
() => Math.round(dateRange.length * dayWidth),
|
|
7664
8192
|
[dateRange.length, dayWidth]
|
|
7665
8193
|
);
|
|
7666
|
-
const visibleTasks =
|
|
8194
|
+
const visibleTasks = useMemo10(() => {
|
|
7667
8195
|
const parentMap = new Map(normalizedTasks.map((t) => [t.id, t.parentId]));
|
|
7668
8196
|
function isAnyAncestorCollapsed(parentId) {
|
|
7669
8197
|
let current = parentId;
|
|
@@ -7679,11 +8207,11 @@ function GanttChartInner(props, ref) {
|
|
|
7679
8207
|
}
|
|
7680
8208
|
return tasks2;
|
|
7681
8209
|
}, [normalizedTasks, collapsedParentIds, filterMode, taskFilter]);
|
|
7682
|
-
const matchedTaskIds =
|
|
8210
|
+
const matchedTaskIds = useMemo10(() => {
|
|
7683
8211
|
if (!taskFilter) return /* @__PURE__ */ new Set();
|
|
7684
8212
|
return new Set(visibleTasks.filter(taskFilter).map((task) => task.id));
|
|
7685
8213
|
}, [visibleTasks, taskFilter]);
|
|
7686
|
-
const taskListHighlightedTaskIds =
|
|
8214
|
+
const taskListHighlightedTaskIds = useMemo10(() => {
|
|
7687
8215
|
if (filterMode === "hide") {
|
|
7688
8216
|
return /* @__PURE__ */ new Set();
|
|
7689
8217
|
}
|
|
@@ -7694,23 +8222,23 @@ function GanttChartInner(props, ref) {
|
|
|
7694
8222
|
matchedTaskIds.forEach((taskId) => mergedHighlightedTaskIds.add(taskId));
|
|
7695
8223
|
return mergedHighlightedTaskIds;
|
|
7696
8224
|
}, [filterMode, highlightedTaskIds, matchedTaskIds]);
|
|
7697
|
-
const totalGridHeight =
|
|
8225
|
+
const totalGridHeight = useMemo10(
|
|
7698
8226
|
() => visibleTasks.length * rowHeight,
|
|
7699
8227
|
[visibleTasks.length, rowHeight]
|
|
7700
8228
|
);
|
|
7701
|
-
const monthStart =
|
|
8229
|
+
const monthStart = useMemo10(() => {
|
|
7702
8230
|
if (dateRange.length === 0) {
|
|
7703
8231
|
return new Date(Date.UTC((/* @__PURE__ */ new Date()).getUTCFullYear(), (/* @__PURE__ */ new Date()).getUTCMonth(), 1));
|
|
7704
8232
|
}
|
|
7705
8233
|
const firstDay = dateRange[0];
|
|
7706
8234
|
return new Date(Date.UTC(firstDay.getUTCFullYear(), firstDay.getUTCMonth(), 1));
|
|
7707
8235
|
}, [dateRange]);
|
|
7708
|
-
const todayInRange =
|
|
8236
|
+
const todayInRange = useMemo10(() => {
|
|
7709
8237
|
const now = /* @__PURE__ */ new Date();
|
|
7710
8238
|
const today = new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate()));
|
|
7711
8239
|
return dateRange.some((day) => day.getTime() === today.getTime());
|
|
7712
8240
|
}, [dateRange]);
|
|
7713
|
-
|
|
8241
|
+
useEffect9(() => {
|
|
7714
8242
|
const container = scrollContainerRef.current;
|
|
7715
8243
|
if (!container || dateRange.length === 0) return;
|
|
7716
8244
|
const now = /* @__PURE__ */ new Date();
|
|
@@ -7722,7 +8250,7 @@ function GanttChartInner(props, ref) {
|
|
|
7722
8250
|
const scrollLeft = Math.round(todayOffset + dayWidth / 2 - containerWidth * 0.3);
|
|
7723
8251
|
container.scrollLeft = Math.max(0, scrollLeft);
|
|
7724
8252
|
}, []);
|
|
7725
|
-
|
|
8253
|
+
useEffect9(() => {
|
|
7726
8254
|
const container = scrollContainerRef.current;
|
|
7727
8255
|
if (!container) return;
|
|
7728
8256
|
const updateShadow = () => {
|
|
@@ -7734,7 +8262,7 @@ function GanttChartInner(props, ref) {
|
|
|
7734
8262
|
container.removeEventListener("scroll", updateShadow);
|
|
7735
8263
|
};
|
|
7736
8264
|
}, []);
|
|
7737
|
-
const scrollToToday =
|
|
8265
|
+
const scrollToToday = useCallback8(() => {
|
|
7738
8266
|
const container = scrollContainerRef.current;
|
|
7739
8267
|
if (!container || dateRange.length === 0) return;
|
|
7740
8268
|
const now = /* @__PURE__ */ new Date();
|
|
@@ -7746,7 +8274,7 @@ function GanttChartInner(props, ref) {
|
|
|
7746
8274
|
const scrollLeft = Math.round(todayOffset + dayWidth / 2 - containerWidth * 0.3);
|
|
7747
8275
|
container.scrollTo({ left: Math.max(0, scrollLeft), behavior: "smooth" });
|
|
7748
8276
|
}, [dateRange, dayWidth]);
|
|
7749
|
-
const scrollToTask =
|
|
8277
|
+
const scrollToTask = useCallback8((taskId) => {
|
|
7750
8278
|
const container = scrollContainerRef.current;
|
|
7751
8279
|
if (!container || dateRange.length === 0) return;
|
|
7752
8280
|
const task = tasks.find((t) => t.id === taskId);
|
|
@@ -7763,7 +8291,7 @@ function GanttChartInner(props, ref) {
|
|
|
7763
8291
|
const scrollLeft = Math.round(taskOffset - dayWidth * 2);
|
|
7764
8292
|
container.scrollTo({ left: Math.max(0, scrollLeft), behavior: "smooth" });
|
|
7765
8293
|
}, [tasks, dateRange, dayWidth]);
|
|
7766
|
-
const scrollToRow =
|
|
8294
|
+
const scrollToRow = useCallback8((taskId) => {
|
|
7767
8295
|
const container = scrollContainerRef.current;
|
|
7768
8296
|
if (!container) return;
|
|
7769
8297
|
const task = tasks.find((t) => t.id === taskId);
|
|
@@ -7775,15 +8303,15 @@ function GanttChartInner(props, ref) {
|
|
|
7775
8303
|
setSelectedTaskId(taskId);
|
|
7776
8304
|
container.scrollTo({ top: scrollTop, behavior: "smooth" });
|
|
7777
8305
|
}, [tasks, visibleTasks, rowHeight]);
|
|
7778
|
-
const [dragGuideLines, setDragGuideLines] =
|
|
7779
|
-
const [draggedTaskOverride, setDraggedTaskOverride] =
|
|
7780
|
-
const [previewTasksById, setPreviewTasksById] =
|
|
7781
|
-
|
|
8306
|
+
const [dragGuideLines, setDragGuideLines] = useState8(null);
|
|
8307
|
+
const [draggedTaskOverride, setDraggedTaskOverride] = useState8(null);
|
|
8308
|
+
const [previewTasksById, setPreviewTasksById] = useState8(/* @__PURE__ */ new Map());
|
|
8309
|
+
useEffect9(() => {
|
|
7782
8310
|
const result = validateDependencies(tasks);
|
|
7783
8311
|
setValidationResult(result);
|
|
7784
8312
|
onValidateDependencies?.(result);
|
|
7785
8313
|
}, [tasks, onValidateDependencies]);
|
|
7786
|
-
const handleTaskChange =
|
|
8314
|
+
const handleTaskChange = useCallback8((updatedTasks) => {
|
|
7787
8315
|
const updatedTask = updatedTasks[0];
|
|
7788
8316
|
if (!updatedTask) return;
|
|
7789
8317
|
const originalTask = tasks.find((t) => t.id === updatedTask.id);
|
|
@@ -7829,7 +8357,7 @@ function GanttChartInner(props, ref) {
|
|
|
7829
8357
|
const cascadedTasks = disableConstraints ? [updatedTask] : universalCascade(updatedTask, newStart, newEnd, sourceTasks, businessDays, isCustomWeekend);
|
|
7830
8358
|
onTasksChange?.(cascadedTasks);
|
|
7831
8359
|
}, [tasks, onTasksChange, disableConstraints, editingTaskId, businessDays, isCustomWeekend]);
|
|
7832
|
-
const handleDelete =
|
|
8360
|
+
const handleDelete = useCallback8((taskId) => {
|
|
7833
8361
|
const toDelete = /* @__PURE__ */ new Set([taskId]);
|
|
7834
8362
|
function collectDescendants(parentId) {
|
|
7835
8363
|
const children = getChildren(parentId, tasks);
|
|
@@ -7854,10 +8382,10 @@ function GanttChartInner(props, ref) {
|
|
|
7854
8382
|
}
|
|
7855
8383
|
toDelete.forEach((id) => onDelete?.(id));
|
|
7856
8384
|
}, [tasks, onTasksChange, onDelete]);
|
|
7857
|
-
const handleInsertAfter =
|
|
8385
|
+
const handleInsertAfter = useCallback8((taskId, newTask) => {
|
|
7858
8386
|
onInsertAfter?.(taskId, newTask);
|
|
7859
8387
|
}, [onInsertAfter]);
|
|
7860
|
-
const handleReorder =
|
|
8388
|
+
const handleReorder = useCallback8((reorderedTasks, movedTaskId, inferredParentId) => {
|
|
7861
8389
|
let updated = reorderedTasks;
|
|
7862
8390
|
if (movedTaskId) {
|
|
7863
8391
|
updated = updated.map((t) => {
|
|
@@ -7874,7 +8402,7 @@ function GanttChartInner(props, ref) {
|
|
|
7874
8402
|
}
|
|
7875
8403
|
onTasksChange?.(normalized);
|
|
7876
8404
|
}, [onTasksChange, onReorder]);
|
|
7877
|
-
const dependencyOverrides =
|
|
8405
|
+
const dependencyOverrides = useMemo10(() => {
|
|
7878
8406
|
const map = new Map(cascadeOverrides);
|
|
7879
8407
|
if (draggedTaskOverride) {
|
|
7880
8408
|
map.set(draggedTaskOverride.taskId, {
|
|
@@ -7884,25 +8412,25 @@ function GanttChartInner(props, ref) {
|
|
|
7884
8412
|
}
|
|
7885
8413
|
return map;
|
|
7886
8414
|
}, [cascadeOverrides, draggedTaskOverride]);
|
|
7887
|
-
const handleCascadeProgress =
|
|
8415
|
+
const handleCascadeProgress = useCallback8((overrides, previewTasks = []) => {
|
|
7888
8416
|
setCascadeOverrides(new Map(overrides));
|
|
7889
8417
|
setPreviewTasksById(new Map(previewTasks.map((task) => [task.id, task])));
|
|
7890
8418
|
}, []);
|
|
7891
|
-
const previewNormalizedTasks =
|
|
8419
|
+
const previewNormalizedTasks = useMemo10(() => {
|
|
7892
8420
|
if (previewTasksById.size === 0) return normalizedTasks;
|
|
7893
8421
|
return normalizedTasks.map((task) => previewTasksById.get(task.id) ?? task);
|
|
7894
8422
|
}, [normalizedTasks, previewTasksById]);
|
|
7895
|
-
const previewVisibleTasks =
|
|
8423
|
+
const previewVisibleTasks = useMemo10(() => {
|
|
7896
8424
|
if (previewTasksById.size === 0) return visibleTasks;
|
|
7897
8425
|
return visibleTasks.map((task) => previewTasksById.get(task.id) ?? task);
|
|
7898
8426
|
}, [visibleTasks, previewTasksById]);
|
|
7899
|
-
const handleCascade =
|
|
8427
|
+
const handleCascade = useCallback8((cascadedTasks) => {
|
|
7900
8428
|
onTasksChange?.(cascadedTasks);
|
|
7901
8429
|
}, [tasks, onTasksChange]);
|
|
7902
|
-
const handleTaskSelect =
|
|
8430
|
+
const handleTaskSelect = useCallback8((taskId) => {
|
|
7903
8431
|
setSelectedTaskId(taskId);
|
|
7904
8432
|
}, []);
|
|
7905
|
-
const handleToggleCollapse = externalOnToggleCollapse ??
|
|
8433
|
+
const handleToggleCollapse = externalOnToggleCollapse ?? useCallback8((parentId) => {
|
|
7906
8434
|
setInternalCollapsedParentIds((prev) => {
|
|
7907
8435
|
const next = new Set(prev);
|
|
7908
8436
|
if (next.has(parentId)) {
|
|
@@ -7913,20 +8441,20 @@ function GanttChartInner(props, ref) {
|
|
|
7913
8441
|
return next;
|
|
7914
8442
|
});
|
|
7915
8443
|
}, []);
|
|
7916
|
-
const allParentIds =
|
|
8444
|
+
const allParentIds = useMemo10(() => {
|
|
7917
8445
|
return new Set(
|
|
7918
8446
|
normalizedTasks.filter((t) => isTaskParent(t.id, normalizedTasks)).map((t) => t.id)
|
|
7919
8447
|
);
|
|
7920
8448
|
}, [normalizedTasks]);
|
|
7921
|
-
const handleCollapseAll =
|
|
8449
|
+
const handleCollapseAll = useCallback8(() => {
|
|
7922
8450
|
if (externalCollapsedParentIds) return;
|
|
7923
8451
|
setInternalCollapsedParentIds(allParentIds);
|
|
7924
8452
|
}, [allParentIds, externalCollapsedParentIds]);
|
|
7925
|
-
const handleExpandAll =
|
|
8453
|
+
const handleExpandAll = useCallback8(() => {
|
|
7926
8454
|
if (externalCollapsedParentIds) return;
|
|
7927
8455
|
setInternalCollapsedParentIds(/* @__PURE__ */ new Set());
|
|
7928
8456
|
}, [externalCollapsedParentIds]);
|
|
7929
|
-
const exportToPdf =
|
|
8457
|
+
const exportToPdf = useCallback8(async (options) => {
|
|
7930
8458
|
const sourceContainer = containerRef.current;
|
|
7931
8459
|
const sourceContent = scrollContentRef.current;
|
|
7932
8460
|
if (!sourceContainer || !sourceContent || typeof window === "undefined" || typeof document === "undefined") {
|
|
@@ -7985,7 +8513,7 @@ function GanttChartInner(props, ref) {
|
|
|
7985
8513
|
}
|
|
7986
8514
|
return depth;
|
|
7987
8515
|
}
|
|
7988
|
-
const handlePromoteTask =
|
|
8516
|
+
const handlePromoteTask = useCallback8((taskId) => {
|
|
7989
8517
|
if (onPromoteTask) {
|
|
7990
8518
|
onPromoteTask(taskId);
|
|
7991
8519
|
return;
|
|
@@ -8015,7 +8543,7 @@ function GanttChartInner(props, ref) {
|
|
|
8015
8543
|
]);
|
|
8016
8544
|
onTasksChange?.(reorderedTasks);
|
|
8017
8545
|
}, [tasks, onTasksChange, onPromoteTask]);
|
|
8018
|
-
const handleDemoteTask =
|
|
8546
|
+
const handleDemoteTask = useCallback8((taskId, newParentId) => {
|
|
8019
8547
|
if (onDemoteTask) {
|
|
8020
8548
|
onDemoteTask(taskId, newParentId);
|
|
8021
8549
|
return;
|
|
@@ -8056,7 +8584,7 @@ function GanttChartInner(props, ref) {
|
|
|
8056
8584
|
};
|
|
8057
8585
|
onTasksChange?.([updatedDemotedTask]);
|
|
8058
8586
|
}, [tasks, onTasksChange, onDemoteTask]);
|
|
8059
|
-
const handleUngroupTask =
|
|
8587
|
+
const handleUngroupTask = useCallback8((taskId) => {
|
|
8060
8588
|
if (onUngroupTask) {
|
|
8061
8589
|
onUngroupTask(taskId);
|
|
8062
8590
|
return;
|
|
@@ -8083,8 +8611,8 @@ function GanttChartInner(props, ref) {
|
|
|
8083
8611
|
}
|
|
8084
8612
|
onDelete?.(taskId);
|
|
8085
8613
|
}, [tasks, onTasksChange, onDelete, onUngroupTask]);
|
|
8086
|
-
const panStateRef =
|
|
8087
|
-
const handlePanStart =
|
|
8614
|
+
const panStateRef = useRef9(null);
|
|
8615
|
+
const handlePanStart = useCallback8((e) => {
|
|
8088
8616
|
if (e.button !== 0) return;
|
|
8089
8617
|
const target = e.target;
|
|
8090
8618
|
if (target.closest("[data-taskbar]")) return;
|
|
@@ -8105,7 +8633,7 @@ function GanttChartInner(props, ref) {
|
|
|
8105
8633
|
container.style.cursor = "grabbing";
|
|
8106
8634
|
e.preventDefault();
|
|
8107
8635
|
}, []);
|
|
8108
|
-
|
|
8636
|
+
useEffect9(() => {
|
|
8109
8637
|
const handlePanMove = (e) => {
|
|
8110
8638
|
const pan = panStateRef.current;
|
|
8111
8639
|
if (!pan?.active) return;
|
|
@@ -8127,15 +8655,15 @@ function GanttChartInner(props, ref) {
|
|
|
8127
8655
|
window.removeEventListener("mouseup", handlePanEnd);
|
|
8128
8656
|
};
|
|
8129
8657
|
}, []);
|
|
8130
|
-
return /* @__PURE__ */
|
|
8658
|
+
return /* @__PURE__ */ jsx16("div", { ref: containerRef, className: "gantt-container", children: /* @__PURE__ */ jsx16(
|
|
8131
8659
|
"div",
|
|
8132
8660
|
{
|
|
8133
8661
|
ref: scrollContainerRef,
|
|
8134
8662
|
className: "gantt-scrollContainer",
|
|
8135
8663
|
style: { height: containerHeight ?? "auto", cursor: "grab" },
|
|
8136
8664
|
onMouseDown: handlePanStart,
|
|
8137
|
-
children: /* @__PURE__ */
|
|
8138
|
-
/* @__PURE__ */
|
|
8665
|
+
children: /* @__PURE__ */ jsxs13("div", { ref: scrollContentRef, className: "gantt-scrollContent", children: [
|
|
8666
|
+
/* @__PURE__ */ jsx16(
|
|
8139
8667
|
TaskList,
|
|
8140
8668
|
{
|
|
8141
8669
|
tasks: normalizedTasks,
|
|
@@ -8173,13 +8701,13 @@ function GanttChartInner(props, ref) {
|
|
|
8173
8701
|
taskListMenuCommands
|
|
8174
8702
|
}
|
|
8175
8703
|
),
|
|
8176
|
-
/* @__PURE__ */
|
|
8704
|
+
/* @__PURE__ */ jsxs13(
|
|
8177
8705
|
"div",
|
|
8178
8706
|
{
|
|
8179
8707
|
className: showChart ? "gantt-chartSurface" : "gantt-chartSurface gantt-chart-hidden",
|
|
8180
8708
|
style: { minWidth: `${gridWidth}px`, flex: 1, display: showChart ? void 0 : "none" },
|
|
8181
8709
|
children: [
|
|
8182
|
-
/* @__PURE__ */
|
|
8710
|
+
/* @__PURE__ */ jsx16("div", { className: "gantt-stickyHeader", style: { width: `${gridWidth}px` }, children: /* @__PURE__ */ jsx16(
|
|
8183
8711
|
TimeScaleHeader_default,
|
|
8184
8712
|
{
|
|
8185
8713
|
days: dateRange,
|
|
@@ -8189,7 +8717,7 @@ function GanttChartInner(props, ref) {
|
|
|
8189
8717
|
isCustomWeekend
|
|
8190
8718
|
}
|
|
8191
8719
|
) }),
|
|
8192
|
-
/* @__PURE__ */
|
|
8720
|
+
/* @__PURE__ */ jsxs13(
|
|
8193
8721
|
"div",
|
|
8194
8722
|
{
|
|
8195
8723
|
className: "gantt-taskArea",
|
|
@@ -8198,7 +8726,7 @@ function GanttChartInner(props, ref) {
|
|
|
8198
8726
|
width: `${gridWidth}px`
|
|
8199
8727
|
},
|
|
8200
8728
|
children: [
|
|
8201
|
-
/* @__PURE__ */
|
|
8729
|
+
/* @__PURE__ */ jsx16(
|
|
8202
8730
|
GridBackground_default,
|
|
8203
8731
|
{
|
|
8204
8732
|
dateRange,
|
|
@@ -8208,8 +8736,8 @@ function GanttChartInner(props, ref) {
|
|
|
8208
8736
|
isCustomWeekend
|
|
8209
8737
|
}
|
|
8210
8738
|
),
|
|
8211
|
-
todayInRange && /* @__PURE__ */
|
|
8212
|
-
/* @__PURE__ */
|
|
8739
|
+
todayInRange && /* @__PURE__ */ jsx16(TodayIndicator_default, { monthStart, dayWidth }),
|
|
8740
|
+
/* @__PURE__ */ jsx16(
|
|
8213
8741
|
DependencyLines_default,
|
|
8214
8742
|
{
|
|
8215
8743
|
tasks: previewVisibleTasks,
|
|
@@ -8225,7 +8753,7 @@ function GanttChartInner(props, ref) {
|
|
|
8225
8753
|
weekendPredicate: isCustomWeekend
|
|
8226
8754
|
}
|
|
8227
8755
|
),
|
|
8228
|
-
dragGuideLines && /* @__PURE__ */
|
|
8756
|
+
dragGuideLines && /* @__PURE__ */ jsx16(
|
|
8229
8757
|
DragGuideLines_default,
|
|
8230
8758
|
{
|
|
8231
8759
|
isDragging: dragGuideLines.isDragging,
|
|
@@ -8235,7 +8763,7 @@ function GanttChartInner(props, ref) {
|
|
|
8235
8763
|
totalHeight: totalGridHeight
|
|
8236
8764
|
}
|
|
8237
8765
|
),
|
|
8238
|
-
visibleTasks.map((task, index) => /* @__PURE__ */
|
|
8766
|
+
visibleTasks.map((task, index) => /* @__PURE__ */ jsx16(
|
|
8239
8767
|
TaskRow_default,
|
|
8240
8768
|
{
|
|
8241
8769
|
task,
|
|
@@ -8279,13 +8807,14 @@ function GanttChartInner(props, ref) {
|
|
|
8279
8807
|
}
|
|
8280
8808
|
) });
|
|
8281
8809
|
}
|
|
8810
|
+
var TaskGanttChart = forwardRef(TaskGanttChartInner);
|
|
8282
8811
|
var GanttChart = forwardRef(GanttChartInner);
|
|
8283
8812
|
GanttChart.displayName = "GanttChart";
|
|
8284
8813
|
|
|
8285
8814
|
// src/components/ui/Button.tsx
|
|
8286
|
-
import
|
|
8287
|
-
import { jsx as
|
|
8288
|
-
var Button =
|
|
8815
|
+
import React14 from "react";
|
|
8816
|
+
import { jsx as jsx17 } from "react/jsx-runtime";
|
|
8817
|
+
var Button = React14.forwardRef(
|
|
8289
8818
|
({ className, variant = "default", size = "default", children, ...props }, ref) => {
|
|
8290
8819
|
const classes = [
|
|
8291
8820
|
"gantt-btn",
|
|
@@ -8293,7 +8822,7 @@ var Button = React13.forwardRef(
|
|
|
8293
8822
|
size !== "default" ? `gantt-btn-${size}` : "",
|
|
8294
8823
|
className || ""
|
|
8295
8824
|
].filter(Boolean).join(" ");
|
|
8296
|
-
return /* @__PURE__ */
|
|
8825
|
+
return /* @__PURE__ */ jsx17("button", { ref, className: classes, ...props, children });
|
|
8297
8826
|
}
|
|
8298
8827
|
);
|
|
8299
8828
|
Button.displayName = "Button";
|
|
@@ -8338,6 +8867,7 @@ export {
|
|
|
8338
8867
|
Popover,
|
|
8339
8868
|
PopoverContent,
|
|
8340
8869
|
PopoverTrigger,
|
|
8870
|
+
ResourceTimelineChart,
|
|
8341
8871
|
TaskList,
|
|
8342
8872
|
TaskRow_default as TaskRow,
|
|
8343
8873
|
TimeScaleHeader_default as TimeScaleHeader,
|
|
@@ -8401,6 +8931,7 @@ export {
|
|
|
8401
8931
|
isTaskParent,
|
|
8402
8932
|
isToday,
|
|
8403
8933
|
isWeekend,
|
|
8934
|
+
layoutResourceTimelineItems,
|
|
8404
8935
|
moveTaskRange,
|
|
8405
8936
|
moveTaskWithCascade,
|
|
8406
8937
|
nameContains,
|