gantt-lib 0.90.0 → 0.100.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.
package/dist/index.js CHANGED
@@ -45,6 +45,7 @@ __export(index_exports, {
45
45
  PopoverContent: () => PopoverContent,
46
46
  PopoverTrigger: () => PopoverTrigger,
47
47
  ResourceTimelineChart: () => ResourceTimelineChart,
48
+ TableMatrix: () => TableMatrix,
48
49
  TaskList: () => TaskList,
49
50
  TaskRow: () => TaskRow_default,
50
51
  TimeScaleHeader: () => TimeScaleHeader_default,
@@ -142,7 +143,7 @@ __export(index_exports, {
142
143
  module.exports = __toCommonJS(index_exports);
143
144
 
144
145
  // src/components/GanttChart/GanttChart.tsx
145
- var import_react15 = require("react");
146
+ var import_react16 = require("react");
146
147
 
147
148
  // src/core/scheduling/dateMath.ts
148
149
  var DAY_MS = 24 * 60 * 60 * 1e3;
@@ -3922,7 +3923,8 @@ var DatePicker = ({
3922
3923
  className,
3923
3924
  disabled = false,
3924
3925
  isWeekend: isWeekend3,
3925
- businessDays = true
3926
+ businessDays = true,
3927
+ footer
3926
3928
  }) => {
3927
3929
  const [open, setOpen] = (0, import_react9.useState)(false);
3928
3930
  const [inputValue, setInputValue] = (0, import_react9.useState)("");
@@ -4200,7 +4202,8 @@ var DatePicker = ({
4200
4202
  initialDate: activeDate,
4201
4203
  isWeekend: isWeekend3
4202
4204
  }
4203
- )
4205
+ ),
4206
+ footer ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "gantt-datepicker-footer", children: footer }) : null
4204
4207
  ]
4205
4208
  }
4206
4209
  )
@@ -4842,9 +4845,15 @@ var TaskListRow = import_react10.default.memo(
4842
4845
  resolvedColumns,
4843
4846
  isTaskSelected = false,
4844
4847
  onTaskSelectionChange,
4845
- taskListMenuCommands = []
4848
+ activeCustomCell,
4849
+ onActiveCustomCellChange,
4850
+ taskListMenuCommands = [],
4851
+ hideTaskListRowActions = false,
4852
+ taskDateChangeMode = "preserve-duration",
4853
+ onTaskDateChangeModeChange
4846
4854
  }) => {
4847
4855
  const [editingColumnId, setEditingColumnId] = (0, import_react10.useState)(null);
4856
+ const [editingColumnStartValue, setEditingColumnStartValue] = (0, import_react10.useState)(void 0);
4848
4857
  const editingName = editingColumnId === "name";
4849
4858
  const editingDuration = editingColumnId === "duration";
4850
4859
  const editingProgress = editingColumnId === "progress";
@@ -4870,12 +4879,15 @@ var TaskListRow = import_react10.default.memo(
4870
4879
  const editTriggerRef = (0, import_react10.useRef)(
4871
4880
  "doubleclick"
4872
4881
  );
4882
+ const rowRef = (0, import_react10.useRef)(null);
4873
4883
  const isSelected = selectedTaskId === task.id;
4874
4884
  const isParent = (0, import_react10.useMemo)(
4875
4885
  () => isTaskParent(task.id, allTasks),
4876
4886
  [task.id, allTasks]
4877
4887
  );
4878
4888
  const isChild = task.parentId !== void 0;
4889
+ const rowFillLevel = Math.min(nestingDepth, 2);
4890
+ const isTotalRow = Boolean(task.isTotal);
4879
4891
  const isMilestoneRow = normalizedTask.type === "milestone";
4880
4892
  const weekendPredicate = (0, import_react10.useMemo)(
4881
4893
  () => createCustomDayPredicate({ customDays, isWeekend: isWeekend3 }),
@@ -5245,24 +5257,22 @@ var TaskListRow = import_react10.default.memo(
5245
5257
  emitMilestoneDateChange(newDateISO);
5246
5258
  return;
5247
5259
  }
5248
- let nextEndISO;
5249
5260
  const normalizedInputStart = businessDays ? alignToWorkingDay(/* @__PURE__ */ new Date(`${newDateISO}T00:00:00.000Z`), 1, weekendPredicate) : /* @__PURE__ */ new Date(`${newDateISO}T00:00:00.000Z`);
5250
- if (businessDays) {
5251
- const duration = getDuration(task.startDate, task.endDate);
5252
- nextEndISO = buildTaskRangeFromStart(
5261
+ const { startDate: normalizedStart, endDate: normalizedEnd } = taskDateChangeMode === "free" ? normalizeTaskDates(
5262
+ normalizedInputStart,
5263
+ normalizedInputStart.getTime() > parseUTCDate(task.endDate).getTime() ? normalizedInputStart : parseUTCDate(task.endDate)
5264
+ ) : normalizeTaskDates(
5265
+ normalizedInputStart,
5266
+ businessDays ? buildTaskRangeFromStart(
5253
5267
  normalizedInputStart,
5254
- duration,
5268
+ getDuration(task.startDate, task.endDate),
5255
5269
  true,
5256
5270
  weekendPredicate,
5257
5271
  1
5258
- ).end.toISOString().split("T")[0];
5259
- } else {
5260
- const origStart = parseUTCDate(task.startDate);
5261
- const origEnd = parseUTCDate(task.endDate);
5262
- const durationMs = origEnd.getTime() - origStart.getTime();
5263
- nextEndISO = new Date(normalizedInputStart.getTime() + durationMs).toISOString().split("T")[0];
5264
- }
5265
- const { startDate: normalizedStart, endDate: normalizedEnd } = normalizeTaskDates(normalizedInputStart, nextEndISO);
5272
+ ).end.toISOString().split("T")[0] : new Date(
5273
+ normalizedInputStart.getTime() + (parseUTCDate(task.endDate).getTime() - parseUTCDate(task.startDate).getTime())
5274
+ ).toISOString().split("T")[0]
5275
+ );
5266
5276
  const clampedRange = clampTaskRangeForIncomingFS(
5267
5277
  task,
5268
5278
  /* @__PURE__ */ new Date(`${normalizedStart}T00:00:00.000Z`),
@@ -5291,7 +5301,7 @@ var TaskListRow = import_react10.default.memo(
5291
5301
  }
5292
5302
  ]);
5293
5303
  },
5294
- [task, onTasksChange, businessDays, getDuration, getEndDate, allTasks, weekendPredicate, isMilestone, emitMilestoneDateChange]
5304
+ [task, onTasksChange, businessDays, getDuration, allTasks, weekendPredicate, isMilestone, emitMilestoneDateChange, taskDateChangeMode]
5295
5305
  );
5296
5306
  const handleEndDateChange = (0, import_react10.useCallback)(
5297
5307
  (newDateISO) => {
@@ -5300,24 +5310,22 @@ var TaskListRow = import_react10.default.memo(
5300
5310
  emitMilestoneDateChange(newDateISO);
5301
5311
  return;
5302
5312
  }
5303
- let nextStartISO;
5304
5313
  const normalizedInputEnd = businessDays ? alignToWorkingDay(/* @__PURE__ */ new Date(`${newDateISO}T00:00:00.000Z`), -1, weekendPredicate) : /* @__PURE__ */ new Date(`${newDateISO}T00:00:00.000Z`);
5305
- if (businessDays) {
5306
- const duration = getDuration(task.startDate, task.endDate);
5307
- nextStartISO = buildTaskRangeFromEnd(
5314
+ const { startDate: normalizedStart, endDate: normalizedEnd } = taskDateChangeMode === "free" ? normalizeTaskDates(
5315
+ normalizedInputEnd.getTime() < parseUTCDate(task.startDate).getTime() ? normalizedInputEnd : parseUTCDate(task.startDate),
5316
+ normalizedInputEnd
5317
+ ) : normalizeTaskDates(
5318
+ businessDays ? buildTaskRangeFromEnd(
5308
5319
  normalizedInputEnd,
5309
- duration,
5320
+ getDuration(task.startDate, task.endDate),
5310
5321
  true,
5311
5322
  weekendPredicate,
5312
5323
  -1
5313
- ).start.toISOString().split("T")[0];
5314
- } else {
5315
- const origStart = parseUTCDate(task.startDate);
5316
- const origEnd = parseUTCDate(task.endDate);
5317
- const durationMs = origEnd.getTime() - origStart.getTime();
5318
- nextStartISO = new Date(normalizedInputEnd.getTime() - durationMs).toISOString().split("T")[0];
5319
- }
5320
- const { startDate: normalizedStart, endDate: normalizedEnd } = normalizeTaskDates(nextStartISO, normalizedInputEnd);
5324
+ ).start.toISOString().split("T")[0] : new Date(
5325
+ normalizedInputEnd.getTime() - (parseUTCDate(task.endDate).getTime() - parseUTCDate(task.startDate).getTime())
5326
+ ).toISOString().split("T")[0],
5327
+ normalizedInputEnd
5328
+ );
5321
5329
  const clampedRange = clampTaskRangeForIncomingFS(
5322
5330
  task,
5323
5331
  /* @__PURE__ */ new Date(`${normalizedStart}T00:00:00.000Z`),
@@ -5346,8 +5354,19 @@ var TaskListRow = import_react10.default.memo(
5346
5354
  }
5347
5355
  ]);
5348
5356
  },
5349
- [task, onTasksChange, businessDays, getDuration, weekendPredicate, allTasks, isMilestone, emitMilestoneDateChange]
5357
+ [task, onTasksChange, businessDays, getDuration, weekendPredicate, allTasks, isMilestone, emitMilestoneDateChange, taskDateChangeMode]
5350
5358
  );
5359
+ const datePickerFooter = onTaskDateChangeModeChange ? /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("label", { className: "gantt-datepicker-mode-checkbox", children: [
5360
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
5361
+ "input",
5362
+ {
5363
+ type: "checkbox",
5364
+ checked: taskDateChangeMode === "preserve-duration",
5365
+ onChange: (event) => onTaskDateChangeModeChange(event.target.checked ? "preserve-duration" : "free")
5366
+ }
5367
+ ),
5368
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { children: "\u0421\u043E\u0445\u0440\u0430\u043D\u044F\u0442\u044C \u0434\u043B\u0438\u0442\u0435\u043B\u044C\u043D\u043E\u0441\u0442\u044C" })
5369
+ ] }) : null;
5351
5370
  const handleRowClickInternal = (0, import_react10.useCallback)(() => {
5352
5371
  onRowClick?.(task.id);
5353
5372
  }, [task.id, onRowClick]);
@@ -5415,7 +5434,7 @@ var TaskListRow = import_react10.default.memo(
5415
5434
  ),
5416
5435
  [taskListMenuCommands, task, isParent, isMilestoneRow]
5417
5436
  );
5418
- const hasContextMenu = visibleCustomMenuCommands.length > 0 || !!onDuplicateTask || !!onDelete || !!onTasksChange || isParent && !!onUngroupTask;
5437
+ const hasContextMenu = !hideTaskListRowActions && (visibleCustomMenuCommands.length > 0 || !!onDuplicateTask || !!onDelete || !!onTasksChange || isParent && !!onUngroupTask);
5419
5438
  const handleCustomMenuCommandClick = (0, import_react10.useCallback)(
5420
5439
  (command) => (e) => {
5421
5440
  e.stopPropagation();
@@ -5654,14 +5673,14 @@ var TaskListRow = import_react10.default.memo(
5654
5673
  className: "gantt-tl-cell gantt-tl-cell-number",
5655
5674
  onClick: handleNumberClick,
5656
5675
  children: [
5657
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
5676
+ onDragStart && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
5658
5677
  "span",
5659
5678
  {
5660
5679
  className: "gantt-tl-drag-handle",
5661
5680
  draggable: true,
5662
5681
  onDragStart: (e) => {
5663
5682
  e.stopPropagation();
5664
- onDragStart?.(rowIndex, e);
5683
+ onDragStart(rowIndex, e);
5665
5684
  },
5666
5685
  onDragEnd: (e) => onDragEnd?.(e),
5667
5686
  onClick: (e) => e.stopPropagation(),
@@ -5857,7 +5876,7 @@ var TaskListRow = import_react10.default.memo(
5857
5876
  "aria-hidden": "true"
5858
5877
  }
5859
5878
  ),
5860
- !editingName && (onInsertAfter || onDelete || onPromoteTask || onDemoteTask || onUngroupTask || onDuplicateTask || onTasksChange || hasContextMenu) && /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: `gantt-tl-name-actions${contextMenuOpen ? " gantt-tl-name-actions-open" : ""}`, children: [
5879
+ !editingName && !hideTaskListRowActions && (onInsertAfter || onDelete || onPromoteTask || onDemoteTask || onUngroupTask || onDuplicateTask || onTasksChange || hasContextMenu) && /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: `gantt-tl-name-actions${contextMenuOpen ? " gantt-tl-name-actions-open" : ""}`, children: [
5861
5880
  onInsertAfter && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
5862
5881
  "button",
5863
5882
  {
@@ -6046,7 +6065,8 @@ var TaskListRow = import_react10.default.memo(
6046
6065
  portal: true,
6047
6066
  disabled: task.locked,
6048
6067
  isWeekend: weekendPredicate,
6049
- businessDays
6068
+ businessDays,
6069
+ footer: datePickerFooter
6050
6070
  }
6051
6071
  )
6052
6072
  }
@@ -6065,7 +6085,8 @@ var TaskListRow = import_react10.default.memo(
6065
6085
  portal: true,
6066
6086
  disabled: task.locked,
6067
6087
  isWeekend: weekendPredicate,
6068
- businessDays
6088
+ businessDays,
6089
+ footer: datePickerFooter
6069
6090
  }
6070
6091
  )
6071
6092
  }
@@ -6374,9 +6395,52 @@ var TaskListRow = import_react10.default.memo(
6374
6395
  progress: progressCell,
6375
6396
  dependencies: dependenciesCell
6376
6397
  };
6398
+ const focusCustomCell = (0, import_react10.useCallback)((taskId, columnId) => {
6399
+ const overlay = rowRef.current?.closest(".gantt-tl-overlay");
6400
+ if (!overlay) {
6401
+ return;
6402
+ }
6403
+ const selector = `[data-gantt-task-row-id="${taskId}"] [data-custom-column-id="${columnId}"]`;
6404
+ const nextCell = overlay.querySelector(selector);
6405
+ nextCell?.focus();
6406
+ }, []);
6407
+ const moveActiveCustomCell = (0, import_react10.useCallback)((columnId, direction) => {
6408
+ const overlay = rowRef.current?.closest(".gantt-tl-overlay");
6409
+ if (!overlay || !resolvedColumns) {
6410
+ return;
6411
+ }
6412
+ const customColumnIds = resolvedColumns.filter((column) => !["selection", "number", "name", "startDate", "endDate", "duration", "progress", "dependencies"].includes(column.id)).map((column) => column.id);
6413
+ const columnIndex = customColumnIds.indexOf(columnId);
6414
+ if (columnIndex === -1) {
6415
+ return;
6416
+ }
6417
+ const rowElements = Array.from(
6418
+ overlay.querySelectorAll(".gantt-tl-row[data-gantt-task-row-id]")
6419
+ );
6420
+ const rowIds = rowElements.map((element) => element.dataset.ganttTaskRowId).filter((value) => Boolean(value));
6421
+ const rowIndex2 = rowIds.indexOf(task.id);
6422
+ if (rowIndex2 === -1) {
6423
+ return;
6424
+ }
6425
+ let nextRowIndex = rowIndex2;
6426
+ let nextColumnIndex = columnIndex;
6427
+ if (direction === "left") nextColumnIndex -= 1;
6428
+ if (direction === "right") nextColumnIndex += 1;
6429
+ if (direction === "up") nextRowIndex -= 1;
6430
+ if (direction === "down") nextRowIndex += 1;
6431
+ if (nextRowIndex < 0 || nextRowIndex >= rowIds.length || nextColumnIndex < 0 || nextColumnIndex >= customColumnIds.length) {
6432
+ return;
6433
+ }
6434
+ const nextCell = { taskId: rowIds[nextRowIndex], columnId: customColumnIds[nextColumnIndex] };
6435
+ onActiveCustomCellChange?.(nextCell);
6436
+ window.requestAnimationFrame(() => {
6437
+ focusCustomCell(nextCell.taskId, nextCell.columnId);
6438
+ });
6439
+ }, [focusCustomCell, onActiveCustomCellChange, resolvedColumns, task.id]);
6377
6440
  return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
6378
6441
  "div",
6379
6442
  {
6443
+ ref: rowRef,
6380
6444
  "data-filter-match": isFilterMatch ? "true" : "false",
6381
6445
  className: [
6382
6446
  "gantt-tl-row",
@@ -6389,9 +6453,11 @@ var TaskListRow = import_react10.default.memo(
6389
6453
  isDragging ? "gantt-tl-row-dragging" : "",
6390
6454
  isDragOver ? "gantt-tl-row-drag-over" : "",
6391
6455
  isChild ? "gantt-tl-row-child" : "",
6392
- isParent ? "gantt-tl-row-parent" : ""
6456
+ isParent ? "gantt-tl-row-parent" : "",
6457
+ `gantt-tl-row-level-${rowFillLevel}`,
6458
+ isTotalRow ? "gantt-tl-row-total" : ""
6393
6459
  ].filter(Boolean).join(" "),
6394
- style: { minHeight: `${rowHeight}px`, position: "relative" },
6460
+ style: { height: `${rowHeight}px`, position: "relative" },
6395
6461
  "data-gantt-task-row-id": task.id,
6396
6462
  onClick: handleRowClickInternal,
6397
6463
  onKeyDown: handleRowKeyDown,
@@ -6403,43 +6469,120 @@ var TaskListRow = import_react10.default.memo(
6403
6469
  if (builtIn) return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_react10.default.Fragment, { children: builtIn }, col.id);
6404
6470
  const isEditing = editingColumnId === col.id;
6405
6471
  const editorFn = col.renderEditor;
6472
+ const isActiveCustomCell = activeCustomCell?.taskId === task.id && activeCustomCell?.columnId === col.id;
6473
+ const startEditingCustomCell = (startValue) => {
6474
+ if (!editorFn) return;
6475
+ onActiveCustomCellChange?.({ taskId: task.id, columnId: col.id });
6476
+ setEditingColumnStartValue(startValue);
6477
+ setEditingColumnId(col.id);
6478
+ };
6406
6479
  const columnContext = {
6407
6480
  task,
6408
6481
  rowIndex,
6409
6482
  isEditing,
6483
+ editStartValue: isEditing ? editingColumnStartValue : void 0,
6410
6484
  openEditor: () => {
6411
- if (editorFn) setEditingColumnId(col.id);
6485
+ startEditingCustomCell();
6412
6486
  },
6413
6487
  closeEditor: () => {
6414
- if (editingColumnId === col.id) setEditingColumnId(null);
6488
+ if (editingColumnId === col.id) {
6489
+ setEditingColumnId(null);
6490
+ setEditingColumnStartValue(void 0);
6491
+ onActiveCustomCellChange?.({ taskId: task.id, columnId: col.id });
6492
+ window.requestAnimationFrame(() => {
6493
+ focusCustomCell(task.id, col.id);
6494
+ });
6495
+ }
6415
6496
  },
6416
6497
  updateTask: (patch) => {
6417
6498
  onTasksChange?.([{ ...task, ...patch }]);
6499
+ onActiveCustomCellChange?.({ taskId: task.id, columnId: col.id });
6500
+ setEditingColumnStartValue(void 0);
6418
6501
  setEditingColumnId(null);
6502
+ window.requestAnimationFrame(() => {
6503
+ focusCustomCell(task.id, col.id);
6504
+ });
6419
6505
  }
6420
6506
  };
6421
6507
  return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
6422
6508
  "div",
6423
6509
  {
6424
- className: "gantt-tl-cell gantt-tl-cell-custom",
6510
+ className: `gantt-tl-cell gantt-tl-cell-custom gantt-tl-cell-align-${col.align ?? "left"}`,
6425
6511
  "data-column-id": `custom:${col.id}`,
6426
6512
  "data-custom-column-id": col.id,
6513
+ "data-custom-column-active": isActiveCustomCell ? "true" : "false",
6427
6514
  "data-custom-column-editing": isEditing ? "true" : "false",
6428
6515
  "data-testid": `custom-cell-${col.id}`,
6429
- onClick: editorFn && !isEditing ? (e) => {
6516
+ tabIndex: editorFn ? 0 : -1,
6517
+ onFocus: editorFn ? () => {
6518
+ onActiveCustomCellChange?.({ taskId: task.id, columnId: col.id });
6519
+ } : void 0,
6520
+ onClick: editorFn ? (e) => {
6521
+ e.stopPropagation();
6522
+ onActiveCustomCellChange?.({ taskId: task.id, columnId: col.id });
6523
+ if (isEditing) {
6524
+ return;
6525
+ }
6526
+ e.currentTarget.focus();
6527
+ } : void 0,
6528
+ onDoubleClick: editorFn && !isEditing ? (e) => {
6430
6529
  e.stopPropagation();
6431
- setEditingColumnId(col.id);
6530
+ startEditingCustomCell();
6531
+ } : void 0,
6532
+ onKeyDown: editorFn && !isEditing ? (e) => {
6533
+ if (e.key === "ArrowLeft") {
6534
+ e.preventDefault();
6535
+ e.stopPropagation();
6536
+ moveActiveCustomCell(col.id, "left");
6537
+ return;
6538
+ }
6539
+ if (e.key === "ArrowRight") {
6540
+ e.preventDefault();
6541
+ e.stopPropagation();
6542
+ moveActiveCustomCell(col.id, "right");
6543
+ return;
6544
+ }
6545
+ if (e.key === "ArrowUp") {
6546
+ e.preventDefault();
6547
+ e.stopPropagation();
6548
+ moveActiveCustomCell(col.id, "up");
6549
+ return;
6550
+ }
6551
+ if (e.key === "ArrowDown") {
6552
+ e.preventDefault();
6553
+ e.stopPropagation();
6554
+ moveActiveCustomCell(col.id, "down");
6555
+ return;
6556
+ }
6557
+ if (e.key === "Enter" || e.key === "F2") {
6558
+ e.preventDefault();
6559
+ e.stopPropagation();
6560
+ startEditingCustomCell();
6561
+ return;
6562
+ }
6563
+ if (e.key === "Backspace" || e.key === "Delete") {
6564
+ e.preventDefault();
6565
+ e.stopPropagation();
6566
+ startEditingCustomCell("");
6567
+ return;
6568
+ }
6569
+ if (e.key.length === 1 && !e.ctrlKey && !e.metaKey && !e.altKey) {
6570
+ e.preventDefault();
6571
+ e.stopPropagation();
6572
+ startEditingCustomCell(e.key);
6573
+ }
6432
6574
  } : void 0,
6433
6575
  style: { width: col.width ?? 120, minWidth: col.width ?? 120, flexShrink: 0 },
6434
6576
  children: isEditing && editorFn ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
6435
6577
  "div",
6436
6578
  {
6579
+ className: "gantt-tl-cell-custom-editor",
6437
6580
  "data-custom-column-editor": col.id,
6438
6581
  onMouseDown: (e) => e.stopPropagation(),
6439
6582
  onClick: (e) => e.stopPropagation(),
6440
6583
  children: editorFn(columnContext)
6441
6584
  }
6442
- ) : col.renderCell(columnContext)
6585
+ ) : /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "gantt-tl-cell-custom-content", children: col.renderCell(columnContext) })
6443
6586
  },
6444
6587
  col.id
6445
6588
  );
@@ -6491,7 +6634,7 @@ var NewTaskRow = ({
6491
6634
  onCancel();
6492
6635
  }
6493
6636
  };
6494
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "gantt-tl-row gantt-tl-row-new", style: { minHeight: `${rowHeight}px` }, children: [
6637
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "gantt-tl-row gantt-tl-row-new", style: { height: `${rowHeight}px` }, children: [
6495
6638
  /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "gantt-tl-cell gantt-tl-cell-number" }),
6496
6639
  /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "gantt-tl-cell gantt-tl-cell-name gantt-tl-cell-new-name", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
6497
6640
  Input,
@@ -6725,6 +6868,7 @@ var TaskList = ({
6725
6868
  onDelete,
6726
6869
  onInsertAfter,
6727
6870
  onReorder,
6871
+ disableTaskDrag = false,
6728
6872
  editingTaskId: propEditingTaskId,
6729
6873
  enableAddTask = true,
6730
6874
  defaultTaskDurationDays = DEFAULT_TASK_DURATION_DAYS,
@@ -6745,9 +6889,14 @@ var TaskList = ({
6745
6889
  isFilterActive = false,
6746
6890
  additionalColumns,
6747
6891
  hiddenTaskListColumns,
6748
- taskListMenuCommands
6892
+ taskListMenuCommands,
6893
+ hideTaskListRowActions = false,
6894
+ rowContentLines = 1,
6895
+ taskDateChangeMode = "preserve-duration",
6896
+ onTaskDateChangeModeChange
6749
6897
  }) => {
6750
6898
  const [internalSelectedTaskIds, setInternalSelectedTaskIds] = (0, import_react12.useState)(/* @__PURE__ */ new Set());
6899
+ const [activeCustomCell, setActiveCustomCell] = (0, import_react12.useState)(null);
6751
6900
  const effectiveSelectedTaskIds = selectedTaskIds ?? internalSelectedTaskIds;
6752
6901
  const emitSelectedTaskIdsChange = (0, import_react12.useCallback)((nextSelectedTaskIds) => {
6753
6902
  if (!selectedTaskIds) {
@@ -6919,21 +7068,28 @@ var TaskList = ({
6919
7068
  onSelectedChipChange?.(chip);
6920
7069
  }, [onSelectedChipChange]);
6921
7070
  (0, import_react12.useEffect)(() => {
6922
- if (!selectingPredecessorFor && !selectedChip && !selectedTaskId) return;
7071
+ if (!selectingPredecessorFor && !selectedChip && !selectedTaskId && !activeCustomCell) return;
6923
7072
  const handleKeyDown = (e) => {
6924
7073
  if (e.key === "Escape") {
6925
7074
  setSelectingPredecessorFor(null);
6926
7075
  setSelectedChip(null);
7076
+ setActiveCustomCell(null);
6927
7077
  onSelectedChipChange?.(null);
6928
7078
  onTaskSelect?.(null);
6929
7079
  }
6930
7080
  };
6931
7081
  const handleMouseDown = (e) => {
6932
7082
  const target = e.target;
6933
- if (overlayRef.current?.contains(target)) return;
7083
+ if (overlayRef.current?.contains(target)) {
7084
+ if (activeCustomCell && !target.closest?.("[data-custom-column-id]")) {
7085
+ setActiveCustomCell(null);
7086
+ }
7087
+ return;
7088
+ }
6934
7089
  if (target.closest?.(".gantt-popover")) return;
6935
7090
  setSelectingPredecessorFor(null);
6936
7091
  setSelectedChip(null);
7092
+ setActiveCustomCell(null);
6937
7093
  onSelectedChipChange?.(null);
6938
7094
  onTaskSelect?.(null);
6939
7095
  };
@@ -6943,7 +7099,7 @@ var TaskList = ({
6943
7099
  document.removeEventListener("keydown", handleKeyDown);
6944
7100
  document.removeEventListener("mousedown", handleMouseDown, true);
6945
7101
  };
6946
- }, [selectingPredecessorFor, selectedChip, selectedTaskId, onTaskSelect, onSelectedChipChange]);
7102
+ }, [selectingPredecessorFor, selectedChip, selectedTaskId, activeCustomCell, onTaskSelect, onSelectedChipChange]);
6947
7103
  const handleAddDependency = (0, import_react12.useCallback)((successorTaskId, predecessorTaskId, linkType) => {
6948
7104
  if (successorTaskId === predecessorTaskId) return;
6949
7105
  if (areTasksHierarchicallyRelated(successorTaskId, predecessorTaskId, tasks)) {
@@ -7333,7 +7489,10 @@ var TaskList = ({
7333
7489
  {
7334
7490
  ref: overlayRef,
7335
7491
  className: `gantt-tl-overlay${show ? "" : " gantt-tl-hidden"}${hasRightShadow ? " gantt-tl-overlay-shadowed" : ""}`,
7336
- style: { "--tasklist-width": `${effectiveTaskListWidth}px` },
7492
+ style: {
7493
+ "--tasklist-width": `${effectiveTaskListWidth}px`,
7494
+ "--gantt-row-content-lines": String(Math.max(2, Math.floor(rowContentLines)))
7495
+ },
7337
7496
  children: /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "gantt-tl-table", children: [
7338
7497
  /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "gantt-tl-header", style: { height: `${tableHeaderHeight}px` }, children: resolvedColumns.map((col) => {
7339
7498
  if (col.id === "selection") {
@@ -7413,7 +7572,7 @@ var TaskList = ({
7413
7572
  return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
7414
7573
  "div",
7415
7574
  {
7416
- className: "gantt-tl-headerCell gantt-tl-headerCell-custom",
7575
+ className: `gantt-tl-headerCell gantt-tl-headerCell-custom gantt-tl-cell-align-${col.align ?? "left"}`,
7417
7576
  "data-column-id": `custom:${col.id}`,
7418
7577
  "data-custom-column-id": col.id,
7419
7578
  style: { width: col.width, minWidth: col.width, flexShrink: 0 },
@@ -7455,12 +7614,12 @@ var TaskList = ({
7455
7614
  onAdd,
7456
7615
  onInsertAfter: handleStartInsertAfter,
7457
7616
  editingTaskId: propEditingTaskId,
7458
- isDragging: draggingIndex === index,
7459
- isDragOver: dragOverIndex === index,
7460
- onDragStart: handleDragStart,
7461
- onDragOver: handleDragOver,
7462
- onDrop: handleDrop,
7463
- onDragEnd: handleDragEnd,
7617
+ isDragging: !disableTaskDrag && draggingIndex === index,
7618
+ isDragOver: !disableTaskDrag && dragOverIndex === index,
7619
+ onDragStart: disableTaskDrag ? void 0 : handleDragStart,
7620
+ onDragOver: disableTaskDrag ? void 0 : handleDragOver,
7621
+ onDrop: disableTaskDrag ? void 0 : handleDrop,
7622
+ onDragEnd: disableTaskDrag ? void 0 : handleDragEnd,
7464
7623
  collapsedParentIds,
7465
7624
  onToggleCollapse: handleToggleCollapse,
7466
7625
  onPromoteTask,
@@ -7481,7 +7640,12 @@ var TaskList = ({
7481
7640
  resolvedColumns,
7482
7641
  isTaskSelected: effectiveSelectedTaskIds.has(task.id),
7483
7642
  onTaskSelectionChange: handleToggleTaskSelection,
7484
- taskListMenuCommands
7643
+ activeCustomCell,
7644
+ onActiveCustomCellChange: setActiveCustomCell,
7645
+ taskListMenuCommands,
7646
+ hideTaskListRowActions,
7647
+ taskDateChangeMode,
7648
+ onTaskDateChangeModeChange
7485
7649
  }
7486
7650
  ),
7487
7651
  pendingInsertDisplayTaskId === task.id && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
@@ -7507,25 +7671,25 @@ var TaskList = ({
7507
7671
  enableAddTask && onAdd && !isCreating && !pendingInsert && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
7508
7672
  "button",
7509
7673
  {
7510
- className: `gantt-tl-add-btn${dragOverIndex === visibleTasks.length ? " gantt-tl-add-btn-drag-over" : ""}`,
7674
+ className: `gantt-tl-add-btn${!disableTaskDrag && dragOverIndex === visibleTasks.length ? " gantt-tl-add-btn-drag-over" : ""}`,
7511
7675
  onClick: () => {
7512
7676
  setPendingInsert(null);
7513
7677
  setIsCreating(true);
7514
7678
  },
7515
- onDragEnter: (e) => {
7679
+ onDragEnter: disableTaskDrag ? void 0 : (e) => {
7516
7680
  e.preventDefault();
7517
7681
  setDragOverIndex(visibleTasks.length);
7518
7682
  },
7519
- onDragOver: (e) => {
7683
+ onDragOver: disableTaskDrag ? void 0 : (e) => {
7520
7684
  e.preventDefault();
7521
7685
  e.dataTransfer.dropEffect = "move";
7522
7686
  setDragOverIndex(visibleTasks.length);
7523
7687
  },
7524
- onDragLeave: (e) => {
7688
+ onDragLeave: disableTaskDrag ? void 0 : (e) => {
7525
7689
  e.preventDefault();
7526
7690
  setDragOverIndex(null);
7527
7691
  },
7528
- onDrop: (e) => {
7692
+ onDrop: disableTaskDrag ? void 0 : (e) => {
7529
7693
  e.preventDefault();
7530
7694
  handleDrop(visibleTasks.length, e);
7531
7695
  },
@@ -9218,6 +9382,190 @@ function ResourceTimelineChart({
9218
9382
  ) });
9219
9383
  }
9220
9384
 
9385
+ // src/components/TableMatrix/TableMatrix.tsx
9386
+ var import_react15 = require("react");
9387
+ var import_jsx_runtime16 = require("react/jsx-runtime");
9388
+ function joinClasses(...values) {
9389
+ return values.filter(Boolean).join(" ");
9390
+ }
9391
+ function TableMatrix({
9392
+ tasks,
9393
+ allTasks = tasks,
9394
+ columns,
9395
+ columnGroups,
9396
+ rowHeight,
9397
+ headerHeight,
9398
+ selectedTaskId,
9399
+ onTaskSelect,
9400
+ onCellClick,
9401
+ highlightedTaskIds,
9402
+ filterMode = "highlight"
9403
+ }) {
9404
+ const gridTemplateColumns = (0, import_react15.useMemo)(
9405
+ () => columns.map((column) => `${column.width}px`).join(" "),
9406
+ [columns]
9407
+ );
9408
+ const totalWidth = (0, import_react15.useMemo)(
9409
+ () => columns.reduce((sum, column) => sum + column.width, 0),
9410
+ [columns]
9411
+ );
9412
+ const hasGroupHeader = (0, import_react15.useMemo)(
9413
+ () => columns.some((column) => !!column.groupId) || (columnGroups?.length ?? 0) > 0,
9414
+ [columnGroups, columns]
9415
+ );
9416
+ const groupMap = (0, import_react15.useMemo)(
9417
+ () => new Map((columnGroups ?? []).map((group) => [group.id, group])),
9418
+ [columnGroups]
9419
+ );
9420
+ const headerSpans = (0, import_react15.useMemo)(() => {
9421
+ if (!hasGroupHeader) return [];
9422
+ if (columnGroups?.some((group) => typeof group.width === "number")) {
9423
+ return columnGroups.map((group) => ({
9424
+ id: group.id,
9425
+ header: group.header,
9426
+ width: group.width ?? 0,
9427
+ className: group.className
9428
+ }));
9429
+ }
9430
+ const spans = [];
9431
+ for (const column of columns) {
9432
+ const groupId = column.groupId ?? column.id;
9433
+ const lastSpan = spans[spans.length - 1];
9434
+ if (lastSpan?.id === groupId) {
9435
+ lastSpan.width += column.width;
9436
+ continue;
9437
+ }
9438
+ const group = groupMap.get(groupId);
9439
+ spans.push({
9440
+ id: groupId,
9441
+ header: group?.header ?? column.header,
9442
+ width: column.width,
9443
+ className: group?.className
9444
+ });
9445
+ }
9446
+ return spans;
9447
+ }, [columns, groupMap, hasGroupHeader]);
9448
+ const headerContentHeight = Math.max(0, headerHeight - 1);
9449
+ const topRowHeight = hasGroupHeader ? Math.ceil(headerContentHeight / 2) : headerContentHeight;
9450
+ const bottomRowHeight = hasGroupHeader ? Math.floor(headerContentHeight / 2) : 0;
9451
+ const parentTaskIds = (0, import_react15.useMemo)(() => {
9452
+ const ids = /* @__PURE__ */ new Set();
9453
+ for (const task of allTasks) {
9454
+ if (task.parentId) {
9455
+ ids.add(task.parentId);
9456
+ }
9457
+ }
9458
+ return ids;
9459
+ }, [allTasks]);
9460
+ const nestingDepthMap = (0, import_react15.useMemo)(() => {
9461
+ const depthMap = /* @__PURE__ */ new Map();
9462
+ const taskById = new Map(allTasks.map((task) => [task.id, task]));
9463
+ const getDepth = (taskId, seen = /* @__PURE__ */ new Set()) => {
9464
+ if (depthMap.has(taskId)) return depthMap.get(taskId);
9465
+ if (seen.has(taskId)) return 0;
9466
+ const task = taskById.get(taskId);
9467
+ if (!task?.parentId || !taskById.has(task.parentId)) {
9468
+ depthMap.set(taskId, 0);
9469
+ return 0;
9470
+ }
9471
+ seen.add(taskId);
9472
+ const depth = getDepth(task.parentId, seen) + 1;
9473
+ depthMap.set(taskId, depth);
9474
+ return depth;
9475
+ };
9476
+ for (const task of allTasks) {
9477
+ getDepth(task.id);
9478
+ }
9479
+ return depthMap;
9480
+ }, [allTasks]);
9481
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "gantt-mx-root", style: { width: `${totalWidth}px` }, children: [
9482
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "gantt-mx-header", style: { height: `${headerHeight}px` }, children: [
9483
+ hasGroupHeader && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
9484
+ "div",
9485
+ {
9486
+ className: "gantt-mx-headerRow gantt-mx-headerGroupRow",
9487
+ style: { gridTemplateColumns: headerSpans.map((span) => `${span.width}px`).join(" "), height: `${topRowHeight}px` },
9488
+ children: headerSpans.map((span) => /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: joinClasses("gantt-mx-groupCell", span.className), children: span.header }, span.id))
9489
+ }
9490
+ ),
9491
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
9492
+ "div",
9493
+ {
9494
+ className: "gantt-mx-headerRow",
9495
+ style: { gridTemplateColumns, height: `${hasGroupHeader ? bottomRowHeight : topRowHeight}px` },
9496
+ children: columns.map((column) => /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
9497
+ "div",
9498
+ {
9499
+ className: joinClasses(
9500
+ "gantt-mx-headerCell",
9501
+ column.headerClassName
9502
+ ),
9503
+ children: column.header
9504
+ },
9505
+ column.id
9506
+ ))
9507
+ }
9508
+ )
9509
+ ] }),
9510
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
9511
+ "div",
9512
+ {
9513
+ className: "gantt-mx-body",
9514
+ style: { height: `${tasks.length * rowHeight}px` },
9515
+ children: tasks.map((task, index) => {
9516
+ const isHighlighted = filterMode === "highlight" && !!highlightedTaskIds?.has(task.id);
9517
+ const isParent = parentTaskIds.has(task.id);
9518
+ const nestingDepth = nestingDepthMap.get(task.id) ?? 0;
9519
+ const rowFillLevel = Math.min(nestingDepth, 2);
9520
+ const isTotal = Boolean(task.isTotal);
9521
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
9522
+ "div",
9523
+ {
9524
+ "data-gantt-task-row-id": task.id,
9525
+ className: joinClasses(
9526
+ "gantt-mx-row",
9527
+ task.parentId && "gantt-mx-row-child",
9528
+ isParent && "gantt-mx-row-parent",
9529
+ `gantt-mx-row-level-${rowFillLevel}`,
9530
+ isTotal && "gantt-mx-row-total",
9531
+ selectedTaskId === task.id && "gantt-mx-row-selected",
9532
+ isHighlighted && "gantt-mx-row-highlighted"
9533
+ ),
9534
+ style: {
9535
+ gridTemplateColumns,
9536
+ top: `${index * rowHeight}px`,
9537
+ height: `${rowHeight}px`
9538
+ },
9539
+ onClick: () => onTaskSelect?.(task.id),
9540
+ children: columns.map((column, columnIndex) => {
9541
+ const resolvedCellClassName = typeof column.cellClassName === "function" ? column.cellClassName(task) : column.cellClassName;
9542
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
9543
+ "div",
9544
+ {
9545
+ className: joinClasses(
9546
+ "gantt-mx-cell",
9547
+ onCellClick && "gantt-mx-cell-clickable",
9548
+ `gantt-mx-cellAlign-${column.align ?? "right"}`,
9549
+ column.className,
9550
+ resolvedCellClassName
9551
+ ),
9552
+ onClick: (event) => {
9553
+ onCellClick?.({ task, column, rowIndex: index, columnIndex, event });
9554
+ },
9555
+ children: column.renderCell(task)
9556
+ },
9557
+ `${task.id}:${column.id}`
9558
+ );
9559
+ })
9560
+ },
9561
+ task.id
9562
+ );
9563
+ })
9564
+ }
9565
+ )
9566
+ ] });
9567
+ }
9568
+
9221
9569
  // src/components/GanttChart/print.ts
9222
9570
  function getPrintDocumentTitle({
9223
9571
  header,
@@ -9556,13 +9904,13 @@ async function printGanttChart({
9556
9904
  }
9557
9905
 
9558
9906
  // src/components/GanttChart/GanttChart.tsx
9559
- var import_jsx_runtime16 = require("react/jsx-runtime");
9907
+ var import_jsx_runtime17 = require("react/jsx-runtime");
9560
9908
  var SCROLL_TO_ROW_CONTEXT_ROWS = 2;
9561
9909
  function GanttChartInner(props, ref) {
9562
9910
  if (props.mode === "resource-planner") {
9563
- return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(ResourceTimelineChart, { ...props });
9911
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(ResourceTimelineChart, { ...props });
9564
9912
  }
9565
- return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
9913
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
9566
9914
  TaskGanttChart,
9567
9915
  {
9568
9916
  ...props,
@@ -9571,9 +9919,9 @@ function GanttChartInner(props, ref) {
9571
9919
  );
9572
9920
  }
9573
9921
  function TaskGanttChartInner(props, ref) {
9922
+ const isTableMatrixMode = props.mode === "table-matrix";
9574
9923
  const {
9575
9924
  tasks,
9576
- dayWidth = 40,
9577
9925
  rowHeight = 40,
9578
9926
  headerHeight = 40,
9579
9927
  containerHeight,
@@ -9597,10 +9945,6 @@ function TaskGanttChartInner(props, ref) {
9597
9945
  onUngroupTask,
9598
9946
  enableAddTask = true,
9599
9947
  defaultTaskDurationDays,
9600
- viewMode = "day",
9601
- customDays,
9602
- isWeekend: isWeekend3,
9603
- businessDays = true,
9604
9948
  taskFilter,
9605
9949
  filterMode = "highlight",
9606
9950
  collapsedParentIds: externalCollapsedParentIds,
@@ -9613,24 +9957,44 @@ function TaskGanttChartInner(props, ref) {
9613
9957
  showChart = true,
9614
9958
  additionalColumns,
9615
9959
  hiddenTaskListColumns,
9616
- taskListMenuCommands
9960
+ taskListMenuCommands,
9961
+ hideTaskListRowActions = false,
9962
+ rowContentLines = 1,
9963
+ taskDateChangeMode: externalTaskDateChangeMode,
9964
+ onTaskDateChangeModeChange: externalOnTaskDateChangeModeChange
9617
9965
  } = props;
9618
- const containerRef = (0, import_react15.useRef)(null);
9619
- const scrollContainerRef = (0, import_react15.useRef)(null);
9620
- const scrollContentRef = (0, import_react15.useRef)(null);
9621
- const clearSelectedTaskTimeoutRef = (0, import_react15.useRef)(null);
9622
- const [selectedTaskId, setSelectedTaskId] = (0, import_react15.useState)(null);
9623
- const [taskListHasRightShadow, setTaskListHasRightShadow] = (0, import_react15.useState)(false);
9624
- const [selectedChip, setSelectedChip] = (0, import_react15.useState)(null);
9625
- const [internalCollapsedParentIds, setInternalCollapsedParentIds] = (0, import_react15.useState)(/* @__PURE__ */ new Set());
9966
+ const dayWidth = !isTableMatrixMode ? props.dayWidth ?? 40 : 40;
9967
+ const viewMode = !isTableMatrixMode ? props.viewMode ?? "day" : "day";
9968
+ const customDays = !isTableMatrixMode ? props.customDays : void 0;
9969
+ const isWeekend3 = !isTableMatrixMode ? props.isWeekend : void 0;
9970
+ const businessDays = !isTableMatrixMode ? props.businessDays ?? true : true;
9971
+ const matrixColumns = isTableMatrixMode ? props.matrixColumns : [];
9972
+ const matrixColumnGroups = isTableMatrixMode ? props.matrixColumnGroups : void 0;
9973
+ const onMatrixCellClick = isTableMatrixMode ? props.onMatrixCellClick : void 0;
9974
+ const containerRef = (0, import_react16.useRef)(null);
9975
+ const scrollContainerRef = (0, import_react16.useRef)(null);
9976
+ const scrollContentRef = (0, import_react16.useRef)(null);
9977
+ const clearSelectedTaskTimeoutRef = (0, import_react16.useRef)(null);
9978
+ const [selectedTaskId, setSelectedTaskId] = (0, import_react16.useState)(null);
9979
+ const [taskListHasRightShadow, setTaskListHasRightShadow] = (0, import_react16.useState)(false);
9980
+ const [internalTaskDateChangeMode, setInternalTaskDateChangeMode] = (0, import_react16.useState)("preserve-duration");
9981
+ const [selectedChip, setSelectedChip] = (0, import_react16.useState)(null);
9982
+ const [internalCollapsedParentIds, setInternalCollapsedParentIds] = (0, import_react16.useState)(/* @__PURE__ */ new Set());
9626
9983
  const collapsedParentIds = externalCollapsedParentIds ?? internalCollapsedParentIds;
9627
- const [editingTaskId, setEditingTaskId] = (0, import_react15.useState)(null);
9628
- const normalizedTasks = (0, import_react15.useMemo)(() => normalizeHierarchyTasks(tasks), [tasks]);
9629
- const isCustomWeekend = (0, import_react15.useMemo)(
9984
+ const [editingTaskId, setEditingTaskId] = (0, import_react16.useState)(null);
9985
+ const taskDateChangeMode = externalTaskDateChangeMode ?? internalTaskDateChangeMode;
9986
+ const handleTaskDateChangeMode = externalOnTaskDateChangeModeChange ?? setInternalTaskDateChangeMode;
9987
+ const resolvedRowContentLines = Math.max(1, Math.floor(rowContentLines));
9988
+ const effectiveRowHeight = (0, import_react16.useMemo)(
9989
+ () => Math.max(rowHeight, 10 + resolvedRowContentLines * 18),
9990
+ [resolvedRowContentLines, rowHeight]
9991
+ );
9992
+ const normalizedTasks = (0, import_react16.useMemo)(() => normalizeHierarchyTasks(tasks), [tasks]);
9993
+ const isCustomWeekend = (0, import_react16.useMemo)(
9630
9994
  () => createCustomDayPredicate({ customDays, isWeekend: isWeekend3 }),
9631
9995
  [customDays, isWeekend3]
9632
9996
  );
9633
- const dateRangeTasks = (0, import_react15.useMemo)(() => {
9997
+ const dateRangeTasks = (0, import_react16.useMemo)(() => {
9634
9998
  if (!showBaseline) {
9635
9999
  return normalizedTasks;
9636
10000
  }
@@ -9640,14 +10004,18 @@ function TaskGanttChartInner(props, ref) {
9640
10004
  endDate: task.baselineEndDate && parseUTCDate(task.baselineEndDate).getTime() > parseUTCDate(task.endDate).getTime() ? task.baselineEndDate : task.endDate
9641
10005
  }));
9642
10006
  }, [normalizedTasks, showBaseline]);
9643
- const dateRange = (0, import_react15.useMemo)(() => getMultiMonthDays(dateRangeTasks), [dateRangeTasks]);
9644
- const [validationResult, setValidationResult] = (0, import_react15.useState)(null);
9645
- const [cascadeOverrides, setCascadeOverrides] = (0, import_react15.useState)(/* @__PURE__ */ new Map());
9646
- const gridWidth = (0, import_react15.useMemo)(
10007
+ const dateRange = (0, import_react16.useMemo)(() => getMultiMonthDays(dateRangeTasks), [dateRangeTasks]);
10008
+ const [validationResult, setValidationResult] = (0, import_react16.useState)(null);
10009
+ const [cascadeOverrides, setCascadeOverrides] = (0, import_react16.useState)(/* @__PURE__ */ new Map());
10010
+ const gridWidth = (0, import_react16.useMemo)(
9647
10011
  () => Math.round(dateRange.length * dayWidth),
9648
10012
  [dateRange.length, dayWidth]
9649
10013
  );
9650
- const visibleTasks = (0, import_react15.useMemo)(() => {
10014
+ const matrixWidth = (0, import_react16.useMemo)(
10015
+ () => matrixColumns.reduce((sum, column) => sum + column.width, 0),
10016
+ [matrixColumns]
10017
+ );
10018
+ const visibleTasks = (0, import_react16.useMemo)(() => {
9651
10019
  const parentMap = new Map(normalizedTasks.map((t) => [t.id, t.parentId]));
9652
10020
  function isAnyAncestorCollapsed(parentId) {
9653
10021
  let current = parentId;
@@ -9663,11 +10031,11 @@ function TaskGanttChartInner(props, ref) {
9663
10031
  }
9664
10032
  return tasks2;
9665
10033
  }, [normalizedTasks, collapsedParentIds, filterMode, taskFilter]);
9666
- const matchedTaskIds = (0, import_react15.useMemo)(() => {
10034
+ const matchedTaskIds = (0, import_react16.useMemo)(() => {
9667
10035
  if (!taskFilter) return /* @__PURE__ */ new Set();
9668
10036
  return new Set(visibleTasks.filter(taskFilter).map((task) => task.id));
9669
10037
  }, [visibleTasks, taskFilter]);
9670
- const taskListHighlightedTaskIds = (0, import_react15.useMemo)(() => {
10038
+ const taskListHighlightedTaskIds = (0, import_react16.useMemo)(() => {
9671
10039
  if (filterMode === "hide") {
9672
10040
  return /* @__PURE__ */ new Set();
9673
10041
  }
@@ -9678,24 +10046,25 @@ function TaskGanttChartInner(props, ref) {
9678
10046
  matchedTaskIds.forEach((taskId) => mergedHighlightedTaskIds.add(taskId));
9679
10047
  return mergedHighlightedTaskIds;
9680
10048
  }, [filterMode, highlightedTaskIds, matchedTaskIds]);
9681
- const totalGridHeight = (0, import_react15.useMemo)(
9682
- () => visibleTasks.length * rowHeight,
9683
- [visibleTasks.length, rowHeight]
10049
+ const totalGridHeight = (0, import_react16.useMemo)(
10050
+ () => visibleTasks.length * effectiveRowHeight,
10051
+ [effectiveRowHeight, visibleTasks.length]
9684
10052
  );
9685
10053
  const timelineHeaderHeight = headerHeight + 1;
9686
- const monthStart = (0, import_react15.useMemo)(() => {
10054
+ const monthStart = (0, import_react16.useMemo)(() => {
9687
10055
  if (dateRange.length === 0) {
9688
10056
  return new Date(Date.UTC((/* @__PURE__ */ new Date()).getUTCFullYear(), (/* @__PURE__ */ new Date()).getUTCMonth(), 1));
9689
10057
  }
9690
10058
  const firstDay = dateRange[0];
9691
10059
  return new Date(Date.UTC(firstDay.getUTCFullYear(), firstDay.getUTCMonth(), 1));
9692
10060
  }, [dateRange]);
9693
- const todayInRange = (0, import_react15.useMemo)(() => {
10061
+ const todayInRange = (0, import_react16.useMemo)(() => {
9694
10062
  const now = /* @__PURE__ */ new Date();
9695
10063
  const today = new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate()));
9696
10064
  return dateRange.some((day) => day.getTime() === today.getTime());
9697
10065
  }, [dateRange]);
9698
- (0, import_react15.useEffect)(() => {
10066
+ (0, import_react16.useEffect)(() => {
10067
+ if (isTableMatrixMode) return;
9699
10068
  const container = scrollContainerRef.current;
9700
10069
  if (!container || dateRange.length === 0) return;
9701
10070
  const now = /* @__PURE__ */ new Date();
@@ -9706,8 +10075,8 @@ function TaskGanttChartInner(props, ref) {
9706
10075
  const containerWidth = container.clientWidth;
9707
10076
  const scrollLeft = Math.round(todayOffset + dayWidth / 2 - containerWidth * 0.3);
9708
10077
  container.scrollLeft = Math.max(0, scrollLeft);
9709
- }, []);
9710
- (0, import_react15.useEffect)(() => {
10078
+ }, [dateRange, dayWidth, isTableMatrixMode]);
10079
+ (0, import_react16.useEffect)(() => {
9711
10080
  const container = scrollContainerRef.current;
9712
10081
  if (!container) return;
9713
10082
  const updateShadow = () => {
@@ -9719,7 +10088,8 @@ function TaskGanttChartInner(props, ref) {
9719
10088
  container.removeEventListener("scroll", updateShadow);
9720
10089
  };
9721
10090
  }, []);
9722
- const scrollToToday = (0, import_react15.useCallback)(() => {
10091
+ const scrollToToday = (0, import_react16.useCallback)(() => {
10092
+ if (isTableMatrixMode) return;
9723
10093
  const container = scrollContainerRef.current;
9724
10094
  if (!container || dateRange.length === 0) return;
9725
10095
  const now = /* @__PURE__ */ new Date();
@@ -9730,8 +10100,18 @@ function TaskGanttChartInner(props, ref) {
9730
10100
  const containerWidth = container.clientWidth;
9731
10101
  const scrollLeft = Math.round(todayOffset + dayWidth / 2 - containerWidth * 0.3);
9732
10102
  container.scrollTo({ left: Math.max(0, scrollLeft), behavior: "smooth" });
9733
- }, [dateRange, dayWidth]);
9734
- const scrollToTask = (0, import_react15.useCallback)((taskId) => {
10103
+ }, [dateRange, dayWidth, isTableMatrixMode]);
10104
+ const scrollToTask = (0, import_react16.useCallback)((taskId) => {
10105
+ if (isTableMatrixMode) {
10106
+ const container2 = scrollContainerRef.current;
10107
+ if (!container2) return;
10108
+ const rowIndex = visibleTasks.findIndex((visibleTask) => visibleTask.id === taskId);
10109
+ if (rowIndex === -1) return;
10110
+ const paddedRowIndex = Math.max(0, rowIndex - SCROLL_TO_ROW_CONTEXT_ROWS);
10111
+ container2.scrollTo({ top: Math.max(0, effectiveRowHeight * paddedRowIndex), behavior: "smooth" });
10112
+ setSelectedTaskId(taskId);
10113
+ return;
10114
+ }
9735
10115
  const container = scrollContainerRef.current;
9736
10116
  if (!container || dateRange.length === 0) return;
9737
10117
  const task = tasks.find((t) => t.id === taskId);
@@ -9747,8 +10127,8 @@ function TaskGanttChartInner(props, ref) {
9747
10127
  const taskOffset = taskIndex * dayWidth;
9748
10128
  const scrollLeft = Math.round(taskOffset - dayWidth * 2);
9749
10129
  container.scrollTo({ left: Math.max(0, scrollLeft), behavior: "smooth" });
9750
- }, [tasks, dateRange, dayWidth]);
9751
- const scrollToRow = (0, import_react15.useCallback)((taskId, options = {}) => {
10130
+ }, [dateRange, dayWidth, effectiveRowHeight, isTableMatrixMode, tasks, visibleTasks]);
10131
+ const scrollToRow = (0, import_react16.useCallback)((taskId, options = {}) => {
9752
10132
  const container = scrollContainerRef.current;
9753
10133
  if (!container) return;
9754
10134
  const task = tasks.find((t) => t.id === taskId);
@@ -9756,7 +10136,7 @@ function TaskGanttChartInner(props, ref) {
9756
10136
  const rowIndex = visibleTasks.findIndex((visibleTask) => visibleTask.id === task.id);
9757
10137
  if (rowIndex === -1) return;
9758
10138
  const paddedRowIndex = Math.max(0, rowIndex - SCROLL_TO_ROW_CONTEXT_ROWS);
9759
- const scrollTop = Math.max(0, rowHeight * paddedRowIndex);
10139
+ const scrollTop = Math.max(0, effectiveRowHeight * paddedRowIndex);
9760
10140
  const {
9761
10141
  select = true,
9762
10142
  behavior = "smooth",
@@ -9776,21 +10156,21 @@ function TaskGanttChartInner(props, ref) {
9776
10156
  }
9777
10157
  }
9778
10158
  container.scrollTo({ top: scrollTop, behavior });
9779
- }, [tasks, visibleTasks, rowHeight]);
9780
- const [dragGuideLines, setDragGuideLines] = (0, import_react15.useState)(null);
9781
- const [draggedTaskOverride, setDraggedTaskOverride] = (0, import_react15.useState)(null);
9782
- const [previewTasksById, setPreviewTasksById] = (0, import_react15.useState)(/* @__PURE__ */ new Map());
9783
- (0, import_react15.useEffect)(() => {
10159
+ }, [effectiveRowHeight, tasks, visibleTasks]);
10160
+ const [dragGuideLines, setDragGuideLines] = (0, import_react16.useState)(null);
10161
+ const [draggedTaskOverride, setDraggedTaskOverride] = (0, import_react16.useState)(null);
10162
+ const [previewTasksById, setPreviewTasksById] = (0, import_react16.useState)(/* @__PURE__ */ new Map());
10163
+ (0, import_react16.useEffect)(() => {
9784
10164
  const result = validateDependencies(tasks);
9785
10165
  setValidationResult(result);
9786
10166
  onValidateDependencies?.(result);
9787
10167
  }, [tasks, onValidateDependencies]);
9788
- (0, import_react15.useEffect)(() => () => {
10168
+ (0, import_react16.useEffect)(() => () => {
9789
10169
  if (clearSelectedTaskTimeoutRef.current !== null) {
9790
10170
  window.clearTimeout(clearSelectedTaskTimeoutRef.current);
9791
10171
  }
9792
10172
  }, []);
9793
- const handleTaskChange = (0, import_react15.useCallback)((updatedTasks) => {
10173
+ const handleTaskChange = (0, import_react16.useCallback)((updatedTasks) => {
9794
10174
  const updatedTask = updatedTasks[0];
9795
10175
  if (!updatedTask) return;
9796
10176
  const originalTask = tasks.find((t) => t.id === updatedTask.id);
@@ -9836,7 +10216,7 @@ function TaskGanttChartInner(props, ref) {
9836
10216
  const cascadedTasks = disableConstraints ? [updatedTask] : universalCascade(updatedTask, newStart, newEnd, sourceTasks, businessDays, isCustomWeekend);
9837
10217
  onTasksChange?.(cascadedTasks);
9838
10218
  }, [tasks, onTasksChange, disableConstraints, editingTaskId, businessDays, isCustomWeekend]);
9839
- const handleDelete = (0, import_react15.useCallback)((taskId) => {
10219
+ const handleDelete = (0, import_react16.useCallback)((taskId) => {
9840
10220
  const toDelete = /* @__PURE__ */ new Set([taskId]);
9841
10221
  function collectDescendants(parentId) {
9842
10222
  const children = getChildren(parentId, tasks);
@@ -9861,10 +10241,10 @@ function TaskGanttChartInner(props, ref) {
9861
10241
  }
9862
10242
  toDelete.forEach((id) => onDelete?.(id));
9863
10243
  }, [tasks, onTasksChange, onDelete]);
9864
- const handleInsertAfter = (0, import_react15.useCallback)((taskId, newTask) => {
10244
+ const handleInsertAfter = (0, import_react16.useCallback)((taskId, newTask) => {
9865
10245
  onInsertAfter?.(taskId, newTask);
9866
10246
  }, [onInsertAfter]);
9867
- const handleReorder = (0, import_react15.useCallback)((reorderedTasks, movedTaskId, inferredParentId) => {
10247
+ const handleReorder = (0, import_react16.useCallback)((reorderedTasks, movedTaskId, inferredParentId) => {
9868
10248
  let updated = reorderedTasks;
9869
10249
  if (movedTaskId) {
9870
10250
  updated = updated.map((t) => {
@@ -9881,7 +10261,7 @@ function TaskGanttChartInner(props, ref) {
9881
10261
  }
9882
10262
  onTasksChange?.(normalized);
9883
10263
  }, [onTasksChange, onReorder]);
9884
- const dependencyOverrides = (0, import_react15.useMemo)(() => {
10264
+ const dependencyOverrides = (0, import_react16.useMemo)(() => {
9885
10265
  const map = new Map(cascadeOverrides);
9886
10266
  if (draggedTaskOverride) {
9887
10267
  map.set(draggedTaskOverride.taskId, {
@@ -9891,32 +10271,32 @@ function TaskGanttChartInner(props, ref) {
9891
10271
  }
9892
10272
  return map;
9893
10273
  }, [cascadeOverrides, draggedTaskOverride]);
9894
- const handleCascadeProgress = (0, import_react15.useCallback)((overrides, previewTasks = []) => {
10274
+ const handleCascadeProgress = (0, import_react16.useCallback)((overrides, previewTasks = []) => {
9895
10275
  setCascadeOverrides(new Map(overrides));
9896
10276
  setPreviewTasksById(new Map(previewTasks.map((task) => [task.id, task])));
9897
10277
  }, []);
9898
- const previewNormalizedTasks = (0, import_react15.useMemo)(() => {
10278
+ const previewNormalizedTasks = (0, import_react16.useMemo)(() => {
9899
10279
  if (previewTasksById.size === 0) return normalizedTasks;
9900
10280
  return normalizedTasks.map((task) => previewTasksById.get(task.id) ?? task);
9901
10281
  }, [normalizedTasks, previewTasksById]);
9902
- const previewVisibleTasks = (0, import_react15.useMemo)(() => {
10282
+ const previewVisibleTasks = (0, import_react16.useMemo)(() => {
9903
10283
  if (previewTasksById.size === 0) return visibleTasks;
9904
10284
  return visibleTasks.map((task) => previewTasksById.get(task.id) ?? task);
9905
10285
  }, [visibleTasks, previewTasksById]);
9906
- const handleCascade = (0, import_react15.useCallback)((cascadedTasks) => {
10286
+ const handleCascade = (0, import_react16.useCallback)((cascadedTasks) => {
9907
10287
  onTasksChange?.(cascadedTasks);
9908
10288
  }, [tasks, onTasksChange]);
9909
- const handleTaskSelect = (0, import_react15.useCallback)((taskId) => {
10289
+ const handleTaskSelect = (0, import_react16.useCallback)((taskId) => {
9910
10290
  setSelectedTaskId(taskId);
9911
10291
  }, []);
9912
- const hoveredRowElementsRef = (0, import_react15.useRef)([]);
9913
- const clearHoveredRows = (0, import_react15.useCallback)(() => {
10292
+ const hoveredRowElementsRef = (0, import_react16.useRef)([]);
10293
+ const clearHoveredRows = (0, import_react16.useCallback)(() => {
9914
10294
  for (const element of hoveredRowElementsRef.current) {
9915
- element.classList.remove("gantt-tl-row-hovered", "gantt-tr-row-hovered");
10295
+ element.classList.remove("gantt-tl-row-hovered", "gantt-tr-row-hovered", "gantt-mx-row-hovered");
9916
10296
  }
9917
10297
  hoveredRowElementsRef.current = [];
9918
10298
  }, []);
9919
- const applyHoveredRows = (0, import_react15.useCallback)((taskId) => {
10299
+ const applyHoveredRows = (0, import_react16.useCallback)((taskId) => {
9920
10300
  const root = scrollContentRef.current;
9921
10301
  if (!root) return;
9922
10302
  clearHoveredRows();
@@ -9930,10 +10310,13 @@ function TaskGanttChartInner(props, ref) {
9930
10310
  if (element.classList.contains("gantt-tr-row")) {
9931
10311
  element.classList.add("gantt-tr-row-hovered");
9932
10312
  }
10313
+ if (element.classList.contains("gantt-mx-row")) {
10314
+ element.classList.add("gantt-mx-row-hovered");
10315
+ }
9933
10316
  }
9934
10317
  hoveredRowElementsRef.current = nextHoveredRows;
9935
10318
  }, [clearHoveredRows]);
9936
- const handleSharedRowHover = (0, import_react15.useCallback)((event) => {
10319
+ const handleSharedRowHover = (0, import_react16.useCallback)((event) => {
9937
10320
  const target = event.target;
9938
10321
  const row = target.closest("[data-gantt-task-row-id]");
9939
10322
  const taskId = row?.dataset.ganttTaskRowId;
@@ -9943,7 +10326,7 @@ function TaskGanttChartInner(props, ref) {
9943
10326
  }
9944
10327
  applyHoveredRows(taskId);
9945
10328
  }, [applyHoveredRows]);
9946
- const handleToggleCollapse = externalOnToggleCollapse ?? (0, import_react15.useCallback)((parentId) => {
10329
+ const handleToggleCollapse = externalOnToggleCollapse ?? (0, import_react16.useCallback)((parentId) => {
9947
10330
  setInternalCollapsedParentIds((prev) => {
9948
10331
  const next = new Set(prev);
9949
10332
  if (next.has(parentId)) {
@@ -9954,20 +10337,20 @@ function TaskGanttChartInner(props, ref) {
9954
10337
  return next;
9955
10338
  });
9956
10339
  }, []);
9957
- const allParentIds = (0, import_react15.useMemo)(() => {
10340
+ const allParentIds = (0, import_react16.useMemo)(() => {
9958
10341
  return new Set(
9959
10342
  normalizedTasks.filter((t) => isTaskParent(t.id, normalizedTasks)).map((t) => t.id)
9960
10343
  );
9961
10344
  }, [normalizedTasks]);
9962
- const handleCollapseAll = (0, import_react15.useCallback)(() => {
10345
+ const handleCollapseAll = (0, import_react16.useCallback)(() => {
9963
10346
  if (externalCollapsedParentIds) return;
9964
10347
  setInternalCollapsedParentIds(allParentIds);
9965
10348
  }, [allParentIds, externalCollapsedParentIds]);
9966
- const handleExpandAll = (0, import_react15.useCallback)(() => {
10349
+ const handleExpandAll = (0, import_react16.useCallback)(() => {
9967
10350
  if (externalCollapsedParentIds) return;
9968
10351
  setInternalCollapsedParentIds(/* @__PURE__ */ new Set());
9969
10352
  }, [externalCollapsedParentIds]);
9970
- const exportToPdf = (0, import_react15.useCallback)(async (options) => {
10353
+ const exportToPdf = (0, import_react16.useCallback)(async (options) => {
9971
10354
  const sourceContainer = containerRef.current;
9972
10355
  const sourceContent = scrollContentRef.current;
9973
10356
  if (!sourceContainer || !sourceContent || typeof window === "undefined" || typeof document === "undefined") {
@@ -10003,7 +10386,7 @@ function TaskGanttChartInner(props, ref) {
10003
10386
  orientation: options?.orientation
10004
10387
  });
10005
10388
  }, [showTaskList, showChart]);
10006
- (0, import_react15.useImperativeHandle)(
10389
+ (0, import_react16.useImperativeHandle)(
10007
10390
  ref,
10008
10391
  () => ({
10009
10392
  scrollToToday,
@@ -10026,7 +10409,7 @@ function TaskGanttChartInner(props, ref) {
10026
10409
  }
10027
10410
  return depth;
10028
10411
  }
10029
- const handlePromoteTask = (0, import_react15.useCallback)((taskId) => {
10412
+ const handlePromoteTask = (0, import_react16.useCallback)((taskId) => {
10030
10413
  if (onPromoteTask) {
10031
10414
  onPromoteTask(taskId);
10032
10415
  return;
@@ -10056,7 +10439,7 @@ function TaskGanttChartInner(props, ref) {
10056
10439
  ]);
10057
10440
  onTasksChange?.(reorderedTasks);
10058
10441
  }, [tasks, onTasksChange, onPromoteTask]);
10059
- const handleDemoteTask = (0, import_react15.useCallback)((taskId, newParentId) => {
10442
+ const handleDemoteTask = (0, import_react16.useCallback)((taskId, newParentId) => {
10060
10443
  if (onDemoteTask) {
10061
10444
  onDemoteTask(taskId, newParentId);
10062
10445
  return;
@@ -10097,7 +10480,7 @@ function TaskGanttChartInner(props, ref) {
10097
10480
  };
10098
10481
  onTasksChange?.([updatedDemotedTask]);
10099
10482
  }, [tasks, onTasksChange, onDemoteTask]);
10100
- const handleUngroupTask = (0, import_react15.useCallback)((taskId) => {
10483
+ const handleUngroupTask = (0, import_react16.useCallback)((taskId) => {
10101
10484
  if (onUngroupTask) {
10102
10485
  onUngroupTask(taskId);
10103
10486
  return;
@@ -10122,8 +10505,8 @@ function TaskGanttChartInner(props, ref) {
10122
10505
  onTasksChange?.(changedTasks);
10123
10506
  }
10124
10507
  }, [tasks, onTasksChange, onUngroupTask]);
10125
- const panStateRef = (0, import_react15.useRef)(null);
10126
- const handlePanStart = (0, import_react15.useCallback)((e) => {
10508
+ const panStateRef = (0, import_react16.useRef)(null);
10509
+ const handlePanStart = (0, import_react16.useCallback)((e) => {
10127
10510
  if (e.button !== 0) return;
10128
10511
  const target = e.target;
10129
10512
  if (target.closest("[data-taskbar]")) return;
@@ -10144,7 +10527,7 @@ function TaskGanttChartInner(props, ref) {
10144
10527
  container.style.cursor = "grabbing";
10145
10528
  e.preventDefault();
10146
10529
  }, []);
10147
- (0, import_react15.useEffect)(() => {
10530
+ (0, import_react16.useEffect)(() => {
10148
10531
  const handlePanMove = (e) => {
10149
10532
  const pan = panStateRef.current;
10150
10533
  if (!pan?.active) return;
@@ -10166,188 +10549,219 @@ function TaskGanttChartInner(props, ref) {
10166
10549
  window.removeEventListener("mouseup", handlePanEnd);
10167
10550
  };
10168
10551
  }, []);
10169
- return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { ref: containerRef, className: "gantt-container", children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
10552
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
10170
10553
  "div",
10171
10554
  {
10172
- ref: scrollContainerRef,
10173
- className: "gantt-scrollContainer",
10174
- style: { height: containerHeight ?? "auto", cursor: "grab" },
10175
- onMouseDown: handlePanStart,
10176
- children: /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
10555
+ ref: containerRef,
10556
+ className: isTableMatrixMode ? "gantt-container gantt-container-tableMatrix" : "gantt-container",
10557
+ children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
10177
10558
  "div",
10178
10559
  {
10179
- ref: scrollContentRef,
10180
- className: "gantt-scrollContent",
10181
- onMouseOver: handleSharedRowHover,
10182
- onMouseLeave: clearHoveredRows,
10183
- children: [
10184
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
10185
- TaskList,
10186
- {
10187
- tasks: normalizedTasks,
10188
- rowHeight,
10189
- headerHeight,
10190
- taskListWidth,
10191
- onTasksChange: handleTaskChange,
10192
- selectedTaskId: selectedTaskId ?? void 0,
10193
- onTaskSelect: handleTaskSelect,
10194
- show: showTaskList,
10195
- hasRightShadow: taskListHasRightShadow,
10196
- disableTaskNameEditing,
10197
- disableDependencyEditing,
10198
- onScrollToTask: scrollToTask,
10199
- onSelectedChipChange: setSelectedChip,
10200
- onAdd,
10201
- onDelete: handleDelete,
10202
- onInsertAfter: handleInsertAfter,
10203
- onReorder: handleReorder,
10204
- editingTaskId,
10205
- enableAddTask,
10206
- defaultTaskDurationDays,
10207
- collapsedParentIds,
10208
- onToggleCollapse: handleToggleCollapse,
10209
- onPromoteTask: onPromoteTask ?? handlePromoteTask,
10210
- onDemoteTask: onDemoteTask ?? handleDemoteTask,
10211
- onUngroupTask: onUngroupTask ?? handleUngroupTask,
10212
- highlightedTaskIds: taskListHighlightedTaskIds,
10213
- enableTaskMultiSelect,
10214
- selectedTaskIds,
10215
- onSelectedTaskIdsChange,
10216
- customDays,
10217
- isWeekend: isWeekend3,
10218
- businessDays,
10219
- filterMode,
10220
- filteredTaskIds: matchedTaskIds,
10221
- isFilterActive: !!taskFilter,
10222
- additionalColumns,
10223
- hiddenTaskListColumns,
10224
- taskListMenuCommands
10225
- }
10226
- ),
10227
- /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
10228
- "div",
10229
- {
10230
- className: showChart ? "gantt-chartSurface" : "gantt-chartSurface gantt-chart-hidden",
10231
- style: { minWidth: `${gridWidth}px`, flex: 1, display: showChart ? void 0 : "none" },
10232
- children: [
10233
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
10234
- "div",
10235
- {
10236
- className: "gantt-stickyHeader",
10237
- style: { width: `${gridWidth}px`, height: `${timelineHeaderHeight}px` },
10238
- children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
10239
- TimeScaleHeader_default,
10560
+ ref: scrollContainerRef,
10561
+ className: "gantt-scrollContainer",
10562
+ style: { height: containerHeight ?? "auto", cursor: "grab" },
10563
+ onMouseDown: handlePanStart,
10564
+ children: /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
10565
+ "div",
10566
+ {
10567
+ ref: scrollContentRef,
10568
+ className: "gantt-scrollContent",
10569
+ onMouseOver: handleSharedRowHover,
10570
+ onMouseLeave: clearHoveredRows,
10571
+ children: [
10572
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
10573
+ TaskList,
10574
+ {
10575
+ tasks: normalizedTasks,
10576
+ rowHeight: effectiveRowHeight,
10577
+ headerHeight,
10578
+ taskListWidth,
10579
+ onTasksChange: handleTaskChange,
10580
+ selectedTaskId: selectedTaskId ?? void 0,
10581
+ onTaskSelect: handleTaskSelect,
10582
+ show: showTaskList,
10583
+ hasRightShadow: taskListHasRightShadow,
10584
+ disableTaskNameEditing,
10585
+ disableDependencyEditing,
10586
+ onScrollToTask: scrollToTask,
10587
+ onSelectedChipChange: setSelectedChip,
10588
+ onAdd,
10589
+ onDelete: handleDelete,
10590
+ onInsertAfter: handleInsertAfter,
10591
+ onReorder: handleReorder,
10592
+ disableTaskDrag,
10593
+ editingTaskId,
10594
+ enableAddTask,
10595
+ defaultTaskDurationDays,
10596
+ collapsedParentIds,
10597
+ onToggleCollapse: handleToggleCollapse,
10598
+ onPromoteTask: onPromoteTask ?? handlePromoteTask,
10599
+ onDemoteTask: onDemoteTask ?? handleDemoteTask,
10600
+ onUngroupTask: onUngroupTask ?? handleUngroupTask,
10601
+ highlightedTaskIds: taskListHighlightedTaskIds,
10602
+ enableTaskMultiSelect,
10603
+ selectedTaskIds,
10604
+ onSelectedTaskIdsChange,
10605
+ customDays,
10606
+ isWeekend: isWeekend3,
10607
+ businessDays,
10608
+ filterMode,
10609
+ filteredTaskIds: matchedTaskIds,
10610
+ isFilterActive: !!taskFilter,
10611
+ additionalColumns,
10612
+ hiddenTaskListColumns,
10613
+ taskListMenuCommands,
10614
+ hideTaskListRowActions,
10615
+ rowContentLines: resolvedRowContentLines,
10616
+ taskDateChangeMode,
10617
+ onTaskDateChangeModeChange: handleTaskDateChangeMode
10618
+ }
10619
+ ),
10620
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
10621
+ "div",
10622
+ {
10623
+ className: isTableMatrixMode || showChart ? "gantt-chartSurface" : "gantt-chartSurface gantt-chart-hidden",
10624
+ style: {
10625
+ minWidth: `${isTableMatrixMode ? matrixWidth : gridWidth}px`,
10626
+ flex: 1,
10627
+ display: isTableMatrixMode || showChart ? void 0 : "none"
10628
+ },
10629
+ children: isTableMatrixMode ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
10630
+ TableMatrix,
10631
+ {
10632
+ tasks: visibleTasks,
10633
+ allTasks: normalizedTasks,
10634
+ columns: matrixColumns,
10635
+ columnGroups: matrixColumnGroups,
10636
+ rowHeight: effectiveRowHeight,
10637
+ headerHeight: timelineHeaderHeight,
10638
+ selectedTaskId,
10639
+ onTaskSelect: handleTaskSelect,
10640
+ onCellClick: onMatrixCellClick,
10641
+ highlightedTaskIds: taskListHighlightedTaskIds,
10642
+ filterMode
10643
+ }
10644
+ ) : /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_jsx_runtime17.Fragment, { children: [
10645
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
10646
+ "div",
10240
10647
  {
10241
- days: dateRange,
10242
- dayWidth,
10243
- headerHeight,
10244
- viewMode,
10245
- isCustomWeekend
10648
+ className: "gantt-stickyHeader",
10649
+ style: { width: `${gridWidth}px`, height: `${timelineHeaderHeight}px` },
10650
+ children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
10651
+ TimeScaleHeader_default,
10652
+ {
10653
+ days: dateRange,
10654
+ dayWidth,
10655
+ headerHeight,
10656
+ viewMode,
10657
+ isCustomWeekend
10658
+ }
10659
+ )
10246
10660
  }
10247
- )
10248
- }
10249
- ),
10250
- /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
10251
- "div",
10252
- {
10253
- className: "gantt-taskArea",
10254
- style: {
10255
- position: "relative",
10256
- width: `${gridWidth}px`
10257
- },
10258
- children: [
10259
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
10260
- GridBackground_default,
10261
- {
10262
- dateRange,
10263
- dayWidth,
10264
- totalHeight: totalGridHeight,
10265
- viewMode,
10266
- isCustomWeekend
10267
- }
10268
- ),
10269
- todayInRange && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(TodayIndicator_default, { monthStart, dayWidth }),
10270
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
10271
- DependencyLines_default,
10272
- {
10273
- tasks: previewVisibleTasks,
10274
- allTasks: previewNormalizedTasks,
10275
- collapsedParentIds,
10276
- monthStart,
10277
- dayWidth,
10278
- rowHeight,
10279
- gridWidth,
10280
- dragOverrides: dependencyOverrides,
10281
- selectedDep: selectedChip,
10282
- businessDays,
10283
- weekendPredicate: isCustomWeekend
10284
- }
10285
- ),
10286
- dragGuideLines && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
10287
- DragGuideLines_default,
10288
- {
10289
- isDragging: dragGuideLines.isDragging,
10290
- dragMode: dragGuideLines.dragMode,
10291
- left: dragGuideLines.left,
10292
- width: dragGuideLines.width,
10293
- totalHeight: totalGridHeight
10294
- }
10295
- ),
10296
- visibleTasks.map((task, index) => /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
10297
- TaskRow_default,
10298
- {
10299
- task,
10300
- monthStart,
10301
- dayWidth,
10302
- rowHeight,
10303
- onTasksChange: handleTaskChange,
10304
- onDragStateChange: (state) => {
10305
- if (state.isDragging) {
10306
- setDragGuideLines(state);
10307
- setDraggedTaskOverride({ taskId: task.id, left: state.left, width: state.width });
10308
- } else {
10309
- setDragGuideLines(null);
10310
- setDraggedTaskOverride(null);
10311
- }
10312
- },
10313
- rowIndex: index,
10314
- allTasks: normalizedTasks,
10315
- enableAutoSchedule: enableAutoSchedule ?? false,
10316
- disableConstraints: disableConstraints ?? false,
10317
- overridePosition: cascadeOverrides.get(task.id),
10318
- onCascadeProgress: handleCascadeProgress,
10319
- onCascade: handleCascade,
10320
- highlightExpiredTasks,
10321
- showBaseline,
10322
- isFilterMatch: filterMode === "highlight" ? matchedTaskIds.has(task.id) : false,
10323
- businessDays,
10324
- customDays,
10325
- isWeekend: isWeekend3,
10326
- disableTaskDrag,
10327
- viewMode
10661
+ ),
10662
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
10663
+ "div",
10664
+ {
10665
+ className: "gantt-taskArea",
10666
+ style: {
10667
+ position: "relative",
10668
+ width: `${gridWidth}px`
10328
10669
  },
10329
- task.id
10330
- ))
10331
- ]
10332
- }
10333
- )
10334
- ]
10335
- }
10336
- )
10337
- ]
10670
+ children: [
10671
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
10672
+ GridBackground_default,
10673
+ {
10674
+ dateRange,
10675
+ dayWidth,
10676
+ totalHeight: totalGridHeight,
10677
+ viewMode,
10678
+ isCustomWeekend
10679
+ }
10680
+ ),
10681
+ todayInRange && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(TodayIndicator_default, { monthStart, dayWidth }),
10682
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
10683
+ DependencyLines_default,
10684
+ {
10685
+ tasks: previewVisibleTasks,
10686
+ allTasks: previewNormalizedTasks,
10687
+ collapsedParentIds,
10688
+ monthStart,
10689
+ dayWidth,
10690
+ rowHeight: effectiveRowHeight,
10691
+ gridWidth,
10692
+ dragOverrides: dependencyOverrides,
10693
+ selectedDep: selectedChip,
10694
+ businessDays,
10695
+ weekendPredicate: isCustomWeekend
10696
+ }
10697
+ ),
10698
+ dragGuideLines && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
10699
+ DragGuideLines_default,
10700
+ {
10701
+ isDragging: dragGuideLines.isDragging,
10702
+ dragMode: dragGuideLines.dragMode,
10703
+ left: dragGuideLines.left,
10704
+ width: dragGuideLines.width,
10705
+ totalHeight: totalGridHeight
10706
+ }
10707
+ ),
10708
+ visibleTasks.map((task, index) => /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
10709
+ TaskRow_default,
10710
+ {
10711
+ task,
10712
+ monthStart,
10713
+ dayWidth,
10714
+ rowHeight: effectiveRowHeight,
10715
+ onTasksChange: handleTaskChange,
10716
+ onDragStateChange: (state) => {
10717
+ if (state.isDragging) {
10718
+ setDragGuideLines(state);
10719
+ setDraggedTaskOverride({ taskId: task.id, left: state.left, width: state.width });
10720
+ } else {
10721
+ setDragGuideLines(null);
10722
+ setDraggedTaskOverride(null);
10723
+ }
10724
+ },
10725
+ rowIndex: index,
10726
+ allTasks: normalizedTasks,
10727
+ enableAutoSchedule: enableAutoSchedule ?? false,
10728
+ disableConstraints: disableConstraints ?? false,
10729
+ overridePosition: cascadeOverrides.get(task.id),
10730
+ onCascadeProgress: handleCascadeProgress,
10731
+ onCascade: handleCascade,
10732
+ highlightExpiredTasks,
10733
+ showBaseline,
10734
+ isFilterMatch: filterMode === "highlight" ? matchedTaskIds.has(task.id) : false,
10735
+ businessDays,
10736
+ customDays,
10737
+ isWeekend: isWeekend3,
10738
+ disableTaskDrag,
10739
+ viewMode
10740
+ },
10741
+ task.id
10742
+ ))
10743
+ ]
10744
+ }
10745
+ )
10746
+ ] })
10747
+ }
10748
+ )
10749
+ ]
10750
+ }
10751
+ )
10338
10752
  }
10339
10753
  )
10340
10754
  }
10341
- ) });
10755
+ );
10342
10756
  }
10343
- var TaskGanttChart = (0, import_react15.forwardRef)(TaskGanttChartInner);
10344
- var GanttChart = (0, import_react15.forwardRef)(GanttChartInner);
10757
+ var TaskGanttChart = (0, import_react16.forwardRef)(TaskGanttChartInner);
10758
+ var GanttChart = (0, import_react16.forwardRef)(GanttChartInner);
10345
10759
  GanttChart.displayName = "GanttChart";
10346
10760
 
10347
10761
  // src/components/ui/Button.tsx
10348
- var import_react16 = __toESM(require("react"));
10349
- var import_jsx_runtime17 = require("react/jsx-runtime");
10350
- var Button = import_react16.default.forwardRef(
10762
+ var import_react17 = __toESM(require("react"));
10763
+ var import_jsx_runtime18 = require("react/jsx-runtime");
10764
+ var Button = import_react17.default.forwardRef(
10351
10765
  ({ className, variant = "default", size = "default", children, ...props }, ref) => {
10352
10766
  const classes = [
10353
10767
  "gantt-btn",
@@ -10355,7 +10769,7 @@ var Button = import_react16.default.forwardRef(
10355
10769
  size !== "default" ? `gantt-btn-${size}` : "",
10356
10770
  className || ""
10357
10771
  ].filter(Boolean).join(" ");
10358
- return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("button", { ref, className: classes, ...props, children });
10772
+ return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("button", { ref, className: classes, ...props, children });
10359
10773
  }
10360
10774
  );
10361
10775
  Button.displayName = "Button";
@@ -10407,6 +10821,7 @@ var nameContains = (substring, caseSensitive = false) => (task) => {
10407
10821
  PopoverContent,
10408
10822
  PopoverTrigger,
10409
10823
  ResourceTimelineChart,
10824
+ TableMatrix,
10410
10825
  TaskList,
10411
10826
  TaskRow,
10412
10827
  TimeScaleHeader,