gantt-task-react-v 1.1.2 → 1.1.4

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.
@@ -10021,10 +10021,10 @@ const TaskListTableRowInner = forwardRef(
10021
10021
  const { id, comparisonLevel = 1 } = task;
10022
10022
  const onRootMouseDown = useCallback(
10023
10023
  (event) => {
10024
- event.preventDefault();
10025
10024
  if (event.button !== 0) {
10026
10025
  return;
10027
10026
  }
10027
+ event.preventDefault();
10028
10028
  if (task.type !== "empty") {
10029
10029
  scrollToTask(task);
10030
10030
  }
@@ -10907,204 +10907,6 @@ const styles$c = {
10907
10907
  ganttToday,
10908
10908
  ganttTodayCircle
10909
10909
  };
10910
- const getDateByOffset = (startDate, offset2, viewMode) => {
10911
- switch (viewMode) {
10912
- case ViewMode.Day:
10913
- return addDays(startDate, offset2);
10914
- case ViewMode.HalfDay:
10915
- return addHours(startDate, offset2 * 12);
10916
- case ViewMode.QuarterDay:
10917
- return addHours(startDate, offset2 * 6);
10918
- case ViewMode.Hour:
10919
- return addHours(startDate, offset2);
10920
- case ViewMode.Month:
10921
- return addMonths(startDate, offset2);
10922
- case ViewMode.Week:
10923
- return addWeeks(startDate, offset2);
10924
- case ViewMode.Year:
10925
- return addYears(startDate, offset2);
10926
- default:
10927
- throw new Error("Unknown view mode");
10928
- }
10929
- };
10930
- const taskXCoordinate = (xDate, startDate, viewMode, columnWidth) => {
10931
- const index2 = getDatesDiff(xDate, startDate, viewMode);
10932
- const currentDate = getDateByOffset(startDate, index2, viewMode);
10933
- const nextDate = getDateByOffset(startDate, index2 + 1, viewMode);
10934
- const remainderMillis = xDate.getTime() - currentDate.getTime();
10935
- const percentOfInterval = remainderMillis / (nextDate.getTime() - currentDate.getTime());
10936
- return index2 * columnWidth + percentOfInterval * columnWidth;
10937
- };
10938
- const taskComparisonXCoordinate = (xDate, startDate, viewMode, columnWidth) => {
10939
- const index2 = getDatesDiff(xDate, startDate, viewMode);
10940
- const currentDate = getDateByOffset(startDate, index2, viewMode);
10941
- const nextDate = getDateByOffset(startDate, index2 + 1, viewMode);
10942
- const remainderMillis = xDate.getTime() - currentDate.getTime();
10943
- const percentOfInterval = remainderMillis / (nextDate.getTime() - currentDate.getTime());
10944
- return index2 * columnWidth + percentOfInterval * columnWidth;
10945
- };
10946
- const progressWithByParams = (taskX1, taskX2, progress, rtl) => {
10947
- const progressWidth = Math.max((taskX2 - taskX1) * progress * 0.01, 0);
10948
- let progressX;
10949
- if (rtl) {
10950
- progressX = taskX2 - progressWidth;
10951
- } else {
10952
- progressX = taskX1;
10953
- }
10954
- return [progressWidth, progressX];
10955
- };
10956
- const dateByX = (x, taskX, taskDate, xStep, timeStep) => {
10957
- let newDate = new Date((x - taskX) / xStep * timeStep + taskDate.getTime());
10958
- newDate = new Date(
10959
- newDate.getTime() + (newDate.getTimezoneOffset() - taskDate.getTimezoneOffset()) * 6e4
10960
- );
10961
- return newDate;
10962
- };
10963
- const handleTaskBySVGMouseEvent = (action, selectedTask, initialCoordinates, coordinates, xStep, timeStep, rtl) => {
10964
- let result;
10965
- switch (selectedTask.type) {
10966
- case "milestone":
10967
- result = handleTaskBySVGMouseEventForMilestone(
10968
- action,
10969
- selectedTask,
10970
- initialCoordinates,
10971
- coordinates,
10972
- xStep,
10973
- timeStep
10974
- );
10975
- break;
10976
- default:
10977
- result = handleTaskBySVGMouseEventForBar(
10978
- action,
10979
- selectedTask,
10980
- initialCoordinates,
10981
- coordinates,
10982
- xStep,
10983
- timeStep,
10984
- rtl
10985
- );
10986
- break;
10987
- }
10988
- return result;
10989
- };
10990
- const handleTaskBySVGMouseEventForBar = (action, selectedTask, initialCoordinates, coordinates, xStep, timeStep, rtl) => {
10991
- const changedTask = { ...selectedTask };
10992
- let isChanged = false;
10993
- switch (action) {
10994
- case "progress":
10995
- isChanged = initialCoordinates.progressWidth !== coordinates.progressWidth;
10996
- if (isChanged) {
10997
- changedTask.progress = Math.round(
10998
- coordinates.progressWidth * 100 / (coordinates.x2 - coordinates.x1)
10999
- );
11000
- }
11001
- break;
11002
- case "start": {
11003
- isChanged = initialCoordinates.x1 !== coordinates.x1;
11004
- if (isChanged) {
11005
- if (rtl) {
11006
- changedTask.end = dateByX(
11007
- coordinates.x1,
11008
- initialCoordinates.x1,
11009
- selectedTask.end,
11010
- xStep,
11011
- timeStep
11012
- );
11013
- } else {
11014
- changedTask.start = dateByX(
11015
- coordinates.x1,
11016
- initialCoordinates.x1,
11017
- selectedTask.start,
11018
- xStep,
11019
- timeStep
11020
- );
11021
- }
11022
- }
11023
- break;
11024
- }
11025
- case "end": {
11026
- isChanged = initialCoordinates.x2 !== coordinates.x2;
11027
- if (isChanged) {
11028
- if (rtl) {
11029
- changedTask.start = dateByX(
11030
- coordinates.x2,
11031
- initialCoordinates.x2,
11032
- selectedTask.start,
11033
- xStep,
11034
- timeStep
11035
- );
11036
- } else {
11037
- changedTask.end = dateByX(
11038
- coordinates.x2,
11039
- initialCoordinates.x2,
11040
- selectedTask.end,
11041
- xStep,
11042
- timeStep
11043
- );
11044
- }
11045
- }
11046
- break;
11047
- }
11048
- case "move": {
11049
- isChanged = initialCoordinates.x1 !== coordinates.x1;
11050
- if (isChanged) {
11051
- if (rtl) {
11052
- changedTask.end = dateByX(
11053
- coordinates.x1,
11054
- initialCoordinates.x1,
11055
- selectedTask.end,
11056
- xStep,
11057
- timeStep
11058
- );
11059
- changedTask.start = dateByX(
11060
- coordinates.x2,
11061
- initialCoordinates.x2,
11062
- selectedTask.start,
11063
- xStep,
11064
- timeStep
11065
- );
11066
- } else {
11067
- changedTask.start = dateByX(
11068
- coordinates.x1,
11069
- initialCoordinates.x1,
11070
- selectedTask.start,
11071
- xStep,
11072
- timeStep
11073
- );
11074
- changedTask.end = dateByX(
11075
- coordinates.x2,
11076
- initialCoordinates.x2,
11077
- selectedTask.end,
11078
- xStep,
11079
- timeStep
11080
- );
11081
- }
11082
- }
11083
- break;
11084
- }
11085
- }
11086
- return { isChanged, changedTask };
11087
- };
11088
- const handleTaskBySVGMouseEventForMilestone = (action, selectedTask, initialCoordinates, coordinates, xStep, timeStep) => {
11089
- const changedTask = { ...selectedTask };
11090
- const isChanged = coordinates.x1 !== initialCoordinates.x1;
11091
- if (isChanged) {
11092
- switch (action) {
11093
- case "move": {
11094
- changedTask.start = dateByX(
11095
- coordinates.x1,
11096
- initialCoordinates.x1,
11097
- selectedTask.start,
11098
- xStep,
11099
- timeStep
11100
- );
11101
- changedTask.end = changedTask.start;
11102
- break;
11103
- }
11104
- }
11105
- }
11106
- return { isChanged, changedTask };
11107
- };
11108
10910
  const GanttTodayInner = ({
11109
10911
  additionalLeftSpace,
11110
10912
  distances: { columnWidth },
@@ -11113,8 +10915,6 @@ const GanttTodayInner = ({
11113
10915
  rtl,
11114
10916
  startDate,
11115
10917
  viewMode,
11116
- taskHeight,
11117
- // Add taskHeight parameter
11118
10918
  showTodayLine = true,
11119
10919
  showDataDateLine = false,
11120
10920
  dataDate = null,
@@ -11128,14 +10928,38 @@ const GanttTodayInner = ({
11128
10928
  return null;
11129
10929
  }
11130
10930
  const today = /* @__PURE__ */ new Date();
11131
- const x = taskXCoordinate(today, startDate, viewMode, columnWidth);
11132
- const adjustedX = rtl ? x + columnWidth : x;
10931
+ const todayIndex = getDatesDiff(today, startDate, viewMode);
10932
+ const extraMultiplier = () => {
10933
+ switch (viewMode) {
10934
+ case ViewMode.Week: {
10935
+ const percent = today.getDay() / 7;
10936
+ return 1 + percent * 0.2;
10937
+ }
10938
+ case ViewMode.Month: {
10939
+ const dayInMonth = today.getDate();
10940
+ const maxDaysInMonth = getDaysInMonth(
10941
+ today.getMonth(),
10942
+ today.getFullYear()
10943
+ );
10944
+ const percent = dayInMonth / maxDaysInMonth;
10945
+ return 1 + percent * 0.5;
10946
+ }
10947
+ case ViewMode.Year: {
10948
+ const percent = today.getMonth() / 12;
10949
+ return 1 + percent * 0.5;
10950
+ }
10951
+ default:
10952
+ return 1;
10953
+ }
10954
+ };
10955
+ const tickX = todayIndex * columnWidth * extraMultiplier();
10956
+ const x = rtl ? tickX + columnWidth : tickX;
11133
10957
  const color = todayColor || "var(--gantt-calendar-today-color)";
11134
10958
  return /* @__PURE__ */ jsxs(Fragment, { children: [
11135
10959
  /* @__PURE__ */ jsx(
11136
10960
  "rect",
11137
10961
  {
11138
- x: additionalLeftSpace + adjustedX,
10962
+ x: additionalLeftSpace + x,
11139
10963
  y: 0,
11140
10964
  width: 2,
11141
10965
  height: ganttFullHeight,
@@ -11146,7 +10970,7 @@ const GanttTodayInner = ({
11146
10970
  "circle",
11147
10971
  {
11148
10972
  className: styles$c.ganttTodayCircle,
11149
- cx: adjustedX + 1,
10973
+ cx: x + 1,
11150
10974
  cy: 6,
11151
10975
  r: 6,
11152
10976
  fill: color
@@ -11155,7 +10979,7 @@ const GanttTodayInner = ({
11155
10979
  /* @__PURE__ */ jsx(
11156
10980
  "text",
11157
10981
  {
11158
- x: additionalLeftSpace + adjustedX + 8,
10982
+ x: additionalLeftSpace + x + 8,
11159
10983
  y: 10,
11160
10984
  fill: color,
11161
10985
  fontSize: 12,
@@ -11180,16 +11004,38 @@ const GanttTodayInner = ({
11180
11004
  if (!showDataDateLine || !dataDate) {
11181
11005
  return null;
11182
11006
  }
11183
- const index2 = getDatesDiff(dataDate, startDate, viewMode);
11184
- const intervalEndX = (index2 + 1) * columnWidth;
11185
- const milestoneEndX = intervalEndX + taskHeight * 0.5;
11186
- const adjustedX = rtl ? milestoneEndX + columnWidth : milestoneEndX;
11007
+ const dataIndex = getDatesDiff(dataDate, startDate, viewMode);
11008
+ const extraMultiplier = () => {
11009
+ switch (viewMode) {
11010
+ case ViewMode.Week: {
11011
+ const percent = dataDate.getDay() / 7;
11012
+ return 1 + percent * 0.2;
11013
+ }
11014
+ case ViewMode.Month: {
11015
+ const dayInMonth = dataDate.getDate();
11016
+ const maxDaysInMonth = getDaysInMonth(
11017
+ dataDate.getMonth(),
11018
+ dataDate.getFullYear()
11019
+ );
11020
+ const percent = dayInMonth / maxDaysInMonth;
11021
+ return 1 + percent * 0.5;
11022
+ }
11023
+ case ViewMode.Year: {
11024
+ const percent = dataDate.getMonth() / 12;
11025
+ return 1 + percent * 0.5;
11026
+ }
11027
+ default:
11028
+ return 1;
11029
+ }
11030
+ };
11031
+ const tickX = dataIndex * columnWidth * extraMultiplier();
11032
+ const x = rtl ? tickX + columnWidth : tickX;
11187
11033
  const color = dataDateColor || "var(--gantt-calendar-today-color)";
11188
11034
  return /* @__PURE__ */ jsxs(Fragment, { children: [
11189
11035
  /* @__PURE__ */ jsx(
11190
11036
  "rect",
11191
11037
  {
11192
- x: additionalLeftSpace + adjustedX,
11038
+ x: additionalLeftSpace + x,
11193
11039
  y: 0,
11194
11040
  width: 2,
11195
11041
  height: ganttFullHeight,
@@ -11201,7 +11047,7 @@ const GanttTodayInner = ({
11201
11047
  "circle",
11202
11048
  {
11203
11049
  className: styles$c.ganttTodayCircle,
11204
- cx: adjustedX + 1,
11050
+ cx: x + 1,
11205
11051
  cy: 6,
11206
11052
  r: 6,
11207
11053
  fill: color
@@ -11210,7 +11056,7 @@ const GanttTodayInner = ({
11210
11056
  /* @__PURE__ */ jsx(
11211
11057
  "text",
11212
11058
  {
11213
- x: additionalLeftSpace + adjustedX + 8,
11059
+ x: additionalLeftSpace + x + 8,
11214
11060
  y: 10,
11215
11061
  fill: color,
11216
11062
  fontSize: 12,
@@ -11226,7 +11072,6 @@ const GanttTodayInner = ({
11226
11072
  rtl,
11227
11073
  startDate,
11228
11074
  viewMode,
11229
- taskHeight,
11230
11075
  showDataDateLine,
11231
11076
  dataDate,
11232
11077
  dataDateColor,
@@ -11925,6 +11770,204 @@ const RelationLine = ({
11925
11770
  }
11926
11771
  );
11927
11772
  };
11773
+ const getDateByOffset = (startDate, offset2, viewMode) => {
11774
+ switch (viewMode) {
11775
+ case ViewMode.Day:
11776
+ return addDays(startDate, offset2);
11777
+ case ViewMode.HalfDay:
11778
+ return addHours(startDate, offset2 * 12);
11779
+ case ViewMode.QuarterDay:
11780
+ return addHours(startDate, offset2 * 6);
11781
+ case ViewMode.Hour:
11782
+ return addHours(startDate, offset2);
11783
+ case ViewMode.Month:
11784
+ return addMonths(startDate, offset2);
11785
+ case ViewMode.Week:
11786
+ return addWeeks(startDate, offset2);
11787
+ case ViewMode.Year:
11788
+ return addYears(startDate, offset2);
11789
+ default:
11790
+ throw new Error("Unknown view mode");
11791
+ }
11792
+ };
11793
+ const taskXCoordinate = (xDate, startDate, viewMode, columnWidth) => {
11794
+ const index2 = getDatesDiff(xDate, startDate, viewMode);
11795
+ const currentDate = getDateByOffset(startDate, index2, viewMode);
11796
+ const nextDate = getDateByOffset(startDate, index2 + 1, viewMode);
11797
+ const remainderMillis = xDate.getTime() - currentDate.getTime();
11798
+ const percentOfInterval = remainderMillis / (nextDate.getTime() - currentDate.getTime());
11799
+ return index2 * columnWidth + percentOfInterval * columnWidth;
11800
+ };
11801
+ const taskComparisonXCoordinate = (xDate, startDate, viewMode, columnWidth) => {
11802
+ const index2 = getDatesDiff(xDate, startDate, viewMode);
11803
+ const currentDate = getDateByOffset(startDate, index2, viewMode);
11804
+ const nextDate = getDateByOffset(startDate, index2 + 1, viewMode);
11805
+ const remainderMillis = xDate.getTime() - currentDate.getTime();
11806
+ const percentOfInterval = remainderMillis / (nextDate.getTime() - currentDate.getTime());
11807
+ return index2 * columnWidth + percentOfInterval * columnWidth;
11808
+ };
11809
+ const progressWithByParams = (taskX1, taskX2, progress, rtl) => {
11810
+ const progressWidth = Math.max((taskX2 - taskX1) * progress * 0.01, 0);
11811
+ let progressX;
11812
+ if (rtl) {
11813
+ progressX = taskX2 - progressWidth;
11814
+ } else {
11815
+ progressX = taskX1;
11816
+ }
11817
+ return [progressWidth, progressX];
11818
+ };
11819
+ const dateByX = (x, taskX, taskDate, xStep, timeStep) => {
11820
+ let newDate = new Date((x - taskX) / xStep * timeStep + taskDate.getTime());
11821
+ newDate = new Date(
11822
+ newDate.getTime() + (newDate.getTimezoneOffset() - taskDate.getTimezoneOffset()) * 6e4
11823
+ );
11824
+ return newDate;
11825
+ };
11826
+ const handleTaskBySVGMouseEvent = (action, selectedTask, initialCoordinates, coordinates, xStep, timeStep, rtl) => {
11827
+ let result;
11828
+ switch (selectedTask.type) {
11829
+ case "milestone":
11830
+ result = handleTaskBySVGMouseEventForMilestone(
11831
+ action,
11832
+ selectedTask,
11833
+ initialCoordinates,
11834
+ coordinates,
11835
+ xStep,
11836
+ timeStep
11837
+ );
11838
+ break;
11839
+ default:
11840
+ result = handleTaskBySVGMouseEventForBar(
11841
+ action,
11842
+ selectedTask,
11843
+ initialCoordinates,
11844
+ coordinates,
11845
+ xStep,
11846
+ timeStep,
11847
+ rtl
11848
+ );
11849
+ break;
11850
+ }
11851
+ return result;
11852
+ };
11853
+ const handleTaskBySVGMouseEventForBar = (action, selectedTask, initialCoordinates, coordinates, xStep, timeStep, rtl) => {
11854
+ const changedTask = { ...selectedTask };
11855
+ let isChanged = false;
11856
+ switch (action) {
11857
+ case "progress":
11858
+ isChanged = initialCoordinates.progressWidth !== coordinates.progressWidth;
11859
+ if (isChanged) {
11860
+ changedTask.progress = Math.round(
11861
+ coordinates.progressWidth * 100 / (coordinates.x2 - coordinates.x1)
11862
+ );
11863
+ }
11864
+ break;
11865
+ case "start": {
11866
+ isChanged = initialCoordinates.x1 !== coordinates.x1;
11867
+ if (isChanged) {
11868
+ if (rtl) {
11869
+ changedTask.end = dateByX(
11870
+ coordinates.x1,
11871
+ initialCoordinates.x1,
11872
+ selectedTask.end,
11873
+ xStep,
11874
+ timeStep
11875
+ );
11876
+ } else {
11877
+ changedTask.start = dateByX(
11878
+ coordinates.x1,
11879
+ initialCoordinates.x1,
11880
+ selectedTask.start,
11881
+ xStep,
11882
+ timeStep
11883
+ );
11884
+ }
11885
+ }
11886
+ break;
11887
+ }
11888
+ case "end": {
11889
+ isChanged = initialCoordinates.x2 !== coordinates.x2;
11890
+ if (isChanged) {
11891
+ if (rtl) {
11892
+ changedTask.start = dateByX(
11893
+ coordinates.x2,
11894
+ initialCoordinates.x2,
11895
+ selectedTask.start,
11896
+ xStep,
11897
+ timeStep
11898
+ );
11899
+ } else {
11900
+ changedTask.end = dateByX(
11901
+ coordinates.x2,
11902
+ initialCoordinates.x2,
11903
+ selectedTask.end,
11904
+ xStep,
11905
+ timeStep
11906
+ );
11907
+ }
11908
+ }
11909
+ break;
11910
+ }
11911
+ case "move": {
11912
+ isChanged = initialCoordinates.x1 !== coordinates.x1;
11913
+ if (isChanged) {
11914
+ if (rtl) {
11915
+ changedTask.end = dateByX(
11916
+ coordinates.x1,
11917
+ initialCoordinates.x1,
11918
+ selectedTask.end,
11919
+ xStep,
11920
+ timeStep
11921
+ );
11922
+ changedTask.start = dateByX(
11923
+ coordinates.x2,
11924
+ initialCoordinates.x2,
11925
+ selectedTask.start,
11926
+ xStep,
11927
+ timeStep
11928
+ );
11929
+ } else {
11930
+ changedTask.start = dateByX(
11931
+ coordinates.x1,
11932
+ initialCoordinates.x1,
11933
+ selectedTask.start,
11934
+ xStep,
11935
+ timeStep
11936
+ );
11937
+ changedTask.end = dateByX(
11938
+ coordinates.x2,
11939
+ initialCoordinates.x2,
11940
+ selectedTask.end,
11941
+ xStep,
11942
+ timeStep
11943
+ );
11944
+ }
11945
+ }
11946
+ break;
11947
+ }
11948
+ }
11949
+ return { isChanged, changedTask };
11950
+ };
11951
+ const handleTaskBySVGMouseEventForMilestone = (action, selectedTask, initialCoordinates, coordinates, xStep, timeStep) => {
11952
+ const changedTask = { ...selectedTask };
11953
+ const isChanged = coordinates.x1 !== initialCoordinates.x1;
11954
+ if (isChanged) {
11955
+ switch (action) {
11956
+ case "move": {
11957
+ changedTask.start = dateByX(
11958
+ coordinates.x1,
11959
+ initialCoordinates.x1,
11960
+ selectedTask.start,
11961
+ xStep,
11962
+ timeStep
11963
+ );
11964
+ changedTask.end = changedTask.start;
11965
+ break;
11966
+ }
11967
+ }
11968
+ }
11969
+ return { isChanged, changedTask };
11970
+ };
11928
11971
  const barWrapper = "_barWrapper_5jhkr_1";
11929
11972
  const barHandle = "_barHandle_5jhkr_11";
11930
11973
  const barHandleImportantVisible = "_barHandleImportantVisible_5jhkr_37";
@@ -12740,6 +12783,9 @@ const TaskItemInner = (props) => {
12740
12783
  ]);
12741
12784
  const onMouseDown = useCallback(
12742
12785
  (event) => {
12786
+ if (event.button !== 0) {
12787
+ return;
12788
+ }
12743
12789
  event.stopPropagation();
12744
12790
  onSelectTaskOnMouseDown(task.id, event);
12745
12791
  },
@@ -13281,7 +13327,9 @@ const TaskGanttContentInner = (props) => {
13281
13327
  isDateChangeable,
13282
13328
  isRelationChangeable,
13283
13329
  visibleTasksMirror,
13284
- onArrowDoubleClick
13330
+ onArrowDoubleClick,
13331
+ showProgress,
13332
+ progressColor
13285
13333
  ]);
13286
13334
  return /* @__PURE__ */ jsxs("g", { className: "content", children: [
13287
13335
  renderedSelectedTasks,
@@ -13343,7 +13391,8 @@ const TaskGanttInner = (props) => {
13343
13391
  horizontalContainerRef,
13344
13392
  onVerticalScrollbarScrollX,
13345
13393
  verticalGanttContainerRef,
13346
- verticalScrollbarRef
13394
+ verticalScrollbarRef,
13395
+ onOpenGanttContextMenu
13347
13396
  } = props;
13348
13397
  const contentRef = React__default.useRef(null);
13349
13398
  const moveStateVertRef = useRef(null);
@@ -13481,6 +13530,12 @@ const TaskGanttInner = (props) => {
13481
13530
  height: ganttFullHeight,
13482
13531
  fontFamily: "var(--gantt-font-family)",
13483
13532
  ref: ganttSVGRef,
13533
+ onContextMenu: (event) => {
13534
+ event.preventDefault();
13535
+ if (onOpenGanttContextMenu) {
13536
+ onOpenGanttContextMenu(event.clientX, event.clientY);
13537
+ }
13538
+ },
13484
13539
  children: [
13485
13540
  /* @__PURE__ */ jsx(GanttToday, { ...ganttTodayProps }),
13486
13541
  /* @__PURE__ */ jsx(
@@ -17680,9 +17735,13 @@ const useSelection = (taskToRowIndexMap, rowIndexToTaskMap, checkTaskIdExists, o
17680
17735
  toggleTask(taskId);
17681
17736
  return;
17682
17737
  }
17683
- selectTask(taskId);
17738
+ if (selectedIdsMirror[taskId]) {
17739
+ toggleTask(taskId);
17740
+ } else {
17741
+ selectTask(taskId);
17742
+ }
17684
17743
  },
17685
- [selectTask, selectTasksFromLastSelected, toggleTask]
17744
+ [selectTask, selectTasksFromLastSelected, toggleTask, selectedIdsMirror]
17686
17745
  );
17687
17746
  const cutTask = useCallback((task) => {
17688
17747
  setCutIdsMirror({
@@ -17712,7 +17771,9 @@ const useSelection = (taskToRowIndexMap, rowIndexToTaskMap, checkTaskIdExists, o
17712
17771
  );
17713
17772
  useEffect(() => {
17714
17773
  if (onSelectTaskIds) {
17715
- const selectedTaskIds = Object.keys(selectedIdsMirror).filter((x) => selectedIdsMirror[x]);
17774
+ const selectedTaskIds = Object.keys(selectedIdsMirror).filter(
17775
+ (x) => selectedIdsMirror[x]
17776
+ );
17716
17777
  onSelectTaskIds(selectedTaskIds);
17717
17778
  }
17718
17779
  }, [onSelectTaskIds, selectedIdsMirror]);
@@ -17915,9 +17976,16 @@ const useContextMenu = (wrapperRef, scrollToTask) => {
17915
17976
  }
17916
17977
  const { top, left } = wrapperNode.getBoundingClientRect();
17917
17978
  setContextMenu({
17918
- task,
17919
- x: clientX - left,
17920
- y: clientY - top
17979
+ task: null,
17980
+ x: 0,
17981
+ y: 0
17982
+ });
17983
+ requestAnimationFrame(() => {
17984
+ setContextMenu({
17985
+ task,
17986
+ x: clientX - left,
17987
+ y: clientY - top
17988
+ });
17921
17989
  });
17922
17990
  if (task.type !== "empty") {
17923
17991
  scrollToTask(task);
@@ -18057,7 +18125,12 @@ function ContextMenu(props) {
18057
18125
  }
18058
18126
  }, [context, task, x, y]);
18059
18127
  const focus = useFocus(context);
18060
- const dismiss = useDismiss(context);
18128
+ const dismiss = useDismiss(context, {
18129
+ outsidePress: true,
18130
+ outsidePressEvent: "mousedown",
18131
+ ancestorScroll: true,
18132
+ escapeKey: true
18133
+ });
18061
18134
  const role = useRole(context, { role: "tooltip" });
18062
18135
  const { getReferenceProps, getFloatingProps } = useInteractions([
18063
18136
  focus,
@@ -19034,6 +19107,34 @@ const Gantt = (props) => {
19034
19107
  [mapTaskToCoordinates, setScrollXProgrammatically]
19035
19108
  );
19036
19109
  const { contextMenu, handleCloseContextMenu, handleOpenContextMenu } = useContextMenu(wrapperRef, scrollToTask);
19110
+ const [ganttContextMenu, setGanttContextMenu] = useState({
19111
+ task: null,
19112
+ x: 0,
19113
+ y: 0
19114
+ });
19115
+ const handleOpenGanttContextMenu = useCallback(
19116
+ (task, clientX, clientY) => {
19117
+ const wrapperNode = wrapperRef.current;
19118
+ if (!wrapperNode) {
19119
+ return;
19120
+ }
19121
+ const { top, left } = wrapperNode.getBoundingClientRect();
19122
+ setGanttContextMenu({
19123
+ task: task || { id: "__gantt_area__", type: "empty" },
19124
+ // Use a dummy task for gantt area
19125
+ x: clientX - left,
19126
+ y: clientY - top
19127
+ });
19128
+ },
19129
+ [wrapperRef]
19130
+ );
19131
+ const handleCloseGanttContextMenu = useCallback(() => {
19132
+ setGanttContextMenu({
19133
+ task: null,
19134
+ x: 0,
19135
+ y: 0
19136
+ });
19137
+ }, []);
19037
19138
  const [dependencyMap, dependentMap, dependencyMarginsMap] = useMemo(
19038
19139
  () => getDependencyMap(
19039
19140
  sortedTasks,
@@ -19822,6 +19923,12 @@ const Gantt = (props) => {
19822
19923
  createDeleteOption(locale)
19823
19924
  ];
19824
19925
  }, [taskList.contextMenuOptions, locale]);
19926
+ const ganttContextMenuOptions = useMemo(() => {
19927
+ if (taskBar.taskGanttContextMenuOption) {
19928
+ return taskBar.taskGanttContextMenuOption;
19929
+ }
19930
+ return [createPasteOption(locale)];
19931
+ }, [taskBar.taskGanttContextMenuOption, locale]);
19825
19932
  const tooltipTaskFromMap = useMemo(() => {
19826
19933
  if (!tooltipTask) {
19827
19934
  return null;
@@ -19865,7 +19972,6 @@ const Gantt = (props) => {
19865
19972
  rtl,
19866
19973
  startDate,
19867
19974
  viewMode,
19868
- taskHeight,
19869
19975
  showTodayLine,
19870
19976
  showDataDateLine,
19871
19977
  dataDate,
@@ -19882,7 +19988,6 @@ const Gantt = (props) => {
19882
19988
  rtl,
19883
19989
  startDate,
19884
19990
  viewMode,
19885
- taskHeight,
19886
19991
  showTodayLine,
19887
19992
  showDataDateLine,
19888
19993
  dataDate,
@@ -20092,7 +20197,10 @@ const Gantt = (props) => {
20092
20197
  horizontalContainerRef,
20093
20198
  verticalScrollbarRef,
20094
20199
  onVerticalScrollbarScrollX,
20095
- verticalGanttContainerRef
20200
+ verticalGanttContainerRef,
20201
+ onOpenGanttContextMenu: (clientX, clientY) => {
20202
+ handleOpenGanttContextMenu(null, clientX, clientY);
20203
+ }
20096
20204
  }
20097
20205
  ),
20098
20206
  tooltipTaskFromMap && /* @__PURE__ */ jsx(
@@ -20131,6 +20239,18 @@ const Gantt = (props) => {
20131
20239
  options: contextMenuOptions
20132
20240
  }
20133
20241
  ),
20242
+ ganttContextMenu.task && !waitCommitTasks && /* @__PURE__ */ jsx(
20243
+ ContextMenu,
20244
+ {
20245
+ checkHasCopyTasks,
20246
+ checkHasCutTasks,
20247
+ contextMenu: ganttContextMenu,
20248
+ distances,
20249
+ handleAction,
20250
+ handleCloseContextMenu: handleCloseGanttContextMenu,
20251
+ options: ganttContextMenuOptions
20252
+ }
20253
+ ),
20134
20254
  /* @__PURE__ */ jsx(GanttLoader, { loading: waitCommitTasks })
20135
20255
  ]
20136
20256
  }