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.mjs CHANGED
@@ -5250,53 +5250,6 @@ var TaskRow = React2.memo(
5250
5250
  }
5251
5251
  return { left: segment.left, width: segment.width + activityDrag.dayDelta * dayWidth };
5252
5252
  };
5253
- const activityLinks = useMemo2(() => {
5254
- const gaps = [];
5255
- const elbows = [];
5256
- if (!showActivityLinks || !renderActivities || !activityLayout) return { gaps, elbows };
5257
- const activities = task.activities ?? [];
5258
- const segmentById = new Map(activityLayout.segments.map((segment) => [segment.id, segment]));
5259
- const visibleIds = new Set(visibleActivitySegments.map((segment) => segment.id));
5260
- const laneTopY = (lane) => activityTopOffset + lane * ACTIVITY_LANE_STEP + (ACTIVITY_LANE_STEP - ACTIVITY_LANE_BAR_HEIGHT) / 2;
5261
- const liveRect = (segment) => {
5262
- const geometry = liveActivityGeometry(segment);
5263
- const chainDelta = activityOverrides?.get(segment.id) ?? 0;
5264
- const left2 = geometry.left + (chainDelta !== 0 ? chainDelta * dayWidth : 0);
5265
- return { left: left2, right: left2 + geometry.width };
5266
- };
5267
- for (let index = 0; index < activities.length - 1; index += 1) {
5268
- const predecessor = segmentById.get(activities[index].id);
5269
- const successor = segmentById.get(activities[index + 1].id);
5270
- if (!predecessor || !successor) continue;
5271
- if (!visibleIds.has(predecessor.id) || !visibleIds.has(successor.id)) continue;
5272
- const lag = activities[index + 1].lag ?? 0;
5273
- const predRect = liveRect(predecessor);
5274
- const succRect = liveRect(successor);
5275
- if (predecessor.lane === successor.lane && succRect.left >= predRect.right) {
5276
- const width2 = succRect.left - predRect.right;
5277
- if (width2 >= 1) {
5278
- gaps.push({ key: `${predecessor.id}->${successor.id}`, left: predRect.right, width: width2, lane: predecessor.lane, lag });
5279
- }
5280
- continue;
5281
- }
5282
- const predecessorLaneTop = laneTopY(predecessor.lane);
5283
- const successorLaneTop = laneTopY(successor.lane);
5284
- const sameLane = predecessor.lane === successor.lane;
5285
- const reverseOrder = !sameLane && successorLaneTop < predecessorLaneTop;
5286
- const fromY = reverseOrder ? predecessorLaneTop + 6 : predecessorLaneTop + ACTIVITY_LANE_BAR_HEIGHT - 6;
5287
- const toY = reverseOrder ? successorLaneTop + ACTIVITY_LANE_BAR_HEIGHT - 6 : successorLaneTop + (sameLane ? ACTIVITY_LANE_STEP : 0) + 6;
5288
- const fromX = predRect.right;
5289
- const toX = succRect.left;
5290
- elbows.push({
5291
- key: `${predecessor.id}->${successor.id}`,
5292
- d: calculateDependencyPath({ x: fromX, y: fromY }, { x: toX, y: toY }, false),
5293
- lagX: toX - 14,
5294
- lagY: reverseOrder ? fromY - 4 : fromY + 12,
5295
- lag
5296
- });
5297
- }
5298
- return { gaps, elbows };
5299
- }, [showActivityLinks, renderActivities, activityLayout, visibleActivitySegments, activityTopOffset, activityOverrides, activityDrag, dayWidth, task.activities]);
5300
5253
  const activityTipData = useMemo2(() => {
5301
5254
  if (!activityTipId || !task.activities) return null;
5302
5255
  const activity = task.activities.find((item) => item.id === activityTipId);
@@ -5368,121 +5321,72 @@ var TaskRow = React2.memo(
5368
5321
  }
5369
5322
  }
5370
5323
  ),
5371
- renderActivities && activityLayout && /* @__PURE__ */ jsxs2("div", { className: "gantt-tr-activityLanes", children: [
5372
- activityLinks.elbows.length > 0 && /* @__PURE__ */ jsxs2("svg", { className: "gantt-tr-activityLinksSvg", width: "100%", height: "100%", "aria-hidden": "true", children: [
5373
- /* @__PURE__ */ jsx2("defs", { children: /* @__PURE__ */ jsx2("marker", { id: "arrowhead", markerWidth: "8", markerHeight: "6", markerUnits: "userSpaceOnUse", refX: "7", refY: "3", orient: "auto", children: /* @__PURE__ */ jsx2("polygon", { points: "0 0, 8 3, 0 6", fill: "var(--gantt-dependency-line-color, #666666)" }) }) }),
5374
- activityLinks.elbows.map((link) => /* @__PURE__ */ jsxs2("g", { children: [
5375
- /* @__PURE__ */ jsx2("path", { className: "gantt-dependency-path", d: link.d, markerEnd: "url(#arrowhead)" }),
5376
- showActivityLag && link.lag !== 0 && /* @__PURE__ */ jsx2(
5377
- "text",
5378
- {
5379
- className: "gantt-dependency-lag-label",
5380
- x: link.lagX,
5381
- y: link.lagY,
5382
- textAnchor: "middle",
5383
- fontSize: "10",
5384
- fill: "var(--gantt-dependency-line-color, #666666)",
5385
- children: link.lag > 0 ? `+${link.lag}` : `${link.lag}`
5324
+ renderActivities && activityLayout && /* @__PURE__ */ jsx2("div", { className: "gantt-tr-activityLanes", children: visibleActivitySegments.map((segment) => {
5325
+ const live = liveActivityGeometry(segment);
5326
+ const chainDelta = activityOverrides?.get(segment.id) ?? 0;
5327
+ const activityProgress = segment.progress === void 0 ? 0 : Math.min(100, Math.max(0, Math.round(segment.progress)));
5328
+ const liveLeft = live.left + (chainDelta !== 0 ? chainDelta * dayWidth : 0);
5329
+ const isDraggingActivity = activityDrag?.id === segment.id;
5330
+ const isBlockingActivity = blockedActivityIds?.has(segment.id) ?? false;
5331
+ const isAtLimit = isDraggingActivity && activityBlockedBy !== null;
5332
+ const isActiveActivity = activationVisualEnabled && activeActivityKey === activityOwnerKey(task.id, segment.id);
5333
+ const isSameWorkType = activeWork !== null && (segment.id === activeWork.id || activeWork.name !== null && segment.name === activeWork.name);
5334
+ const isDimmed = dimOthers && activeWork !== null && !isSameWorkType;
5335
+ const isChainHighlighted = highlightChain && activeWork !== null && isSameWorkType;
5336
+ return /* @__PURE__ */ jsxs2(
5337
+ "div",
5338
+ {
5339
+ "data-activity-id": segment.id,
5340
+ 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"}`,
5341
+ style: {
5342
+ left: `${liveLeft}px`,
5343
+ width: `${live.width}px`,
5344
+ top: `${activityTopOffset + segment.lane * ACTIVITY_LANE_STEP + (ACTIVITY_LANE_STEP - ACTIVITY_LANE_BAR_HEIGHT) / 2}px`,
5345
+ height: `${ACTIVITY_LANE_BAR_HEIGHT}px`,
5346
+ backgroundColor: segment.color || "var(--gantt-task-bar-default-color)"
5347
+ },
5348
+ onMouseDown: (event) => {
5349
+ if (!activityDragEnabled) return;
5350
+ const activationKey = activityOwnerKey(task.id, segment.id);
5351
+ const isActive = activityActivationStore?.getActiveKey() === activationKey;
5352
+ if (activationVisualEnabled && !isActive) {
5353
+ activityActivationStore?.setActiveKey(activationKey);
5386
5354
  }
5387
- )
5388
- ] }, link.key))
5389
- ] }),
5390
- visibleActivitySegments.map((segment) => {
5391
- const live = liveActivityGeometry(segment);
5392
- const chainDelta = activityOverrides?.get(segment.id) ?? 0;
5393
- const activityProgress = segment.progress === void 0 ? 0 : Math.min(100, Math.max(0, Math.round(segment.progress)));
5394
- const liveLeft = live.left + (chainDelta !== 0 ? chainDelta * dayWidth : 0);
5395
- const isDraggingActivity = activityDrag?.id === segment.id;
5396
- const isBlockingActivity = blockedActivityIds?.has(segment.id) ?? false;
5397
- const isAtLimit = isDraggingActivity && activityBlockedBy !== null;
5398
- const isActiveActivity = activationVisualEnabled && activeActivityKey === activityOwnerKey(task.id, segment.id);
5399
- const isSameWorkType = activeWork !== null && (segment.id === activeWork.id || activeWork.name !== null && segment.name === activeWork.name);
5400
- const isDimmed = dimOthers && activeWork !== null && !isSameWorkType;
5401
- const isChainHighlighted = highlightChain && activeWork !== null && isSameWorkType;
5402
- return /* @__PURE__ */ jsxs2(
5403
- "div",
5404
- {
5405
- "data-activity-id": segment.id,
5406
- 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"}`,
5407
- style: {
5408
- left: `${liveLeft}px`,
5409
- width: `${live.width}px`,
5410
- top: `${activityTopOffset + segment.lane * ACTIVITY_LANE_STEP + (ACTIVITY_LANE_STEP - ACTIVITY_LANE_BAR_HEIGHT) / 2}px`,
5411
- height: `${ACTIVITY_LANE_BAR_HEIGHT}px`,
5412
- backgroundColor: segment.color || "var(--gantt-task-bar-default-color)"
5413
- },
5414
- onMouseDown: (event) => {
5415
- if (!activityDragEnabled) return;
5416
- const activationKey = activityOwnerKey(task.id, segment.id);
5417
- const isActive = activityActivationStore?.getActiveKey() === activationKey;
5418
- if (activationVisualEnabled && !isActive) {
5419
- activityActivationStore?.setActiveKey(activationKey);
5420
- }
5421
- if (activityClickToDrag && !isActive) return;
5422
- const target = event.target;
5423
- const mode = target.closest(".gantt-tr-resizeHandleLeft") ? "resize-left" : target.closest(".gantt-tr-resizeHandleRight") ? "resize-right" : "move";
5424
- handleActivityPointerDown(segment, mode)(event);
5425
- },
5426
- onMouseEnter: (event) => {
5427
- if (activityDrag || activityDragOwner?.get()) return;
5428
- setActivityTipPosition(anchorActivityTip(event.currentTarget.getBoundingClientRect()));
5429
- setActivityTipId(segment.id);
5430
- },
5431
- onMouseLeave: () => {
5432
- if (!activityDrag) {
5433
- setActivityTipId((current) => current === segment.id ? null : current);
5434
- activityTipAnchor.current = null;
5435
- setActivityTipPosition(null);
5436
- }
5437
- },
5438
- children: [
5439
- activityProgress > 0 && /* @__PURE__ */ jsx2(
5440
- "span",
5441
- {
5442
- className: "gantt-tr-activityProgress",
5443
- style: { width: `${activityProgress}%` }
5444
- }
5445
- ),
5446
- /* @__PURE__ */ jsx2("span", { className: "gantt-tr-activityName", style: { color: activityTextColor(segment.color) }, children: segment.name }),
5447
- activityDragEnabled && /* @__PURE__ */ jsxs2(Fragment, { children: [
5448
- /* @__PURE__ */ jsx2("div", { className: "gantt-tr-resizeHandle gantt-tr-resizeHandleLeft" }),
5449
- /* @__PURE__ */ jsx2("div", { className: "gantt-tr-resizeHandle gantt-tr-resizeHandleRight" })
5450
- ] })
5451
- ]
5355
+ if (activityClickToDrag && !isActive) return;
5356
+ const target = event.target;
5357
+ const mode = target.closest(".gantt-tr-resizeHandleLeft") ? "resize-left" : target.closest(".gantt-tr-resizeHandleRight") ? "resize-right" : "move";
5358
+ handleActivityPointerDown(segment, mode)(event);
5452
5359
  },
5453
- segment.id
5454
- );
5455
- }),
5456
- activityLinks.gaps.map((gap) => /* @__PURE__ */ jsxs2(React2.Fragment, { children: [
5457
- /* @__PURE__ */ jsx2(
5458
- "span",
5459
- {
5460
- className: "gantt-tr-activityLink",
5461
- "aria-hidden": "true",
5462
- style: {
5463
- left: `${gap.left}px`,
5464
- width: `${gap.width}px`,
5465
- top: `${activityTopOffset + gap.lane * ACTIVITY_LANE_STEP + ACTIVITY_LANE_STEP / 2}px`
5360
+ onMouseEnter: (event) => {
5361
+ if (activityDrag || activityDragOwner?.get()) return;
5362
+ setActivityTipPosition(anchorActivityTip(event.currentTarget.getBoundingClientRect()));
5363
+ setActivityTipId(segment.id);
5364
+ },
5365
+ onMouseLeave: () => {
5366
+ if (!activityDrag) {
5367
+ setActivityTipId((current) => current === segment.id ? null : current);
5368
+ activityTipAnchor.current = null;
5369
+ setActivityTipPosition(null);
5466
5370
  }
5467
- }
5468
- ),
5469
- showActivityLag && gap.lag > 0 && /* @__PURE__ */ jsxs2(
5470
- "span",
5471
- {
5472
- className: "gantt-tr-activityLag",
5473
- title: `\u0417\u0430\u0437\u043E\u0440 ${gap.lag} \u0434`,
5474
- style: {
5475
- left: `${gap.left + gap.width - 14}px`,
5476
- top: `${activityTopOffset + gap.lane * ACTIVITY_LANE_STEP + ACTIVITY_LANE_STEP / 2}px`
5477
- },
5478
- children: [
5479
- "+",
5480
- gap.lag
5481
- ]
5482
- }
5483
- )
5484
- ] }, gap.key))
5485
- ] }),
5371
+ },
5372
+ children: [
5373
+ activityProgress > 0 && /* @__PURE__ */ jsx2(
5374
+ "span",
5375
+ {
5376
+ className: "gantt-tr-activityProgress",
5377
+ style: { width: `${activityProgress}%` }
5378
+ }
5379
+ ),
5380
+ /* @__PURE__ */ jsx2("span", { className: "gantt-tr-activityName", style: { color: activityTextColor(segment.color) }, children: segment.name }),
5381
+ activityDragEnabled && /* @__PURE__ */ jsxs2(Fragment, { children: [
5382
+ /* @__PURE__ */ jsx2("div", { className: "gantt-tr-resizeHandle gantt-tr-resizeHandleLeft" }),
5383
+ /* @__PURE__ */ jsx2("div", { className: "gantt-tr-resizeHandle gantt-tr-resizeHandleRight" })
5384
+ ] })
5385
+ ]
5386
+ },
5387
+ segment.id
5388
+ );
5389
+ }) }),
5486
5390
  !renderActivities && /* @__PURE__ */ jsxs2(
5487
5391
  "div",
5488
5392
  {
@@ -6054,10 +5958,11 @@ function areBothHiddenInSameParent(predecessorId, successorId, collapsedParentId
6054
5958
  if (!predVisibleAncestor || !succVisibleAncestor) return false;
6055
5959
  return predVisibleAncestor.id === succVisibleAncestor.id;
6056
5960
  }
5961
+ var EMPTY_COLLAPSED_PARENT_IDS = /* @__PURE__ */ new Set();
6057
5962
  var DependencyLines = React6.memo(({
6058
5963
  tasks,
6059
5964
  allTasks,
6060
- collapsedParentIds = /* @__PURE__ */ new Set(),
5965
+ collapsedParentIds = EMPTY_COLLAPSED_PARENT_IDS,
6061
5966
  monthStart,
6062
5967
  dayWidth,
6063
5968
  rowHeight,
@@ -6202,8 +6107,8 @@ var DependencyLines = React6.memo(({
6202
6107
  fromY = predecessor.rowTop + predecessor.rowHeight / 2;
6203
6108
  toY = successor.rowTop + successor.rowHeight / 2;
6204
6109
  } else if (activityEndpoints) {
6205
- fromY = reverseOrder ? predecessor.rowTop : predecessor.rowTop + predecessor.rowHeight;
6206
- toY = reverseOrder ? successor.rowTop + successor.rowHeight : successor.rowTop;
6110
+ fromY = reverseOrder ? predecessor.rowTop + 6 : predecessor.rowTop + predecessor.rowHeight - 6;
6111
+ toY = reverseOrder ? successor.rowTop + successor.rowHeight - 6 : successor.rowTop + 6;
6207
6112
  } else if (reverseOrder) {
6208
6113
  fromY = predecessor.rowTop + 10;
6209
6114
  toY = successor.rowTop + successor.rowHeight - 6;
@@ -6438,10 +6343,12 @@ function ActivityDependencyLines(props) {
6438
6343
  const layout = useMemo7(() => {
6439
6344
  const flattened = [], rendered = [], tops = [], heights = [];
6440
6345
  const indices = /* @__PURE__ */ new Map();
6346
+ const neededRows = /* @__PURE__ */ new Set();
6441
6347
  const incoming = /* @__PURE__ */ new Map();
6442
6348
  const selected = props.highlight ? new Set(props.highlight.activities.map((activity) => activityKey(activity.taskId, activity.activityId))) : void 0;
6443
6349
  const highlightMode = props.highlight?.mode ?? "chain";
6444
6350
  for (const edge of dependencies) {
6351
+ if (!props.renderedTaskIds.has(edge.predecessorTaskId) && !props.renderedTaskIds.has(edge.successorTaskId)) continue;
6445
6352
  if (selected) {
6446
6353
  const fromSelected = selected.has(activityKey(edge.predecessorTaskId, edge.predecessorActivityId));
6447
6354
  const toSelected = selected.has(activityKey(edge.successorTaskId, edge.successorActivityId));
@@ -6450,12 +6357,15 @@ function ActivityDependencyLines(props) {
6450
6357
  const outgoing = fromSelected && !toSelected && (highlightMode === "chain-outgoing" || highlightMode === "chain-all");
6451
6358
  if (!internal && !incoming2 && !outgoing) continue;
6452
6359
  }
6360
+ neededRows.add(edge.predecessorTaskId);
6361
+ neededRows.add(edge.successorTaskId);
6453
6362
  const id = activityKey(edge.successorTaskId, edge.successorActivityId);
6454
6363
  const values = incoming.get(id) ?? [];
6455
6364
  values.push({ taskId: activityKey(edge.predecessorTaskId, edge.predecessorActivityId), type: edge.type, lag: edge.lag });
6456
6365
  incoming.set(id, values);
6457
6366
  }
6458
6367
  for (const task of tasks) {
6368
+ if (!neededRows.has(task.id)) continue;
6459
6369
  const row = props.rowIndexByTaskId.get(task.id);
6460
6370
  if (row === void 0 || !task.activities?.length) continue;
6461
6371
  const height = props.rowHeights[row] ?? props.rowHeight;
@@ -15393,6 +15303,17 @@ function TaskGanttChartInner(props, ref) {
15393
15303
  onTaskDateChangeModeChange: externalOnTaskDateChangeModeChange,
15394
15304
  printDependencyLabels = false
15395
15305
  } = props;
15306
+ const resolvedActivityDependencies = useMemo14(() => {
15307
+ if (activityDependencies !== void 0) return activityDependencies;
15308
+ return tasks.flatMap((task) => (task.activities ?? []).slice(1).map((successor, index) => ({
15309
+ predecessorTaskId: task.id,
15310
+ predecessorActivityId: task.activities[index].id,
15311
+ successorTaskId: task.id,
15312
+ successorActivityId: successor.id,
15313
+ type: "FS",
15314
+ lag: successor.lag ?? 0
15315
+ })));
15316
+ }, [tasks, activityDependencies]);
15396
15317
  const dayWidth = !isTableMatrixMode ? props.dayWidth ?? 40 : 40;
15397
15318
  const criticalPathMode = !isTableMatrixMode && !isPlanFactMode ? props.criticalPathMode : void 0;
15398
15319
  const onSubtreeScaleResult = !isTableMatrixMode && !isPlanFactMode ? props.onSubtreeScaleResult : void 0;
@@ -16869,7 +16790,7 @@ function TaskGanttChartInner(props, ref) {
16869
16790
  onHoverEnd: () => setActiveTimelineTooltip(null)
16870
16791
  }
16871
16792
  ),
16872
- showActivityLinks && activityDependencies !== void 0 && /* @__PURE__ */ jsx22(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 }),
16793
+ showActivityLinks && resolvedActivityDependencies.length > 0 && /* @__PURE__ */ jsx22(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 }),
16873
16794
  /* @__PURE__ */ jsx22(
16874
16795
  DependencyLines_default,
16875
16796
  {
@@ -17012,7 +16933,7 @@ function TaskGanttChartInner(props, ref) {
17012
16933
  activityActivationStore,
17013
16934
  activityClickToDrag,
17014
16935
  activityActivationMode,
17015
- showActivityLinks: showActivityLinks && activityDependencies === void 0,
16936
+ showActivityLinks: false,
17016
16937
  showActivityLag,
17017
16938
  activityTooltip,
17018
16939
  horizontalWindow,