gantt-task-react-v 1.4.0 → 1.4.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.
@@ -11727,9 +11727,9 @@ const generateTrianglePoints = (x, y, width, isLeftDirected) => {
11727
11727
  ${x - width},${y - width}
11728
11728
  ${x - width},${y + width}`;
11729
11729
  };
11730
- const arrow_clickable = "_arrow_clickable_3bsl2_1";
11731
- const mainPath = "_mainPath_3bsl2_11";
11732
- const clickZone = "_clickZone_3bsl2_43";
11730
+ const arrow_clickable = "_arrow_clickable_50mfa_1";
11731
+ const mainPath = "_mainPath_50mfa_11";
11732
+ const clickZone = "_clickZone_50mfa_49";
11733
11733
  const styles$a = {
11734
11734
  arrow_clickable,
11735
11735
  mainPath,
@@ -11821,18 +11821,60 @@ const ArrowInner = (props) => {
11821
11821
  ) });
11822
11822
  };
11823
11823
  const Arrow = memo(ArrowInner);
11824
+ const roundedPath = (points, radius) => {
11825
+ if (points.length < 2)
11826
+ return "";
11827
+ let d = `M ${points[0][0]} ${points[0][1]}`;
11828
+ for (let i = 1; i < points.length - 1; i++) {
11829
+ const prev = points[i - 1];
11830
+ const curr = points[i];
11831
+ const next = points[i + 1];
11832
+ const dx1 = prev[0] - curr[0];
11833
+ const dy1 = prev[1] - curr[1];
11834
+ const len1 = Math.abs(dx1) + Math.abs(dy1);
11835
+ const dx2 = next[0] - curr[0];
11836
+ const dy2 = next[1] - curr[1];
11837
+ const len2 = Math.abs(dx2) + Math.abs(dy2);
11838
+ const r = Math.min(radius, len1 / 2, len2 / 2);
11839
+ if (r <= 0 || len1 === 0 || len2 === 0) {
11840
+ d += ` L ${curr[0]} ${curr[1]}`;
11841
+ continue;
11842
+ }
11843
+ const ux1 = dx1 === 0 ? 0 : dx1 / Math.abs(dx1);
11844
+ const uy1 = dy1 === 0 ? 0 : dy1 / Math.abs(dy1);
11845
+ const ux2 = dx2 === 0 ? 0 : dx2 / Math.abs(dx2);
11846
+ const uy2 = dy2 === 0 ? 0 : dy2 / Math.abs(dy2);
11847
+ d += ` L ${curr[0] + ux1 * r} ${curr[1] + uy1 * r}`;
11848
+ d += ` Q ${curr[0]} ${curr[1]} ${curr[0] + ux2 * r} ${curr[1] + uy2 * r}`;
11849
+ }
11850
+ const last = points[points.length - 1];
11851
+ d += ` L ${last[0]} ${last[1]}`;
11852
+ return d;
11853
+ };
11854
+ const ARROW_CORNER_RADIUS = 6;
11824
11855
  const drownPathAndTriangle = (indexForm, fromX1, fromX2, fromY, isTaskFromLeftSide, indexTo, toX1, toX2, toY, isTaskToLeftSide, fullRowHeight, taskHeight, arrowIndent) => {
11825
11856
  const isDownDirected = indexTo > indexForm;
11826
- const horizontalDockingY = isDownDirected ? (indexForm + 1) * fullRowHeight : indexForm * fullRowHeight;
11857
+ const spreadSeed = Math.abs(
11858
+ Math.round(fromX1 + fromX2) * 7 + Math.round(toX1 + toX2) * 13
11859
+ );
11860
+ const maxSpread = Math.min(fullRowHeight * 0.15, 8);
11861
+ const spreadOffset = (spreadSeed % 11 / 10 - 0.5) * maxSpread * 2;
11862
+ const horizontalDockingY = isDownDirected ? (indexForm + 1) * fullRowHeight + spreadOffset : indexForm * fullRowHeight + spreadOffset;
11827
11863
  const taskFromEndPositionX = isTaskFromLeftSide ? fromX1 - arrowIndent : fromX2 + arrowIndent;
11828
11864
  const taskToEndPositionX = isTaskToLeftSide ? toX1 - arrowIndent : toX2 + arrowIndent;
11829
11865
  const taskToEndPositionY = toY + taskHeight / 2;
11830
- const path = `M ${isTaskFromLeftSide ? fromX1 : fromX2} ${fromY + taskHeight / 2}
11831
- H ${taskFromEndPositionX}
11832
- V ${horizontalDockingY}
11833
- H ${taskToEndPositionX}
11834
- V ${taskToEndPositionY}
11835
- H ${isTaskToLeftSide ? toX1 : toX2}`;
11866
+ const startX = isTaskFromLeftSide ? fromX1 : fromX2;
11867
+ const startY = fromY + taskHeight / 2;
11868
+ const endX = isTaskToLeftSide ? toX1 : toX2;
11869
+ const waypoints = [
11870
+ [startX, startY],
11871
+ [taskFromEndPositionX, startY],
11872
+ [taskFromEndPositionX, horizontalDockingY],
11873
+ [taskToEndPositionX, horizontalDockingY],
11874
+ [taskToEndPositionX, taskToEndPositionY],
11875
+ [endX, taskToEndPositionY]
11876
+ ];
11877
+ const path = roundedPath(waypoints, ARROW_CORNER_RADIUS);
11836
11878
  const trianglePoints = isTaskToLeftSide ? generateTrianglePoints(toX1, taskToEndPositionY, 5, false) : generateTrianglePoints(toX2, taskToEndPositionY, 5, true);
11837
11879
  return [path, trianglePoints];
11838
11880
  };
@@ -13126,6 +13168,12 @@ const TaskGanttContentInner = (props) => {
13126
13168
  const tasksRes = [];
13127
13169
  const arrowsRes = [];
13128
13170
  const selectedTasksRes = [];
13171
+ const taskById = /* @__PURE__ */ new Map();
13172
+ mapGlobalRowIndexToTask.forEach((task) => {
13173
+ if (task.type !== "empty") {
13174
+ taskById.set(task.id, task);
13175
+ }
13176
+ });
13129
13177
  const addedSelectedTasks = {};
13130
13178
  const addedDependencies = {};
13131
13179
  for (let index2 = start; index2 <= end; ++index2) {
@@ -13420,6 +13468,93 @@ const TaskGanttContentInner = (props) => {
13420
13468
  );
13421
13469
  }
13422
13470
  }
13471
+ const renderedTop = start * fullRowHeight;
13472
+ const renderedBottom = (end + 1) * fullRowHeight;
13473
+ for (const [comparisonLevel, dependenciesByLevel] of dependencyMap) {
13474
+ let addedDependenciesAtLevel = addedDependencies[comparisonLevel];
13475
+ if (!addedDependenciesAtLevel) {
13476
+ addedDependenciesAtLevel = {};
13477
+ addedDependencies[comparisonLevel] = addedDependenciesAtLevel;
13478
+ }
13479
+ const criticalPathOnLevel = criticalPaths ? criticalPaths.get(comparisonLevel) : void 0;
13480
+ for (const [taskId, dependencies] of dependenciesByLevel) {
13481
+ let addedDependenciesAtTask = addedDependenciesAtLevel[taskId];
13482
+ if (!addedDependenciesAtTask) {
13483
+ addedDependenciesAtTask = {};
13484
+ addedDependenciesAtLevel[taskId] = addedDependenciesAtTask;
13485
+ }
13486
+ const targetTask = taskById.get(taskId);
13487
+ if (!targetTask)
13488
+ continue;
13489
+ const criticalPathForTask = criticalPathOnLevel ? criticalPathOnLevel.dependencies.get(taskId) : void 0;
13490
+ dependencies.filter(({ source }) => {
13491
+ if (addedDependenciesAtTask[source.id])
13492
+ return false;
13493
+ if (!visibleTasksMirror[source.id])
13494
+ return false;
13495
+ return true;
13496
+ }).forEach(
13497
+ ({
13498
+ containerHeight,
13499
+ containerY,
13500
+ innerFromY,
13501
+ innerToY,
13502
+ ownTarget,
13503
+ source,
13504
+ sourceTarget
13505
+ }) => {
13506
+ if (containerY + containerHeight < renderedTop || containerY > renderedBottom) {
13507
+ return;
13508
+ }
13509
+ addedDependenciesAtTask[source.id] = true;
13510
+ const isCritical = criticalPathForTask ? criticalPathForTask.has(source.id) : false;
13511
+ const { x1: fromX1, x2: fromX2 } = getTaskCoordinates2(source);
13512
+ const { x1: targetX1, x2: targetX2 } = getTaskCoordinates2(targetTask);
13513
+ const safeFromX1 = isNaN(fromX1) || !isFinite(fromX1) ? 0 : fromX1;
13514
+ const safeFromX2 = isNaN(fromX2) || !isFinite(fromX2) ? safeFromX1 + 10 : fromX2;
13515
+ const safeTargetX1 = isNaN(targetX1) || !isFinite(targetX1) ? 0 : targetX1;
13516
+ const safeTargetX2 = isNaN(targetX2) || !isFinite(targetX2) ? safeTargetX1 + 10 : targetX2;
13517
+ const cX = Math.min(safeFromX1, safeTargetX1) - DELTA_RELATION_WIDTH;
13518
+ const cW = Math.max(safeFromX2, safeTargetX2) - cX + DELTA_RELATION_WIDTH;
13519
+ const safeCX = isNaN(cX) || !isFinite(cX) ? 0 : cX;
13520
+ const safeCW = isNaN(cW) || !isFinite(cW) ? 100 : Math.max(cW, 0);
13521
+ arrowsRes.push(
13522
+ /* @__PURE__ */ jsx(
13523
+ "svg",
13524
+ {
13525
+ x: Math.max(safeCX + (additionalLeftSpace || 0), 0),
13526
+ y: containerY,
13527
+ width: safeCW,
13528
+ height: containerHeight,
13529
+ children: /* @__PURE__ */ jsx(
13530
+ Arrow,
13531
+ {
13532
+ distances,
13533
+ taskFrom: source,
13534
+ targetFrom: sourceTarget,
13535
+ fromX1: safeFromX1 - safeCX,
13536
+ fromX2: safeFromX2 - safeCX,
13537
+ fromY: innerFromY,
13538
+ taskTo: targetTask,
13539
+ targetTo: ownTarget,
13540
+ toX1: safeTargetX1 - safeCX,
13541
+ toX2: safeTargetX2 - safeCX,
13542
+ toY: innerToY,
13543
+ fullRowHeight,
13544
+ taskHeight,
13545
+ isCritical,
13546
+ rtl,
13547
+ onArrowDoubleClick
13548
+ }
13549
+ )
13550
+ },
13551
+ `Arrow from ${source.id} to ${taskId} on ${comparisonLevel}`
13552
+ )
13553
+ );
13554
+ }
13555
+ );
13556
+ }
13557
+ }
13423
13558
  return [tasksRes, arrowsRes, selectedTasksRes];
13424
13559
  }, [
13425
13560
  viewMode,
@@ -11744,9 +11744,9 @@
11744
11744
  ${x - width},${y - width}
11745
11745
  ${x - width},${y + width}`;
11746
11746
  };
11747
- const arrow_clickable = "_arrow_clickable_3bsl2_1";
11748
- const mainPath = "_mainPath_3bsl2_11";
11749
- const clickZone = "_clickZone_3bsl2_43";
11747
+ const arrow_clickable = "_arrow_clickable_50mfa_1";
11748
+ const mainPath = "_mainPath_50mfa_11";
11749
+ const clickZone = "_clickZone_50mfa_49";
11750
11750
  const styles$a = {
11751
11751
  arrow_clickable,
11752
11752
  mainPath,
@@ -11838,18 +11838,60 @@
11838
11838
  ) });
11839
11839
  };
11840
11840
  const Arrow = React.memo(ArrowInner);
11841
+ const roundedPath = (points, radius) => {
11842
+ if (points.length < 2)
11843
+ return "";
11844
+ let d = `M ${points[0][0]} ${points[0][1]}`;
11845
+ for (let i = 1; i < points.length - 1; i++) {
11846
+ const prev = points[i - 1];
11847
+ const curr = points[i];
11848
+ const next = points[i + 1];
11849
+ const dx1 = prev[0] - curr[0];
11850
+ const dy1 = prev[1] - curr[1];
11851
+ const len1 = Math.abs(dx1) + Math.abs(dy1);
11852
+ const dx2 = next[0] - curr[0];
11853
+ const dy2 = next[1] - curr[1];
11854
+ const len2 = Math.abs(dx2) + Math.abs(dy2);
11855
+ const r = Math.min(radius, len1 / 2, len2 / 2);
11856
+ if (r <= 0 || len1 === 0 || len2 === 0) {
11857
+ d += ` L ${curr[0]} ${curr[1]}`;
11858
+ continue;
11859
+ }
11860
+ const ux1 = dx1 === 0 ? 0 : dx1 / Math.abs(dx1);
11861
+ const uy1 = dy1 === 0 ? 0 : dy1 / Math.abs(dy1);
11862
+ const ux2 = dx2 === 0 ? 0 : dx2 / Math.abs(dx2);
11863
+ const uy2 = dy2 === 0 ? 0 : dy2 / Math.abs(dy2);
11864
+ d += ` L ${curr[0] + ux1 * r} ${curr[1] + uy1 * r}`;
11865
+ d += ` Q ${curr[0]} ${curr[1]} ${curr[0] + ux2 * r} ${curr[1] + uy2 * r}`;
11866
+ }
11867
+ const last = points[points.length - 1];
11868
+ d += ` L ${last[0]} ${last[1]}`;
11869
+ return d;
11870
+ };
11871
+ const ARROW_CORNER_RADIUS = 6;
11841
11872
  const drownPathAndTriangle = (indexForm, fromX1, fromX2, fromY, isTaskFromLeftSide, indexTo, toX1, toX2, toY, isTaskToLeftSide, fullRowHeight, taskHeight, arrowIndent) => {
11842
11873
  const isDownDirected = indexTo > indexForm;
11843
- const horizontalDockingY = isDownDirected ? (indexForm + 1) * fullRowHeight : indexForm * fullRowHeight;
11874
+ const spreadSeed = Math.abs(
11875
+ Math.round(fromX1 + fromX2) * 7 + Math.round(toX1 + toX2) * 13
11876
+ );
11877
+ const maxSpread = Math.min(fullRowHeight * 0.15, 8);
11878
+ const spreadOffset = (spreadSeed % 11 / 10 - 0.5) * maxSpread * 2;
11879
+ const horizontalDockingY = isDownDirected ? (indexForm + 1) * fullRowHeight + spreadOffset : indexForm * fullRowHeight + spreadOffset;
11844
11880
  const taskFromEndPositionX = isTaskFromLeftSide ? fromX1 - arrowIndent : fromX2 + arrowIndent;
11845
11881
  const taskToEndPositionX = isTaskToLeftSide ? toX1 - arrowIndent : toX2 + arrowIndent;
11846
11882
  const taskToEndPositionY = toY + taskHeight / 2;
11847
- const path = `M ${isTaskFromLeftSide ? fromX1 : fromX2} ${fromY + taskHeight / 2}
11848
- H ${taskFromEndPositionX}
11849
- V ${horizontalDockingY}
11850
- H ${taskToEndPositionX}
11851
- V ${taskToEndPositionY}
11852
- H ${isTaskToLeftSide ? toX1 : toX2}`;
11883
+ const startX = isTaskFromLeftSide ? fromX1 : fromX2;
11884
+ const startY = fromY + taskHeight / 2;
11885
+ const endX = isTaskToLeftSide ? toX1 : toX2;
11886
+ const waypoints = [
11887
+ [startX, startY],
11888
+ [taskFromEndPositionX, startY],
11889
+ [taskFromEndPositionX, horizontalDockingY],
11890
+ [taskToEndPositionX, horizontalDockingY],
11891
+ [taskToEndPositionX, taskToEndPositionY],
11892
+ [endX, taskToEndPositionY]
11893
+ ];
11894
+ const path = roundedPath(waypoints, ARROW_CORNER_RADIUS);
11853
11895
  const trianglePoints = isTaskToLeftSide ? generateTrianglePoints(toX1, taskToEndPositionY, 5, false) : generateTrianglePoints(toX2, taskToEndPositionY, 5, true);
11854
11896
  return [path, trianglePoints];
11855
11897
  };
@@ -13143,6 +13185,12 @@
13143
13185
  const tasksRes = [];
13144
13186
  const arrowsRes = [];
13145
13187
  const selectedTasksRes = [];
13188
+ const taskById = /* @__PURE__ */ new Map();
13189
+ mapGlobalRowIndexToTask.forEach((task) => {
13190
+ if (task.type !== "empty") {
13191
+ taskById.set(task.id, task);
13192
+ }
13193
+ });
13146
13194
  const addedSelectedTasks = {};
13147
13195
  const addedDependencies = {};
13148
13196
  for (let index2 = start; index2 <= end; ++index2) {
@@ -13437,6 +13485,93 @@
13437
13485
  );
13438
13486
  }
13439
13487
  }
13488
+ const renderedTop = start * fullRowHeight;
13489
+ const renderedBottom = (end + 1) * fullRowHeight;
13490
+ for (const [comparisonLevel, dependenciesByLevel] of dependencyMap) {
13491
+ let addedDependenciesAtLevel = addedDependencies[comparisonLevel];
13492
+ if (!addedDependenciesAtLevel) {
13493
+ addedDependenciesAtLevel = {};
13494
+ addedDependencies[comparisonLevel] = addedDependenciesAtLevel;
13495
+ }
13496
+ const criticalPathOnLevel = criticalPaths ? criticalPaths.get(comparisonLevel) : void 0;
13497
+ for (const [taskId, dependencies] of dependenciesByLevel) {
13498
+ let addedDependenciesAtTask = addedDependenciesAtLevel[taskId];
13499
+ if (!addedDependenciesAtTask) {
13500
+ addedDependenciesAtTask = {};
13501
+ addedDependenciesAtLevel[taskId] = addedDependenciesAtTask;
13502
+ }
13503
+ const targetTask = taskById.get(taskId);
13504
+ if (!targetTask)
13505
+ continue;
13506
+ const criticalPathForTask = criticalPathOnLevel ? criticalPathOnLevel.dependencies.get(taskId) : void 0;
13507
+ dependencies.filter(({ source }) => {
13508
+ if (addedDependenciesAtTask[source.id])
13509
+ return false;
13510
+ if (!visibleTasksMirror[source.id])
13511
+ return false;
13512
+ return true;
13513
+ }).forEach(
13514
+ ({
13515
+ containerHeight,
13516
+ containerY,
13517
+ innerFromY,
13518
+ innerToY,
13519
+ ownTarget,
13520
+ source,
13521
+ sourceTarget
13522
+ }) => {
13523
+ if (containerY + containerHeight < renderedTop || containerY > renderedBottom) {
13524
+ return;
13525
+ }
13526
+ addedDependenciesAtTask[source.id] = true;
13527
+ const isCritical = criticalPathForTask ? criticalPathForTask.has(source.id) : false;
13528
+ const { x1: fromX1, x2: fromX2 } = getTaskCoordinates2(source);
13529
+ const { x1: targetX1, x2: targetX2 } = getTaskCoordinates2(targetTask);
13530
+ const safeFromX1 = isNaN(fromX1) || !isFinite(fromX1) ? 0 : fromX1;
13531
+ const safeFromX2 = isNaN(fromX2) || !isFinite(fromX2) ? safeFromX1 + 10 : fromX2;
13532
+ const safeTargetX1 = isNaN(targetX1) || !isFinite(targetX1) ? 0 : targetX1;
13533
+ const safeTargetX2 = isNaN(targetX2) || !isFinite(targetX2) ? safeTargetX1 + 10 : targetX2;
13534
+ const cX = Math.min(safeFromX1, safeTargetX1) - DELTA_RELATION_WIDTH;
13535
+ const cW = Math.max(safeFromX2, safeTargetX2) - cX + DELTA_RELATION_WIDTH;
13536
+ const safeCX = isNaN(cX) || !isFinite(cX) ? 0 : cX;
13537
+ const safeCW = isNaN(cW) || !isFinite(cW) ? 100 : Math.max(cW, 0);
13538
+ arrowsRes.push(
13539
+ /* @__PURE__ */ jsxRuntime.jsx(
13540
+ "svg",
13541
+ {
13542
+ x: Math.max(safeCX + (additionalLeftSpace || 0), 0),
13543
+ y: containerY,
13544
+ width: safeCW,
13545
+ height: containerHeight,
13546
+ children: /* @__PURE__ */ jsxRuntime.jsx(
13547
+ Arrow,
13548
+ {
13549
+ distances,
13550
+ taskFrom: source,
13551
+ targetFrom: sourceTarget,
13552
+ fromX1: safeFromX1 - safeCX,
13553
+ fromX2: safeFromX2 - safeCX,
13554
+ fromY: innerFromY,
13555
+ taskTo: targetTask,
13556
+ targetTo: ownTarget,
13557
+ toX1: safeTargetX1 - safeCX,
13558
+ toX2: safeTargetX2 - safeCX,
13559
+ toY: innerToY,
13560
+ fullRowHeight,
13561
+ taskHeight,
13562
+ isCritical,
13563
+ rtl,
13564
+ onArrowDoubleClick
13565
+ }
13566
+ )
13567
+ },
13568
+ `Arrow from ${source.id} to ${taskId} on ${comparisonLevel}`
13569
+ )
13570
+ );
13571
+ }
13572
+ );
13573
+ }
13574
+ }
13440
13575
  return [tasksRes, arrowsRes, selectedTasksRes];
13441
13576
  }, [
13442
13577
  viewMode,
package/dist/style.css CHANGED
@@ -439,31 +439,34 @@
439
439
  ._calendarDragging_15t8b_85 {
440
440
  cursor: ew-resize;
441
441
  }
442
- ._arrow_clickable_3bsl2_1 {
442
+ ._arrow_clickable_50mfa_1 {
443
443
  cursor: pointer;
444
444
  }
445
445
 
446
446
  /*noinspection CssUnresolvedCustomProperty*/
447
- ._arrow_clickable_3bsl2_1:hover ._mainPath_3bsl2_11 {
447
+ ._arrow_clickable_50mfa_1:hover ._mainPath_50mfa_11 {
448
448
  filter: var(--gantt-hover-filter);
449
449
  stroke: var(--gantt-arrow-hover-color, red);
450
450
  stroke-width: 3px;
451
451
  }
452
452
 
453
453
  /*noinspection CssUnresolvedCustomProperty*/
454
- ._arrow_clickable_3bsl2_1:hover polygon {
454
+ ._arrow_clickable_50mfa_1:hover polygon {
455
455
  fill: var(--gantt-arrow-hover-color, red);
456
456
  }
457
457
 
458
- ._mainPath_3bsl2_11 {
458
+ ._mainPath_50mfa_11 {
459
459
  fill: none;
460
- stroke-width: 2px;
460
+ stroke-width: 1.5px;
461
+ stroke-linecap: round;
462
+ stroke-linejoin: round;
463
+ opacity: 0.85;
461
464
  }
462
465
 
463
- ._clickZone_3bsl2_43 {
466
+ ._clickZone_50mfa_49 {
464
467
  fill: none;
465
468
  stroke: transparent;
466
- stroke-width: 8px;
469
+ stroke-width: 10px;
467
470
  }
468
471
  ._relationLine_wh2qy_1 {
469
472
  /*noinspection CssUnresolvedCustomProperty*/
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gantt-task-react-v",
3
- "version": "1.4.0",
3
+ "version": "1.4.2",
4
4
  "description": "Interactive Gantt Chart for React with TypeScript.",
5
5
  "author": "aguilanbon",
6
6
  "homepage": "https://github.com/aguilanbon/gantt-task-react-v",