gantt-lib 0.142.0 → 0.142.2

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.js CHANGED
@@ -5413,53 +5413,6 @@ var TaskRow = import_react3.default.memo(
5413
5413
  }
5414
5414
  return { left: segment.left, width: segment.width + activityDrag.dayDelta * dayWidth };
5415
5415
  };
5416
- const activityLinks = (0, import_react3.useMemo)(() => {
5417
- const gaps = [];
5418
- const elbows = [];
5419
- if (!showActivityLinks || !renderActivities || !activityLayout) return { gaps, elbows };
5420
- const activities = task.activities ?? [];
5421
- const segmentById = new Map(activityLayout.segments.map((segment) => [segment.id, segment]));
5422
- const visibleIds = new Set(visibleActivitySegments.map((segment) => segment.id));
5423
- const laneTopY = (lane) => activityTopOffset + lane * ACTIVITY_LANE_STEP + (ACTIVITY_LANE_STEP - ACTIVITY_LANE_BAR_HEIGHT) / 2;
5424
- const liveRect = (segment) => {
5425
- const geometry = liveActivityGeometry(segment);
5426
- const chainDelta = activityOverrides?.get(segment.id) ?? 0;
5427
- const left2 = geometry.left + (chainDelta !== 0 ? chainDelta * dayWidth : 0);
5428
- return { left: left2, right: left2 + geometry.width };
5429
- };
5430
- for (let index = 0; index < activities.length - 1; index += 1) {
5431
- const predecessor = segmentById.get(activities[index].id);
5432
- const successor = segmentById.get(activities[index + 1].id);
5433
- if (!predecessor || !successor) continue;
5434
- if (!visibleIds.has(predecessor.id) || !visibleIds.has(successor.id)) continue;
5435
- const lag = activities[index + 1].lag ?? 0;
5436
- const predRect = liveRect(predecessor);
5437
- const succRect = liveRect(successor);
5438
- if (predecessor.lane === successor.lane && succRect.left >= predRect.right) {
5439
- const width2 = succRect.left - predRect.right;
5440
- if (width2 >= 1) {
5441
- gaps.push({ key: `${predecessor.id}->${successor.id}`, left: predRect.right, width: width2, lane: predecessor.lane, lag });
5442
- }
5443
- continue;
5444
- }
5445
- const predecessorLaneTop = laneTopY(predecessor.lane);
5446
- const successorLaneTop = laneTopY(successor.lane);
5447
- const sameLane = predecessor.lane === successor.lane;
5448
- const reverseOrder = !sameLane && successorLaneTop < predecessorLaneTop;
5449
- const fromY = reverseOrder ? predecessorLaneTop + 6 : predecessorLaneTop + ACTIVITY_LANE_BAR_HEIGHT - 6;
5450
- const toY = reverseOrder ? successorLaneTop + ACTIVITY_LANE_BAR_HEIGHT - 6 : successorLaneTop + (sameLane ? ACTIVITY_LANE_STEP : 0) + 6;
5451
- const fromX = predRect.right;
5452
- const toX = succRect.left;
5453
- elbows.push({
5454
- key: `${predecessor.id}->${successor.id}`,
5455
- d: calculateDependencyPath({ x: fromX, y: fromY }, { x: toX, y: toY }, false),
5456
- lagX: toX - 14,
5457
- lagY: reverseOrder ? fromY - 4 : fromY + 12,
5458
- lag
5459
- });
5460
- }
5461
- return { gaps, elbows };
5462
- }, [showActivityLinks, renderActivities, activityLayout, visibleActivitySegments, activityTopOffset, activityOverrides, activityDrag, dayWidth, task.activities]);
5463
5416
  const activityTipData = (0, import_react3.useMemo)(() => {
5464
5417
  if (!activityTipId || !task.activities) return null;
5465
5418
  const activity = task.activities.find((item) => item.id === activityTipId);
@@ -5531,121 +5484,72 @@ var TaskRow = import_react3.default.memo(
5531
5484
  }
5532
5485
  }
5533
5486
  ),
5534
- renderActivities && activityLayout && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "gantt-tr-activityLanes", children: [
5535
- activityLinks.elbows.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("svg", { className: "gantt-tr-activityLinksSvg", width: "100%", height: "100%", "aria-hidden": "true", children: [
5536
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("defs", { children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("marker", { id: "arrowhead", markerWidth: "8", markerHeight: "6", markerUnits: "userSpaceOnUse", refX: "7", refY: "3", orient: "auto", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("polygon", { points: "0 0, 8 3, 0 6", fill: "var(--gantt-dependency-line-color, #666666)" }) }) }),
5537
- activityLinks.elbows.map((link) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("g", { children: [
5538
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { className: "gantt-dependency-path", d: link.d, markerEnd: "url(#arrowhead)" }),
5539
- showActivityLag && link.lag !== 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
5540
- "text",
5541
- {
5542
- className: "gantt-dependency-lag-label",
5543
- x: link.lagX,
5544
- y: link.lagY,
5545
- textAnchor: "middle",
5546
- fontSize: "10",
5547
- fill: "var(--gantt-dependency-line-color, #666666)",
5548
- children: link.lag > 0 ? `+${link.lag}` : `${link.lag}`
5487
+ renderActivities && activityLayout && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "gantt-tr-activityLanes", children: visibleActivitySegments.map((segment) => {
5488
+ const live = liveActivityGeometry(segment);
5489
+ const chainDelta = activityOverrides?.get(segment.id) ?? 0;
5490
+ const activityProgress = segment.progress === void 0 ? 0 : Math.min(100, Math.max(0, Math.round(segment.progress)));
5491
+ const liveLeft = live.left + (chainDelta !== 0 ? chainDelta * dayWidth : 0);
5492
+ const isDraggingActivity = activityDrag?.id === segment.id;
5493
+ const isBlockingActivity = blockedActivityIds?.has(segment.id) ?? false;
5494
+ const isAtLimit = isDraggingActivity && activityBlockedBy !== null;
5495
+ const isActiveActivity = activationVisualEnabled && activeActivityKey === activityOwnerKey(task.id, segment.id);
5496
+ const isSameWorkType = activeWork !== null && (segment.id === activeWork.id || activeWork.name !== null && segment.name === activeWork.name);
5497
+ const isDimmed = dimOthers && activeWork !== null && !isSameWorkType;
5498
+ const isChainHighlighted = highlightChain && activeWork !== null && isSameWorkType;
5499
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
5500
+ "div",
5501
+ {
5502
+ "data-activity-id": segment.id,
5503
+ className: `gantt-tr-activityBar${isDraggingActivity ? " gantt-tr-activityBar-dragging" : ""}${isBlockingActivity ? " gantt-tr-activityBar-blocking" : ""}${isAtLimit ? " gantt-tr-activityBar-atLimit" : ""}${isActiveActivity ? " gantt-tr-activityBar-active" : ""}${isDimmed ? " gantt-tr-activityBar-dimmed" : ""}${isChainHighlighted ? " gantt-tr-activityBar-chain" : ""}${activityDragEnabled ? "" : " gantt-tr-activityBar-locked"}`,
5504
+ style: {
5505
+ left: `${liveLeft}px`,
5506
+ width: `${live.width}px`,
5507
+ top: `${activityTopOffset + segment.lane * ACTIVITY_LANE_STEP + (ACTIVITY_LANE_STEP - ACTIVITY_LANE_BAR_HEIGHT) / 2}px`,
5508
+ height: `${ACTIVITY_LANE_BAR_HEIGHT}px`,
5509
+ backgroundColor: segment.color || "var(--gantt-task-bar-default-color)"
5510
+ },
5511
+ onMouseDown: (event) => {
5512
+ if (!activityDragEnabled) return;
5513
+ const activationKey = activityOwnerKey(task.id, segment.id);
5514
+ const isActive = activityActivationStore?.getActiveKey() === activationKey;
5515
+ if (activationVisualEnabled && !isActive) {
5516
+ activityActivationStore?.setActiveKey(activationKey);
5549
5517
  }
5550
- )
5551
- ] }, link.key))
5552
- ] }),
5553
- visibleActivitySegments.map((segment) => {
5554
- const live = liveActivityGeometry(segment);
5555
- const chainDelta = activityOverrides?.get(segment.id) ?? 0;
5556
- const activityProgress = segment.progress === void 0 ? 0 : Math.min(100, Math.max(0, Math.round(segment.progress)));
5557
- const liveLeft = live.left + (chainDelta !== 0 ? chainDelta * dayWidth : 0);
5558
- const isDraggingActivity = activityDrag?.id === segment.id;
5559
- const isBlockingActivity = blockedActivityIds?.has(segment.id) ?? false;
5560
- const isAtLimit = isDraggingActivity && activityBlockedBy !== null;
5561
- const isActiveActivity = activationVisualEnabled && activeActivityKey === activityOwnerKey(task.id, segment.id);
5562
- const isSameWorkType = activeWork !== null && (segment.id === activeWork.id || activeWork.name !== null && segment.name === activeWork.name);
5563
- const isDimmed = dimOthers && activeWork !== null && !isSameWorkType;
5564
- const isChainHighlighted = highlightChain && activeWork !== null && isSameWorkType;
5565
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
5566
- "div",
5567
- {
5568
- "data-activity-id": segment.id,
5569
- className: `gantt-tr-activityBar${isDraggingActivity ? " gantt-tr-activityBar-dragging" : ""}${isBlockingActivity ? " gantt-tr-activityBar-blocking" : ""}${isAtLimit ? " gantt-tr-activityBar-atLimit" : ""}${isActiveActivity ? " gantt-tr-activityBar-active" : ""}${isDimmed ? " gantt-tr-activityBar-dimmed" : ""}${isChainHighlighted ? " gantt-tr-activityBar-chain" : ""}${activityDragEnabled ? "" : " gantt-tr-activityBar-locked"}`,
5570
- style: {
5571
- left: `${liveLeft}px`,
5572
- width: `${live.width}px`,
5573
- top: `${activityTopOffset + segment.lane * ACTIVITY_LANE_STEP + (ACTIVITY_LANE_STEP - ACTIVITY_LANE_BAR_HEIGHT) / 2}px`,
5574
- height: `${ACTIVITY_LANE_BAR_HEIGHT}px`,
5575
- backgroundColor: segment.color || "var(--gantt-task-bar-default-color)"
5576
- },
5577
- onMouseDown: (event) => {
5578
- if (!activityDragEnabled) return;
5579
- const activationKey = activityOwnerKey(task.id, segment.id);
5580
- const isActive = activityActivationStore?.getActiveKey() === activationKey;
5581
- if (activationVisualEnabled && !isActive) {
5582
- activityActivationStore?.setActiveKey(activationKey);
5583
- }
5584
- if (activityClickToDrag && !isActive) return;
5585
- const target = event.target;
5586
- const mode = target.closest(".gantt-tr-resizeHandleLeft") ? "resize-left" : target.closest(".gantt-tr-resizeHandleRight") ? "resize-right" : "move";
5587
- handleActivityPointerDown(segment, mode)(event);
5588
- },
5589
- onMouseEnter: (event) => {
5590
- if (activityDrag || activityDragOwner?.get()) return;
5591
- setActivityTipPosition(anchorActivityTip(event.currentTarget.getBoundingClientRect()));
5592
- setActivityTipId(segment.id);
5593
- },
5594
- onMouseLeave: () => {
5595
- if (!activityDrag) {
5596
- setActivityTipId((current) => current === segment.id ? null : current);
5597
- activityTipAnchor.current = null;
5598
- setActivityTipPosition(null);
5599
- }
5600
- },
5601
- children: [
5602
- activityProgress > 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
5603
- "span",
5604
- {
5605
- className: "gantt-tr-activityProgress",
5606
- style: { width: `${activityProgress}%` }
5607
- }
5608
- ),
5609
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "gantt-tr-activityName", style: { color: activityTextColor(segment.color) }, children: segment.name }),
5610
- activityDragEnabled && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
5611
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "gantt-tr-resizeHandle gantt-tr-resizeHandleLeft" }),
5612
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "gantt-tr-resizeHandle gantt-tr-resizeHandleRight" })
5613
- ] })
5614
- ]
5518
+ if (activityClickToDrag && !isActive) return;
5519
+ const target = event.target;
5520
+ const mode = target.closest(".gantt-tr-resizeHandleLeft") ? "resize-left" : target.closest(".gantt-tr-resizeHandleRight") ? "resize-right" : "move";
5521
+ handleActivityPointerDown(segment, mode)(event);
5615
5522
  },
5616
- segment.id
5617
- );
5618
- }),
5619
- activityLinks.gaps.map((gap) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_react3.default.Fragment, { children: [
5620
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
5621
- "span",
5622
- {
5623
- className: "gantt-tr-activityLink",
5624
- "aria-hidden": "true",
5625
- style: {
5626
- left: `${gap.left}px`,
5627
- width: `${gap.width}px`,
5628
- top: `${activityTopOffset + gap.lane * ACTIVITY_LANE_STEP + ACTIVITY_LANE_STEP / 2}px`
5523
+ onMouseEnter: (event) => {
5524
+ if (activityDrag || activityDragOwner?.get()) return;
5525
+ setActivityTipPosition(anchorActivityTip(event.currentTarget.getBoundingClientRect()));
5526
+ setActivityTipId(segment.id);
5527
+ },
5528
+ onMouseLeave: () => {
5529
+ if (!activityDrag) {
5530
+ setActivityTipId((current) => current === segment.id ? null : current);
5531
+ activityTipAnchor.current = null;
5532
+ setActivityTipPosition(null);
5629
5533
  }
5630
- }
5631
- ),
5632
- showActivityLag && gap.lag > 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
5633
- "span",
5634
- {
5635
- className: "gantt-tr-activityLag",
5636
- title: `\u0417\u0430\u0437\u043E\u0440 ${gap.lag} \u0434`,
5637
- style: {
5638
- left: `${gap.left + gap.width - 14}px`,
5639
- top: `${activityTopOffset + gap.lane * ACTIVITY_LANE_STEP + ACTIVITY_LANE_STEP / 2}px`
5640
- },
5641
- children: [
5642
- "+",
5643
- gap.lag
5644
- ]
5645
- }
5646
- )
5647
- ] }, gap.key))
5648
- ] }),
5534
+ },
5535
+ children: [
5536
+ activityProgress > 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
5537
+ "span",
5538
+ {
5539
+ className: "gantt-tr-activityProgress",
5540
+ style: { width: `${activityProgress}%` }
5541
+ }
5542
+ ),
5543
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "gantt-tr-activityName", style: { color: activityTextColor(segment.color) }, children: segment.name }),
5544
+ activityDragEnabled && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
5545
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "gantt-tr-resizeHandle gantt-tr-resizeHandleLeft" }),
5546
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "gantt-tr-resizeHandle gantt-tr-resizeHandleRight" })
5547
+ ] })
5548
+ ]
5549
+ },
5550
+ segment.id
5551
+ );
5552
+ }) }),
5649
5553
  !renderActivities && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
5650
5554
  "div",
5651
5555
  {
@@ -6217,10 +6121,11 @@ function areBothHiddenInSameParent(predecessorId, successorId, collapsedParentId
6217
6121
  if (!predVisibleAncestor || !succVisibleAncestor) return false;
6218
6122
  return predVisibleAncestor.id === succVisibleAncestor.id;
6219
6123
  }
6124
+ var EMPTY_COLLAPSED_PARENT_IDS = /* @__PURE__ */ new Set();
6220
6125
  var DependencyLines = import_react7.default.memo(({
6221
6126
  tasks,
6222
6127
  allTasks,
6223
- collapsedParentIds = /* @__PURE__ */ new Set(),
6128
+ collapsedParentIds = EMPTY_COLLAPSED_PARENT_IDS,
6224
6129
  monthStart,
6225
6130
  dayWidth,
6226
6131
  rowHeight,
@@ -6365,8 +6270,8 @@ var DependencyLines = import_react7.default.memo(({
6365
6270
  fromY = predecessor.rowTop + predecessor.rowHeight / 2;
6366
6271
  toY = successor.rowTop + successor.rowHeight / 2;
6367
6272
  } else if (activityEndpoints) {
6368
- fromY = reverseOrder ? predecessor.rowTop : predecessor.rowTop + predecessor.rowHeight;
6369
- toY = reverseOrder ? successor.rowTop + successor.rowHeight : successor.rowTop;
6273
+ fromY = reverseOrder ? predecessor.rowTop + 6 : predecessor.rowTop + predecessor.rowHeight - 6;
6274
+ toY = reverseOrder ? successor.rowTop + successor.rowHeight - 6 : successor.rowTop + 6;
6370
6275
  } else if (reverseOrder) {
6371
6276
  fromY = predecessor.rowTop + 10;
6372
6277
  toY = successor.rowTop + successor.rowHeight - 6;
@@ -6601,10 +6506,12 @@ function ActivityDependencyLines(props) {
6601
6506
  const layout = (0, import_react8.useMemo)(() => {
6602
6507
  const flattened = [], rendered = [], tops = [], heights = [];
6603
6508
  const indices = /* @__PURE__ */ new Map();
6509
+ const neededRows = /* @__PURE__ */ new Set();
6604
6510
  const incoming = /* @__PURE__ */ new Map();
6605
6511
  const selected = props.highlight ? new Set(props.highlight.activities.map((activity) => activityKey(activity.taskId, activity.activityId))) : void 0;
6606
6512
  const highlightMode = props.highlight?.mode ?? "chain";
6607
6513
  for (const edge of dependencies) {
6514
+ if (!props.renderedTaskIds.has(edge.predecessorTaskId) && !props.renderedTaskIds.has(edge.successorTaskId)) continue;
6608
6515
  if (selected) {
6609
6516
  const fromSelected = selected.has(activityKey(edge.predecessorTaskId, edge.predecessorActivityId));
6610
6517
  const toSelected = selected.has(activityKey(edge.successorTaskId, edge.successorActivityId));
@@ -6613,12 +6520,15 @@ function ActivityDependencyLines(props) {
6613
6520
  const outgoing = fromSelected && !toSelected && (highlightMode === "chain-outgoing" || highlightMode === "chain-all");
6614
6521
  if (!internal && !incoming2 && !outgoing) continue;
6615
6522
  }
6523
+ neededRows.add(edge.predecessorTaskId);
6524
+ neededRows.add(edge.successorTaskId);
6616
6525
  const id = activityKey(edge.successorTaskId, edge.successorActivityId);
6617
6526
  const values = incoming.get(id) ?? [];
6618
6527
  values.push({ taskId: activityKey(edge.predecessorTaskId, edge.predecessorActivityId), type: edge.type, lag: edge.lag });
6619
6528
  incoming.set(id, values);
6620
6529
  }
6621
6530
  for (const task of tasks) {
6531
+ if (!neededRows.has(task.id)) continue;
6622
6532
  const row = props.rowIndexByTaskId.get(task.id);
6623
6533
  if (row === void 0 || !task.activities?.length) continue;
6624
6534
  const height = props.rowHeights[row] ?? props.rowHeight;
@@ -15532,6 +15442,17 @@ function TaskGanttChartInner(props, ref) {
15532
15442
  onTaskDateChangeModeChange: externalOnTaskDateChangeModeChange,
15533
15443
  printDependencyLabels = false
15534
15444
  } = props;
15445
+ const resolvedActivityDependencies = (0, import_react20.useMemo)(() => {
15446
+ if (activityDependencies !== void 0) return activityDependencies;
15447
+ return tasks.flatMap((task) => (task.activities ?? []).slice(1).map((successor, index) => ({
15448
+ predecessorTaskId: task.id,
15449
+ predecessorActivityId: task.activities[index].id,
15450
+ successorTaskId: task.id,
15451
+ successorActivityId: successor.id,
15452
+ type: "FS",
15453
+ lag: successor.lag ?? 0
15454
+ })));
15455
+ }, [tasks, activityDependencies]);
15535
15456
  const dayWidth = !isTableMatrixMode ? props.dayWidth ?? 40 : 40;
15536
15457
  const criticalPathMode = !isTableMatrixMode && !isPlanFactMode ? props.criticalPathMode : void 0;
15537
15458
  const onSubtreeScaleResult = !isTableMatrixMode && !isPlanFactMode ? props.onSubtreeScaleResult : void 0;
@@ -17008,7 +16929,7 @@ function TaskGanttChartInner(props, ref) {
17008
16929
  onHoverEnd: () => setActiveTimelineTooltip(null)
17009
16930
  }
17010
16931
  ),
17011
- showActivityLinks && activityDependencies !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ActivityDependencyLines, { tasks: visibleTasks, renderedTaskIds: renderedTaskIdsRef.current, dependencies: activityDependencies, highlight: activityDependencyHighlight, monthStart, dayWidth, rowHeight: effectiveRowHeight, gridWidth: renderGridWidth, totalHeight: totalGridHeight, rowIndexByTaskId: visibleTaskIndexMap, rowTops: compositeRowLayout.tops, rowHeights: compositeRowLayout.heights, showLag: showActivityLag, previewStore: activityPreviewStore, horizontalWindow }),
16932
+ showActivityLinks && resolvedActivityDependencies.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ActivityDependencyLines, { tasks: visibleTasks, renderedTaskIds: renderedTaskIdsRef.current, dependencies: resolvedActivityDependencies, highlight: activityDependencyHighlight, monthStart, dayWidth, rowHeight: effectiveRowHeight, gridWidth: renderGridWidth, totalHeight: totalGridHeight, rowIndexByTaskId: visibleTaskIndexMap, rowTops: compositeRowLayout.tops, rowHeights: compositeRowLayout.heights, showLag: showActivityLag, previewStore: activityPreviewStore, horizontalWindow }),
17012
16933
  /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
17013
16934
  DependencyLines_default,
17014
16935
  {
@@ -17151,7 +17072,7 @@ function TaskGanttChartInner(props, ref) {
17151
17072
  activityActivationStore,
17152
17073
  activityClickToDrag,
17153
17074
  activityActivationMode,
17154
- showActivityLinks: showActivityLinks && activityDependencies === void 0,
17075
+ showActivityLinks: false,
17155
17076
  showActivityLag,
17156
17077
  activityTooltip,
17157
17078
  horizontalWindow,