gantt-task-react-v 1.4.8 → 1.5.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.
@@ -0,0 +1,8 @@
1
+ import React from "react";
2
+ import { Column } from "../../../types";
3
+ interface ColumnVisibilityToggleProps {
4
+ allColumns: readonly Column[];
5
+ onColumnVisibilityChange?: (columnId: string, hidden: boolean) => void;
6
+ }
7
+ export declare const ColumnVisibilityToggle: React.NamedExoticComponent<ColumnVisibilityToggleProps>;
8
+ export {};
@@ -1,6 +1,6 @@
1
1
  import type { MouseEvent, RefObject } from "react";
2
2
  import React from "react";
3
- import { AllowReorderTask, ChildByLevelMap, Column, DateSetup, DependencyMap, Distances, GanttRenderIconsProps, MapTaskToNestedIndex, OnResizeColumn, Task, RenderTask, TableRenderBottomProps } from "../../types";
3
+ import { AllowReorderTask, ChildByLevelMap, Column, DateSetup, DependencyMap, Distances, GanttRenderIconsProps, MapTaskToNestedIndex, OnColumnVisibilityChange, OnResizeColumn, Task, RenderTask, TableRenderBottomProps } from "../../types";
4
4
  export type TaskListProps = {
5
5
  ganttRef: RefObject<HTMLDivElement>;
6
6
  /** Ref to the horizontal scroll wrapper (used for containing popups) */
@@ -39,6 +39,8 @@ export type TaskListProps = {
39
39
  taskListRef: RefObject<HTMLDivElement>;
40
40
  tasks: readonly RenderTask[];
41
41
  onResizeColumn?: OnResizeColumn;
42
+ canToggleColumns?: boolean;
43
+ onColumnVisibilityChange?: OnColumnVisibilityChange;
42
44
  tableBottom?: TableRenderBottomProps;
43
45
  };
44
46
  export declare const TaskList: React.NamedExoticComponent<TaskListProps>;
@@ -4589,7 +4589,7 @@ const tooltipDefaultContainerTexts = "_tooltipDefaultContainerTexts_16o9s_17";
4589
4589
  const tooltipDefaultContainerParagraph = "_tooltipDefaultContainerParagraph_16o9s_31";
4590
4590
  const tooltipDetailsContainer = "_tooltipDetailsContainer_16o9s_47";
4591
4591
  const tooltipDetailsContainerHidden = "_tooltipDetailsContainerHidden_16o9s_71";
4592
- const styles$m = {
4592
+ const styles$n = {
4593
4593
  tooltipDefaultContainer,
4594
4594
  tooltipDefaultContainerTexts,
4595
4595
  tooltipDefaultContainerParagraph,
@@ -4632,26 +4632,26 @@ const StandardTooltipContent = ({ task }) => {
4632
4632
  return /* @__PURE__ */ jsxs(
4633
4633
  "div",
4634
4634
  {
4635
- className: styles$m.tooltipDefaultContainer,
4635
+ className: styles$n.tooltipDefaultContainer,
4636
4636
  style: { fontSize: "var(--gantt-font-size)" },
4637
4637
  children: [
4638
4638
  /* @__PURE__ */ jsx("b", { style: { fontSize: "var(--gantt-font-size)" }, children: `${task.name}: ${task.start.getDate()}-${task.start.getMonth() + 1}-${task.start.getFullYear()} - ${task.end.getDate()}-${task.end.getMonth() + 1}-${task.end.getFullYear()}` }),
4639
- /* @__PURE__ */ jsxs("div", { className: styles$m.tooltipDefaultContainerTexts, children: [
4639
+ /* @__PURE__ */ jsxs("div", { className: styles$n.tooltipDefaultContainerTexts, children: [
4640
4640
  task.end.getTime() - task.start.getTime() !== 0 && /* @__PURE__ */ jsx(
4641
4641
  "p",
4642
4642
  {
4643
- className: styles$m.tooltipDefaultContainerParagraph,
4643
+ className: styles$n.tooltipDefaultContainerParagraph,
4644
4644
  children: `${locale.tooltip.duration},: ${~~((task.end.getTime() - task.start.getTime()) / (1e3 * 60 * 60 * 24))} ${locale.suffix.days}`
4645
4645
  }
4646
4646
  ),
4647
- !!locale.tooltip.progress && /* @__PURE__ */ jsx("p", { className: styles$m.tooltipDefaultContainerParagraph, children: !!task.progress && `${locale.tooltip.progress}: ${task.progress} %` })
4647
+ !!locale.tooltip.progress && /* @__PURE__ */ jsx("p", { className: styles$n.tooltipDefaultContainerParagraph, children: !!task.progress && `${locale.tooltip.progress}: ${task.progress} %` })
4648
4648
  ] })
4649
4649
  ]
4650
4650
  }
4651
4651
  );
4652
4652
  };
4653
4653
  const scroll = "_scroll_hp3qb_1";
4654
- const styles$l = {
4654
+ const styles$m = {
4655
4655
  scroll
4656
4656
  };
4657
4657
  const VerticalScroll = ({
@@ -4672,7 +4672,7 @@ const VerticalScroll = ({
4672
4672
  marginLeft: rtl ? void 0 : "-1rem",
4673
4673
  pointerEvents: isChangeInProgress ? "none" : void 0
4674
4674
  },
4675
- className: styles$l.scroll,
4675
+ className: styles$m.scroll,
4676
4676
  onScroll,
4677
4677
  ref: verticalScrollbarRef,
4678
4678
  children: /* @__PURE__ */ jsx("div", { style: { height: ganttFullHeight, width: 1 } })
@@ -4750,7 +4750,7 @@ const dragging = "_dragging_16z6n_15";
4750
4750
  const taskListExpander = "_taskListExpander_16z6n_23";
4751
4751
  const taskListEmptyExpander = "_taskListEmptyExpander_16z6n_45";
4752
4752
  const taskName = "_taskName_16z6n_55";
4753
- const styles$k = {
4753
+ const styles$l = {
4754
4754
  taskListNameWrapper,
4755
4755
  dragging,
4756
4756
  taskListExpander,
@@ -4827,7 +4827,7 @@ const TitleColumn = ({
4827
4827
  "div",
4828
4828
  {
4829
4829
  "data-testid": `title-table-cell-${name}`,
4830
- className: `${styles$k.taskListNameWrapper}`,
4830
+ className: `${styles$l.taskListNameWrapper}`,
4831
4831
  style: {
4832
4832
  paddingLeft: depth * nestedTaskNameOffset
4833
4833
  },
@@ -4836,7 +4836,7 @@ const TitleColumn = ({
4836
4836
  /* @__PURE__ */ jsx(
4837
4837
  "div",
4838
4838
  {
4839
- className: `gantt-expander ${styles$k.taskListExpander} ${!hasChildren ? styles$k.taskListEmptyExpander : ""}`,
4839
+ className: `gantt-expander ${styles$l.taskListExpander} ${!hasChildren ? styles$l.taskListEmptyExpander : ""}`,
4840
4840
  style: {
4841
4841
  left: depth * nestedTaskNameOffset
4842
4842
  },
@@ -4847,7 +4847,7 @@ const TitleColumn = ({
4847
4847
  /* @__PURE__ */ jsxs(
4848
4848
  "div",
4849
4849
  {
4850
- className: styles$k.taskName,
4850
+ className: styles$l.taskName,
4851
4851
  style: { fontWeight: isProject ? "bold" : "regular" },
4852
4852
  children: [
4853
4853
  isShowTaskNumbers && /* @__PURE__ */ jsxs("b", { children: [
@@ -4902,7 +4902,7 @@ const DependenciesColumn = ({
4902
4902
  return /* @__PURE__ */ jsx(Fragment, { children: dependencies.map(({ name }) => name).join(", ") });
4903
4903
  };
4904
4904
  const button = "_button_l55x0_1";
4905
- const styles$j = {
4905
+ const styles$k = {
4906
4906
  button
4907
4907
  };
4908
4908
  const DeleteIcon = (props) => /* @__PURE__ */ jsxs(
@@ -4936,7 +4936,7 @@ const DeleteColumn = ({
4936
4936
  e.stopPropagation();
4937
4937
  },
4938
4938
  onClick,
4939
- className: styles$j.button,
4939
+ className: styles$k.button,
4940
4940
  children: (icons == null ? void 0 : icons.renderDeleteIcon) ? icons.renderDeleteIcon() : /* @__PURE__ */ jsx(DeleteIcon, {})
4941
4941
  }
4942
4942
  );
@@ -4971,7 +4971,7 @@ const EditColumn = ({
4971
4971
  e.stopPropagation();
4972
4972
  },
4973
4973
  onClick,
4974
- className: styles$j.button,
4974
+ className: styles$k.button,
4975
4975
  children: (icons == null ? void 0 : icons.renderEditIcon) ? icons.renderEditIcon() : /* @__PURE__ */ jsx(EditIcon, {})
4976
4976
  }
4977
4977
  );
@@ -5012,7 +5012,7 @@ const AddColumn = ({
5012
5012
  e.stopPropagation();
5013
5013
  },
5014
5014
  onClick,
5015
- className: styles$j.button,
5015
+ className: styles$k.button,
5016
5016
  children: (icons == null ? void 0 : icons.renderAddIcon) ? icons.renderAddIcon() : /* @__PURE__ */ jsx(AddIcon, {})
5017
5017
  }
5018
5018
  );
@@ -5515,6 +5515,131 @@ const useTableListResize = (clientColumns, canMoveTasks, onResizeColumn, ganttRe
5515
5515
  onColumnResizeStart
5516
5516
  ];
5517
5517
  };
5518
+ const toggleWrapper = "_toggleWrapper_rjfhl_1";
5519
+ const toggleButton = "_toggleButton_rjfhl_15";
5520
+ const dropdown = "_dropdown_rjfhl_51";
5521
+ const dropdownItem = "_dropdownItem_rjfhl_85";
5522
+ const checkbox = "_checkbox_rjfhl_141";
5523
+ const columnLabel = "_columnLabel_rjfhl_157";
5524
+ const dropdownTitle = "_dropdownTitle_rjfhl_169";
5525
+ const divider = "_divider_rjfhl_211";
5526
+ const styles$j = {
5527
+ toggleWrapper,
5528
+ toggleButton,
5529
+ dropdown,
5530
+ dropdownItem,
5531
+ checkbox,
5532
+ columnLabel,
5533
+ dropdownTitle,
5534
+ divider
5535
+ };
5536
+ const ColumnsIcon = ({ className }) => /* @__PURE__ */ jsxs(
5537
+ "svg",
5538
+ {
5539
+ className,
5540
+ width: "16",
5541
+ height: "16",
5542
+ viewBox: "0 0 16 16",
5543
+ fill: "none",
5544
+ xmlns: "http://www.w3.org/2000/svg",
5545
+ children: [
5546
+ /* @__PURE__ */ jsx(
5547
+ "path",
5548
+ {
5549
+ d: "M2 3.5h12M2 8h12M2 12.5h12",
5550
+ stroke: "currentColor",
5551
+ strokeWidth: "1.5",
5552
+ strokeLinecap: "round"
5553
+ }
5554
+ ),
5555
+ /* @__PURE__ */ jsx(
5556
+ "path",
5557
+ {
5558
+ d: "M5 3.5v9M11 3.5v9",
5559
+ stroke: "currentColor",
5560
+ strokeWidth: "1.5",
5561
+ strokeLinecap: "round",
5562
+ strokeDasharray: "1 2"
5563
+ }
5564
+ )
5565
+ ]
5566
+ }
5567
+ );
5568
+ const ColumnVisibilityToggleInner = ({
5569
+ allColumns,
5570
+ onColumnVisibilityChange
5571
+ }) => {
5572
+ const [isOpen, setIsOpen] = useState(false);
5573
+ const wrapperRef = useRef(null);
5574
+ const toggleDropdown = useCallback(() => {
5575
+ setIsOpen((prev) => !prev);
5576
+ }, []);
5577
+ const handleToggle = useCallback(
5578
+ (columnId, currentlyHidden) => {
5579
+ if (onColumnVisibilityChange) {
5580
+ onColumnVisibilityChange(columnId, !currentlyHidden);
5581
+ }
5582
+ },
5583
+ [onColumnVisibilityChange]
5584
+ );
5585
+ useEffect(() => {
5586
+ if (!isOpen)
5587
+ return void 0;
5588
+ const handleClickOutside = (event) => {
5589
+ if (wrapperRef.current && !wrapperRef.current.contains(event.target)) {
5590
+ setIsOpen(false);
5591
+ }
5592
+ };
5593
+ document.addEventListener("mousedown", handleClickOutside);
5594
+ return () => {
5595
+ document.removeEventListener("mousedown", handleClickOutside);
5596
+ };
5597
+ }, [isOpen]);
5598
+ const toggleableColumns = allColumns.filter((col) => col.title);
5599
+ if (toggleableColumns.length === 0) {
5600
+ return null;
5601
+ }
5602
+ return /* @__PURE__ */ jsxs("div", { className: styles$j.toggleWrapper, ref: wrapperRef, children: [
5603
+ /* @__PURE__ */ jsx(
5604
+ "button",
5605
+ {
5606
+ className: styles$j.toggleButton,
5607
+ onClick: toggleDropdown,
5608
+ title: "Toggle column visibility",
5609
+ type: "button",
5610
+ children: /* @__PURE__ */ jsx(ColumnsIcon, {})
5611
+ }
5612
+ ),
5613
+ isOpen && /* @__PURE__ */ jsxs("div", { className: styles$j.dropdown, children: [
5614
+ /* @__PURE__ */ jsx("div", { className: styles$j.dropdownTitle, children: "Columns" }),
5615
+ /* @__PURE__ */ jsx("div", { className: styles$j.divider }),
5616
+ toggleableColumns.map((column) => {
5617
+ const isVisible = !column.hidden;
5618
+ return /* @__PURE__ */ jsxs(
5619
+ "label",
5620
+ {
5621
+ className: styles$j.dropdownItem,
5622
+ onClick: (e) => e.stopPropagation(),
5623
+ children: [
5624
+ /* @__PURE__ */ jsx(
5625
+ "input",
5626
+ {
5627
+ type: "checkbox",
5628
+ className: styles$j.checkbox,
5629
+ checked: isVisible,
5630
+ onChange: () => handleToggle(column.id, !!column.hidden)
5631
+ }
5632
+ ),
5633
+ /* @__PURE__ */ jsx("span", { className: styles$j.columnLabel, children: column.title || column.id })
5634
+ ]
5635
+ },
5636
+ column.id
5637
+ );
5638
+ })
5639
+ ] })
5640
+ ] });
5641
+ };
5642
+ const ColumnVisibilityToggle = memo(ColumnVisibilityToggleInner);
5518
5643
  const ganttTable = "_ganttTable_5goa0_3";
5519
5644
  const ganttTable_Header = "_ganttTable_Header_5goa0_15";
5520
5645
  const ganttTable_HeaderMoveTask = "_ganttTable_HeaderMoveTask_5goa0_27";
@@ -5532,9 +5657,12 @@ const styles$i = {
5532
5657
  const TaskListTableHeadersDefaultInner = ({
5533
5658
  headerHeight,
5534
5659
  columns,
5660
+ allColumns,
5535
5661
  canResizeColumns,
5536
5662
  canMoveTasks,
5537
- onColumnResizeStart
5663
+ canToggleColumns,
5664
+ onColumnResizeStart,
5665
+ onColumnVisibilityChange
5538
5666
  }) => {
5539
5667
  const pinnedStyles = useMemo(() => {
5540
5668
  const result = {};
@@ -5628,7 +5756,21 @@ const TaskListTableHeadersDefaultInner = ({
5628
5756
  }
5629
5757
  )
5630
5758
  ] }, index2);
5631
- })
5759
+ }),
5760
+ canToggleColumns && /* @__PURE__ */ jsx(
5761
+ "div",
5762
+ {
5763
+ className: styles$i.ganttTable_HeaderItem,
5764
+ style: { minWidth: 28, maxWidth: 28 },
5765
+ children: /* @__PURE__ */ jsx(
5766
+ ColumnVisibilityToggle,
5767
+ {
5768
+ allColumns,
5769
+ onColumnVisibilityChange
5770
+ }
5771
+ )
5772
+ }
5773
+ )
5632
5774
  ]
5633
5775
  }
5634
5776
  )
@@ -10787,10 +10929,12 @@ const TaskListInner = ({
10787
10929
  tasks,
10788
10930
  onResizeColumn,
10789
10931
  canReorderTasks,
10932
+ canToggleColumns,
10933
+ onColumnVisibilityChange,
10790
10934
  tableBottom
10791
10935
  }) => {
10792
10936
  const [
10793
- columns,
10937
+ allColumns,
10794
10938
  taskListWidth,
10795
10939
  tableWidth,
10796
10940
  onTableResizeStart,
@@ -10801,6 +10945,10 @@ const TaskListInner = ({
10801
10945
  onResizeColumn,
10802
10946
  ganttRef
10803
10947
  );
10948
+ const columns = useMemo(
10949
+ () => allColumns.filter((col) => !col.hidden),
10950
+ [allColumns]
10951
+ );
10804
10952
  const renderedIndexes = useOptimizedList(
10805
10953
  taskListContainerRef,
10806
10954
  "scrollTop",
@@ -10885,7 +11033,10 @@ const TaskListInner = ({
10885
11033
  canMoveTasks: canReorderTasks,
10886
11034
  headerHeight: distances.headerHeight,
10887
11035
  columns,
11036
+ allColumns,
11037
+ canToggleColumns: !!canToggleColumns,
10888
11038
  onColumnResizeStart,
11039
+ onColumnVisibilityChange,
10889
11040
  canResizeColumns
10890
11041
  }
10891
11042
  ),
@@ -12741,9 +12892,9 @@ const Milestone = ({
12741
12892
  relationHandles
12742
12893
  ] });
12743
12894
  };
12744
- const barLabel = "_barLabel_1ca31_1";
12745
- const barLabelHidden = "_barLabelHidden_1ca31_27";
12746
- const barLabelOutside = "_barLabelOutside_1ca31_37";
12895
+ const barLabel = "_barLabel_81831_1";
12896
+ const barLabelHidden = "_barLabelHidden_81831_27";
12897
+ const barLabelOutside = "_barLabelOutside_81831_37";
12747
12898
  const style = {
12748
12899
  barLabel,
12749
12900
  barLabelHidden,
@@ -21153,6 +21304,7 @@ const Gantt = (props) => {
21153
21304
  };
21154
21305
  export {
21155
21306
  AddColumn,
21307
+ ColumnVisibilityToggle,
21156
21308
  DateEndColumn,
21157
21309
  DateStartColumn,
21158
21310
  DeleteColumn,
@@ -4606,7 +4606,7 @@
4606
4606
  const tooltipDefaultContainerParagraph = "_tooltipDefaultContainerParagraph_16o9s_31";
4607
4607
  const tooltipDetailsContainer = "_tooltipDetailsContainer_16o9s_47";
4608
4608
  const tooltipDetailsContainerHidden = "_tooltipDetailsContainerHidden_16o9s_71";
4609
- const styles$m = {
4609
+ const styles$n = {
4610
4610
  tooltipDefaultContainer,
4611
4611
  tooltipDefaultContainerTexts,
4612
4612
  tooltipDefaultContainerParagraph,
@@ -4649,26 +4649,26 @@
4649
4649
  return /* @__PURE__ */ jsxRuntime.jsxs(
4650
4650
  "div",
4651
4651
  {
4652
- className: styles$m.tooltipDefaultContainer,
4652
+ className: styles$n.tooltipDefaultContainer,
4653
4653
  style: { fontSize: "var(--gantt-font-size)" },
4654
4654
  children: [
4655
4655
  /* @__PURE__ */ jsxRuntime.jsx("b", { style: { fontSize: "var(--gantt-font-size)" }, children: `${task.name}: ${task.start.getDate()}-${task.start.getMonth() + 1}-${task.start.getFullYear()} - ${task.end.getDate()}-${task.end.getMonth() + 1}-${task.end.getFullYear()}` }),
4656
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles$m.tooltipDefaultContainerTexts, children: [
4656
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles$n.tooltipDefaultContainerTexts, children: [
4657
4657
  task.end.getTime() - task.start.getTime() !== 0 && /* @__PURE__ */ jsxRuntime.jsx(
4658
4658
  "p",
4659
4659
  {
4660
- className: styles$m.tooltipDefaultContainerParagraph,
4660
+ className: styles$n.tooltipDefaultContainerParagraph,
4661
4661
  children: `${locale.tooltip.duration},: ${~~((task.end.getTime() - task.start.getTime()) / (1e3 * 60 * 60 * 24))} ${locale.suffix.days}`
4662
4662
  }
4663
4663
  ),
4664
- !!locale.tooltip.progress && /* @__PURE__ */ jsxRuntime.jsx("p", { className: styles$m.tooltipDefaultContainerParagraph, children: !!task.progress && `${locale.tooltip.progress}: ${task.progress} %` })
4664
+ !!locale.tooltip.progress && /* @__PURE__ */ jsxRuntime.jsx("p", { className: styles$n.tooltipDefaultContainerParagraph, children: !!task.progress && `${locale.tooltip.progress}: ${task.progress} %` })
4665
4665
  ] })
4666
4666
  ]
4667
4667
  }
4668
4668
  );
4669
4669
  };
4670
4670
  const scroll = "_scroll_hp3qb_1";
4671
- const styles$l = {
4671
+ const styles$m = {
4672
4672
  scroll
4673
4673
  };
4674
4674
  const VerticalScroll = ({
@@ -4689,7 +4689,7 @@
4689
4689
  marginLeft: rtl ? void 0 : "-1rem",
4690
4690
  pointerEvents: isChangeInProgress ? "none" : void 0
4691
4691
  },
4692
- className: styles$l.scroll,
4692
+ className: styles$m.scroll,
4693
4693
  onScroll,
4694
4694
  ref: verticalScrollbarRef,
4695
4695
  children: /* @__PURE__ */ jsxRuntime.jsx("div", { style: { height: ganttFullHeight, width: 1 } })
@@ -4767,7 +4767,7 @@
4767
4767
  const taskListExpander = "_taskListExpander_16z6n_23";
4768
4768
  const taskListEmptyExpander = "_taskListEmptyExpander_16z6n_45";
4769
4769
  const taskName = "_taskName_16z6n_55";
4770
- const styles$k = {
4770
+ const styles$l = {
4771
4771
  taskListNameWrapper,
4772
4772
  dragging,
4773
4773
  taskListExpander,
@@ -4844,7 +4844,7 @@
4844
4844
  "div",
4845
4845
  {
4846
4846
  "data-testid": `title-table-cell-${name}`,
4847
- className: `${styles$k.taskListNameWrapper}`,
4847
+ className: `${styles$l.taskListNameWrapper}`,
4848
4848
  style: {
4849
4849
  paddingLeft: depth * nestedTaskNameOffset
4850
4850
  },
@@ -4853,7 +4853,7 @@
4853
4853
  /* @__PURE__ */ jsxRuntime.jsx(
4854
4854
  "div",
4855
4855
  {
4856
- className: `gantt-expander ${styles$k.taskListExpander} ${!hasChildren ? styles$k.taskListEmptyExpander : ""}`,
4856
+ className: `gantt-expander ${styles$l.taskListExpander} ${!hasChildren ? styles$l.taskListEmptyExpander : ""}`,
4857
4857
  style: {
4858
4858
  left: depth * nestedTaskNameOffset
4859
4859
  },
@@ -4864,7 +4864,7 @@
4864
4864
  /* @__PURE__ */ jsxRuntime.jsxs(
4865
4865
  "div",
4866
4866
  {
4867
- className: styles$k.taskName,
4867
+ className: styles$l.taskName,
4868
4868
  style: { fontWeight: isProject ? "bold" : "regular" },
4869
4869
  children: [
4870
4870
  isShowTaskNumbers && /* @__PURE__ */ jsxRuntime.jsxs("b", { children: [
@@ -4919,7 +4919,7 @@
4919
4919
  return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: dependencies.map(({ name }) => name).join(", ") });
4920
4920
  };
4921
4921
  const button = "_button_l55x0_1";
4922
- const styles$j = {
4922
+ const styles$k = {
4923
4923
  button
4924
4924
  };
4925
4925
  const DeleteIcon = (props) => /* @__PURE__ */ jsxRuntime.jsxs(
@@ -4953,7 +4953,7 @@
4953
4953
  e.stopPropagation();
4954
4954
  },
4955
4955
  onClick,
4956
- className: styles$j.button,
4956
+ className: styles$k.button,
4957
4957
  children: (icons == null ? void 0 : icons.renderDeleteIcon) ? icons.renderDeleteIcon() : /* @__PURE__ */ jsxRuntime.jsx(DeleteIcon, {})
4958
4958
  }
4959
4959
  );
@@ -4988,7 +4988,7 @@
4988
4988
  e.stopPropagation();
4989
4989
  },
4990
4990
  onClick,
4991
- className: styles$j.button,
4991
+ className: styles$k.button,
4992
4992
  children: (icons == null ? void 0 : icons.renderEditIcon) ? icons.renderEditIcon() : /* @__PURE__ */ jsxRuntime.jsx(EditIcon, {})
4993
4993
  }
4994
4994
  );
@@ -5029,7 +5029,7 @@
5029
5029
  e.stopPropagation();
5030
5030
  },
5031
5031
  onClick,
5032
- className: styles$j.button,
5032
+ className: styles$k.button,
5033
5033
  children: (icons == null ? void 0 : icons.renderAddIcon) ? icons.renderAddIcon() : /* @__PURE__ */ jsxRuntime.jsx(AddIcon, {})
5034
5034
  }
5035
5035
  );
@@ -5532,6 +5532,131 @@
5532
5532
  onColumnResizeStart
5533
5533
  ];
5534
5534
  };
5535
+ const toggleWrapper = "_toggleWrapper_rjfhl_1";
5536
+ const toggleButton = "_toggleButton_rjfhl_15";
5537
+ const dropdown = "_dropdown_rjfhl_51";
5538
+ const dropdownItem = "_dropdownItem_rjfhl_85";
5539
+ const checkbox = "_checkbox_rjfhl_141";
5540
+ const columnLabel = "_columnLabel_rjfhl_157";
5541
+ const dropdownTitle = "_dropdownTitle_rjfhl_169";
5542
+ const divider = "_divider_rjfhl_211";
5543
+ const styles$j = {
5544
+ toggleWrapper,
5545
+ toggleButton,
5546
+ dropdown,
5547
+ dropdownItem,
5548
+ checkbox,
5549
+ columnLabel,
5550
+ dropdownTitle,
5551
+ divider
5552
+ };
5553
+ const ColumnsIcon = ({ className }) => /* @__PURE__ */ jsxRuntime.jsxs(
5554
+ "svg",
5555
+ {
5556
+ className,
5557
+ width: "16",
5558
+ height: "16",
5559
+ viewBox: "0 0 16 16",
5560
+ fill: "none",
5561
+ xmlns: "http://www.w3.org/2000/svg",
5562
+ children: [
5563
+ /* @__PURE__ */ jsxRuntime.jsx(
5564
+ "path",
5565
+ {
5566
+ d: "M2 3.5h12M2 8h12M2 12.5h12",
5567
+ stroke: "currentColor",
5568
+ strokeWidth: "1.5",
5569
+ strokeLinecap: "round"
5570
+ }
5571
+ ),
5572
+ /* @__PURE__ */ jsxRuntime.jsx(
5573
+ "path",
5574
+ {
5575
+ d: "M5 3.5v9M11 3.5v9",
5576
+ stroke: "currentColor",
5577
+ strokeWidth: "1.5",
5578
+ strokeLinecap: "round",
5579
+ strokeDasharray: "1 2"
5580
+ }
5581
+ )
5582
+ ]
5583
+ }
5584
+ );
5585
+ const ColumnVisibilityToggleInner = ({
5586
+ allColumns,
5587
+ onColumnVisibilityChange
5588
+ }) => {
5589
+ const [isOpen, setIsOpen] = React.useState(false);
5590
+ const wrapperRef = React.useRef(null);
5591
+ const toggleDropdown = React.useCallback(() => {
5592
+ setIsOpen((prev) => !prev);
5593
+ }, []);
5594
+ const handleToggle = React.useCallback(
5595
+ (columnId, currentlyHidden) => {
5596
+ if (onColumnVisibilityChange) {
5597
+ onColumnVisibilityChange(columnId, !currentlyHidden);
5598
+ }
5599
+ },
5600
+ [onColumnVisibilityChange]
5601
+ );
5602
+ React.useEffect(() => {
5603
+ if (!isOpen)
5604
+ return void 0;
5605
+ const handleClickOutside = (event) => {
5606
+ if (wrapperRef.current && !wrapperRef.current.contains(event.target)) {
5607
+ setIsOpen(false);
5608
+ }
5609
+ };
5610
+ document.addEventListener("mousedown", handleClickOutside);
5611
+ return () => {
5612
+ document.removeEventListener("mousedown", handleClickOutside);
5613
+ };
5614
+ }, [isOpen]);
5615
+ const toggleableColumns = allColumns.filter((col) => col.title);
5616
+ if (toggleableColumns.length === 0) {
5617
+ return null;
5618
+ }
5619
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles$j.toggleWrapper, ref: wrapperRef, children: [
5620
+ /* @__PURE__ */ jsxRuntime.jsx(
5621
+ "button",
5622
+ {
5623
+ className: styles$j.toggleButton,
5624
+ onClick: toggleDropdown,
5625
+ title: "Toggle column visibility",
5626
+ type: "button",
5627
+ children: /* @__PURE__ */ jsxRuntime.jsx(ColumnsIcon, {})
5628
+ }
5629
+ ),
5630
+ isOpen && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles$j.dropdown, children: [
5631
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles$j.dropdownTitle, children: "Columns" }),
5632
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles$j.divider }),
5633
+ toggleableColumns.map((column) => {
5634
+ const isVisible = !column.hidden;
5635
+ return /* @__PURE__ */ jsxRuntime.jsxs(
5636
+ "label",
5637
+ {
5638
+ className: styles$j.dropdownItem,
5639
+ onClick: (e) => e.stopPropagation(),
5640
+ children: [
5641
+ /* @__PURE__ */ jsxRuntime.jsx(
5642
+ "input",
5643
+ {
5644
+ type: "checkbox",
5645
+ className: styles$j.checkbox,
5646
+ checked: isVisible,
5647
+ onChange: () => handleToggle(column.id, !!column.hidden)
5648
+ }
5649
+ ),
5650
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: styles$j.columnLabel, children: column.title || column.id })
5651
+ ]
5652
+ },
5653
+ column.id
5654
+ );
5655
+ })
5656
+ ] })
5657
+ ] });
5658
+ };
5659
+ const ColumnVisibilityToggle = React.memo(ColumnVisibilityToggleInner);
5535
5660
  const ganttTable = "_ganttTable_5goa0_3";
5536
5661
  const ganttTable_Header = "_ganttTable_Header_5goa0_15";
5537
5662
  const ganttTable_HeaderMoveTask = "_ganttTable_HeaderMoveTask_5goa0_27";
@@ -5549,9 +5674,12 @@
5549
5674
  const TaskListTableHeadersDefaultInner = ({
5550
5675
  headerHeight,
5551
5676
  columns,
5677
+ allColumns,
5552
5678
  canResizeColumns,
5553
5679
  canMoveTasks,
5554
- onColumnResizeStart
5680
+ canToggleColumns,
5681
+ onColumnResizeStart,
5682
+ onColumnVisibilityChange
5555
5683
  }) => {
5556
5684
  const pinnedStyles = React.useMemo(() => {
5557
5685
  const result = {};
@@ -5645,7 +5773,21 @@
5645
5773
  }
5646
5774
  )
5647
5775
  ] }, index2);
5648
- })
5776
+ }),
5777
+ canToggleColumns && /* @__PURE__ */ jsxRuntime.jsx(
5778
+ "div",
5779
+ {
5780
+ className: styles$i.ganttTable_HeaderItem,
5781
+ style: { minWidth: 28, maxWidth: 28 },
5782
+ children: /* @__PURE__ */ jsxRuntime.jsx(
5783
+ ColumnVisibilityToggle,
5784
+ {
5785
+ allColumns,
5786
+ onColumnVisibilityChange
5787
+ }
5788
+ )
5789
+ }
5790
+ )
5649
5791
  ]
5650
5792
  }
5651
5793
  )
@@ -10804,10 +10946,12 @@
10804
10946
  tasks,
10805
10947
  onResizeColumn,
10806
10948
  canReorderTasks,
10949
+ canToggleColumns,
10950
+ onColumnVisibilityChange,
10807
10951
  tableBottom
10808
10952
  }) => {
10809
10953
  const [
10810
- columns,
10954
+ allColumns,
10811
10955
  taskListWidth,
10812
10956
  tableWidth,
10813
10957
  onTableResizeStart,
@@ -10818,6 +10962,10 @@
10818
10962
  onResizeColumn,
10819
10963
  ganttRef
10820
10964
  );
10965
+ const columns = React.useMemo(
10966
+ () => allColumns.filter((col) => !col.hidden),
10967
+ [allColumns]
10968
+ );
10821
10969
  const renderedIndexes = useOptimizedList(
10822
10970
  taskListContainerRef,
10823
10971
  "scrollTop",
@@ -10902,7 +11050,10 @@
10902
11050
  canMoveTasks: canReorderTasks,
10903
11051
  headerHeight: distances.headerHeight,
10904
11052
  columns,
11053
+ allColumns,
11054
+ canToggleColumns: !!canToggleColumns,
10905
11055
  onColumnResizeStart,
11056
+ onColumnVisibilityChange,
10906
11057
  canResizeColumns
10907
11058
  }
10908
11059
  ),
@@ -12758,9 +12909,9 @@
12758
12909
  relationHandles
12759
12910
  ] });
12760
12911
  };
12761
- const barLabel = "_barLabel_1ca31_1";
12762
- const barLabelHidden = "_barLabelHidden_1ca31_27";
12763
- const barLabelOutside = "_barLabelOutside_1ca31_37";
12912
+ const barLabel = "_barLabel_81831_1";
12913
+ const barLabelHidden = "_barLabelHidden_81831_27";
12914
+ const barLabelOutside = "_barLabelOutside_81831_37";
12764
12915
  const style = {
12765
12916
  barLabel,
12766
12917
  barLabelHidden,
@@ -21169,6 +21320,7 @@
21169
21320
  ) }) });
21170
21321
  };
21171
21322
  exports2.AddColumn = AddColumn;
21323
+ exports2.ColumnVisibilityToggle = ColumnVisibilityToggle;
21172
21324
  exports2.DateEndColumn = DateEndColumn;
21173
21325
  exports2.DateStartColumn = DateStartColumn;
21174
21326
  exports2.DeleteColumn = DeleteColumn;
package/dist/index.d.ts CHANGED
@@ -7,8 +7,9 @@ export { DateStartColumn } from "./components/task-list/task-list-table-columns/
7
7
  export { DeleteColumn } from "./components/task-list/task-list-table-columns/delete-column";
8
8
  export { DependenciesColumn } from "./components/task-list/task-list-table-columns/dependencies-column";
9
9
  export { TitleColumn } from "./components/task-list/task-list-table-columns/title-column";
10
- export { TaskResponsiveLabel, TaskCenterLabel, TaskOutlineLabel } from "./components/task-item/task-label";
10
+ export { TaskResponsiveLabel, TaskCenterLabel, TaskOutlineLabel, } from "./components/task-item/task-label";
11
11
  export { useTaskListColumnsBuilder } from "./components/task-list/task-list-table-columns/use-task-list-columns-builder";
12
+ export { ColumnVisibilityToggle } from "./components/task-list/column-visibility-toggle";
12
13
  export * from "./components/context-menu-options";
13
14
  export * from "./constants";
14
15
  export * from "./types";
package/dist/style.css CHANGED
@@ -122,6 +122,119 @@
122
122
  width: 20px;
123
123
  height: 20px;
124
124
  }
125
+ ._toggleWrapper_rjfhl_1 {
126
+ position: relative;
127
+ display: inline-flex;
128
+ align-items: center;
129
+ justify-content: center;
130
+ }
131
+
132
+ ._toggleButton_rjfhl_15 {
133
+ display: flex;
134
+ align-items: center;
135
+ justify-content: center;
136
+ width: 24px;
137
+ height: 24px;
138
+ border: none;
139
+ background: transparent;
140
+ cursor: pointer;
141
+ border-radius: 4px;
142
+ color: var(--gantt-table-header-color, #555);
143
+ padding: 2px;
144
+ }
145
+
146
+ ._toggleButton_rjfhl_15:hover {
147
+ background-color: var(--gantt-table-hover-action-color, rgba(0, 0, 0, 0.08));
148
+ }
149
+
150
+ ._dropdown_rjfhl_51 {
151
+ position: absolute;
152
+ top: 100%;
153
+ right: 0;
154
+ z-index: 100;
155
+ min-width: 180px;
156
+ max-height: 300px;
157
+ overflow-y: auto;
158
+ background: var(--gantt-table-header-background-color, #fff);
159
+ border: 1px solid
160
+ var(--gantt-table-divider-color, var(--gantt-divider-color, #e0e0e0));
161
+ border-radius: 6px;
162
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.12);
163
+ padding: 4px 0;
164
+ margin-top: 4px;
165
+ }
166
+
167
+ ._dropdownItem_rjfhl_85 {
168
+ display: flex;
169
+ align-items: center;
170
+ gap: 8px;
171
+ padding: 6px 12px;
172
+ cursor: pointer;
173
+ font-size: var(--gantt-font-size, 12px);
174
+ font-family: var(
175
+ --gantt-font-family,
176
+ Arial,
177
+ Roboto,
178
+ Oxygen,
179
+ Ubuntu,
180
+ Cantarell,
181
+ "Fira Sans",
182
+ "Droid Sans",
183
+ "Helvetica Neue",
184
+ sans-serif
185
+ );
186
+ color: var(--gantt-table-header-color, #333);
187
+ white-space: nowrap;
188
+ user-select: none;
189
+ }
190
+
191
+ ._dropdownItem_rjfhl_85:hover {
192
+ background-color: var(--gantt-table-hover-action-color, rgba(0, 0, 0, 0.04));
193
+ }
194
+
195
+ ._checkbox_rjfhl_141 {
196
+ width: 14px;
197
+ height: 14px;
198
+ accent-color: var(--gantt-bar-background-color, #4e87c4);
199
+ cursor: pointer;
200
+ margin: 0;
201
+ }
202
+
203
+ ._columnLabel_rjfhl_157 {
204
+ flex: 1;
205
+ overflow: hidden;
206
+ text-overflow: ellipsis;
207
+ }
208
+
209
+ ._dropdownTitle_rjfhl_169 {
210
+ padding: 6px 12px 4px;
211
+ font-size: 11px;
212
+ font-weight: 600;
213
+ text-transform: uppercase;
214
+ letter-spacing: 0.5px;
215
+ color: var(--gantt-table-header-color, #999);
216
+ font-family: var(
217
+ --gantt-font-family,
218
+ Arial,
219
+ Roboto,
220
+ Oxygen,
221
+ Ubuntu,
222
+ Cantarell,
223
+ "Fira Sans",
224
+ "Droid Sans",
225
+ "Helvetica Neue",
226
+ sans-serif
227
+ );
228
+ }
229
+
230
+ ._divider_rjfhl_211 {
231
+ height: 1px;
232
+ margin: 4px 0;
233
+ background: var(
234
+ --gantt-table-divider-color,
235
+ var(--gantt-divider-color, #e0e0e0)
236
+ );
237
+ }
125
238
  /*noinspection CssUnresolvedCustomProperty*/
126
239
  ._ganttTable_5goa0_3 {
127
240
  display: table;
@@ -560,7 +673,7 @@
560
673
  ._milestoneBackground_vcirf_11 {
561
674
  user-select: none;
562
675
  }
563
- ._barLabel_1ca31_1 {
676
+ ._barLabel_81831_1 {
564
677
  fill: #fff;
565
678
  text-anchor: middle;
566
679
  font-weight: lighter;
@@ -573,14 +686,18 @@
573
686
  pointer-events: none;
574
687
  }
575
688
 
576
- ._barLabelHidden_1ca31_27 {
689
+ ._barLabelHidden_81831_27 {
577
690
  display: none;
578
691
  }
579
692
 
580
693
  /*noinspection CssUnresolvedCustomProperty*/
581
- ._barLabelOutside_1ca31_37 {
694
+ ._barLabelOutside_81831_37 {
582
695
  fill: var(--gantt-secondary-text-color);
583
696
  text-anchor: start;
697
+ stroke: white;
698
+ stroke-width: 4px;
699
+ stroke-linejoin: round;
700
+ paint-order: stroke;
584
701
  -webkit-touch-callout: none;
585
702
  -webkit-user-select: none;
586
703
  -moz-user-select: none;
@@ -193,9 +193,12 @@ export type TaskListTableRowProps = {
193
193
  export interface TaskListHeaderProps {
194
194
  headerHeight: number;
195
195
  columns: readonly Column[];
196
+ allColumns: readonly Column[];
196
197
  canMoveTasks: boolean;
197
198
  canResizeColumns: boolean;
199
+ canToggleColumns: boolean;
198
200
  onColumnResizeStart: (columnIndex: number, clientX: number) => void;
201
+ onColumnVisibilityChange?: (columnId: string, hidden: boolean) => void;
199
202
  }
200
203
  export type MinAndMaxChildsOfTask = [
201
204
  [
@@ -156,6 +156,10 @@ export interface GanttTaskListProps {
156
156
  * Can resize columns
157
157
  */
158
158
  canResizeColumns?: boolean;
159
+ /**
160
+ * Show column visibility toggle button in the header
161
+ */
162
+ canToggleColumns?: boolean;
159
163
  /**
160
164
  * Custom icons
161
165
  */
@@ -172,6 +176,10 @@ export interface GanttTaskListProps {
172
176
  * Can reorder tasks
173
177
  */
174
178
  onResizeColumn?: OnResizeColumn;
179
+ /**
180
+ * Callback when column visibility is toggled
181
+ */
182
+ onColumnVisibilityChange?: OnColumnVisibilityChange;
175
183
  /**
176
184
  * Render bottom table content
177
185
  */
@@ -438,8 +446,13 @@ export type Column = {
438
446
  * Pinned columns stay visible while scrolling horizontally.
439
447
  */
440
448
  pinned?: "left" | "right";
449
+ /**
450
+ * Hide this column from the table. Defaults to false.
451
+ */
452
+ hidden?: boolean;
441
453
  };
442
454
  export type OnResizeColumn = (nextColumns: readonly Column[], columnIndex: number, deltaWidth: number) => void;
455
+ export type OnColumnVisibilityChange = (columnId: string, hidden: boolean) => void;
443
456
  export type ChangeAction = {
444
457
  type: "add-childs";
445
458
  parent: Task;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gantt-task-react-v",
3
- "version": "1.4.8",
3
+ "version": "1.5.0",
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",