gantt-lib 0.75.1 → 0.76.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -7305,12 +7305,86 @@ var compareParsedItems = (a, b) => {
7305
7305
  }
7306
7306
  return a.item.id.localeCompare(b.item.id);
7307
7307
  };
7308
+ var getOverlapRange = (left, right) => {
7309
+ const startDay = Math.max(getUTCDayNumber(left.startDate), getUTCDayNumber(right.startDate));
7310
+ const endDay = Math.min(getUTCDayNumber(left.endDate), getUTCDayNumber(right.endDate));
7311
+ if (startDay > endDay) {
7312
+ return null;
7313
+ }
7314
+ return {
7315
+ startDate: new Date(startDay * 864e5),
7316
+ endDate: new Date(endDay * 864e5),
7317
+ itemIds: [left.item.id, right.item.id]
7318
+ };
7319
+ };
7320
+ var mergeConflictRanges = (ranges) => {
7321
+ const sortedRanges = [...ranges].sort(
7322
+ (left, right) => getUTCDayNumber(left.startDate) - getUTCDayNumber(right.startDate) || getUTCDayNumber(left.endDate) - getUTCDayNumber(right.endDate)
7323
+ );
7324
+ const merged = [];
7325
+ for (const range of sortedRanges) {
7326
+ const previous = merged[merged.length - 1];
7327
+ const rangeStartDay = getUTCDayNumber(range.startDate);
7328
+ const rangeEndDay = getUTCDayNumber(range.endDate);
7329
+ if (!previous || rangeStartDay > getUTCDayNumber(previous.endDate) + 1) {
7330
+ merged.push({
7331
+ startDate: range.startDate,
7332
+ endDate: range.endDate,
7333
+ itemIds: [...range.itemIds]
7334
+ });
7335
+ continue;
7336
+ }
7337
+ if (rangeEndDay > getUTCDayNumber(previous.endDate)) {
7338
+ previous.endDate = range.endDate;
7339
+ }
7340
+ previous.itemIds = Array.from(/* @__PURE__ */ new Set([...previous.itemIds, ...range.itemIds])).sort();
7341
+ }
7342
+ return merged;
7343
+ };
7344
+ var calculateConflictInfo = (parsedItems) => {
7345
+ const conflictRangesByItemId = /* @__PURE__ */ new Map();
7346
+ const conflictsWithByItemId = /* @__PURE__ */ new Map();
7347
+ for (let i = 0; i < parsedItems.length; i++) {
7348
+ for (let j = i + 1; j < parsedItems.length; j++) {
7349
+ const left = parsedItems[i];
7350
+ const right = parsedItems[j];
7351
+ if (getUTCDayNumber(right.startDate) > getUTCDayNumber(left.endDate)) {
7352
+ break;
7353
+ }
7354
+ const overlap = getOverlapRange(left, right);
7355
+ if (!overlap) {
7356
+ continue;
7357
+ }
7358
+ const leftRanges = conflictRangesByItemId.get(left.item.id) ?? [];
7359
+ const rightRanges = conflictRangesByItemId.get(right.item.id) ?? [];
7360
+ leftRanges.push(overlap);
7361
+ rightRanges.push(overlap);
7362
+ conflictRangesByItemId.set(left.item.id, leftRanges);
7363
+ conflictRangesByItemId.set(right.item.id, rightRanges);
7364
+ const leftConflicts = conflictsWithByItemId.get(left.item.id) ?? /* @__PURE__ */ new Set();
7365
+ const rightConflicts = conflictsWithByItemId.get(right.item.id) ?? /* @__PURE__ */ new Set();
7366
+ leftConflicts.add(right.item.id);
7367
+ rightConflicts.add(left.item.id);
7368
+ conflictsWithByItemId.set(left.item.id, leftConflicts);
7369
+ conflictsWithByItemId.set(right.item.id, rightConflicts);
7370
+ }
7371
+ }
7372
+ const result = /* @__PURE__ */ new Map();
7373
+ for (const parsedItem of parsedItems) {
7374
+ result.set(parsedItem.item.id, {
7375
+ conflictRanges: mergeConflictRanges(conflictRangesByItemId.get(parsedItem.item.id) ?? []),
7376
+ conflictsWith: Array.from(conflictsWithByItemId.get(parsedItem.item.id) ?? []).sort()
7377
+ });
7378
+ }
7379
+ return result;
7380
+ };
7308
7381
  var layoutResourceTimelineItems = (resources, options) => {
7309
7382
  const rows = [];
7310
7383
  const items = [];
7311
7384
  const diagnostics = [];
7312
7385
  let currentTop = 0;
7313
- for (const resource of resources) {
7386
+ const rowGap = options.rowGap ?? 0;
7387
+ resources.forEach((resource, resourceIndex) => {
7314
7388
  const parsedItems = [];
7315
7389
  for (const item of resource.items) {
7316
7390
  try {
@@ -7329,6 +7403,7 @@ var layoutResourceTimelineItems = (resources, options) => {
7329
7403
  }
7330
7404
  }
7331
7405
  parsedItems.sort(compareParsedItems);
7406
+ const conflictInfoByItemId = calculateConflictInfo(parsedItems);
7332
7407
  const laneEndDays = [];
7333
7408
  const laidOutItems = [];
7334
7409
  for (const parsed of parsedItems) {
@@ -7342,6 +7417,7 @@ var layoutResourceTimelineItems = (resources, options) => {
7342
7417
  laneEndDays[laneIndex] = endDay;
7343
7418
  }
7344
7419
  const { left, width } = calculateTaskBar(parsed.startDate, parsed.endDate, options.monthStart, options.dayWidth);
7420
+ const conflictInfo = conflictInfoByItemId.get(parsed.item.id);
7345
7421
  laidOutItems.push({
7346
7422
  item: parsed.item,
7347
7423
  itemId: parsed.item.id,
@@ -7354,15 +7430,19 @@ var layoutResourceTimelineItems = (resources, options) => {
7354
7430
  top: currentTop + laneIndex * options.laneHeight,
7355
7431
  height: options.laneHeight,
7356
7432
  startDate: parsed.startDate,
7357
- endDate: parsed.endDate
7433
+ endDate: parsed.endDate,
7434
+ conflictRanges: conflictInfo?.conflictRanges ?? [],
7435
+ conflictsWith: conflictInfo?.conflictsWith ?? []
7358
7436
  });
7359
7437
  }
7360
7438
  const laneCount = Math.max(1, laneEndDays.length);
7361
7439
  const resourceRowHeight = laneCount * options.laneHeight;
7440
+ const conflictCount = laidOutItems.filter((item) => item.conflictsWith.length > 0).length;
7362
7441
  const row = {
7363
7442
  resource,
7364
7443
  resourceId: resource.id,
7365
7444
  laneCount,
7445
+ conflictCount,
7366
7446
  resourceRowTop: currentTop,
7367
7447
  resourceRowHeight
7368
7448
  };
@@ -7371,8 +7451,8 @@ var layoutResourceTimelineItems = (resources, options) => {
7371
7451
  ...item,
7372
7452
  resourceRowHeight
7373
7453
  })));
7374
- currentTop += resourceRowHeight;
7375
- }
7454
+ currentTop += resourceRowHeight + rowGap;
7455
+ });
7376
7456
  return {
7377
7457
  rows,
7378
7458
  items,
@@ -7389,6 +7469,56 @@ var snapToDay = (pixels, dayWidth) => {
7389
7469
  var addUTCDays = (date, days) => {
7390
7470
  return new Date(Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate() + days));
7391
7471
  };
7472
+ var getDayOffset2 = (date, monthStart) => {
7473
+ return Math.round(
7474
+ (Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate()) - Date.UTC(monthStart.getUTCFullYear(), monthStart.getUTCMonth(), monthStart.getUTCDate())) / (24 * 60 * 60 * 1e3)
7475
+ );
7476
+ };
7477
+ var resolveResourceMoveRange = (activeDrag, nextLeft, nextWidth) => {
7478
+ const dayOffset = Math.round(nextLeft / activeDrag.dayWidth);
7479
+ const durationDays = Math.round(nextWidth / activeDrag.dayWidth);
7480
+ const rawStartDate = addUTCDays(activeDrag.monthStart, dayOffset);
7481
+ const rawEndDate = addUTCDays(rawStartDate, durationDays - 1);
7482
+ if (!activeDrag.businessDays || !activeDrag.weekendPredicate) {
7483
+ return {
7484
+ startDate: rawStartDate,
7485
+ endDate: rawEndDate,
7486
+ left: nextLeft,
7487
+ width: nextWidth
7488
+ };
7489
+ }
7490
+ const range = (() => {
7491
+ if (activeDrag.mode === "resize-start") {
7492
+ const snapDirection2 = rawStartDate.getTime() >= activeDrag.startDate.getTime() ? 1 : -1;
7493
+ const duration = getBusinessDaysCount(rawStartDate, activeDrag.endDate, activeDrag.weekendPredicate);
7494
+ return buildTaskRangeFromEnd(activeDrag.endDate, duration, true, activeDrag.weekendPredicate, snapDirection2);
7495
+ }
7496
+ if (activeDrag.mode === "resize-end") {
7497
+ const snapDirection2 = rawEndDate.getTime() >= activeDrag.endDate.getTime() ? 1 : -1;
7498
+ const duration = getBusinessDaysCount(activeDrag.startDate, rawEndDate, activeDrag.weekendPredicate);
7499
+ return buildTaskRangeFromStart(activeDrag.startDate, duration, true, activeDrag.weekendPredicate, snapDirection2);
7500
+ }
7501
+ const dayDelta = Math.round((nextLeft - activeDrag.initialLeft) / activeDrag.dayWidth);
7502
+ const proposedStartDate = addUTCDays(activeDrag.startDate, dayDelta);
7503
+ const snapDirection = proposedStartDate.getTime() >= activeDrag.startDate.getTime() ? 1 : -1;
7504
+ return moveTaskRange(
7505
+ activeDrag.startDate,
7506
+ activeDrag.endDate,
7507
+ proposedStartDate,
7508
+ true,
7509
+ activeDrag.weekendPredicate,
7510
+ snapDirection
7511
+ );
7512
+ })();
7513
+ const startOffset = getDayOffset2(range.start, activeDrag.monthStart);
7514
+ const endOffset = getDayOffset2(range.end, activeDrag.monthStart);
7515
+ return {
7516
+ startDate: range.start,
7517
+ endDate: range.end,
7518
+ left: Math.round(startOffset * activeDrag.dayWidth),
7519
+ width: Math.round((endOffset - startOffset + 1) * activeDrag.dayWidth)
7520
+ };
7521
+ };
7392
7522
  var resolveTargetResource = (rows, clientY, gridTop) => {
7393
7523
  const localY = clientY - gridTop;
7394
7524
  return rows.find(
@@ -7397,10 +7527,13 @@ var resolveTargetResource = (rows, clientY, gridTop) => {
7397
7527
  };
7398
7528
  var useResourceItemDrag = ({
7399
7529
  dayWidth,
7530
+ monthStart,
7400
7531
  rows,
7401
7532
  gridElementRef,
7402
7533
  readonly,
7403
7534
  disableResourceReassignment,
7535
+ businessDays = false,
7536
+ weekendPredicate,
7404
7537
  onResourceItemMove
7405
7538
  }) => {
7406
7539
  const activeDragRef = useRef7(null);
@@ -7437,14 +7570,30 @@ var useResourceItemDrag = ({
7437
7570
  if (!latestDrag) {
7438
7571
  return;
7439
7572
  }
7440
- const nextLeft = latestDrag.initialLeft + snapToDay(event.clientX - latestDrag.startX, latestDrag.dayWidth);
7441
- const nextTop = disableResourceReassignment ? latestDrag.initialTop : latestDrag.initialTop + (event.clientY - latestDrag.startY);
7442
- latestDrag.currentLeft = nextLeft;
7573
+ const snappedDelta = snapToDay(event.clientX - latestDrag.startX, latestDrag.dayWidth);
7574
+ const rightEdge = latestDrag.initialLeft + latestDrag.initialWidth;
7575
+ const nextGeometry = (() => {
7576
+ if (latestDrag.mode === "resize-start") {
7577
+ const left = Math.min(latestDrag.initialLeft + snappedDelta, rightEdge - latestDrag.dayWidth);
7578
+ return { left, width: rightEdge - left };
7579
+ }
7580
+ if (latestDrag.mode === "resize-end") {
7581
+ return { left: latestDrag.initialLeft, width: Math.max(latestDrag.dayWidth, latestDrag.initialWidth + snappedDelta) };
7582
+ }
7583
+ return { left: latestDrag.initialLeft + snappedDelta, width: latestDrag.initialWidth };
7584
+ })();
7585
+ const nextRange = resolveResourceMoveRange(latestDrag, nextGeometry.left, nextGeometry.width);
7586
+ const nextTop = disableResourceReassignment || latestDrag.mode !== "move" ? latestDrag.initialTop : latestDrag.initialTop + (event.clientY - latestDrag.startY);
7587
+ latestDrag.currentLeft = nextRange.left;
7588
+ latestDrag.currentWidth = nextRange.width;
7443
7589
  latestDrag.currentTop = nextTop;
7444
7590
  setPreview({
7445
7591
  itemId: latestDrag.itemId,
7446
- left: nextLeft,
7447
- top: nextTop
7592
+ left: nextRange.left,
7593
+ top: nextTop,
7594
+ width: nextRange.width,
7595
+ startDate: nextRange.startDate,
7596
+ endDate: nextRange.endDate
7448
7597
  });
7449
7598
  });
7450
7599
  };
@@ -7457,18 +7606,20 @@ var useResourceItemDrag = ({
7457
7606
  activeDragRef.current = null;
7458
7607
  setPreview(null);
7459
7608
  const gridTop = gridElementRef?.current?.getBoundingClientRect().top ?? 0;
7460
- const targetResource = disableResourceReassignment ? rowsRef.current.find((row) => row.resourceId === activeDrag.fromResourceId)?.resource ?? null : resolveTargetResource(rowsRef.current, event.clientY, gridTop);
7609
+ const targetResource = disableResourceReassignment || activeDrag.mode !== "move" ? rowsRef.current.find((row) => row.resourceId === activeDrag.fromResourceId)?.resource ?? null : resolveTargetResource(rowsRef.current, event.clientY, gridTop);
7461
7610
  if (!targetResource) {
7462
7611
  return;
7463
7612
  }
7464
- const dayDelta = Math.round((activeDrag.currentLeft - activeDrag.initialLeft) / activeDrag.dayWidth);
7613
+ const nextRange = resolveResourceMoveRange(activeDrag, activeDrag.currentLeft, activeDrag.currentWidth);
7465
7614
  onResourceItemMoveRef.current?.({
7466
7615
  item: activeDrag.item,
7467
7616
  itemId: activeDrag.itemId,
7617
+ taskId: activeDrag.item.taskId,
7468
7618
  fromResourceId: activeDrag.fromResourceId,
7469
7619
  toResourceId: targetResource.id,
7470
- startDate: addUTCDays(activeDrag.startDate, dayDelta),
7471
- endDate: addUTCDays(activeDrag.endDate, dayDelta)
7620
+ startDate: nextRange.startDate,
7621
+ endDate: nextRange.endDate,
7622
+ changeType: activeDrag.mode
7472
7623
  });
7473
7624
  };
7474
7625
  window.addEventListener("mousemove", handleMouseMove);
@@ -7483,27 +7634,38 @@ var useResourceItemDrag = ({
7483
7634
  if (readonly || layoutItem.item.locked || event.button !== 0) {
7484
7635
  return;
7485
7636
  }
7637
+ const target = event.target;
7638
+ const mode = target.closest(".gantt-resourceTimeline-resizeHandleStart") ? "resize-start" : target.closest(".gantt-resourceTimeline-resizeHandleEnd") ? "resize-end" : "move";
7486
7639
  event.preventDefault();
7487
7640
  activeDragRef.current = {
7488
7641
  item: layoutItem.item,
7489
7642
  itemId: layoutItem.itemId,
7643
+ mode,
7490
7644
  fromResourceId: layoutItem.resourceId,
7491
7645
  startX: event.clientX,
7492
7646
  startY: event.clientY,
7493
7647
  initialLeft: layoutItem.left,
7494
7648
  initialTop: layoutItem.top,
7649
+ initialWidth: layoutItem.width,
7495
7650
  currentLeft: layoutItem.left,
7496
7651
  currentTop: layoutItem.top,
7652
+ currentWidth: layoutItem.width,
7497
7653
  dayWidth,
7498
7654
  startDate: layoutItem.startDate,
7499
- endDate: layoutItem.endDate
7655
+ endDate: layoutItem.endDate,
7656
+ monthStart,
7657
+ businessDays,
7658
+ weekendPredicate
7500
7659
  };
7501
7660
  setPreview({
7502
7661
  itemId: layoutItem.itemId,
7503
7662
  left: layoutItem.left,
7504
- top: layoutItem.top
7663
+ top: layoutItem.top,
7664
+ width: layoutItem.width,
7665
+ startDate: layoutItem.startDate,
7666
+ endDate: layoutItem.endDate
7505
7667
  });
7506
- }, [dayWidth, readonly]);
7668
+ }, [businessDays, dayWidth, monthStart, readonly, weekendPredicate]);
7507
7669
  return {
7508
7670
  preview,
7509
7671
  startDrag,
@@ -7517,6 +7679,7 @@ var DEFAULT_DAY_WIDTH = 40;
7517
7679
  var DEFAULT_HEADER_HEIGHT = 40;
7518
7680
  var DEFAULT_LANE_HEIGHT = 40;
7519
7681
  var DEFAULT_ROW_HEADER_WIDTH = 240;
7682
+ var DEFAULT_RESOURCE_ROW_GAP = 8;
7520
7683
  var ITEM_OUTER_VERTICAL_INSET = 2;
7521
7684
  var ITEM_INNER_VERTICAL_INSET = 1;
7522
7685
  var ITEM_HORIZONTAL_INSET = 1;
@@ -7576,12 +7739,58 @@ var getVisualItemGeometry = (geometry, laneIndex, laneCount) => {
7576
7739
  height: Math.max(0, geometry.height - topInset - bottomInset)
7577
7740
  };
7578
7741
  };
7742
+ var getWeekendOverlaySegments = (startDate, endDate, dayWidth, weekendPredicate) => {
7743
+ const segments2 = [];
7744
+ const current = new Date(Date.UTC(startDate.getUTCFullYear(), startDate.getUTCMonth(), startDate.getUTCDate()));
7745
+ let activeStartOffset = null;
7746
+ let offset = 0;
7747
+ while (current.getTime() <= endDate.getTime()) {
7748
+ const isWeekendDay = weekendPredicate(current);
7749
+ if (isWeekendDay && activeStartOffset === null) {
7750
+ activeStartOffset = offset;
7751
+ }
7752
+ if (!isWeekendDay && activeStartOffset !== null) {
7753
+ segments2.push({
7754
+ left: Math.round(activeStartOffset * dayWidth),
7755
+ width: Math.round((offset - activeStartOffset) * dayWidth)
7756
+ });
7757
+ activeStartOffset = null;
7758
+ }
7759
+ current.setUTCDate(current.getUTCDate() + 1);
7760
+ offset += 1;
7761
+ }
7762
+ if (activeStartOffset !== null) {
7763
+ segments2.push({
7764
+ left: Math.round(activeStartOffset * dayWidth),
7765
+ width: Math.round((offset - activeStartOffset) * dayWidth)
7766
+ });
7767
+ }
7768
+ return segments2;
7769
+ };
7770
+ var getRangeOverlaySegments = (itemStartDate, ranges, dayWidth) => {
7771
+ return ranges.map((range) => {
7772
+ const startOffset = Math.max(0, Math.round(
7773
+ (Date.UTC(range.startDate.getUTCFullYear(), range.startDate.getUTCMonth(), range.startDate.getUTCDate()) - Date.UTC(itemStartDate.getUTCFullYear(), itemStartDate.getUTCMonth(), itemStartDate.getUTCDate())) / (24 * 60 * 60 * 1e3)
7774
+ ));
7775
+ const endOffset = Math.max(startOffset, Math.round(
7776
+ (Date.UTC(range.endDate.getUTCFullYear(), range.endDate.getUTCMonth(), range.endDate.getUTCDate()) - Date.UTC(itemStartDate.getUTCFullYear(), itemStartDate.getUTCMonth(), itemStartDate.getUTCDate())) / (24 * 60 * 60 * 1e3)
7777
+ ));
7778
+ return {
7779
+ left: Math.round(startOffset * dayWidth),
7780
+ width: Math.round((endOffset - startOffset + 1) * dayWidth)
7781
+ };
7782
+ });
7783
+ };
7784
+ var getDurationValue = (startDate, endDate, businessDays, weekendPredicate) => businessDays ? getBusinessDaysCount(startDate, endDate, weekendPredicate) : Math.max(1, Math.round((endDate.getTime() - startDate.getTime()) / (24 * 60 * 60 * 1e3)) + 1);
7579
7785
  function ResourceTimelineChart({
7580
7786
  resources,
7581
7787
  dayWidth = DEFAULT_DAY_WIDTH,
7582
7788
  rowHeaderWidth = DEFAULT_ROW_HEADER_WIDTH,
7583
7789
  laneHeight = DEFAULT_LANE_HEIGHT,
7584
7790
  headerHeight = DEFAULT_HEADER_HEIGHT,
7791
+ customDays,
7792
+ isWeekend: isWeekend3,
7793
+ businessDays = true,
7585
7794
  readonly,
7586
7795
  disableResourceReassignment,
7587
7796
  renderItem,
@@ -7599,9 +7808,18 @@ function ResourceTimelineChart({
7599
7808
  const firstDay = dateRange[0] ?? /* @__PURE__ */ new Date();
7600
7809
  return new Date(Date.UTC(firstDay.getUTCFullYear(), firstDay.getUTCMonth(), 1));
7601
7810
  }, [dateRange]);
7811
+ const weekendPredicate = useMemo9(
7812
+ () => createCustomDayPredicate({ customDays, isWeekend: isWeekend3 }),
7813
+ [customDays, isWeekend3]
7814
+ );
7602
7815
  const gridWidth = useMemo9(() => Math.round(dateRange.length * dayWidth), [dateRange.length, dayWidth]);
7603
7816
  const layout = useMemo9(
7604
- () => layoutResourceTimelineItems(resources, { monthStart, dayWidth, laneHeight }),
7817
+ () => layoutResourceTimelineItems(resources, {
7818
+ monthStart,
7819
+ dayWidth,
7820
+ laneHeight,
7821
+ rowGap: DEFAULT_RESOURCE_ROW_GAP
7822
+ }),
7605
7823
  [resources, monthStart, dayWidth, laneHeight]
7606
7824
  );
7607
7825
  const todayInRange = useMemo9(() => {
@@ -7620,10 +7838,13 @@ function ResourceTimelineChart({
7620
7838
  }, [layout.items]);
7621
7839
  const { preview, startDrag } = useResourceItemDrag({
7622
7840
  dayWidth,
7841
+ monthStart,
7623
7842
  rows: layout.rows,
7624
7843
  gridElementRef: gridRef,
7625
7844
  readonly,
7626
7845
  disableResourceReassignment,
7846
+ businessDays,
7847
+ weekendPredicate,
7627
7848
  onResourceItemMove
7628
7849
  });
7629
7850
  const handlePanStart = useCallback7((event) => {
@@ -7702,13 +7923,26 @@ function ResourceTimelineChart({
7702
7923
  style: { height: `${headerHeight}px` }
7703
7924
  }
7704
7925
  ),
7705
- layout.rows.map((row) => /* @__PURE__ */ jsx15(
7926
+ layout.rows.map((row) => /* @__PURE__ */ jsxs12(
7706
7927
  "div",
7707
7928
  {
7708
7929
  className: "gantt-resourceTimeline-resourceHeader",
7709
7930
  "data-resource-row-id": row.resourceId,
7710
- style: { height: `${row.resourceRowHeight}px` },
7711
- children: /* @__PURE__ */ jsx15("span", { className: "gantt-resourceTimeline-resourceName", children: row.resource.name })
7931
+ style: {
7932
+ height: `${row.resourceRowHeight + DEFAULT_RESOURCE_ROW_GAP}px`,
7933
+ paddingBottom: `${DEFAULT_RESOURCE_ROW_GAP}px`
7934
+ },
7935
+ children: [
7936
+ /* @__PURE__ */ jsx15("span", { className: "gantt-resourceTimeline-resourceName", children: row.resource.name }),
7937
+ row.conflictCount > 0 && /* @__PURE__ */ jsx15(
7938
+ "span",
7939
+ {
7940
+ className: "gantt-resourceTimeline-conflictBadge",
7941
+ "aria-label": `${row.conflictCount} \u043A\u043E\u043D\u0444\u043B\u0438\u043A\u0442\u043E\u0432`,
7942
+ children: row.conflictCount
7943
+ }
7944
+ )
7945
+ ]
7712
7946
  },
7713
7947
  row.resourceId
7714
7948
  ))
@@ -7721,7 +7955,15 @@ function ResourceTimelineChart({
7721
7955
  className: "gantt-resourceTimeline-chartSurface",
7722
7956
  style: { minWidth: `${gridWidth}px` },
7723
7957
  children: [
7724
- /* @__PURE__ */ jsx15("div", { className: "gantt-resourceTimeline-stickyHeader", style: { width: `${gridWidth}px` }, children: /* @__PURE__ */ jsx15(TimeScaleHeader_default, { days: dateRange, dayWidth, headerHeight }) }),
7958
+ /* @__PURE__ */ jsx15("div", { className: "gantt-resourceTimeline-stickyHeader", style: { width: `${gridWidth}px` }, children: /* @__PURE__ */ jsx15(
7959
+ TimeScaleHeader_default,
7960
+ {
7961
+ days: dateRange,
7962
+ dayWidth,
7963
+ headerHeight,
7964
+ isCustomWeekend: weekendPredicate
7965
+ }
7966
+ ) }),
7725
7967
  /* @__PURE__ */ jsxs12(
7726
7968
  "div",
7727
7969
  {
@@ -7729,7 +7971,15 @@ function ResourceTimelineChart({
7729
7971
  className: "gantt-resourceTimeline-grid",
7730
7972
  style: { width: `${gridWidth}px`, height: `${layout.totalHeight}px` },
7731
7973
  children: [
7732
- /* @__PURE__ */ jsx15(GridBackground_default, { dateRange, dayWidth, totalHeight: layout.totalHeight }),
7974
+ /* @__PURE__ */ jsx15(
7975
+ GridBackground_default,
7976
+ {
7977
+ dateRange,
7978
+ dayWidth,
7979
+ totalHeight: layout.totalHeight,
7980
+ isCustomWeekend: weekendPredicate
7981
+ }
7982
+ ),
7733
7983
  todayInRange && /* @__PURE__ */ jsx15(TodayIndicator_default, { monthStart, dayWidth }),
7734
7984
  layout.rows.map((row) => /* @__PURE__ */ jsx15(
7735
7985
  "div",
@@ -7738,7 +7988,7 @@ function ResourceTimelineChart({
7738
7988
  "data-resource-row-id": row.resourceId,
7739
7989
  style: {
7740
7990
  top: `${row.resourceRowTop}px`,
7741
- height: `${row.resourceRowHeight}px`
7991
+ height: `${row.resourceRowHeight + DEFAULT_RESOURCE_ROW_GAP}px`
7742
7992
  }
7743
7993
  },
7744
7994
  row.resourceId
@@ -7746,17 +7996,18 @@ function ResourceTimelineChart({
7746
7996
  Array.from(itemsByResourceId.values()).flatMap(
7747
7997
  (resourceItems) => resourceItems.map((layoutItem) => {
7748
7998
  const customClassName = getItemClassName?.(layoutItem.item);
7999
+ const isDraggingItem = preview?.itemId === layoutItem.itemId;
7749
8000
  const className = [
7750
8001
  "gantt-resourceTimeline-item",
7751
- preview?.itemId === layoutItem.itemId && "gantt-resourceTimeline-itemDragging",
8002
+ isDraggingItem && "gantt-resourceTimeline-itemDragging",
7752
8003
  (readonly || layoutItem.item.locked) && "gantt-resourceTimeline-itemDisabled",
7753
8004
  customClassName
7754
8005
  ].filter(Boolean).join(" ");
7755
8006
  const laneCount = Math.max(1, Math.round(layoutItem.resourceRowHeight / layoutItem.height));
7756
- const previewStyle = preview?.itemId === layoutItem.itemId ? getVisualItemGeometry({
8007
+ const previewStyle = isDraggingItem ? getVisualItemGeometry({
7757
8008
  left: preview.left,
7758
8009
  top: preview.top,
7759
- width: layoutItem.width,
8010
+ width: preview.width,
7760
8011
  height: layoutItem.height
7761
8012
  }, layoutItem.laneIndex, laneCount) : void 0;
7762
8013
  const itemGeometry = getVisualItemGeometry({
@@ -7765,7 +8016,27 @@ function ResourceTimelineChart({
7765
8016
  width: layoutItem.width,
7766
8017
  height: layoutItem.height
7767
8018
  }, layoutItem.laneIndex, laneCount);
7768
- return /* @__PURE__ */ jsx15(
8019
+ const overlayStartDate = isDraggingItem ? preview.startDate : layoutItem.startDate;
8020
+ const overlayEndDate = isDraggingItem ? preview.endDate : layoutItem.endDate;
8021
+ const weekendOverlaySegments = businessDays ? getWeekendOverlaySegments(overlayStartDate, overlayEndDate, dayWidth, weekendPredicate) : [];
8022
+ const conflictOverlaySegments = getRangeOverlaySegments(
8023
+ overlayStartDate,
8024
+ isDraggingItem ? [] : layoutItem.conflictRanges,
8025
+ dayWidth
8026
+ );
8027
+ const durationValue = getDurationValue(
8028
+ overlayStartDate,
8029
+ overlayEndDate,
8030
+ businessDays,
8031
+ weekendPredicate
8032
+ );
8033
+ const renderContext = {
8034
+ startDate: overlayStartDate,
8035
+ endDate: overlayEndDate,
8036
+ durationDays: durationValue,
8037
+ isDragging: isDraggingItem
8038
+ };
8039
+ return /* @__PURE__ */ jsxs12(
7769
8040
  "div",
7770
8041
  {
7771
8042
  className,
@@ -7774,16 +8045,54 @@ function ResourceTimelineChart({
7774
8045
  style: {
7775
8046
  left: `${itemGeometry.left}px`,
7776
8047
  top: `${itemGeometry.top}px`,
7777
- ...previewStyle,
7778
8048
  width: `${itemGeometry.width}px`,
7779
8049
  height: `${itemGeometry.height}px`,
8050
+ ...previewStyle,
7780
8051
  backgroundColor: layoutItem.item.color ?? "var(--gantt-task-bar-default-color, #3b82f6)"
7781
8052
  },
7782
- children: /* @__PURE__ */ jsx15("div", { className: "gantt-resourceTimeline-itemInner", children: renderItem ? renderItem(layoutItem.item) : /* @__PURE__ */ jsxs12(Fragment3, { children: [
7783
- /* @__PURE__ */ jsx15("span", { className: "gantt-resourceTimeline-itemTitle", children: layoutItem.item.title }),
7784
- layoutItem.item.subtitle && /* @__PURE__ */ jsx15("span", { className: "gantt-resourceTimeline-itemSubtitle", children: layoutItem.item.subtitle }),
7785
- /* @__PURE__ */ jsx15("span", { className: "gantt-resourceTimeline-itemDates", children: formatDateRangeLabel(layoutItem.startDate, layoutItem.endDate) })
7786
- ] }) })
8053
+ children: [
8054
+ !readonly && !layoutItem.item.locked && /* @__PURE__ */ jsxs12(Fragment3, { children: [
8055
+ /* @__PURE__ */ jsx15("span", { className: "gantt-resourceTimeline-resizeHandle gantt-resourceTimeline-resizeHandleStart" }),
8056
+ /* @__PURE__ */ jsx15("span", { className: "gantt-resourceTimeline-resizeHandle gantt-resourceTimeline-resizeHandleEnd" })
8057
+ ] }),
8058
+ weekendOverlaySegments.map((segment, index) => /* @__PURE__ */ jsx15(
8059
+ "span",
8060
+ {
8061
+ className: "gantt-resourceTimeline-weekendOverlay",
8062
+ "data-resource-weekend-overlay": "true",
8063
+ style: {
8064
+ left: `${segment.left}px`,
8065
+ width: `${segment.width}px`
8066
+ }
8067
+ },
8068
+ `weekend-overlay-${index}`
8069
+ )),
8070
+ conflictOverlaySegments.map((segment, index) => /* @__PURE__ */ jsx15(
8071
+ "span",
8072
+ {
8073
+ className: "gantt-resourceTimeline-conflictOverlay",
8074
+ "data-resource-conflict-overlay": "true",
8075
+ style: {
8076
+ left: `${segment.left}px`,
8077
+ width: `${segment.width}px`
8078
+ }
8079
+ },
8080
+ `conflict-overlay-${index}`
8081
+ )),
8082
+ /* @__PURE__ */ jsx15("div", { className: "gantt-resourceTimeline-itemInner", children: renderItem ? renderItem(layoutItem.item, renderContext) : /* @__PURE__ */ jsxs12(Fragment3, { children: [
8083
+ /* @__PURE__ */ jsx15(
8084
+ "span",
8085
+ {
8086
+ className: "gantt-resourceTimeline-itemDurationChip",
8087
+ "aria-label": `${durationValue} \u0434`,
8088
+ children: durationValue
8089
+ }
8090
+ ),
8091
+ /* @__PURE__ */ jsx15("span", { className: "gantt-resourceTimeline-itemTitle", children: layoutItem.item.title }),
8092
+ layoutItem.item.subtitle && /* @__PURE__ */ jsx15("span", { className: "gantt-resourceTimeline-itemSubtitle", children: layoutItem.item.subtitle }),
8093
+ /* @__PURE__ */ jsx15("span", { className: "gantt-resourceTimeline-itemDates", children: formatDateRangeLabel(layoutItem.startDate, layoutItem.endDate) })
8094
+ ] }) })
8095
+ ]
7787
8096
  },
7788
8097
  layoutItem.itemId
7789
8098
  );