gantt-task-react-v 1.6.16 → 1.6.18

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.
@@ -43,5 +43,6 @@ export type TaskListProps = {
43
43
  canToggleColumns?: boolean;
44
44
  onColumnVisibilityChange?: OnColumnVisibilityChange;
45
45
  tableBottom?: TableRenderBottomProps;
46
+ onTaskInlineEdit?: (task: RenderTask, columnId: string, newValue: unknown) => void;
46
47
  };
47
48
  export declare const TaskList: React.NamedExoticComponent<TaskListProps>;
@@ -0,0 +1,17 @@
1
+ import React from "react";
2
+ import type { ColumnEditType } from "../../../types";
3
+ export interface InlineEditCellProps {
4
+ value: unknown;
5
+ editType?: ColumnEditType;
6
+ editOptions?: {
7
+ value: string;
8
+ label: string;
9
+ }[];
10
+ onCommit: (value: unknown) => void;
11
+ onCancel: () => void;
12
+ }
13
+ /**
14
+ * Built-in inline editor rendered inside a table cell.
15
+ * Supports text, number, date, and select types.
16
+ */
17
+ export declare const InlineEditCell: React.FC<InlineEditCellProps>;
@@ -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$n = {
4592
+ const styles$o = {
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$n.tooltipDefaultContainer,
4635
+ className: styles$o.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$n.tooltipDefaultContainerTexts, children: [
4639
+ /* @__PURE__ */ jsxs("div", { className: styles$o.tooltipDefaultContainerTexts, children: [
4640
4640
  task.end.getTime() - task.start.getTime() !== 0 && /* @__PURE__ */ jsx(
4641
4641
  "p",
4642
4642
  {
4643
- className: styles$n.tooltipDefaultContainerParagraph,
4643
+ className: styles$o.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$n.tooltipDefaultContainerParagraph, children: !!task.progress && `${locale.tooltip.progress}: ${task.progress} %` })
4647
+ !!locale.tooltip.progress && /* @__PURE__ */ jsx("p", { className: styles$o.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$m = {
4654
+ const styles$n = {
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$m.scroll,
4675
+ className: styles$n.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$l = {
4753
+ const styles$m = {
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$l.taskListNameWrapper}`,
4830
+ className: `${styles$m.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$l.taskListExpander} ${!hasChildren ? styles$l.taskListEmptyExpander : ""}`,
4839
+ className: `gantt-expander ${styles$m.taskListExpander} ${!hasChildren ? styles$m.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$l.taskName,
4850
+ className: styles$m.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$k = {
4905
+ const styles$l = {
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$k.button,
4939
+ className: styles$l.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$k.button,
4974
+ className: styles$l.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$k.button,
5015
+ className: styles$l.button,
5016
5016
  children: (icons == null ? void 0 : icons.renderAddIcon) ? icons.renderAddIcon() : /* @__PURE__ */ jsx(AddIcon, {})
5017
5017
  }
5018
5018
  );
@@ -5545,7 +5545,7 @@ const checkbox = "_checkbox_rjfhl_141";
5545
5545
  const columnLabel = "_columnLabel_rjfhl_157";
5546
5546
  const dropdownTitle = "_dropdownTitle_rjfhl_169";
5547
5547
  const divider = "_divider_rjfhl_211";
5548
- const styles$j = {
5548
+ const styles$k = {
5549
5549
  toggleWrapper,
5550
5550
  toggleButton,
5551
5551
  dropdown,
@@ -5621,38 +5621,38 @@ const ColumnVisibilityToggleInner = ({
5621
5621
  if (toggleableColumns.length === 0) {
5622
5622
  return null;
5623
5623
  }
5624
- return /* @__PURE__ */ jsxs("div", { className: styles$j.toggleWrapper, ref: wrapperRef, children: [
5624
+ return /* @__PURE__ */ jsxs("div", { className: styles$k.toggleWrapper, ref: wrapperRef, children: [
5625
5625
  /* @__PURE__ */ jsx(
5626
5626
  "button",
5627
5627
  {
5628
- className: styles$j.toggleButton,
5628
+ className: styles$k.toggleButton,
5629
5629
  onClick: toggleDropdown,
5630
5630
  title: "Toggle column visibility",
5631
5631
  type: "button",
5632
5632
  children: /* @__PURE__ */ jsx(ColumnsIcon, {})
5633
5633
  }
5634
5634
  ),
5635
- isOpen && /* @__PURE__ */ jsxs("div", { className: styles$j.dropdown, children: [
5636
- /* @__PURE__ */ jsx("div", { className: styles$j.dropdownTitle, children: "Columns" }),
5637
- /* @__PURE__ */ jsx("div", { className: styles$j.divider }),
5635
+ isOpen && /* @__PURE__ */ jsxs("div", { className: styles$k.dropdown, children: [
5636
+ /* @__PURE__ */ jsx("div", { className: styles$k.dropdownTitle, children: "Columns" }),
5637
+ /* @__PURE__ */ jsx("div", { className: styles$k.divider }),
5638
5638
  toggleableColumns.map((column) => {
5639
5639
  const isVisible = !column.hidden;
5640
5640
  return /* @__PURE__ */ jsxs(
5641
5641
  "label",
5642
5642
  {
5643
- className: styles$j.dropdownItem,
5643
+ className: styles$k.dropdownItem,
5644
5644
  onClick: (e) => e.stopPropagation(),
5645
5645
  children: [
5646
5646
  /* @__PURE__ */ jsx(
5647
5647
  "input",
5648
5648
  {
5649
5649
  type: "checkbox",
5650
- className: styles$j.checkbox,
5650
+ className: styles$k.checkbox,
5651
5651
  checked: isVisible,
5652
5652
  onChange: () => handleToggle(column.id, !!column.hidden)
5653
5653
  }
5654
5654
  ),
5655
- /* @__PURE__ */ jsx("span", { className: styles$j.columnLabel, children: column.title || column.id })
5655
+ /* @__PURE__ */ jsx("span", { className: styles$k.columnLabel, children: column.title || column.id })
5656
5656
  ]
5657
5657
  },
5658
5658
  column.id
@@ -5668,7 +5668,7 @@ const ganttTable_HeaderMoveTask = "_ganttTable_HeaderMoveTask_5goa0_27";
5668
5668
  const ganttTable_HeaderSeparator = "_ganttTable_HeaderSeparator_5goa0_39";
5669
5669
  const ganttTable_HeaderItem = "_ganttTable_HeaderItem_5goa0_53";
5670
5670
  const resizer = "_resizer_5goa0_77";
5671
- const styles$i = {
5671
+ const styles$j = {
5672
5672
  ganttTable,
5673
5673
  ganttTable_Header,
5674
5674
  ganttTable_HeaderMoveTask,
@@ -5720,7 +5720,7 @@ const TaskListTableHeadersDefaultInner = ({
5720
5720
  return /* @__PURE__ */ jsx(
5721
5721
  "div",
5722
5722
  {
5723
- className: styles$i.ganttTable,
5723
+ className: styles$j.ganttTable,
5724
5724
  style: {
5725
5725
  fontFamily: "var(--gantt-font-family)",
5726
5726
  fontSize: "var(--gantt-font-size)"
@@ -5728,18 +5728,18 @@ const TaskListTableHeadersDefaultInner = ({
5728
5728
  children: /* @__PURE__ */ jsxs(
5729
5729
  "div",
5730
5730
  {
5731
- className: styles$i.ganttTable_Header,
5731
+ className: styles$j.ganttTable_Header,
5732
5732
  style: {
5733
5733
  height: headerHeight - 2
5734
5734
  },
5735
5735
  children: [
5736
- canMoveTasks && /* @__PURE__ */ jsx("div", { className: styles$i.ganttTable_HeaderMoveTask }),
5736
+ canMoveTasks && /* @__PURE__ */ jsx("div", { className: styles$j.ganttTable_HeaderMoveTask }),
5737
5737
  columns.map(({ title: title2, width, canResize }, index2) => {
5738
5738
  return /* @__PURE__ */ jsxs(Fragment$1, { children: [
5739
5739
  index2 > 0 && !!title2 && /* @__PURE__ */ jsx(
5740
5740
  "div",
5741
5741
  {
5742
- className: styles$i.ganttTable_HeaderSeparator,
5742
+ className: styles$j.ganttTable_HeaderSeparator,
5743
5743
  style: {
5744
5744
  height: headerHeight * 0.5,
5745
5745
  marginTop: headerHeight * 0.2
@@ -5750,7 +5750,7 @@ const TaskListTableHeadersDefaultInner = ({
5750
5750
  "div",
5751
5751
  {
5752
5752
  "data-testid": `table-column-header-${title2}`,
5753
- className: styles$i.ganttTable_HeaderItem,
5753
+ className: styles$j.ganttTable_HeaderItem,
5754
5754
  style: {
5755
5755
  minWidth: width,
5756
5756
  maxWidth: width,
@@ -5762,7 +5762,7 @@ const TaskListTableHeadersDefaultInner = ({
5762
5762
  "div",
5763
5763
  {
5764
5764
  "data-testid": `table-column-header-resize-handle-${title2}`,
5765
- className: styles$i.resizer,
5765
+ className: styles$j.resizer,
5766
5766
  onMouseDown: (event) => {
5767
5767
  onColumnResizeStart(index2, event.clientX);
5768
5768
  },
@@ -5782,7 +5782,7 @@ const TaskListTableHeadersDefaultInner = ({
5782
5782
  canToggleColumns && /* @__PURE__ */ jsx(
5783
5783
  "div",
5784
5784
  {
5785
- className: styles$i.ganttTable_HeaderItem,
5785
+ className: styles$j.ganttTable_HeaderItem,
5786
5786
  style: { minWidth: 28, maxWidth: 28 },
5787
5787
  children: /* @__PURE__ */ jsx(
5788
5788
  ColumnVisibilityToggle,
@@ -9990,7 +9990,7 @@ function normalizeLocalDisabled(localDisabled, globalDisabled) {
9990
9990
  }
9991
9991
  [KeyboardCode.Down, KeyboardCode.Right, KeyboardCode.Up, KeyboardCode.Left];
9992
9992
  const taskListWrapper$1 = "_taskListWrapper_196te_3";
9993
- const styles$h = {
9993
+ const styles$i = {
9994
9994
  taskListWrapper: taskListWrapper$1
9995
9995
  };
9996
9996
  function getDragDepth(offset2, indentationWidth2) {
@@ -10176,7 +10176,7 @@ const dragIndicator = "_dragIndicator_1yqtr_99";
10176
10176
  const dragIndicatorIcon = "_dragIndicatorIcon_1yqtr_119";
10177
10177
  const isCut = "_isCut_1yqtr_135";
10178
10178
  const taskListCell = "_taskListCell_1yqtr_167";
10179
- const styles$g = {
10179
+ const styles$h = {
10180
10180
  taskListTableRow,
10181
10181
  isAfter,
10182
10182
  isBefore,
@@ -10202,6 +10202,128 @@ const DragIndicatorIcon = (props) => /* @__PURE__ */ jsxs(
10202
10202
  ]
10203
10203
  }
10204
10204
  );
10205
+ const inlineEditWrapper = "_inlineEditWrapper_118p4_1";
10206
+ const inlineEditInput = "_inlineEditInput_118p4_19";
10207
+ const styles$g = {
10208
+ inlineEditWrapper,
10209
+ inlineEditInput
10210
+ };
10211
+ const InlineEditCell = ({
10212
+ value,
10213
+ editType = "text",
10214
+ editOptions,
10215
+ onCommit,
10216
+ onCancel
10217
+ }) => {
10218
+ const inputRef = useRef(null);
10219
+ const [localValue, setLocalValue] = useState(
10220
+ () => formatForInput(value, editType)
10221
+ );
10222
+ useEffect(() => {
10223
+ const el = inputRef.current;
10224
+ if (el) {
10225
+ el.focus();
10226
+ if ("select" in el && editType !== "select") {
10227
+ el.select();
10228
+ }
10229
+ }
10230
+ }, [editType]);
10231
+ const commitValue = useCallback(() => {
10232
+ const parsed = parseFromInput(localValue, editType);
10233
+ onCommit(parsed);
10234
+ }, [localValue, editType, onCommit]);
10235
+ const handleKeyDown = useCallback(
10236
+ (e) => {
10237
+ if (e.key === "Enter") {
10238
+ e.preventDefault();
10239
+ commitValue();
10240
+ } else if (e.key === "Escape") {
10241
+ e.preventDefault();
10242
+ onCancel();
10243
+ }
10244
+ e.stopPropagation();
10245
+ },
10246
+ [commitValue, onCancel]
10247
+ );
10248
+ const handleBlur = useCallback(() => {
10249
+ commitValue();
10250
+ }, [commitValue]);
10251
+ const stopPropagation2 = useCallback((e) => {
10252
+ e.stopPropagation();
10253
+ }, []);
10254
+ if (editType === "select") {
10255
+ return /* @__PURE__ */ jsx("div", { className: styles$g.inlineEditWrapper, onMouseDown: stopPropagation2, children: /* @__PURE__ */ jsx(
10256
+ "select",
10257
+ {
10258
+ ref: inputRef,
10259
+ className: styles$g.inlineEditInput,
10260
+ value: localValue,
10261
+ onChange: (e) => setLocalValue(e.target.value),
10262
+ onKeyDown: handleKeyDown,
10263
+ onBlur: handleBlur,
10264
+ children: editOptions == null ? void 0 : editOptions.map((opt) => /* @__PURE__ */ jsx("option", { value: opt.value, children: opt.label }, opt.value))
10265
+ }
10266
+ ) });
10267
+ }
10268
+ return /* @__PURE__ */ jsx("div", { className: styles$g.inlineEditWrapper, onMouseDown: stopPropagation2, children: /* @__PURE__ */ jsx(
10269
+ "input",
10270
+ {
10271
+ ref: inputRef,
10272
+ className: styles$g.inlineEditInput,
10273
+ type: editType === "number" ? "number" : editType === "date" ? "date" : "text",
10274
+ value: localValue,
10275
+ onChange: (e) => setLocalValue(e.target.value),
10276
+ onKeyDown: handleKeyDown,
10277
+ onBlur: handleBlur
10278
+ }
10279
+ ) });
10280
+ };
10281
+ function formatForInput(value, editType) {
10282
+ if (value == null)
10283
+ return "";
10284
+ if (editType === "date") {
10285
+ if (value instanceof Date) {
10286
+ return Number.isNaN(value.getTime()) ? "" : value.toISOString().slice(0, 10);
10287
+ }
10288
+ if (typeof value === "number") {
10289
+ const d = new Date(value);
10290
+ return Number.isNaN(d.getTime()) ? "" : d.toISOString().slice(0, 10);
10291
+ }
10292
+ if (typeof value === "string") {
10293
+ const d = new Date(value);
10294
+ if (!Number.isNaN(d.getTime())) {
10295
+ return d.toISOString().slice(0, 10);
10296
+ }
10297
+ return value.slice(0, 10);
10298
+ }
10299
+ return "";
10300
+ }
10301
+ if (editType === "number") {
10302
+ if (typeof value === "number") {
10303
+ return Number.isNaN(value) ? "" : String(value);
10304
+ }
10305
+ if (typeof value === "string") {
10306
+ const n = Number(value);
10307
+ return Number.isNaN(n) ? value : String(n);
10308
+ }
10309
+ return String(value);
10310
+ }
10311
+ if (editType === "select") {
10312
+ return String(value);
10313
+ }
10314
+ return String(value);
10315
+ }
10316
+ function parseFromInput(raw, editType) {
10317
+ if (editType === "number") {
10318
+ const n = Number(raw);
10319
+ return Number.isNaN(n) ? raw : n;
10320
+ }
10321
+ if (editType === "date") {
10322
+ const d = new Date(raw);
10323
+ return Number.isNaN(d.getTime()) ? raw : d;
10324
+ }
10325
+ return raw;
10326
+ }
10205
10327
  const TaskListTableRowInner = forwardRef(
10206
10328
  (props, ref) => {
10207
10329
  const {
@@ -10234,9 +10356,11 @@ const TaskListTableRowInner = forwardRef(
10234
10356
  task,
10235
10357
  moveHandleProps,
10236
10358
  isOverlay: isOverlay2,
10237
- moveOverPosition
10359
+ moveOverPosition,
10360
+ onTaskInlineEdit
10238
10361
  } = props;
10239
10362
  const { id, comparisonLevel = 1 } = task;
10363
+ const [editingColumnId, setEditingColumnId] = useState(null);
10240
10364
  const onRootMouseDown = useCallback(
10241
10365
  (event) => {
10242
10366
  event.preventDefault();
@@ -10329,18 +10453,18 @@ const TaskListTableRowInner = forwardRef(
10329
10453
  return isSelected ? "var(--gantt-table-selected-task-background-color)" : isEven ? "var(--gantt-table-even-background-color)" : void 0;
10330
10454
  }, [isEven, isOverlay2, isSelected]);
10331
10455
  const rowClassName = useMemo(() => {
10332
- const classNames = [styles$g.taskListTableRow];
10456
+ const classNames = [styles$h.taskListTableRow];
10333
10457
  if (moveOverPosition === "after") {
10334
- classNames.push(styles$g.isAfter);
10458
+ classNames.push(styles$h.isAfter);
10335
10459
  }
10336
10460
  if (moveOverPosition === "before") {
10337
- classNames.push(styles$g.isBefore);
10461
+ classNames.push(styles$h.isBefore);
10338
10462
  }
10339
10463
  if (isOverlay2 && !isDragging) {
10340
- classNames.push(styles$g.isOverlay);
10464
+ classNames.push(styles$h.isOverlay);
10341
10465
  }
10342
10466
  if (isCut2) {
10343
- classNames.push(styles$g.isCut);
10467
+ classNames.push(styles$h.isCut);
10344
10468
  }
10345
10469
  return classNames.join(" ");
10346
10470
  }, [isCut2, moveOverPosition, isOverlay2, isDragging]);
@@ -10389,20 +10513,89 @@ const TaskListTableRowInner = forwardRef(
10389
10513
  },
10390
10514
  onContextMenu,
10391
10515
  children: [
10392
- task.type !== "project" && task.id !== "no-project-asigned" && !isOverlay2 && moveHandleProps ? /* @__PURE__ */ jsx("div", { className: `${styles$g.dragIndicator}`, ...moveHandleProps, children: /* @__PURE__ */ jsx(DragIndicatorIcon, { className: styles$g.dragIndicatorIcon }) }) : /* @__PURE__ */ jsx("div", {}),
10393
- columns.map(({ id: id2, component: Component, width }, index2) => {
10516
+ task.type !== "project" && task.id !== "no-project-asigned" && !isOverlay2 && moveHandleProps ? /* @__PURE__ */ jsx("div", { className: `${styles$h.dragIndicator}`, ...moveHandleProps, children: /* @__PURE__ */ jsx(DragIndicatorIcon, { className: styles$h.dragIndicatorIcon }) }) : /* @__PURE__ */ jsx("div", {}),
10517
+ columns.map((col, index2) => {
10518
+ const { id: colId, component: Component, width } = col;
10519
+ const isEditingCell = editingColumnId === colId;
10520
+ const resolveValue = (c) => {
10521
+ const t = columnData.task;
10522
+ if (c.getValueFromTask)
10523
+ return c.getValueFromTask(t);
10524
+ if (t.type !== "empty" && t.payload) {
10525
+ if (c.id in t.payload)
10526
+ return t.payload[c.id];
10527
+ }
10528
+ if (c.id in t)
10529
+ return t[c.id];
10530
+ if (t.type !== "empty") {
10531
+ const task2 = t;
10532
+ const aliasMap = {
10533
+ startDate: task2.start,
10534
+ finishDate: task2.end,
10535
+ endDate: task2.end,
10536
+ duration: task2.end && task2.start ? Math.round(
10537
+ (task2.end.getTime() - task2.start.getTime()) / (1e3 * 60 * 60 * 24)
10538
+ ) : void 0
10539
+ };
10540
+ if (c.id in aliasMap)
10541
+ return aliasMap[c.id];
10542
+ }
10543
+ return void 0;
10544
+ };
10545
+ const handleStartEdit = () => {
10546
+ if (col.editable && onTaskInlineEdit) {
10547
+ setEditingColumnId(colId);
10548
+ }
10549
+ };
10550
+ const handleCommitEdit = (newValue) => {
10551
+ setEditingColumnId(null);
10552
+ if (onTaskInlineEdit) {
10553
+ onTaskInlineEdit(task, colId, newValue);
10554
+ }
10555
+ };
10556
+ const handleCancelEdit = () => {
10557
+ setEditingColumnId(null);
10558
+ };
10559
+ const cellColumnData = {
10560
+ ...columnData,
10561
+ isEditing: isEditingCell,
10562
+ onStartEdit: handleStartEdit,
10563
+ onCommitEdit: handleCommitEdit,
10564
+ onCancelEdit: handleCancelEdit
10565
+ };
10394
10566
  return /* @__PURE__ */ jsx(
10395
10567
  "div",
10396
10568
  {
10397
- className: styles$g.taskListCell,
10569
+ className: styles$h.taskListCell,
10398
10570
  style: {
10399
10571
  minWidth: width,
10400
10572
  maxWidth: width,
10401
10573
  ...pinnedStyles[index2]
10402
10574
  },
10403
- children: /* @__PURE__ */ jsx(Component, { data: columnData })
10575
+ onDoubleClick: col.editable && onTaskInlineEdit && !isEditingCell ? (e) => {
10576
+ e.stopPropagation();
10577
+ handleStartEdit();
10578
+ } : void 0,
10579
+ children: isEditingCell ? col.editComponent ? /* @__PURE__ */ jsx(
10580
+ col.editComponent,
10581
+ {
10582
+ data: cellColumnData,
10583
+ value: resolveValue(col),
10584
+ onCommit: handleCommitEdit,
10585
+ onCancel: handleCancelEdit
10586
+ }
10587
+ ) : /* @__PURE__ */ jsx(
10588
+ InlineEditCell,
10589
+ {
10590
+ value: resolveValue(col),
10591
+ editType: col.editType,
10592
+ editOptions: col.editOptions,
10593
+ onCommit: handleCommitEdit,
10594
+ onCancel: handleCancelEdit
10595
+ }
10596
+ ) : /* @__PURE__ */ jsx(Component, { data: cellColumnData })
10404
10597
  },
10405
- `${id2}-${index2}`
10598
+ `${colId}-${index2}`
10406
10599
  );
10407
10600
  })
10408
10601
  ]
@@ -10805,7 +10998,7 @@ const TaskListSortableTableDefaultInner = (props) => {
10805
10998
  children: /* @__PURE__ */ jsx(
10806
10999
  "div",
10807
11000
  {
10808
- className: styles$h.taskListWrapper,
11001
+ className: styles$i.taskListWrapper,
10809
11002
  style: {
10810
11003
  fontFamily: "var(--gantt-font-family)",
10811
11004
  fontSize: "var(--gantt-font-size)"
@@ -10968,7 +11161,8 @@ const TaskListInner = ({
10968
11161
  canReorderTasks,
10969
11162
  canToggleColumns,
10970
11163
  onColumnVisibilityChange,
10971
- tableBottom
11164
+ tableBottom,
11165
+ onTaskInlineEdit
10972
11166
  }) => {
10973
11167
  const [
10974
11168
  allColumns,
@@ -11028,7 +11222,8 @@ const TaskListInner = ({
11028
11222
  scrollToTask,
11029
11223
  selectTaskOnMouseDown,
11030
11224
  task,
11031
- depth
11225
+ depth,
11226
+ onTaskInlineEdit
11032
11227
  };
11033
11228
  },
11034
11229
  [
@@ -11052,7 +11247,8 @@ const TaskListInner = ({
11052
11247
  onExpanderClick,
11053
11248
  scrollToTask,
11054
11249
  selectTaskOnMouseDown,
11055
- selectedIdsMirror
11250
+ selectedIdsMirror,
11251
+ onTaskInlineEdit
11056
11252
  ]
11057
11253
  );
11058
11254
  const RenderTaskListTable = canReorderTasks ? TaskListSortableTable : TaskListTable;
@@ -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$n = {
4609
+ const styles$o = {
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$n.tooltipDefaultContainer,
4652
+ className: styles$o.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$n.tooltipDefaultContainerTexts, children: [
4656
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles$o.tooltipDefaultContainerTexts, children: [
4657
4657
  task.end.getTime() - task.start.getTime() !== 0 && /* @__PURE__ */ jsxRuntime.jsx(
4658
4658
  "p",
4659
4659
  {
4660
- className: styles$n.tooltipDefaultContainerParagraph,
4660
+ className: styles$o.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$n.tooltipDefaultContainerParagraph, children: !!task.progress && `${locale.tooltip.progress}: ${task.progress} %` })
4664
+ !!locale.tooltip.progress && /* @__PURE__ */ jsxRuntime.jsx("p", { className: styles$o.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$m = {
4671
+ const styles$n = {
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$m.scroll,
4692
+ className: styles$n.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$l = {
4770
+ const styles$m = {
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$l.taskListNameWrapper}`,
4847
+ className: `${styles$m.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$l.taskListExpander} ${!hasChildren ? styles$l.taskListEmptyExpander : ""}`,
4856
+ className: `gantt-expander ${styles$m.taskListExpander} ${!hasChildren ? styles$m.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$l.taskName,
4867
+ className: styles$m.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$k = {
4922
+ const styles$l = {
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$k.button,
4956
+ className: styles$l.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$k.button,
4991
+ className: styles$l.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$k.button,
5032
+ className: styles$l.button,
5033
5033
  children: (icons == null ? void 0 : icons.renderAddIcon) ? icons.renderAddIcon() : /* @__PURE__ */ jsxRuntime.jsx(AddIcon, {})
5034
5034
  }
5035
5035
  );
@@ -5562,7 +5562,7 @@
5562
5562
  const columnLabel = "_columnLabel_rjfhl_157";
5563
5563
  const dropdownTitle = "_dropdownTitle_rjfhl_169";
5564
5564
  const divider = "_divider_rjfhl_211";
5565
- const styles$j = {
5565
+ const styles$k = {
5566
5566
  toggleWrapper,
5567
5567
  toggleButton,
5568
5568
  dropdown,
@@ -5638,38 +5638,38 @@
5638
5638
  if (toggleableColumns.length === 0) {
5639
5639
  return null;
5640
5640
  }
5641
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles$j.toggleWrapper, ref: wrapperRef, children: [
5641
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles$k.toggleWrapper, ref: wrapperRef, children: [
5642
5642
  /* @__PURE__ */ jsxRuntime.jsx(
5643
5643
  "button",
5644
5644
  {
5645
- className: styles$j.toggleButton,
5645
+ className: styles$k.toggleButton,
5646
5646
  onClick: toggleDropdown,
5647
5647
  title: "Toggle column visibility",
5648
5648
  type: "button",
5649
5649
  children: /* @__PURE__ */ jsxRuntime.jsx(ColumnsIcon, {})
5650
5650
  }
5651
5651
  ),
5652
- isOpen && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles$j.dropdown, children: [
5653
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles$j.dropdownTitle, children: "Columns" }),
5654
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles$j.divider }),
5652
+ isOpen && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles$k.dropdown, children: [
5653
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles$k.dropdownTitle, children: "Columns" }),
5654
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles$k.divider }),
5655
5655
  toggleableColumns.map((column) => {
5656
5656
  const isVisible = !column.hidden;
5657
5657
  return /* @__PURE__ */ jsxRuntime.jsxs(
5658
5658
  "label",
5659
5659
  {
5660
- className: styles$j.dropdownItem,
5660
+ className: styles$k.dropdownItem,
5661
5661
  onClick: (e) => e.stopPropagation(),
5662
5662
  children: [
5663
5663
  /* @__PURE__ */ jsxRuntime.jsx(
5664
5664
  "input",
5665
5665
  {
5666
5666
  type: "checkbox",
5667
- className: styles$j.checkbox,
5667
+ className: styles$k.checkbox,
5668
5668
  checked: isVisible,
5669
5669
  onChange: () => handleToggle(column.id, !!column.hidden)
5670
5670
  }
5671
5671
  ),
5672
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: styles$j.columnLabel, children: column.title || column.id })
5672
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: styles$k.columnLabel, children: column.title || column.id })
5673
5673
  ]
5674
5674
  },
5675
5675
  column.id
@@ -5685,7 +5685,7 @@
5685
5685
  const ganttTable_HeaderSeparator = "_ganttTable_HeaderSeparator_5goa0_39";
5686
5686
  const ganttTable_HeaderItem = "_ganttTable_HeaderItem_5goa0_53";
5687
5687
  const resizer = "_resizer_5goa0_77";
5688
- const styles$i = {
5688
+ const styles$j = {
5689
5689
  ganttTable,
5690
5690
  ganttTable_Header,
5691
5691
  ganttTable_HeaderMoveTask,
@@ -5737,7 +5737,7 @@
5737
5737
  return /* @__PURE__ */ jsxRuntime.jsx(
5738
5738
  "div",
5739
5739
  {
5740
- className: styles$i.ganttTable,
5740
+ className: styles$j.ganttTable,
5741
5741
  style: {
5742
5742
  fontFamily: "var(--gantt-font-family)",
5743
5743
  fontSize: "var(--gantt-font-size)"
@@ -5745,18 +5745,18 @@
5745
5745
  children: /* @__PURE__ */ jsxRuntime.jsxs(
5746
5746
  "div",
5747
5747
  {
5748
- className: styles$i.ganttTable_Header,
5748
+ className: styles$j.ganttTable_Header,
5749
5749
  style: {
5750
5750
  height: headerHeight - 2
5751
5751
  },
5752
5752
  children: [
5753
- canMoveTasks && /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles$i.ganttTable_HeaderMoveTask }),
5753
+ canMoveTasks && /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles$j.ganttTable_HeaderMoveTask }),
5754
5754
  columns.map(({ title: title2, width, canResize }, index2) => {
5755
5755
  return /* @__PURE__ */ jsxRuntime.jsxs(React.Fragment, { children: [
5756
5756
  index2 > 0 && !!title2 && /* @__PURE__ */ jsxRuntime.jsx(
5757
5757
  "div",
5758
5758
  {
5759
- className: styles$i.ganttTable_HeaderSeparator,
5759
+ className: styles$j.ganttTable_HeaderSeparator,
5760
5760
  style: {
5761
5761
  height: headerHeight * 0.5,
5762
5762
  marginTop: headerHeight * 0.2
@@ -5767,7 +5767,7 @@
5767
5767
  "div",
5768
5768
  {
5769
5769
  "data-testid": `table-column-header-${title2}`,
5770
- className: styles$i.ganttTable_HeaderItem,
5770
+ className: styles$j.ganttTable_HeaderItem,
5771
5771
  style: {
5772
5772
  minWidth: width,
5773
5773
  maxWidth: width,
@@ -5779,7 +5779,7 @@
5779
5779
  "div",
5780
5780
  {
5781
5781
  "data-testid": `table-column-header-resize-handle-${title2}`,
5782
- className: styles$i.resizer,
5782
+ className: styles$j.resizer,
5783
5783
  onMouseDown: (event) => {
5784
5784
  onColumnResizeStart(index2, event.clientX);
5785
5785
  },
@@ -5799,7 +5799,7 @@
5799
5799
  canToggleColumns && /* @__PURE__ */ jsxRuntime.jsx(
5800
5800
  "div",
5801
5801
  {
5802
- className: styles$i.ganttTable_HeaderItem,
5802
+ className: styles$j.ganttTable_HeaderItem,
5803
5803
  style: { minWidth: 28, maxWidth: 28 },
5804
5804
  children: /* @__PURE__ */ jsxRuntime.jsx(
5805
5805
  ColumnVisibilityToggle,
@@ -10007,7 +10007,7 @@
10007
10007
  }
10008
10008
  [KeyboardCode.Down, KeyboardCode.Right, KeyboardCode.Up, KeyboardCode.Left];
10009
10009
  const taskListWrapper$1 = "_taskListWrapper_196te_3";
10010
- const styles$h = {
10010
+ const styles$i = {
10011
10011
  taskListWrapper: taskListWrapper$1
10012
10012
  };
10013
10013
  function getDragDepth(offset2, indentationWidth2) {
@@ -10193,7 +10193,7 @@
10193
10193
  const dragIndicatorIcon = "_dragIndicatorIcon_1yqtr_119";
10194
10194
  const isCut = "_isCut_1yqtr_135";
10195
10195
  const taskListCell = "_taskListCell_1yqtr_167";
10196
- const styles$g = {
10196
+ const styles$h = {
10197
10197
  taskListTableRow,
10198
10198
  isAfter,
10199
10199
  isBefore,
@@ -10219,6 +10219,128 @@
10219
10219
  ]
10220
10220
  }
10221
10221
  );
10222
+ const inlineEditWrapper = "_inlineEditWrapper_118p4_1";
10223
+ const inlineEditInput = "_inlineEditInput_118p4_19";
10224
+ const styles$g = {
10225
+ inlineEditWrapper,
10226
+ inlineEditInput
10227
+ };
10228
+ const InlineEditCell = ({
10229
+ value,
10230
+ editType = "text",
10231
+ editOptions,
10232
+ onCommit,
10233
+ onCancel
10234
+ }) => {
10235
+ const inputRef = React.useRef(null);
10236
+ const [localValue, setLocalValue] = React.useState(
10237
+ () => formatForInput(value, editType)
10238
+ );
10239
+ React.useEffect(() => {
10240
+ const el = inputRef.current;
10241
+ if (el) {
10242
+ el.focus();
10243
+ if ("select" in el && editType !== "select") {
10244
+ el.select();
10245
+ }
10246
+ }
10247
+ }, [editType]);
10248
+ const commitValue = React.useCallback(() => {
10249
+ const parsed = parseFromInput(localValue, editType);
10250
+ onCommit(parsed);
10251
+ }, [localValue, editType, onCommit]);
10252
+ const handleKeyDown = React.useCallback(
10253
+ (e) => {
10254
+ if (e.key === "Enter") {
10255
+ e.preventDefault();
10256
+ commitValue();
10257
+ } else if (e.key === "Escape") {
10258
+ e.preventDefault();
10259
+ onCancel();
10260
+ }
10261
+ e.stopPropagation();
10262
+ },
10263
+ [commitValue, onCancel]
10264
+ );
10265
+ const handleBlur = React.useCallback(() => {
10266
+ commitValue();
10267
+ }, [commitValue]);
10268
+ const stopPropagation2 = React.useCallback((e) => {
10269
+ e.stopPropagation();
10270
+ }, []);
10271
+ if (editType === "select") {
10272
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles$g.inlineEditWrapper, onMouseDown: stopPropagation2, children: /* @__PURE__ */ jsxRuntime.jsx(
10273
+ "select",
10274
+ {
10275
+ ref: inputRef,
10276
+ className: styles$g.inlineEditInput,
10277
+ value: localValue,
10278
+ onChange: (e) => setLocalValue(e.target.value),
10279
+ onKeyDown: handleKeyDown,
10280
+ onBlur: handleBlur,
10281
+ children: editOptions == null ? void 0 : editOptions.map((opt) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: opt.value, children: opt.label }, opt.value))
10282
+ }
10283
+ ) });
10284
+ }
10285
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles$g.inlineEditWrapper, onMouseDown: stopPropagation2, children: /* @__PURE__ */ jsxRuntime.jsx(
10286
+ "input",
10287
+ {
10288
+ ref: inputRef,
10289
+ className: styles$g.inlineEditInput,
10290
+ type: editType === "number" ? "number" : editType === "date" ? "date" : "text",
10291
+ value: localValue,
10292
+ onChange: (e) => setLocalValue(e.target.value),
10293
+ onKeyDown: handleKeyDown,
10294
+ onBlur: handleBlur
10295
+ }
10296
+ ) });
10297
+ };
10298
+ function formatForInput(value, editType) {
10299
+ if (value == null)
10300
+ return "";
10301
+ if (editType === "date") {
10302
+ if (value instanceof Date) {
10303
+ return Number.isNaN(value.getTime()) ? "" : value.toISOString().slice(0, 10);
10304
+ }
10305
+ if (typeof value === "number") {
10306
+ const d = new Date(value);
10307
+ return Number.isNaN(d.getTime()) ? "" : d.toISOString().slice(0, 10);
10308
+ }
10309
+ if (typeof value === "string") {
10310
+ const d = new Date(value);
10311
+ if (!Number.isNaN(d.getTime())) {
10312
+ return d.toISOString().slice(0, 10);
10313
+ }
10314
+ return value.slice(0, 10);
10315
+ }
10316
+ return "";
10317
+ }
10318
+ if (editType === "number") {
10319
+ if (typeof value === "number") {
10320
+ return Number.isNaN(value) ? "" : String(value);
10321
+ }
10322
+ if (typeof value === "string") {
10323
+ const n = Number(value);
10324
+ return Number.isNaN(n) ? value : String(n);
10325
+ }
10326
+ return String(value);
10327
+ }
10328
+ if (editType === "select") {
10329
+ return String(value);
10330
+ }
10331
+ return String(value);
10332
+ }
10333
+ function parseFromInput(raw, editType) {
10334
+ if (editType === "number") {
10335
+ const n = Number(raw);
10336
+ return Number.isNaN(n) ? raw : n;
10337
+ }
10338
+ if (editType === "date") {
10339
+ const d = new Date(raw);
10340
+ return Number.isNaN(d.getTime()) ? raw : d;
10341
+ }
10342
+ return raw;
10343
+ }
10222
10344
  const TaskListTableRowInner = React.forwardRef(
10223
10345
  (props, ref) => {
10224
10346
  const {
@@ -10251,9 +10373,11 @@
10251
10373
  task,
10252
10374
  moveHandleProps,
10253
10375
  isOverlay: isOverlay2,
10254
- moveOverPosition
10376
+ moveOverPosition,
10377
+ onTaskInlineEdit
10255
10378
  } = props;
10256
10379
  const { id, comparisonLevel = 1 } = task;
10380
+ const [editingColumnId, setEditingColumnId] = React.useState(null);
10257
10381
  const onRootMouseDown = React.useCallback(
10258
10382
  (event) => {
10259
10383
  event.preventDefault();
@@ -10346,18 +10470,18 @@
10346
10470
  return isSelected ? "var(--gantt-table-selected-task-background-color)" : isEven ? "var(--gantt-table-even-background-color)" : void 0;
10347
10471
  }, [isEven, isOverlay2, isSelected]);
10348
10472
  const rowClassName = React.useMemo(() => {
10349
- const classNames = [styles$g.taskListTableRow];
10473
+ const classNames = [styles$h.taskListTableRow];
10350
10474
  if (moveOverPosition === "after") {
10351
- classNames.push(styles$g.isAfter);
10475
+ classNames.push(styles$h.isAfter);
10352
10476
  }
10353
10477
  if (moveOverPosition === "before") {
10354
- classNames.push(styles$g.isBefore);
10478
+ classNames.push(styles$h.isBefore);
10355
10479
  }
10356
10480
  if (isOverlay2 && !isDragging) {
10357
- classNames.push(styles$g.isOverlay);
10481
+ classNames.push(styles$h.isOverlay);
10358
10482
  }
10359
10483
  if (isCut2) {
10360
- classNames.push(styles$g.isCut);
10484
+ classNames.push(styles$h.isCut);
10361
10485
  }
10362
10486
  return classNames.join(" ");
10363
10487
  }, [isCut2, moveOverPosition, isOverlay2, isDragging]);
@@ -10406,20 +10530,89 @@
10406
10530
  },
10407
10531
  onContextMenu,
10408
10532
  children: [
10409
- task.type !== "project" && task.id !== "no-project-asigned" && !isOverlay2 && moveHandleProps ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: `${styles$g.dragIndicator}`, ...moveHandleProps, children: /* @__PURE__ */ jsxRuntime.jsx(DragIndicatorIcon, { className: styles$g.dragIndicatorIcon }) }) : /* @__PURE__ */ jsxRuntime.jsx("div", {}),
10410
- columns.map(({ id: id2, component: Component, width }, index2) => {
10533
+ task.type !== "project" && task.id !== "no-project-asigned" && !isOverlay2 && moveHandleProps ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: `${styles$h.dragIndicator}`, ...moveHandleProps, children: /* @__PURE__ */ jsxRuntime.jsx(DragIndicatorIcon, { className: styles$h.dragIndicatorIcon }) }) : /* @__PURE__ */ jsxRuntime.jsx("div", {}),
10534
+ columns.map((col, index2) => {
10535
+ const { id: colId, component: Component, width } = col;
10536
+ const isEditingCell = editingColumnId === colId;
10537
+ const resolveValue = (c) => {
10538
+ const t = columnData.task;
10539
+ if (c.getValueFromTask)
10540
+ return c.getValueFromTask(t);
10541
+ if (t.type !== "empty" && t.payload) {
10542
+ if (c.id in t.payload)
10543
+ return t.payload[c.id];
10544
+ }
10545
+ if (c.id in t)
10546
+ return t[c.id];
10547
+ if (t.type !== "empty") {
10548
+ const task2 = t;
10549
+ const aliasMap = {
10550
+ startDate: task2.start,
10551
+ finishDate: task2.end,
10552
+ endDate: task2.end,
10553
+ duration: task2.end && task2.start ? Math.round(
10554
+ (task2.end.getTime() - task2.start.getTime()) / (1e3 * 60 * 60 * 24)
10555
+ ) : void 0
10556
+ };
10557
+ if (c.id in aliasMap)
10558
+ return aliasMap[c.id];
10559
+ }
10560
+ return void 0;
10561
+ };
10562
+ const handleStartEdit = () => {
10563
+ if (col.editable && onTaskInlineEdit) {
10564
+ setEditingColumnId(colId);
10565
+ }
10566
+ };
10567
+ const handleCommitEdit = (newValue) => {
10568
+ setEditingColumnId(null);
10569
+ if (onTaskInlineEdit) {
10570
+ onTaskInlineEdit(task, colId, newValue);
10571
+ }
10572
+ };
10573
+ const handleCancelEdit = () => {
10574
+ setEditingColumnId(null);
10575
+ };
10576
+ const cellColumnData = {
10577
+ ...columnData,
10578
+ isEditing: isEditingCell,
10579
+ onStartEdit: handleStartEdit,
10580
+ onCommitEdit: handleCommitEdit,
10581
+ onCancelEdit: handleCancelEdit
10582
+ };
10411
10583
  return /* @__PURE__ */ jsxRuntime.jsx(
10412
10584
  "div",
10413
10585
  {
10414
- className: styles$g.taskListCell,
10586
+ className: styles$h.taskListCell,
10415
10587
  style: {
10416
10588
  minWidth: width,
10417
10589
  maxWidth: width,
10418
10590
  ...pinnedStyles[index2]
10419
10591
  },
10420
- children: /* @__PURE__ */ jsxRuntime.jsx(Component, { data: columnData })
10592
+ onDoubleClick: col.editable && onTaskInlineEdit && !isEditingCell ? (e) => {
10593
+ e.stopPropagation();
10594
+ handleStartEdit();
10595
+ } : void 0,
10596
+ children: isEditingCell ? col.editComponent ? /* @__PURE__ */ jsxRuntime.jsx(
10597
+ col.editComponent,
10598
+ {
10599
+ data: cellColumnData,
10600
+ value: resolveValue(col),
10601
+ onCommit: handleCommitEdit,
10602
+ onCancel: handleCancelEdit
10603
+ }
10604
+ ) : /* @__PURE__ */ jsxRuntime.jsx(
10605
+ InlineEditCell,
10606
+ {
10607
+ value: resolveValue(col),
10608
+ editType: col.editType,
10609
+ editOptions: col.editOptions,
10610
+ onCommit: handleCommitEdit,
10611
+ onCancel: handleCancelEdit
10612
+ }
10613
+ ) : /* @__PURE__ */ jsxRuntime.jsx(Component, { data: cellColumnData })
10421
10614
  },
10422
- `${id2}-${index2}`
10615
+ `${colId}-${index2}`
10423
10616
  );
10424
10617
  })
10425
10618
  ]
@@ -10822,7 +11015,7 @@
10822
11015
  children: /* @__PURE__ */ jsxRuntime.jsx(
10823
11016
  "div",
10824
11017
  {
10825
- className: styles$h.taskListWrapper,
11018
+ className: styles$i.taskListWrapper,
10826
11019
  style: {
10827
11020
  fontFamily: "var(--gantt-font-family)",
10828
11021
  fontSize: "var(--gantt-font-size)"
@@ -10985,7 +11178,8 @@
10985
11178
  canReorderTasks,
10986
11179
  canToggleColumns,
10987
11180
  onColumnVisibilityChange,
10988
- tableBottom
11181
+ tableBottom,
11182
+ onTaskInlineEdit
10989
11183
  }) => {
10990
11184
  const [
10991
11185
  allColumns,
@@ -11045,7 +11239,8 @@
11045
11239
  scrollToTask,
11046
11240
  selectTaskOnMouseDown,
11047
11241
  task,
11048
- depth
11242
+ depth,
11243
+ onTaskInlineEdit
11049
11244
  };
11050
11245
  },
11051
11246
  [
@@ -11069,7 +11264,8 @@
11069
11264
  onExpanderClick,
11070
11265
  scrollToTask,
11071
11266
  selectTaskOnMouseDown,
11072
- selectedIdsMirror
11267
+ selectedIdsMirror,
11268
+ onTaskInlineEdit
11073
11269
  ]
11074
11270
  );
11075
11271
  const RenderTaskListTable = canReorderTasks ? TaskListSortableTable : TaskListTable;
package/dist/style.css CHANGED
@@ -389,6 +389,33 @@
389
389
  overflow: hidden;
390
390
  text-overflow: ellipsis;
391
391
  }
392
+ ._inlineEditWrapper_118p4_1 {
393
+ display: flex;
394
+ align-items: center;
395
+ width: 100%;
396
+ height: 100%;
397
+ padding: 0 4px;
398
+ box-sizing: border-box;
399
+ }
400
+
401
+ ._inlineEditInput_118p4_19 {
402
+ width: 100%;
403
+ height: 80%;
404
+ border: 1px solid var(--gantt-table-selected-task-background-color, #1976d2);
405
+ border-radius: 2px;
406
+ outline: none;
407
+ padding: 2px 4px;
408
+ font-family: inherit;
409
+ font-size: inherit;
410
+ box-sizing: border-box;
411
+ background: #fff;
412
+ }
413
+
414
+ ._inlineEditInput_118p4_19:focus {
415
+ border-color: var(--gantt-table-selected-task-background-color, #1976d2);
416
+ box-shadow: 0 0 0 1px
417
+ var(--gantt-table-selected-task-background-color, #1976d2);
418
+ }
392
419
  /*noinspection CssUnresolvedCustomProperty*/
393
420
  ._taskListWrapper_196te_3 {
394
421
  display: table;
@@ -190,6 +190,10 @@ export type TaskListTableRowProps = {
190
190
  selectTaskOnMouseDown: (taskId: string, event: MouseEvent) => void;
191
191
  style?: CSSProperties;
192
192
  task: RenderTask;
193
+ /**
194
+ * Callback when a cell value is committed via inline editing.
195
+ */
196
+ onTaskInlineEdit?: (task: RenderTask, columnId: string, newValue: unknown) => void;
193
197
  };
194
198
  export interface TaskListHeaderProps {
195
199
  headerHeight: number;
@@ -198,6 +198,11 @@ export interface GanttTaskListProps {
198
198
  * Invokes on double click on a task list row. Receives the task data.
199
199
  */
200
200
  onDoubleClickTaskRow?: (task: RenderTask) => void;
201
+ /**
202
+ * Callback when a cell value is committed via inline editing.
203
+ * Return a promise that resolves to the updated task, or void.
204
+ */
205
+ onTaskInlineEdit?: (task: RenderTask, columnId: string, newValue: unknown) => void | Promise<void>;
201
206
  }
202
207
  export interface TableRenderBottomProps {
203
208
  height?: number;
@@ -449,10 +454,44 @@ export type ColumnData = {
449
454
  isShowTaskNumbers: boolean;
450
455
  onExpanderClick: (task: Task) => void;
451
456
  task: RenderTask;
457
+ /**
458
+ * Whether this cell is currently in inline-edit mode.
459
+ */
460
+ isEditing?: boolean;
461
+ /**
462
+ * Call to enter inline-edit mode for this column/cell.
463
+ */
464
+ onStartEdit?: () => void;
465
+ /**
466
+ * Commit the edited value. `value` is the new raw value for the column.
467
+ */
468
+ onCommitEdit?: (value: unknown) => void;
469
+ /**
470
+ * Cancel inline editing and revert to display mode.
471
+ */
472
+ onCancelEdit?: () => void;
452
473
  };
453
474
  export type ColumnProps = {
454
475
  data: ColumnData;
455
476
  };
477
+ /**
478
+ * The type of inline editor to render when no custom `editComponent` is provided.
479
+ * - `"text"` – a plain text input (default)
480
+ * - `"date"` – a date input (`<input type="date">`)
481
+ * - `"number"` – a numeric input
482
+ * - `"select"` – a `<select>` dropdown (provide `editOptions`)
483
+ */
484
+ export type ColumnEditType = "text" | "date" | "number" | "select";
485
+ export type EditColumnProps = {
486
+ /** Current column data (task, etc.) */
487
+ data: ColumnData;
488
+ /** Current raw value of the cell */
489
+ value: unknown;
490
+ /** Called with the new value when editing is finished */
491
+ onCommit: (value: unknown) => void;
492
+ /** Called to cancel editing */
493
+ onCancel: () => void;
494
+ };
456
495
  export type Column = {
457
496
  id: string;
458
497
  component: ComponentType<ColumnProps>;
@@ -468,6 +507,31 @@ export type Column = {
468
507
  * Hide this column from the table. Defaults to false.
469
508
  */
470
509
  hidden?: boolean;
510
+ /**
511
+ * Enable inline editing for this column. Defaults to false.
512
+ */
513
+ editable?: boolean;
514
+ /**
515
+ * The built-in editor type. Defaults to `"text"`.
516
+ */
517
+ editType?: ColumnEditType;
518
+ /**
519
+ * Options for the `"select"` edit type.
520
+ */
521
+ editOptions?: {
522
+ value: string;
523
+ label: string;
524
+ }[];
525
+ /**
526
+ * Custom edit component. When provided it replaces the built-in editor.
527
+ */
528
+ editComponent?: ComponentType<EditColumnProps>;
529
+ /**
530
+ * Resolve the raw value from the task for this column.
531
+ * Used by the built-in editor and passed to custom `editComponent`.
532
+ * Falls back to `task.payload?.[column.id]` then `(task as any)[column.id]`.
533
+ */
534
+ getValueFromTask?: (task: RenderTask) => unknown;
471
535
  };
472
536
  export type OnResizeColumn = (nextColumns: readonly Column[], columnIndex: number, deltaWidth: number) => void;
473
537
  export type OnColumnVisibilityChange = (columnId: string, hidden: boolean) => void;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gantt-task-react-v",
3
- "version": "1.6.16",
3
+ "version": "1.6.18",
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",