gantt-lib 0.111.0 → 0.112.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/core/scheduling/index.d.mts +1 -1
- package/dist/core/scheduling/index.d.ts +1 -1
- package/dist/{index-CQSAjkhV.d.mts → index-D1s_8MxS.d.mts} +5 -1
- package/dist/{index-CQSAjkhV.d.ts → index-D1s_8MxS.d.ts} +5 -1
- package/dist/index.css.map +1 -1
- package/dist/index.d.mts +40 -4
- package/dist/index.d.ts +40 -4
- package/dist/index.js +958 -116
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +954 -113
- package/dist/index.mjs.map +1 -1
- package/dist/styles.css +225 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -41,6 +41,7 @@ __export(index_exports, {
|
|
|
41
41
|
GanttChart: () => GanttChart,
|
|
42
42
|
GridBackground: () => GridBackground_default,
|
|
43
43
|
Input: () => Input,
|
|
44
|
+
PlanFactMatrix: () => PlanFactMatrix,
|
|
44
45
|
Popover: () => Popover,
|
|
45
46
|
PopoverContent: () => PopoverContent,
|
|
46
47
|
PopoverTrigger: () => PopoverTrigger,
|
|
@@ -144,7 +145,7 @@ __export(index_exports, {
|
|
|
144
145
|
module.exports = __toCommonJS(index_exports);
|
|
145
146
|
|
|
146
147
|
// src/components/GanttChart/GanttChart.tsx
|
|
147
|
-
var
|
|
148
|
+
var import_react18 = require("react");
|
|
148
149
|
|
|
149
150
|
// src/core/scheduling/dateMath.ts
|
|
150
151
|
var DAY_MS = 24 * 60 * 60 * 1e3;
|
|
@@ -10564,6 +10565,824 @@ function TableMatrix({
|
|
|
10564
10565
|
] });
|
|
10565
10566
|
}
|
|
10566
10567
|
|
|
10568
|
+
// src/components/PlanFactMatrix/PlanFactMatrix.tsx
|
|
10569
|
+
var import_react17 = require("react");
|
|
10570
|
+
var import_jsx_runtime18 = require("react/jsx-runtime");
|
|
10571
|
+
function joinClasses2(...values) {
|
|
10572
|
+
return values.filter(Boolean).join(" ");
|
|
10573
|
+
}
|
|
10574
|
+
function formatDateKey(date) {
|
|
10575
|
+
const year = date.getUTCFullYear();
|
|
10576
|
+
const month = String(date.getUTCMonth() + 1).padStart(2, "0");
|
|
10577
|
+
const day = String(date.getUTCDate()).padStart(2, "0");
|
|
10578
|
+
return `${year}-${month}-${day}`;
|
|
10579
|
+
}
|
|
10580
|
+
function escapeAttributeValue(value) {
|
|
10581
|
+
return value.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
|
|
10582
|
+
}
|
|
10583
|
+
function parseNumberInput(value) {
|
|
10584
|
+
const trimmed = value.trim();
|
|
10585
|
+
if (trimmed === "") return void 0;
|
|
10586
|
+
const normalized = trimmed.replace(/\s+/g, "").replace(",", ".");
|
|
10587
|
+
const parsed = Number(normalized);
|
|
10588
|
+
if (!Number.isFinite(parsed) || parsed < 0) {
|
|
10589
|
+
return null;
|
|
10590
|
+
}
|
|
10591
|
+
return parsed;
|
|
10592
|
+
}
|
|
10593
|
+
function isDateWithinTask(task, date) {
|
|
10594
|
+
const start = parseUTCDate(task.startDate);
|
|
10595
|
+
const end = parseUTCDate(task.endDate);
|
|
10596
|
+
const dateMs = Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate());
|
|
10597
|
+
const startMs = Date.UTC(start.getUTCFullYear(), start.getUTCMonth(), start.getUTCDate());
|
|
10598
|
+
const endMs = Date.UTC(end.getUTCFullYear(), end.getUTCMonth(), end.getUTCDate());
|
|
10599
|
+
return startMs <= dateMs && dateMs <= endMs;
|
|
10600
|
+
}
|
|
10601
|
+
function formatValue(value) {
|
|
10602
|
+
if (value === void 0) return "";
|
|
10603
|
+
const absoluteValue = Math.abs(value);
|
|
10604
|
+
if (absoluteValue >= 1e6) {
|
|
10605
|
+
const compactValue = value / 1e6;
|
|
10606
|
+
const fractionDigits = absoluteValue >= 1e7 ? 0 : 1;
|
|
10607
|
+
return `${compactValue.toLocaleString("ru-RU", {
|
|
10608
|
+
minimumFractionDigits: 0,
|
|
10609
|
+
maximumFractionDigits: fractionDigits,
|
|
10610
|
+
useGrouping: false
|
|
10611
|
+
})}m`;
|
|
10612
|
+
}
|
|
10613
|
+
if (absoluteValue >= 1e4) {
|
|
10614
|
+
const compactValue = value / 1e3;
|
|
10615
|
+
const fractionDigits = absoluteValue >= 1e5 ? 0 : 1;
|
|
10616
|
+
return `${compactValue.toLocaleString("ru-RU", {
|
|
10617
|
+
minimumFractionDigits: 0,
|
|
10618
|
+
maximumFractionDigits: fractionDigits,
|
|
10619
|
+
useGrouping: false
|
|
10620
|
+
})}k`;
|
|
10621
|
+
}
|
|
10622
|
+
return Number.isInteger(value) ? String(value) : String(value).replace(".", ",");
|
|
10623
|
+
}
|
|
10624
|
+
function formatTooltipValue(value) {
|
|
10625
|
+
if (value === void 0) return "";
|
|
10626
|
+
return value.toLocaleString("ru-RU", { maximumFractionDigits: 20 });
|
|
10627
|
+
}
|
|
10628
|
+
function getSubrowIndex(taskIndex, kind) {
|
|
10629
|
+
return taskIndex * 2 + (kind === "plan" ? 0 : 1);
|
|
10630
|
+
}
|
|
10631
|
+
function findEditableTaskIndex(tasks, parentTaskIds, startIndex, step) {
|
|
10632
|
+
let index = startIndex;
|
|
10633
|
+
while (index >= 0 && index < tasks.length) {
|
|
10634
|
+
if (!parentTaskIds.has(tasks[index].id)) {
|
|
10635
|
+
return index;
|
|
10636
|
+
}
|
|
10637
|
+
index += step;
|
|
10638
|
+
}
|
|
10639
|
+
return null;
|
|
10640
|
+
}
|
|
10641
|
+
function PlanFactCellEditor({
|
|
10642
|
+
value,
|
|
10643
|
+
startValue,
|
|
10644
|
+
onCommit,
|
|
10645
|
+
onCommitRange,
|
|
10646
|
+
onCancel
|
|
10647
|
+
}) {
|
|
10648
|
+
const [draft, setDraft] = (0, import_react17.useState)(startValue ?? (value === void 0 ? "" : String(value)));
|
|
10649
|
+
const inputRef = (0, import_react17.useRef)(null);
|
|
10650
|
+
(0, import_react17.useEffect)(() => {
|
|
10651
|
+
inputRef.current?.focus();
|
|
10652
|
+
if (startValue === void 0) {
|
|
10653
|
+
inputRef.current?.select();
|
|
10654
|
+
} else {
|
|
10655
|
+
inputRef.current?.setSelectionRange(startValue.length, startValue.length);
|
|
10656
|
+
}
|
|
10657
|
+
}, [startValue]);
|
|
10658
|
+
const commit = (0, import_react17.useCallback)(() => {
|
|
10659
|
+
const parsed = parseNumberInput(draft);
|
|
10660
|
+
if (parsed === null) {
|
|
10661
|
+
onCancel();
|
|
10662
|
+
return;
|
|
10663
|
+
}
|
|
10664
|
+
onCommit(parsed);
|
|
10665
|
+
}, [draft, onCancel, onCommit]);
|
|
10666
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
10667
|
+
"input",
|
|
10668
|
+
{
|
|
10669
|
+
ref: inputRef,
|
|
10670
|
+
value: draft,
|
|
10671
|
+
className: "gantt-pf-editor",
|
|
10672
|
+
inputMode: "decimal",
|
|
10673
|
+
onChange: (event) => setDraft(event.target.value),
|
|
10674
|
+
onBlur: commit,
|
|
10675
|
+
onKeyDown: (event) => {
|
|
10676
|
+
if (event.key === "Escape") {
|
|
10677
|
+
event.preventDefault();
|
|
10678
|
+
onCancel();
|
|
10679
|
+
return;
|
|
10680
|
+
}
|
|
10681
|
+
if (event.key === "Enter") {
|
|
10682
|
+
event.preventDefault();
|
|
10683
|
+
if (event.ctrlKey || event.metaKey) {
|
|
10684
|
+
const parsed = parseNumberInput(draft);
|
|
10685
|
+
if (parsed === null) {
|
|
10686
|
+
onCancel();
|
|
10687
|
+
return;
|
|
10688
|
+
}
|
|
10689
|
+
onCommitRange?.(parsed);
|
|
10690
|
+
} else {
|
|
10691
|
+
commit();
|
|
10692
|
+
}
|
|
10693
|
+
}
|
|
10694
|
+
}
|
|
10695
|
+
}
|
|
10696
|
+
);
|
|
10697
|
+
}
|
|
10698
|
+
function PlanFactMatrix({
|
|
10699
|
+
tasks,
|
|
10700
|
+
allTasks = tasks,
|
|
10701
|
+
dateRange,
|
|
10702
|
+
dayWidth,
|
|
10703
|
+
rowHeight,
|
|
10704
|
+
headerHeight,
|
|
10705
|
+
bodyMinHeight,
|
|
10706
|
+
selectedTaskId,
|
|
10707
|
+
onTaskSelect,
|
|
10708
|
+
onTasksChange,
|
|
10709
|
+
onCellCommit,
|
|
10710
|
+
highlightedTaskIds,
|
|
10711
|
+
filterMode = "highlight"
|
|
10712
|
+
}) {
|
|
10713
|
+
const [activeCell, setActiveCell] = (0, import_react17.useState)(null);
|
|
10714
|
+
const [editingCell, setEditingCell] = (0, import_react17.useState)(null);
|
|
10715
|
+
const [selectedRange, setSelectedRange] = (0, import_react17.useState)(null);
|
|
10716
|
+
const [fillRange, setFillRange] = (0, import_react17.useState)(null);
|
|
10717
|
+
const [overflowTooltip, setOverflowTooltip] = (0, import_react17.useState)(null);
|
|
10718
|
+
const isSelectingRef = (0, import_react17.useRef)(false);
|
|
10719
|
+
const isFillDraggingRef = (0, import_react17.useRef)(false);
|
|
10720
|
+
const didDragSelectRef = (0, import_react17.useRef)(false);
|
|
10721
|
+
const rootRef = (0, import_react17.useRef)(null);
|
|
10722
|
+
const bodyRef = (0, import_react17.useRef)(null);
|
|
10723
|
+
const totalWidth = dateRange.length * dayWidth;
|
|
10724
|
+
const subrowHeight = rowHeight / 2;
|
|
10725
|
+
const parentTaskIds = (0, import_react17.useMemo)(() => {
|
|
10726
|
+
const ids = /* @__PURE__ */ new Set();
|
|
10727
|
+
for (const task of allTasks) {
|
|
10728
|
+
if (task.parentId) ids.add(task.parentId);
|
|
10729
|
+
}
|
|
10730
|
+
return ids;
|
|
10731
|
+
}, [allTasks]);
|
|
10732
|
+
const dateKeys = (0, import_react17.useMemo)(() => dateRange.map(formatDateKey), [dateRange]);
|
|
10733
|
+
const taskIndexById = (0, import_react17.useMemo)(() => {
|
|
10734
|
+
const indexById = /* @__PURE__ */ new Map();
|
|
10735
|
+
tasks.forEach((task, index) => indexById.set(task.id, index));
|
|
10736
|
+
return indexById;
|
|
10737
|
+
}, [tasks]);
|
|
10738
|
+
const focusCell = (0, import_react17.useCallback)((cell) => {
|
|
10739
|
+
window.requestAnimationFrame(() => {
|
|
10740
|
+
const selector = [
|
|
10741
|
+
`[data-plan-fact-task-id="${escapeAttributeValue(cell.taskId)}"]`,
|
|
10742
|
+
`[data-plan-fact-date-index="${cell.dateIndex}"]`,
|
|
10743
|
+
`[data-plan-fact-kind="${cell.kind}"]`
|
|
10744
|
+
].join("");
|
|
10745
|
+
bodyRef.current?.querySelector(selector)?.focus();
|
|
10746
|
+
});
|
|
10747
|
+
}, []);
|
|
10748
|
+
const clearSelection = (0, import_react17.useCallback)(() => {
|
|
10749
|
+
isSelectingRef.current = false;
|
|
10750
|
+
isFillDraggingRef.current = false;
|
|
10751
|
+
didDragSelectRef.current = false;
|
|
10752
|
+
setActiveCell(null);
|
|
10753
|
+
setEditingCell(null);
|
|
10754
|
+
setSelectedRange(null);
|
|
10755
|
+
setFillRange(null);
|
|
10756
|
+
setOverflowTooltip(null);
|
|
10757
|
+
}, []);
|
|
10758
|
+
const hideOverflowTooltip = (0, import_react17.useCallback)(() => {
|
|
10759
|
+
setOverflowTooltip(null);
|
|
10760
|
+
}, []);
|
|
10761
|
+
const showOverflowTooltip = (0, import_react17.useCallback)((target, label, force = false) => {
|
|
10762
|
+
if (!rootRef.current || !label) return;
|
|
10763
|
+
if (!force && target.scrollWidth <= target.clientWidth) {
|
|
10764
|
+
setOverflowTooltip(null);
|
|
10765
|
+
return;
|
|
10766
|
+
}
|
|
10767
|
+
const rootRect = rootRef.current.getBoundingClientRect();
|
|
10768
|
+
const targetRect = target.getBoundingClientRect();
|
|
10769
|
+
setOverflowTooltip({
|
|
10770
|
+
label,
|
|
10771
|
+
left: targetRect.left - rootRect.left + targetRect.width / 2,
|
|
10772
|
+
top: targetRect.top - rootRect.top
|
|
10773
|
+
});
|
|
10774
|
+
}, []);
|
|
10775
|
+
const selectSingleCell = (0, import_react17.useCallback)((cell) => {
|
|
10776
|
+
setActiveCell(cell);
|
|
10777
|
+
setSelectedRange({ anchor: cell, focus: cell });
|
|
10778
|
+
setFillRange(null);
|
|
10779
|
+
}, []);
|
|
10780
|
+
const getRangeBounds = (0, import_react17.useCallback)((range) => {
|
|
10781
|
+
const anchorTaskIndex = taskIndexById.get(range.anchor.taskId);
|
|
10782
|
+
const focusTaskIndex = taskIndexById.get(range.focus.taskId);
|
|
10783
|
+
if (anchorTaskIndex === void 0 || focusTaskIndex === void 0) {
|
|
10784
|
+
return null;
|
|
10785
|
+
}
|
|
10786
|
+
return {
|
|
10787
|
+
fromDateIndex: Math.min(range.anchor.dateIndex, range.focus.dateIndex),
|
|
10788
|
+
toDateIndex: Math.max(range.anchor.dateIndex, range.focus.dateIndex),
|
|
10789
|
+
fromSubrowIndex: Math.min(
|
|
10790
|
+
getSubrowIndex(anchorTaskIndex, range.anchor.kind),
|
|
10791
|
+
getSubrowIndex(focusTaskIndex, range.focus.kind)
|
|
10792
|
+
),
|
|
10793
|
+
toSubrowIndex: Math.max(
|
|
10794
|
+
getSubrowIndex(anchorTaskIndex, range.anchor.kind),
|
|
10795
|
+
getSubrowIndex(focusTaskIndex, range.focus.kind)
|
|
10796
|
+
)
|
|
10797
|
+
};
|
|
10798
|
+
}, [taskIndexById]);
|
|
10799
|
+
const getCellFromPosition = (0, import_react17.useCallback)((subrowIndex, dateIndex) => {
|
|
10800
|
+
const task = tasks[Math.floor(subrowIndex / 2)];
|
|
10801
|
+
if (!task) return null;
|
|
10802
|
+
return {
|
|
10803
|
+
taskId: task.id,
|
|
10804
|
+
dateIndex,
|
|
10805
|
+
kind: subrowIndex % 2 === 0 ? "plan" : "fact"
|
|
10806
|
+
};
|
|
10807
|
+
}, [tasks]);
|
|
10808
|
+
const isCellInRange = (0, import_react17.useCallback)((cell, range) => {
|
|
10809
|
+
const bounds = getRangeBounds(range);
|
|
10810
|
+
if (!bounds) return false;
|
|
10811
|
+
const cellTaskIndex = taskIndexById.get(cell.taskId);
|
|
10812
|
+
if (cellTaskIndex === void 0) {
|
|
10813
|
+
return false;
|
|
10814
|
+
}
|
|
10815
|
+
const cellSubrowIndex = getSubrowIndex(cellTaskIndex, cell.kind);
|
|
10816
|
+
return cell.dateIndex >= bounds.fromDateIndex && cell.dateIndex <= bounds.toDateIndex && cellSubrowIndex >= bounds.fromSubrowIndex && cellSubrowIndex <= bounds.toSubrowIndex;
|
|
10817
|
+
}, [getRangeBounds, taskIndexById]);
|
|
10818
|
+
const isCellInSelectedRange = (0, import_react17.useCallback)((cell) => {
|
|
10819
|
+
if (!selectedRange) return false;
|
|
10820
|
+
return isCellInRange(cell, fillRange ?? selectedRange);
|
|
10821
|
+
}, [fillRange, isCellInRange, selectedRange]);
|
|
10822
|
+
const getSelectedRangeEdgeClasses = (0, import_react17.useCallback)((cell) => {
|
|
10823
|
+
if (!selectedRange) return [];
|
|
10824
|
+
const range = fillRange ?? selectedRange;
|
|
10825
|
+
const bounds = getRangeBounds(range);
|
|
10826
|
+
const taskIndex = taskIndexById.get(cell.taskId);
|
|
10827
|
+
if (!bounds || taskIndex === void 0 || !isCellInRange(cell, range)) return [];
|
|
10828
|
+
const subrowIndex = getSubrowIndex(taskIndex, cell.kind);
|
|
10829
|
+
return [
|
|
10830
|
+
cell.dateIndex === bounds.fromDateIndex && "gantt-pf-cell-rangeLeft",
|
|
10831
|
+
cell.dateIndex === bounds.toDateIndex && "gantt-pf-cell-rangeRight",
|
|
10832
|
+
subrowIndex === bounds.fromSubrowIndex && "gantt-pf-cell-rangeTop",
|
|
10833
|
+
subrowIndex === bounds.toSubrowIndex && "gantt-pf-cell-rangeBottom"
|
|
10834
|
+
];
|
|
10835
|
+
}, [fillRange, getRangeBounds, isCellInRange, selectedRange, taskIndexById]);
|
|
10836
|
+
const isFillHandleCell = (0, import_react17.useCallback)((cell) => {
|
|
10837
|
+
if (!selectedRange) return false;
|
|
10838
|
+
const range = fillRange ?? selectedRange;
|
|
10839
|
+
const bounds = getRangeBounds(range);
|
|
10840
|
+
const taskIndex = taskIndexById.get(cell.taskId);
|
|
10841
|
+
if (!bounds || taskIndex === void 0 || !isCellInRange(cell, range)) return false;
|
|
10842
|
+
const subrowIndex = getSubrowIndex(taskIndex, cell.kind);
|
|
10843
|
+
return cell.dateIndex === bounds.toDateIndex && subrowIndex === bounds.toSubrowIndex;
|
|
10844
|
+
}, [fillRange, getRangeBounds, isCellInRange, selectedRange, taskIndexById]);
|
|
10845
|
+
const commitCell = (0, import_react17.useCallback)((task, dateIndex, kind, value) => {
|
|
10846
|
+
const dateKey = dateKeys[dateIndex];
|
|
10847
|
+
const source = kind === "plan" ? task.planByDate : task.factByDate;
|
|
10848
|
+
const nextValues = { ...source ?? {} };
|
|
10849
|
+
if (value === void 0) {
|
|
10850
|
+
delete nextValues[dateKey];
|
|
10851
|
+
} else {
|
|
10852
|
+
nextValues[dateKey] = value;
|
|
10853
|
+
}
|
|
10854
|
+
const changedTask = {
|
|
10855
|
+
...task,
|
|
10856
|
+
[kind === "plan" ? "planByDate" : "factByDate"]: nextValues
|
|
10857
|
+
};
|
|
10858
|
+
onTasksChange?.([changedTask]);
|
|
10859
|
+
onCellCommit?.({
|
|
10860
|
+
task,
|
|
10861
|
+
date: dateRange[dateIndex],
|
|
10862
|
+
dateKey,
|
|
10863
|
+
kind,
|
|
10864
|
+
value
|
|
10865
|
+
});
|
|
10866
|
+
}, [dateKeys, dateRange, onCellCommit, onTasksChange]);
|
|
10867
|
+
const clearSelectedCells = (0, import_react17.useCallback)(() => {
|
|
10868
|
+
if (!selectedRange) {
|
|
10869
|
+
if (!activeCell) return;
|
|
10870
|
+
const task = tasks.find((candidate) => candidate.id === activeCell.taskId);
|
|
10871
|
+
if (!task || parentTaskIds.has(task.id)) return;
|
|
10872
|
+
commitCell(task, activeCell.dateIndex, activeCell.kind, void 0);
|
|
10873
|
+
return;
|
|
10874
|
+
}
|
|
10875
|
+
const changedTasksById = /* @__PURE__ */ new Map();
|
|
10876
|
+
for (const task of tasks) {
|
|
10877
|
+
if (parentTaskIds.has(task.id)) continue;
|
|
10878
|
+
let nextPlanByDate = task.planByDate;
|
|
10879
|
+
let nextFactByDate = task.factByDate;
|
|
10880
|
+
let didChange = false;
|
|
10881
|
+
for (let dateIndex = 0; dateIndex < dateKeys.length; dateIndex += 1) {
|
|
10882
|
+
const dateKey = dateKeys[dateIndex];
|
|
10883
|
+
const planCell = { taskId: task.id, dateIndex, kind: "plan" };
|
|
10884
|
+
if (isCellInSelectedRange(planCell) && nextPlanByDate?.[dateKey] !== void 0) {
|
|
10885
|
+
nextPlanByDate = { ...nextPlanByDate ?? {} };
|
|
10886
|
+
delete nextPlanByDate[dateKey];
|
|
10887
|
+
didChange = true;
|
|
10888
|
+
}
|
|
10889
|
+
const factCell = { taskId: task.id, dateIndex, kind: "fact" };
|
|
10890
|
+
if (isCellInSelectedRange(factCell) && nextFactByDate?.[dateKey] !== void 0) {
|
|
10891
|
+
nextFactByDate = { ...nextFactByDate ?? {} };
|
|
10892
|
+
delete nextFactByDate[dateKey];
|
|
10893
|
+
didChange = true;
|
|
10894
|
+
}
|
|
10895
|
+
}
|
|
10896
|
+
if (didChange) {
|
|
10897
|
+
changedTasksById.set(task.id, {
|
|
10898
|
+
...task,
|
|
10899
|
+
...nextPlanByDate !== task.planByDate ? { planByDate: nextPlanByDate ?? {} } : {},
|
|
10900
|
+
...nextFactByDate !== task.factByDate ? { factByDate: nextFactByDate ?? {} } : {}
|
|
10901
|
+
});
|
|
10902
|
+
}
|
|
10903
|
+
}
|
|
10904
|
+
const changedTasks = Array.from(changedTasksById.values());
|
|
10905
|
+
if (changedTasks.length > 0) {
|
|
10906
|
+
onTasksChange?.(changedTasks);
|
|
10907
|
+
}
|
|
10908
|
+
}, [activeCell, commitCell, dateKeys, isCellInSelectedRange, onTasksChange, parentTaskIds, selectedRange, tasks]);
|
|
10909
|
+
const commitSelectedCells = (0, import_react17.useCallback)((value) => {
|
|
10910
|
+
if (!selectedRange) {
|
|
10911
|
+
if (!activeCell) return;
|
|
10912
|
+
const task = tasks.find((candidate) => candidate.id === activeCell.taskId);
|
|
10913
|
+
if (!task || parentTaskIds.has(task.id)) return;
|
|
10914
|
+
commitCell(task, activeCell.dateIndex, activeCell.kind, value);
|
|
10915
|
+
return;
|
|
10916
|
+
}
|
|
10917
|
+
const changedTasksById = /* @__PURE__ */ new Map();
|
|
10918
|
+
for (const task of tasks) {
|
|
10919
|
+
if (parentTaskIds.has(task.id)) continue;
|
|
10920
|
+
let nextPlanByDate = task.planByDate;
|
|
10921
|
+
let nextFactByDate = task.factByDate;
|
|
10922
|
+
let didChange = false;
|
|
10923
|
+
for (let dateIndex = 0; dateIndex < dateKeys.length; dateIndex += 1) {
|
|
10924
|
+
const dateKey = dateKeys[dateIndex];
|
|
10925
|
+
const planCell = { taskId: task.id, dateIndex, kind: "plan" };
|
|
10926
|
+
if (isCellInSelectedRange(planCell) && nextPlanByDate?.[dateKey] !== value) {
|
|
10927
|
+
nextPlanByDate = { ...nextPlanByDate ?? {} };
|
|
10928
|
+
if (value === void 0) {
|
|
10929
|
+
delete nextPlanByDate[dateKey];
|
|
10930
|
+
} else {
|
|
10931
|
+
nextPlanByDate[dateKey] = value;
|
|
10932
|
+
}
|
|
10933
|
+
didChange = true;
|
|
10934
|
+
}
|
|
10935
|
+
const factCell = { taskId: task.id, dateIndex, kind: "fact" };
|
|
10936
|
+
if (isCellInSelectedRange(factCell) && nextFactByDate?.[dateKey] !== value) {
|
|
10937
|
+
nextFactByDate = { ...nextFactByDate ?? {} };
|
|
10938
|
+
if (value === void 0) {
|
|
10939
|
+
delete nextFactByDate[dateKey];
|
|
10940
|
+
} else {
|
|
10941
|
+
nextFactByDate[dateKey] = value;
|
|
10942
|
+
}
|
|
10943
|
+
didChange = true;
|
|
10944
|
+
}
|
|
10945
|
+
}
|
|
10946
|
+
if (didChange) {
|
|
10947
|
+
changedTasksById.set(task.id, {
|
|
10948
|
+
...task,
|
|
10949
|
+
...nextPlanByDate !== task.planByDate ? { planByDate: nextPlanByDate ?? {} } : {},
|
|
10950
|
+
...nextFactByDate !== task.factByDate ? { factByDate: nextFactByDate ?? {} } : {}
|
|
10951
|
+
});
|
|
10952
|
+
}
|
|
10953
|
+
}
|
|
10954
|
+
const changedTasks = Array.from(changedTasksById.values());
|
|
10955
|
+
if (changedTasks.length > 0) {
|
|
10956
|
+
onTasksChange?.(changedTasks);
|
|
10957
|
+
}
|
|
10958
|
+
}, [activeCell, commitCell, dateKeys, isCellInSelectedRange, onTasksChange, parentTaskIds, selectedRange, tasks]);
|
|
10959
|
+
const getCellValue = (0, import_react17.useCallback)((cell) => {
|
|
10960
|
+
const task = tasks.find((candidate) => candidate.id === cell.taskId);
|
|
10961
|
+
if (!task) return void 0;
|
|
10962
|
+
const dateKey = dateKeys[cell.dateIndex];
|
|
10963
|
+
return cell.kind === "plan" ? task.planByDate?.[dateKey] : task.factByDate?.[dateKey];
|
|
10964
|
+
}, [dateKeys, tasks]);
|
|
10965
|
+
const applyFillRange = (0, import_react17.useCallback)(() => {
|
|
10966
|
+
if (!selectedRange || !fillRange) return;
|
|
10967
|
+
const sourceBounds = getRangeBounds(selectedRange);
|
|
10968
|
+
const targetBounds = getRangeBounds(fillRange);
|
|
10969
|
+
if (!sourceBounds || !targetBounds) return;
|
|
10970
|
+
const sourceDateSpan = sourceBounds.toDateIndex - sourceBounds.fromDateIndex + 1;
|
|
10971
|
+
const sourceSubrowSpan = sourceBounds.toSubrowIndex - sourceBounds.fromSubrowIndex + 1;
|
|
10972
|
+
const changedTasksById = /* @__PURE__ */ new Map();
|
|
10973
|
+
for (let subrowIndex = targetBounds.fromSubrowIndex; subrowIndex <= targetBounds.toSubrowIndex; subrowIndex += 1) {
|
|
10974
|
+
const targetCellForRow = getCellFromPosition(subrowIndex, targetBounds.fromDateIndex);
|
|
10975
|
+
if (!targetCellForRow || parentTaskIds.has(targetCellForRow.taskId)) continue;
|
|
10976
|
+
const originalTask = tasks.find((task) => task.id === targetCellForRow.taskId);
|
|
10977
|
+
if (!originalTask) continue;
|
|
10978
|
+
let changedTask = changedTasksById.get(originalTask.id) ?? originalTask;
|
|
10979
|
+
let nextPlanByDate = changedTask.planByDate;
|
|
10980
|
+
let nextFactByDate = changedTask.factByDate;
|
|
10981
|
+
let didChange = false;
|
|
10982
|
+
for (let dateIndex = targetBounds.fromDateIndex; dateIndex <= targetBounds.toDateIndex; dateIndex += 1) {
|
|
10983
|
+
const targetCell = getCellFromPosition(subrowIndex, dateIndex);
|
|
10984
|
+
if (!targetCell || isCellInRange(targetCell, selectedRange)) continue;
|
|
10985
|
+
const sourceSubrowIndex = sourceBounds.fromSubrowIndex + ((subrowIndex - sourceBounds.fromSubrowIndex) % sourceSubrowSpan + sourceSubrowSpan) % sourceSubrowSpan;
|
|
10986
|
+
const sourceDateIndex = sourceBounds.fromDateIndex + ((dateIndex - sourceBounds.fromDateIndex) % sourceDateSpan + sourceDateSpan) % sourceDateSpan;
|
|
10987
|
+
const sourceCell = getCellFromPosition(sourceSubrowIndex, sourceDateIndex);
|
|
10988
|
+
if (!sourceCell) continue;
|
|
10989
|
+
const nextValue = getCellValue(sourceCell);
|
|
10990
|
+
const dateKey = dateKeys[dateIndex];
|
|
10991
|
+
const currentValues = targetCell.kind === "plan" ? nextPlanByDate : nextFactByDate;
|
|
10992
|
+
if (currentValues?.[dateKey] === nextValue) continue;
|
|
10993
|
+
if (targetCell.kind === "plan") {
|
|
10994
|
+
nextPlanByDate = { ...nextPlanByDate ?? {} };
|
|
10995
|
+
if (nextValue === void 0) {
|
|
10996
|
+
delete nextPlanByDate[dateKey];
|
|
10997
|
+
} else {
|
|
10998
|
+
nextPlanByDate[dateKey] = nextValue;
|
|
10999
|
+
}
|
|
11000
|
+
} else {
|
|
11001
|
+
nextFactByDate = { ...nextFactByDate ?? {} };
|
|
11002
|
+
if (nextValue === void 0) {
|
|
11003
|
+
delete nextFactByDate[dateKey];
|
|
11004
|
+
} else {
|
|
11005
|
+
nextFactByDate[dateKey] = nextValue;
|
|
11006
|
+
}
|
|
11007
|
+
}
|
|
11008
|
+
didChange = true;
|
|
11009
|
+
}
|
|
11010
|
+
if (didChange) {
|
|
11011
|
+
changedTasksById.set(originalTask.id, {
|
|
11012
|
+
...changedTask,
|
|
11013
|
+
...nextPlanByDate !== changedTask.planByDate ? { planByDate: nextPlanByDate ?? {} } : {},
|
|
11014
|
+
...nextFactByDate !== changedTask.factByDate ? { factByDate: nextFactByDate ?? {} } : {}
|
|
11015
|
+
});
|
|
11016
|
+
}
|
|
11017
|
+
}
|
|
11018
|
+
const changedTasks = Array.from(changedTasksById.values());
|
|
11019
|
+
if (changedTasks.length > 0) {
|
|
11020
|
+
onTasksChange?.(changedTasks);
|
|
11021
|
+
}
|
|
11022
|
+
setSelectedRange(fillRange);
|
|
11023
|
+
setActiveCell(fillRange.anchor);
|
|
11024
|
+
setFillRange(null);
|
|
11025
|
+
}, [
|
|
11026
|
+
dateKeys,
|
|
11027
|
+
fillRange,
|
|
11028
|
+
getCellFromPosition,
|
|
11029
|
+
getCellValue,
|
|
11030
|
+
getRangeBounds,
|
|
11031
|
+
isCellInRange,
|
|
11032
|
+
onTasksChange,
|
|
11033
|
+
parentTaskIds,
|
|
11034
|
+
selectedRange,
|
|
11035
|
+
tasks
|
|
11036
|
+
]);
|
|
11037
|
+
const moveActiveCell = (0, import_react17.useCallback)((cell, direction) => {
|
|
11038
|
+
const taskIndex = tasks.findIndex((task) => task.id === cell.taskId);
|
|
11039
|
+
if (taskIndex < 0) return;
|
|
11040
|
+
let nextCell = { ...cell };
|
|
11041
|
+
if (direction === "left") {
|
|
11042
|
+
nextCell.dateIndex = Math.max(0, cell.dateIndex - 1);
|
|
11043
|
+
} else if (direction === "right") {
|
|
11044
|
+
nextCell.dateIndex = Math.min(dateRange.length - 1, cell.dateIndex + 1);
|
|
11045
|
+
} else if (direction === "up") {
|
|
11046
|
+
if (cell.kind === "fact") {
|
|
11047
|
+
nextCell.kind = "plan";
|
|
11048
|
+
} else {
|
|
11049
|
+
const previousEditableTaskIndex = findEditableTaskIndex(tasks, parentTaskIds, taskIndex - 1, -1);
|
|
11050
|
+
if (previousEditableTaskIndex === null) return;
|
|
11051
|
+
const previousTask = tasks[previousEditableTaskIndex];
|
|
11052
|
+
nextCell = { taskId: previousTask.id, dateIndex: cell.dateIndex, kind: "fact" };
|
|
11053
|
+
}
|
|
11054
|
+
} else if (direction === "down") {
|
|
11055
|
+
if (cell.kind === "plan") {
|
|
11056
|
+
nextCell.kind = "fact";
|
|
11057
|
+
} else {
|
|
11058
|
+
const nextEditableTaskIndex = findEditableTaskIndex(tasks, parentTaskIds, taskIndex + 1, 1);
|
|
11059
|
+
if (nextEditableTaskIndex === null) return;
|
|
11060
|
+
const nextTask = tasks[nextEditableTaskIndex];
|
|
11061
|
+
nextCell = { taskId: nextTask.id, dateIndex: cell.dateIndex, kind: "plan" };
|
|
11062
|
+
}
|
|
11063
|
+
}
|
|
11064
|
+
setActiveCell(nextCell);
|
|
11065
|
+
setSelectedRange({ anchor: nextCell, focus: nextCell });
|
|
11066
|
+
onTaskSelect?.(nextCell.taskId);
|
|
11067
|
+
focusCell(nextCell);
|
|
11068
|
+
}, [dateRange.length, focusCell, onTaskSelect, parentTaskIds, tasks]);
|
|
11069
|
+
const extendSelectedRange = (0, import_react17.useCallback)((cell, direction) => {
|
|
11070
|
+
const taskIndex = tasks.findIndex((task) => task.id === cell.taskId);
|
|
11071
|
+
if (taskIndex < 0) return;
|
|
11072
|
+
let nextCell = { ...cell };
|
|
11073
|
+
if (direction === "left") {
|
|
11074
|
+
nextCell.dateIndex = Math.max(0, cell.dateIndex - 1);
|
|
11075
|
+
} else if (direction === "right") {
|
|
11076
|
+
nextCell.dateIndex = Math.min(dateRange.length - 1, cell.dateIndex + 1);
|
|
11077
|
+
} else if (direction === "up") {
|
|
11078
|
+
if (cell.kind === "fact") {
|
|
11079
|
+
nextCell.kind = "plan";
|
|
11080
|
+
} else {
|
|
11081
|
+
const previousEditableTaskIndex = findEditableTaskIndex(tasks, parentTaskIds, taskIndex - 1, -1);
|
|
11082
|
+
if (previousEditableTaskIndex === null) return;
|
|
11083
|
+
const previousTask = tasks[previousEditableTaskIndex];
|
|
11084
|
+
nextCell = { taskId: previousTask.id, dateIndex: cell.dateIndex, kind: "fact" };
|
|
11085
|
+
}
|
|
11086
|
+
} else if (direction === "down") {
|
|
11087
|
+
if (cell.kind === "plan") {
|
|
11088
|
+
nextCell.kind = "fact";
|
|
11089
|
+
} else {
|
|
11090
|
+
const nextEditableTaskIndex = findEditableTaskIndex(tasks, parentTaskIds, taskIndex + 1, 1);
|
|
11091
|
+
if (nextEditableTaskIndex === null) return;
|
|
11092
|
+
const nextTask = tasks[nextEditableTaskIndex];
|
|
11093
|
+
nextCell = { taskId: nextTask.id, dateIndex: cell.dateIndex, kind: "plan" };
|
|
11094
|
+
}
|
|
11095
|
+
}
|
|
11096
|
+
setActiveCell((currentActiveCell) => currentActiveCell ?? cell);
|
|
11097
|
+
setFillRange(null);
|
|
11098
|
+
setSelectedRange((currentRange) => ({
|
|
11099
|
+
anchor: currentRange?.anchor ?? cell,
|
|
11100
|
+
focus: nextCell
|
|
11101
|
+
}));
|
|
11102
|
+
onTaskSelect?.(nextCell.taskId);
|
|
11103
|
+
focusCell(selectedRange?.anchor ?? cell);
|
|
11104
|
+
}, [dateRange.length, focusCell, onTaskSelect, parentTaskIds, selectedRange, tasks]);
|
|
11105
|
+
(0, import_react17.useEffect)(() => {
|
|
11106
|
+
const endSelection = () => {
|
|
11107
|
+
if (isFillDraggingRef.current) {
|
|
11108
|
+
isFillDraggingRef.current = false;
|
|
11109
|
+
applyFillRange();
|
|
11110
|
+
}
|
|
11111
|
+
isSelectingRef.current = false;
|
|
11112
|
+
};
|
|
11113
|
+
window.addEventListener("mouseup", endSelection);
|
|
11114
|
+
return () => {
|
|
11115
|
+
window.removeEventListener("mouseup", endSelection);
|
|
11116
|
+
};
|
|
11117
|
+
}, [applyFillRange]);
|
|
11118
|
+
(0, import_react17.useEffect)(() => {
|
|
11119
|
+
const handleKeyDown = (event) => {
|
|
11120
|
+
if (event.key !== "Escape") return;
|
|
11121
|
+
clearSelection();
|
|
11122
|
+
};
|
|
11123
|
+
const handleMouseDown = (event) => {
|
|
11124
|
+
const target = event.target;
|
|
11125
|
+
if (target instanceof Node && rootRef.current?.contains(target)) {
|
|
11126
|
+
return;
|
|
11127
|
+
}
|
|
11128
|
+
clearSelection();
|
|
11129
|
+
};
|
|
11130
|
+
window.addEventListener("keydown", handleKeyDown);
|
|
11131
|
+
document.addEventListener("mousedown", handleMouseDown);
|
|
11132
|
+
return () => {
|
|
11133
|
+
window.removeEventListener("keydown", handleKeyDown);
|
|
11134
|
+
document.removeEventListener("mousedown", handleMouseDown);
|
|
11135
|
+
};
|
|
11136
|
+
}, [clearSelection]);
|
|
11137
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
|
|
11138
|
+
"div",
|
|
11139
|
+
{
|
|
11140
|
+
ref: rootRef,
|
|
11141
|
+
className: "gantt-pf-root",
|
|
11142
|
+
style: {
|
|
11143
|
+
width: `${totalWidth}px`,
|
|
11144
|
+
["--gantt-pf-day-width"]: `${dayWidth}px`
|
|
11145
|
+
},
|
|
11146
|
+
children: [
|
|
11147
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "gantt-pf-header", style: { width: `${totalWidth}px`, height: `${headerHeight}px` }, children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
11148
|
+
TimeScaleHeader_default,
|
|
11149
|
+
{
|
|
11150
|
+
days: dateRange,
|
|
11151
|
+
dayWidth,
|
|
11152
|
+
headerHeight: headerHeight - 1,
|
|
11153
|
+
viewMode: "day"
|
|
11154
|
+
}
|
|
11155
|
+
) }),
|
|
11156
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
11157
|
+
"div",
|
|
11158
|
+
{
|
|
11159
|
+
ref: bodyRef,
|
|
11160
|
+
className: "gantt-pf-body",
|
|
11161
|
+
style: {
|
|
11162
|
+
height: `${tasks.length * rowHeight}px`,
|
|
11163
|
+
minHeight: bodyMinHeight,
|
|
11164
|
+
width: `${totalWidth}px`
|
|
11165
|
+
},
|
|
11166
|
+
children: tasks.map((task, rowIndex) => {
|
|
11167
|
+
const isParent = parentTaskIds.has(task.id);
|
|
11168
|
+
const isHighlighted = filterMode === "highlight" && !!highlightedTaskIds?.has(task.id);
|
|
11169
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
11170
|
+
"div",
|
|
11171
|
+
{
|
|
11172
|
+
"data-gantt-task-row-id": task.id,
|
|
11173
|
+
className: joinClasses2(
|
|
11174
|
+
"gantt-pf-row",
|
|
11175
|
+
isParent && "gantt-pf-row-parent",
|
|
11176
|
+
selectedTaskId === task.id && "gantt-pf-row-selected",
|
|
11177
|
+
isHighlighted && "gantt-pf-row-highlighted"
|
|
11178
|
+
),
|
|
11179
|
+
style: {
|
|
11180
|
+
top: `${rowIndex * rowHeight}px`,
|
|
11181
|
+
height: `${rowHeight}px`,
|
|
11182
|
+
gridTemplateColumns: `repeat(${dateRange.length}, ${dayWidth}px)`
|
|
11183
|
+
},
|
|
11184
|
+
onClick: () => onTaskSelect?.(task.id),
|
|
11185
|
+
children: dateRange.map((date, dateIndex) => {
|
|
11186
|
+
const dateKey = dateKeys[dateIndex];
|
|
11187
|
+
const planned = isDateWithinTask(task, date);
|
|
11188
|
+
return ["plan", "fact"].map((kind) => {
|
|
11189
|
+
const planValue = task.planByDate?.[dateKey];
|
|
11190
|
+
const factValue = task.factByDate?.[dateKey];
|
|
11191
|
+
const value = kind === "plan" ? planValue : factValue;
|
|
11192
|
+
const factStatus = factValue === void 0 || planValue === void 0 ? null : factValue >= planValue ? "success" : "warning";
|
|
11193
|
+
const isActive = activeCell?.taskId === task.id && activeCell.dateIndex === dateIndex && activeCell.kind === kind;
|
|
11194
|
+
const isEditing = editingCell?.taskId === task.id && editingCell.dateIndex === dateIndex && editingCell.kind === kind;
|
|
11195
|
+
const currentCell = { taskId: task.id, dateIndex, kind };
|
|
11196
|
+
const isSelected = !isParent && isCellInSelectedRange(currentCell);
|
|
11197
|
+
const showFillHandle = !isParent && !isEditing && isFillHandleCell(currentCell);
|
|
11198
|
+
const isRangeAnchor = !showFillHandle && !isParent && selectedRange?.anchor.taskId === task.id && selectedRange.anchor.dateIndex === dateIndex && selectedRange.anchor.kind === kind;
|
|
11199
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
|
|
11200
|
+
"div",
|
|
11201
|
+
{
|
|
11202
|
+
"data-plan-fact-task-id": task.id,
|
|
11203
|
+
"data-plan-fact-date-index": dateIndex,
|
|
11204
|
+
"data-plan-fact-kind": kind,
|
|
11205
|
+
className: joinClasses2(
|
|
11206
|
+
"gantt-pf-cell",
|
|
11207
|
+
`gantt-pf-cell-${kind}`,
|
|
11208
|
+
planned && kind === "plan" && !isParent && "gantt-pf-cell-planned",
|
|
11209
|
+
value !== void 0 && "gantt-pf-cell-hasValue",
|
|
11210
|
+
kind === "fact" && factStatus === "success" && "gantt-pf-cell-factSuccess",
|
|
11211
|
+
kind === "fact" && factStatus === "warning" && "gantt-pf-cell-factWarning",
|
|
11212
|
+
isSelected && "gantt-pf-cell-selected",
|
|
11213
|
+
...getSelectedRangeEdgeClasses(currentCell),
|
|
11214
|
+
isRangeAnchor && "gantt-pf-cell-rangeAnchor",
|
|
11215
|
+
isActive && "gantt-pf-cell-active",
|
|
11216
|
+
isEditing && "gantt-pf-cell-editing",
|
|
11217
|
+
isParent && "gantt-pf-cell-readonly"
|
|
11218
|
+
),
|
|
11219
|
+
style: {
|
|
11220
|
+
gridColumn: dateIndex + 1,
|
|
11221
|
+
gridRow: kind === "plan" ? 1 : 2,
|
|
11222
|
+
height: `${subrowHeight}px`
|
|
11223
|
+
},
|
|
11224
|
+
tabIndex: isParent ? -1 : 0,
|
|
11225
|
+
onMouseDown: (event) => {
|
|
11226
|
+
if (isParent) return;
|
|
11227
|
+
event.preventDefault();
|
|
11228
|
+
event.stopPropagation();
|
|
11229
|
+
didDragSelectRef.current = false;
|
|
11230
|
+
isSelectingRef.current = true;
|
|
11231
|
+
selectSingleCell(currentCell);
|
|
11232
|
+
onTaskSelect?.(task.id);
|
|
11233
|
+
event.currentTarget.focus();
|
|
11234
|
+
},
|
|
11235
|
+
onMouseEnter: () => {
|
|
11236
|
+
if (!isParent && isFillDraggingRef.current && selectedRange) {
|
|
11237
|
+
setFillRange({ anchor: selectedRange.anchor, focus: currentCell });
|
|
11238
|
+
setActiveCell(currentCell);
|
|
11239
|
+
onTaskSelect?.(task.id);
|
|
11240
|
+
return;
|
|
11241
|
+
}
|
|
11242
|
+
if (isParent || !isSelectingRef.current) return;
|
|
11243
|
+
didDragSelectRef.current = true;
|
|
11244
|
+
setSelectedRange((currentRange) => ({
|
|
11245
|
+
anchor: currentRange?.anchor ?? currentCell,
|
|
11246
|
+
focus: currentCell
|
|
11247
|
+
}));
|
|
11248
|
+
onTaskSelect?.(task.id);
|
|
11249
|
+
},
|
|
11250
|
+
onFocus: () => {
|
|
11251
|
+
if (isParent) return;
|
|
11252
|
+
setActiveCell({ taskId: task.id, dateIndex, kind });
|
|
11253
|
+
},
|
|
11254
|
+
onClick: (event) => {
|
|
11255
|
+
event.stopPropagation();
|
|
11256
|
+
if (didDragSelectRef.current) {
|
|
11257
|
+
didDragSelectRef.current = false;
|
|
11258
|
+
return;
|
|
11259
|
+
}
|
|
11260
|
+
onTaskSelect?.(task.id);
|
|
11261
|
+
if (isParent) return;
|
|
11262
|
+
selectSingleCell(currentCell);
|
|
11263
|
+
event.currentTarget.focus();
|
|
11264
|
+
},
|
|
11265
|
+
onDoubleClick: (event) => {
|
|
11266
|
+
event.stopPropagation();
|
|
11267
|
+
if (isParent) return;
|
|
11268
|
+
setEditingCell({ taskId: task.id, dateIndex, kind });
|
|
11269
|
+
},
|
|
11270
|
+
onKeyDown: (event) => {
|
|
11271
|
+
if (isParent || isEditing) return;
|
|
11272
|
+
if (event.key === "ArrowLeft" || event.key === "ArrowRight" || event.key === "ArrowUp" || event.key === "ArrowDown") {
|
|
11273
|
+
event.preventDefault();
|
|
11274
|
+
event.stopPropagation();
|
|
11275
|
+
const direction = event.key.replace("Arrow", "").toLowerCase();
|
|
11276
|
+
if (event.shiftKey) {
|
|
11277
|
+
extendSelectedRange(selectedRange?.focus ?? currentCell, direction);
|
|
11278
|
+
} else {
|
|
11279
|
+
moveActiveCell(currentCell, direction);
|
|
11280
|
+
}
|
|
11281
|
+
return;
|
|
11282
|
+
}
|
|
11283
|
+
if (event.key === "Enter" || event.key === "F2") {
|
|
11284
|
+
event.preventDefault();
|
|
11285
|
+
event.stopPropagation();
|
|
11286
|
+
setEditingCell(selectedRange?.anchor ?? currentCell);
|
|
11287
|
+
return;
|
|
11288
|
+
}
|
|
11289
|
+
if (event.key === "Backspace" || event.key === "Delete") {
|
|
11290
|
+
event.preventDefault();
|
|
11291
|
+
event.stopPropagation();
|
|
11292
|
+
clearSelectedCells();
|
|
11293
|
+
return;
|
|
11294
|
+
}
|
|
11295
|
+
if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) {
|
|
11296
|
+
event.preventDefault();
|
|
11297
|
+
event.stopPropagation();
|
|
11298
|
+
setEditingCell({ ...currentCell, startValue: event.key });
|
|
11299
|
+
}
|
|
11300
|
+
},
|
|
11301
|
+
children: [
|
|
11302
|
+
isEditing ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
11303
|
+
PlanFactCellEditor,
|
|
11304
|
+
{
|
|
11305
|
+
value,
|
|
11306
|
+
startValue: editingCell.startValue,
|
|
11307
|
+
onCommit: (nextValue) => {
|
|
11308
|
+
commitCell(task, dateIndex, kind, nextValue);
|
|
11309
|
+
setEditingCell(null);
|
|
11310
|
+
const nextActiveCell = { taskId: task.id, dateIndex, kind };
|
|
11311
|
+
selectSingleCell(nextActiveCell);
|
|
11312
|
+
focusCell(nextActiveCell);
|
|
11313
|
+
},
|
|
11314
|
+
onCommitRange: (nextValue) => {
|
|
11315
|
+
commitSelectedCells(nextValue);
|
|
11316
|
+
setEditingCell(null);
|
|
11317
|
+
const nextActiveCell = { taskId: task.id, dateIndex, kind };
|
|
11318
|
+
setActiveCell(nextActiveCell);
|
|
11319
|
+
focusCell(nextActiveCell);
|
|
11320
|
+
},
|
|
11321
|
+
onCancel: () => {
|
|
11322
|
+
setEditingCell(null);
|
|
11323
|
+
const nextActiveCell = { taskId: task.id, dateIndex, kind };
|
|
11324
|
+
setActiveCell(nextActiveCell);
|
|
11325
|
+
focusCell(nextActiveCell);
|
|
11326
|
+
}
|
|
11327
|
+
}
|
|
11328
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
11329
|
+
"span",
|
|
11330
|
+
{
|
|
11331
|
+
className: "gantt-pf-cellValue",
|
|
11332
|
+
onMouseEnter: (event) => {
|
|
11333
|
+
if (isParent || value === void 0) return;
|
|
11334
|
+
const compactValue = formatValue(value);
|
|
11335
|
+
const fullValue = formatTooltipValue(value);
|
|
11336
|
+
showOverflowTooltip(event.currentTarget, fullValue, compactValue !== fullValue);
|
|
11337
|
+
},
|
|
11338
|
+
onMouseLeave: hideOverflowTooltip,
|
|
11339
|
+
children: isParent ? "" : formatValue(value)
|
|
11340
|
+
}
|
|
11341
|
+
),
|
|
11342
|
+
showFillHandle && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
11343
|
+
"span",
|
|
11344
|
+
{
|
|
11345
|
+
className: "gantt-pf-fillHandle",
|
|
11346
|
+
"aria-hidden": "true",
|
|
11347
|
+
onMouseDown: (event) => {
|
|
11348
|
+
event.preventDefault();
|
|
11349
|
+
event.stopPropagation();
|
|
11350
|
+
isSelectingRef.current = false;
|
|
11351
|
+
isFillDraggingRef.current = true;
|
|
11352
|
+
setFillRange(selectedRange);
|
|
11353
|
+
}
|
|
11354
|
+
}
|
|
11355
|
+
)
|
|
11356
|
+
]
|
|
11357
|
+
},
|
|
11358
|
+
`${task.id}:${dateKey}:${kind}`
|
|
11359
|
+
);
|
|
11360
|
+
});
|
|
11361
|
+
})
|
|
11362
|
+
},
|
|
11363
|
+
task.id
|
|
11364
|
+
);
|
|
11365
|
+
})
|
|
11366
|
+
}
|
|
11367
|
+
),
|
|
11368
|
+
overflowTooltip && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
11369
|
+
"div",
|
|
11370
|
+
{
|
|
11371
|
+
className: "gantt-pf-overflowTooltip",
|
|
11372
|
+
role: "tooltip",
|
|
11373
|
+
"aria-hidden": "true",
|
|
11374
|
+
style: {
|
|
11375
|
+
left: `${overflowTooltip.left}px`,
|
|
11376
|
+
top: `${overflowTooltip.top}px`
|
|
11377
|
+
},
|
|
11378
|
+
children: overflowTooltip.label
|
|
11379
|
+
}
|
|
11380
|
+
)
|
|
11381
|
+
]
|
|
11382
|
+
}
|
|
11383
|
+
);
|
|
11384
|
+
}
|
|
11385
|
+
|
|
10567
11386
|
// src/components/GanttChart/print.ts
|
|
10568
11387
|
function getPrintDocumentTitle({
|
|
10569
11388
|
header,
|
|
@@ -10972,7 +11791,7 @@ function createTaskPreviewPositionStore() {
|
|
|
10972
11791
|
}
|
|
10973
11792
|
|
|
10974
11793
|
// src/components/GanttChart/GanttChart.tsx
|
|
10975
|
-
var
|
|
11794
|
+
var import_jsx_runtime19 = require("react/jsx-runtime");
|
|
10976
11795
|
var SCROLL_TO_ROW_CONTEXT_ROWS = 2;
|
|
10977
11796
|
var TASK_ROW_OVERSCAN = 8;
|
|
10978
11797
|
function arePositionMapsEqual(left, right) {
|
|
@@ -11011,9 +11830,9 @@ function arePreviewTaskMapsEqual(left, right) {
|
|
|
11011
11830
|
}
|
|
11012
11831
|
function GanttChartInner(props, ref) {
|
|
11013
11832
|
if (props.mode === "resource-planner") {
|
|
11014
|
-
return /* @__PURE__ */ (0,
|
|
11833
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(ResourceTimelineChart, { ...props });
|
|
11015
11834
|
}
|
|
11016
|
-
return /* @__PURE__ */ (0,
|
|
11835
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
11017
11836
|
TaskGanttChart,
|
|
11018
11837
|
{
|
|
11019
11838
|
...props,
|
|
@@ -11023,6 +11842,7 @@ function GanttChartInner(props, ref) {
|
|
|
11023
11842
|
}
|
|
11024
11843
|
function TaskGanttChartInner(props, ref) {
|
|
11025
11844
|
const isTableMatrixMode = props.mode === "table-matrix";
|
|
11845
|
+
const isPlanFactMode = props.mode === "plan-fact";
|
|
11026
11846
|
const {
|
|
11027
11847
|
tasks,
|
|
11028
11848
|
rowHeight = 40,
|
|
@@ -11072,47 +11892,48 @@ function TaskGanttChartInner(props, ref) {
|
|
|
11072
11892
|
onTaskDateChangeModeChange: externalOnTaskDateChangeModeChange
|
|
11073
11893
|
} = props;
|
|
11074
11894
|
const dayWidth = !isTableMatrixMode ? props.dayWidth ?? 40 : 40;
|
|
11075
|
-
const viewMode = !isTableMatrixMode ? props.viewMode ?? "day" : "day";
|
|
11076
|
-
const customDays = !isTableMatrixMode ? props.customDays : void 0;
|
|
11077
|
-
const isWeekend3 = !isTableMatrixMode ? props.isWeekend : void 0;
|
|
11078
|
-
const businessDays = !isTableMatrixMode ? props.businessDays ?? true : true;
|
|
11895
|
+
const viewMode = !isTableMatrixMode && !isPlanFactMode ? props.viewMode ?? "day" : "day";
|
|
11896
|
+
const customDays = !isTableMatrixMode && !isPlanFactMode ? props.customDays : void 0;
|
|
11897
|
+
const isWeekend3 = !isTableMatrixMode && !isPlanFactMode ? props.isWeekend : void 0;
|
|
11898
|
+
const businessDays = !isTableMatrixMode && !isPlanFactMode ? props.businessDays ?? true : true;
|
|
11079
11899
|
const matrixColumns = isTableMatrixMode ? props.matrixColumns : [];
|
|
11080
11900
|
const matrixColumnGroups = isTableMatrixMode ? props.matrixColumnGroups : void 0;
|
|
11081
11901
|
const onMatrixCellClick = isTableMatrixMode ? props.onMatrixCellClick : void 0;
|
|
11082
11902
|
const matrixDateOverlay = isTableMatrixMode ? props.matrixDateOverlay : void 0;
|
|
11083
|
-
const
|
|
11084
|
-
const
|
|
11085
|
-
const
|
|
11086
|
-
const
|
|
11087
|
-
const
|
|
11088
|
-
const
|
|
11089
|
-
const
|
|
11903
|
+
const onPlanFactCellCommit = isPlanFactMode ? props.onPlanFactCellCommit : void 0;
|
|
11904
|
+
const containerRef = (0, import_react18.useRef)(null);
|
|
11905
|
+
const scrollContainerRef = (0, import_react18.useRef)(null);
|
|
11906
|
+
const scrollContentRef = (0, import_react18.useRef)(null);
|
|
11907
|
+
const clearSelectedTaskTimeoutRef = (0, import_react18.useRef)(null);
|
|
11908
|
+
const hasAutoScrolledToTodayRef = (0, import_react18.useRef)(false);
|
|
11909
|
+
const previewPositionStoreRef = (0, import_react18.useRef)(null);
|
|
11910
|
+
const renderedTaskIdsRef = (0, import_react18.useRef)(/* @__PURE__ */ new Set());
|
|
11090
11911
|
if (previewPositionStoreRef.current === null) {
|
|
11091
11912
|
previewPositionStoreRef.current = createTaskPreviewPositionStore();
|
|
11092
11913
|
}
|
|
11093
11914
|
const previewPositionStore = previewPositionStoreRef.current;
|
|
11094
|
-
const [selectedTaskId, setSelectedTaskId] = (0,
|
|
11095
|
-
const [taskListHasRightShadow, setTaskListHasRightShadow] = (0,
|
|
11096
|
-
const [internalTaskDateChangeMode, setInternalTaskDateChangeMode] = (0,
|
|
11097
|
-
const [scrollViewport, setScrollViewport] = (0,
|
|
11098
|
-
const [selectedChip, setSelectedChip] = (0,
|
|
11099
|
-
const [activeTimelineTooltip, setActiveTimelineTooltip] = (0,
|
|
11100
|
-
const [internalCollapsedParentIds, setInternalCollapsedParentIds] = (0,
|
|
11915
|
+
const [selectedTaskId, setSelectedTaskId] = (0, import_react18.useState)(null);
|
|
11916
|
+
const [taskListHasRightShadow, setTaskListHasRightShadow] = (0, import_react18.useState)(false);
|
|
11917
|
+
const [internalTaskDateChangeMode, setInternalTaskDateChangeMode] = (0, import_react18.useState)("preserve-duration");
|
|
11918
|
+
const [scrollViewport, setScrollViewport] = (0, import_react18.useState)({ scrollTop: 0, viewportHeight: 0 });
|
|
11919
|
+
const [selectedChip, setSelectedChip] = (0, import_react18.useState)(null);
|
|
11920
|
+
const [activeTimelineTooltip, setActiveTimelineTooltip] = (0, import_react18.useState)(null);
|
|
11921
|
+
const [internalCollapsedParentIds, setInternalCollapsedParentIds] = (0, import_react18.useState)(/* @__PURE__ */ new Set());
|
|
11101
11922
|
const collapsedParentIds = externalCollapsedParentIds ?? internalCollapsedParentIds;
|
|
11102
|
-
const [editingTaskId, setEditingTaskId] = (0,
|
|
11923
|
+
const [editingTaskId, setEditingTaskId] = (0, import_react18.useState)(null);
|
|
11103
11924
|
const taskDateChangeMode = externalTaskDateChangeMode ?? internalTaskDateChangeMode;
|
|
11104
11925
|
const handleTaskDateChangeMode = externalOnTaskDateChangeModeChange ?? setInternalTaskDateChangeMode;
|
|
11105
|
-
const resolvedRowContentLines = Math.max(1, Math.floor(rowContentLines));
|
|
11106
|
-
const effectiveRowHeight = (0,
|
|
11926
|
+
const resolvedRowContentLines = isPlanFactMode ? Math.max(2, Math.floor(rowContentLines)) : Math.max(1, Math.floor(rowContentLines));
|
|
11927
|
+
const effectiveRowHeight = (0, import_react18.useMemo)(
|
|
11107
11928
|
() => Math.max(rowHeight, 10 + resolvedRowContentLines * 18),
|
|
11108
11929
|
[resolvedRowContentLines, rowHeight]
|
|
11109
11930
|
);
|
|
11110
|
-
const normalizedTasks = (0,
|
|
11111
|
-
const isCustomWeekend = (0,
|
|
11931
|
+
const normalizedTasks = (0, import_react18.useMemo)(() => normalizeHierarchyTasks(tasks), [tasks]);
|
|
11932
|
+
const isCustomWeekend = (0, import_react18.useMemo)(
|
|
11112
11933
|
() => createCustomDayPredicate({ customDays, isWeekend: isWeekend3 }),
|
|
11113
11934
|
[customDays, isWeekend3]
|
|
11114
11935
|
);
|
|
11115
|
-
const dateRangeTasks = (0,
|
|
11936
|
+
const dateRangeTasks = (0, import_react18.useMemo)(() => {
|
|
11116
11937
|
if (!showBaseline) {
|
|
11117
11938
|
return normalizedTasks;
|
|
11118
11939
|
}
|
|
@@ -11122,21 +11943,21 @@ function TaskGanttChartInner(props, ref) {
|
|
|
11122
11943
|
endDate: task.baselineEndDate && parseUTCDate(task.baselineEndDate).getTime() > parseUTCDate(task.endDate).getTime() ? task.baselineEndDate : task.endDate
|
|
11123
11944
|
}));
|
|
11124
11945
|
}, [normalizedTasks, showBaseline]);
|
|
11125
|
-
const dateRange = (0,
|
|
11126
|
-
const [validationResult, setValidationResult] = (0,
|
|
11127
|
-
const [cascadeOverrides, setCascadeOverrides] = (0,
|
|
11128
|
-
const gridWidth = (0,
|
|
11946
|
+
const dateRange = (0, import_react18.useMemo)(() => getMultiMonthDays(dateRangeTasks), [dateRangeTasks]);
|
|
11947
|
+
const [validationResult, setValidationResult] = (0, import_react18.useState)(null);
|
|
11948
|
+
const [cascadeOverrides, setCascadeOverrides] = (0, import_react18.useState)(/* @__PURE__ */ new Map());
|
|
11949
|
+
const gridWidth = (0, import_react18.useMemo)(
|
|
11129
11950
|
() => Math.round(dateRange.length * dayWidth),
|
|
11130
11951
|
[dateRange.length, dayWidth]
|
|
11131
11952
|
);
|
|
11132
|
-
const matrixWidth = (0,
|
|
11953
|
+
const matrixWidth = (0, import_react18.useMemo)(
|
|
11133
11954
|
() => matrixColumns.reduce((sum, column) => {
|
|
11134
11955
|
if (typeof column.width !== "number") return void 0;
|
|
11135
11956
|
return sum !== void 0 ? sum + column.width : void 0;
|
|
11136
11957
|
}, 0),
|
|
11137
11958
|
[matrixColumns]
|
|
11138
11959
|
);
|
|
11139
|
-
const visibleTasks = (0,
|
|
11960
|
+
const visibleTasks = (0, import_react18.useMemo)(() => {
|
|
11140
11961
|
const parentMap = new Map(normalizedTasks.map((t) => [t.id, t.parentId]));
|
|
11141
11962
|
function isAnyAncestorCollapsed(parentId) {
|
|
11142
11963
|
let current = parentId;
|
|
@@ -11152,11 +11973,11 @@ function TaskGanttChartInner(props, ref) {
|
|
|
11152
11973
|
}
|
|
11153
11974
|
return tasks2;
|
|
11154
11975
|
}, [normalizedTasks, collapsedParentIds, filterMode, taskFilter]);
|
|
11155
|
-
const matchedTaskIds = (0,
|
|
11976
|
+
const matchedTaskIds = (0, import_react18.useMemo)(() => {
|
|
11156
11977
|
if (!taskFilter) return /* @__PURE__ */ new Set();
|
|
11157
11978
|
return new Set(visibleTasks.filter(taskFilter).map((task) => task.id));
|
|
11158
11979
|
}, [visibleTasks, taskFilter]);
|
|
11159
|
-
const taskListHighlightedTaskIds = (0,
|
|
11980
|
+
const taskListHighlightedTaskIds = (0, import_react18.useMemo)(() => {
|
|
11160
11981
|
if (filterMode === "hide") {
|
|
11161
11982
|
return /* @__PURE__ */ new Set();
|
|
11162
11983
|
}
|
|
@@ -11167,33 +11988,33 @@ function TaskGanttChartInner(props, ref) {
|
|
|
11167
11988
|
matchedTaskIds.forEach((taskId) => mergedHighlightedTaskIds.add(taskId));
|
|
11168
11989
|
return mergedHighlightedTaskIds;
|
|
11169
11990
|
}, [filterMode, highlightedTaskIds, matchedTaskIds]);
|
|
11170
|
-
const totalGridHeight = (0,
|
|
11991
|
+
const totalGridHeight = (0, import_react18.useMemo)(
|
|
11171
11992
|
() => visibleTasks.length * effectiveRowHeight,
|
|
11172
11993
|
[effectiveRowHeight, visibleTasks.length]
|
|
11173
11994
|
);
|
|
11174
11995
|
const timelineHeaderHeight = headerHeight + 1;
|
|
11175
|
-
const tableBodyMinHeight = (0,
|
|
11176
|
-
if (!isTableMatrixMode || containerHeight === void 0) {
|
|
11996
|
+
const tableBodyMinHeight = (0, import_react18.useMemo)(() => {
|
|
11997
|
+
if (!isTableMatrixMode && !isPlanFactMode || containerHeight === void 0) {
|
|
11177
11998
|
return void 0;
|
|
11178
11999
|
}
|
|
11179
12000
|
if (typeof containerHeight === "number") {
|
|
11180
12001
|
return Math.max(0, containerHeight - timelineHeaderHeight);
|
|
11181
12002
|
}
|
|
11182
12003
|
return `calc(${containerHeight} - ${timelineHeaderHeight}px)`;
|
|
11183
|
-
}, [containerHeight, isTableMatrixMode, timelineHeaderHeight]);
|
|
11184
|
-
const monthStart = (0,
|
|
12004
|
+
}, [containerHeight, isPlanFactMode, isTableMatrixMode, timelineHeaderHeight]);
|
|
12005
|
+
const monthStart = (0, import_react18.useMemo)(() => {
|
|
11185
12006
|
if (dateRange.length === 0) {
|
|
11186
12007
|
return new Date(Date.UTC((/* @__PURE__ */ new Date()).getUTCFullYear(), (/* @__PURE__ */ new Date()).getUTCMonth(), 1));
|
|
11187
12008
|
}
|
|
11188
12009
|
const firstDay = dateRange[0];
|
|
11189
12010
|
return new Date(Date.UTC(firstDay.getUTCFullYear(), firstDay.getUTCMonth(), 1));
|
|
11190
12011
|
}, [dateRange]);
|
|
11191
|
-
const todayInRange = (0,
|
|
12012
|
+
const todayInRange = (0, import_react18.useMemo)(() => {
|
|
11192
12013
|
const now = /* @__PURE__ */ new Date();
|
|
11193
12014
|
const today = new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate()));
|
|
11194
12015
|
return dateRange.some((day) => day.getTime() === today.getTime());
|
|
11195
12016
|
}, [dateRange]);
|
|
11196
|
-
const visibleTimelineMarkers = (0,
|
|
12017
|
+
const visibleTimelineMarkers = (0, import_react18.useMemo)(() => {
|
|
11197
12018
|
if (isTableMatrixMode || !timelineMarkers || timelineMarkers.length === 0 || dateRange.length === 0) {
|
|
11198
12019
|
return [];
|
|
11199
12020
|
}
|
|
@@ -11204,7 +12025,7 @@ function TaskGanttChartInner(props, ref) {
|
|
|
11204
12025
|
return markerDate >= rangeStartMs && markerDate <= rangeEndMs;
|
|
11205
12026
|
});
|
|
11206
12027
|
}, [dateRange, isTableMatrixMode, timelineMarkers]);
|
|
11207
|
-
(0,
|
|
12028
|
+
(0, import_react18.useEffect)(() => {
|
|
11208
12029
|
if (isTableMatrixMode) return;
|
|
11209
12030
|
if (hasAutoScrolledToTodayRef.current) return;
|
|
11210
12031
|
const container = scrollContainerRef.current;
|
|
@@ -11219,7 +12040,7 @@ function TaskGanttChartInner(props, ref) {
|
|
|
11219
12040
|
container.scrollLeft = Math.max(0, scrollLeft);
|
|
11220
12041
|
hasAutoScrolledToTodayRef.current = true;
|
|
11221
12042
|
}, [dateRange, dayWidth, isTableMatrixMode]);
|
|
11222
|
-
(0,
|
|
12043
|
+
(0, import_react18.useEffect)(() => {
|
|
11223
12044
|
const container = scrollContainerRef.current;
|
|
11224
12045
|
if (!container) return;
|
|
11225
12046
|
let frameId = null;
|
|
@@ -11255,7 +12076,7 @@ function TaskGanttChartInner(props, ref) {
|
|
|
11255
12076
|
window.removeEventListener("resize", scheduleUpdate);
|
|
11256
12077
|
};
|
|
11257
12078
|
}, [timelineHeaderHeight]);
|
|
11258
|
-
const scrollToToday = (0,
|
|
12079
|
+
const scrollToToday = (0, import_react18.useCallback)(() => {
|
|
11259
12080
|
if (isTableMatrixMode) return;
|
|
11260
12081
|
const container = scrollContainerRef.current;
|
|
11261
12082
|
if (!container || dateRange.length === 0) return;
|
|
@@ -11268,7 +12089,7 @@ function TaskGanttChartInner(props, ref) {
|
|
|
11268
12089
|
const scrollLeft = Math.round(todayOffset + dayWidth / 2 - containerWidth * 0.3);
|
|
11269
12090
|
container.scrollTo({ left: Math.max(0, scrollLeft), behavior: "smooth" });
|
|
11270
12091
|
}, [dateRange, dayWidth, isTableMatrixMode]);
|
|
11271
|
-
const scrollToTask = (0,
|
|
12092
|
+
const scrollToTask = (0, import_react18.useCallback)((taskId) => {
|
|
11272
12093
|
if (isTableMatrixMode) {
|
|
11273
12094
|
const container2 = scrollContainerRef.current;
|
|
11274
12095
|
if (!container2) return;
|
|
@@ -11295,7 +12116,7 @@ function TaskGanttChartInner(props, ref) {
|
|
|
11295
12116
|
const scrollLeft = Math.round(taskOffset - dayWidth * 2);
|
|
11296
12117
|
container.scrollTo({ left: Math.max(0, scrollLeft), behavior: "smooth" });
|
|
11297
12118
|
}, [dateRange, dayWidth, effectiveRowHeight, isTableMatrixMode, tasks, visibleTasks]);
|
|
11298
|
-
const scrollToRow = (0,
|
|
12119
|
+
const scrollToRow = (0, import_react18.useCallback)((taskId, options = {}) => {
|
|
11299
12120
|
const container = scrollContainerRef.current;
|
|
11300
12121
|
if (!container) return;
|
|
11301
12122
|
const task = tasks.find((t) => t.id === taskId);
|
|
@@ -11324,21 +12145,21 @@ function TaskGanttChartInner(props, ref) {
|
|
|
11324
12145
|
}
|
|
11325
12146
|
container.scrollTo({ top: scrollTop, behavior });
|
|
11326
12147
|
}, [effectiveRowHeight, tasks, visibleTasks]);
|
|
11327
|
-
const [dragGuideLines, setDragGuideLines] = (0,
|
|
11328
|
-
const [draggedTaskOverride, setDraggedTaskOverride] = (0,
|
|
11329
|
-
const [previewTasksById, setPreviewTasksById] = (0,
|
|
11330
|
-
(0,
|
|
12148
|
+
const [dragGuideLines, setDragGuideLines] = (0, import_react18.useState)(null);
|
|
12149
|
+
const [draggedTaskOverride, setDraggedTaskOverride] = (0, import_react18.useState)(null);
|
|
12150
|
+
const [previewTasksById, setPreviewTasksById] = (0, import_react18.useState)(/* @__PURE__ */ new Map());
|
|
12151
|
+
(0, import_react18.useEffect)(() => {
|
|
11331
12152
|
const result = validateDependencies(tasks);
|
|
11332
12153
|
setValidationResult(result);
|
|
11333
12154
|
onValidateDependencies?.(result);
|
|
11334
12155
|
}, [tasks, onValidateDependencies]);
|
|
11335
|
-
(0,
|
|
12156
|
+
(0, import_react18.useEffect)(() => () => {
|
|
11336
12157
|
if (clearSelectedTaskTimeoutRef.current !== null) {
|
|
11337
12158
|
window.clearTimeout(clearSelectedTaskTimeoutRef.current);
|
|
11338
12159
|
}
|
|
11339
12160
|
previewPositionStore.clear();
|
|
11340
12161
|
}, [previewPositionStore]);
|
|
11341
|
-
const handleTaskChange = (0,
|
|
12162
|
+
const handleTaskChange = (0, import_react18.useCallback)((updatedTasks) => {
|
|
11342
12163
|
const updatedTask = updatedTasks[0];
|
|
11343
12164
|
if (!updatedTask) return;
|
|
11344
12165
|
const originalTask = tasks.find((t) => t.id === updatedTask.id);
|
|
@@ -11384,7 +12205,7 @@ function TaskGanttChartInner(props, ref) {
|
|
|
11384
12205
|
const cascadedTasks = disableConstraints ? [updatedTask] : universalCascade(updatedTask, newStart, newEnd, sourceTasks, businessDays, isCustomWeekend);
|
|
11385
12206
|
onTasksChange?.(cascadedTasks);
|
|
11386
12207
|
}, [tasks, onTasksChange, disableConstraints, editingTaskId, businessDays, isCustomWeekend]);
|
|
11387
|
-
const handleDelete = (0,
|
|
12208
|
+
const handleDelete = (0, import_react18.useCallback)((taskId) => {
|
|
11388
12209
|
const toDelete = /* @__PURE__ */ new Set([taskId]);
|
|
11389
12210
|
function collectDescendants(parentId) {
|
|
11390
12211
|
const children = getChildren(parentId, tasks);
|
|
@@ -11409,10 +12230,10 @@ function TaskGanttChartInner(props, ref) {
|
|
|
11409
12230
|
}
|
|
11410
12231
|
toDelete.forEach((id) => onDelete?.(id));
|
|
11411
12232
|
}, [tasks, onTasksChange, onDelete]);
|
|
11412
|
-
const handleInsertAfter = (0,
|
|
12233
|
+
const handleInsertAfter = (0, import_react18.useCallback)((taskId, newTask) => {
|
|
11413
12234
|
onInsertAfter?.(taskId, newTask);
|
|
11414
12235
|
}, [onInsertAfter]);
|
|
11415
|
-
const handleReorder = (0,
|
|
12236
|
+
const handleReorder = (0, import_react18.useCallback)((reorderedTasks, movedTaskId, inferredParentId) => {
|
|
11416
12237
|
let updated = reorderedTasks;
|
|
11417
12238
|
if (movedTaskId) {
|
|
11418
12239
|
updated = updated.map((t) => {
|
|
@@ -11429,7 +12250,7 @@ function TaskGanttChartInner(props, ref) {
|
|
|
11429
12250
|
}
|
|
11430
12251
|
onTasksChange?.(normalized);
|
|
11431
12252
|
}, [onTasksChange, onReorder]);
|
|
11432
|
-
const dependencyOverrides = (0,
|
|
12253
|
+
const dependencyOverrides = (0, import_react18.useMemo)(() => {
|
|
11433
12254
|
const map = new Map(cascadeOverrides);
|
|
11434
12255
|
if (draggedTaskOverride) {
|
|
11435
12256
|
map.set(draggedTaskOverride.taskId, {
|
|
@@ -11439,7 +12260,7 @@ function TaskGanttChartInner(props, ref) {
|
|
|
11439
12260
|
}
|
|
11440
12261
|
return map;
|
|
11441
12262
|
}, [cascadeOverrides, draggedTaskOverride]);
|
|
11442
|
-
const handleCascadeProgress = (0,
|
|
12263
|
+
const handleCascadeProgress = (0, import_react18.useCallback)((overrides, previewTasks = []) => {
|
|
11443
12264
|
previewPositionStore.setPositions(overrides);
|
|
11444
12265
|
const renderedTaskIds = renderedTaskIdsRef.current;
|
|
11445
12266
|
const renderedOverrides = /* @__PURE__ */ new Map();
|
|
@@ -11454,26 +12275,26 @@ function TaskGanttChartInner(props, ref) {
|
|
|
11454
12275
|
return arePreviewTaskMapsEqual(current, next) ? current : next;
|
|
11455
12276
|
});
|
|
11456
12277
|
}, [previewPositionStore]);
|
|
11457
|
-
const previewNormalizedTasks = (0,
|
|
12278
|
+
const previewNormalizedTasks = (0, import_react18.useMemo)(() => {
|
|
11458
12279
|
if (previewTasksById.size === 0) return normalizedTasks;
|
|
11459
12280
|
return normalizedTasks.map((task) => previewTasksById.get(task.id) ?? task);
|
|
11460
12281
|
}, [normalizedTasks, previewTasksById]);
|
|
11461
|
-
const previewVisibleTasks = (0,
|
|
12282
|
+
const previewVisibleTasks = (0, import_react18.useMemo)(() => {
|
|
11462
12283
|
if (previewTasksById.size === 0) return visibleTasks;
|
|
11463
12284
|
return visibleTasks.map((task) => previewTasksById.get(task.id) ?? task);
|
|
11464
12285
|
}, [visibleTasks, previewTasksById]);
|
|
11465
|
-
const visibleTaskIndexMap = (0,
|
|
12286
|
+
const visibleTaskIndexMap = (0, import_react18.useMemo)(
|
|
11466
12287
|
() => new Map(visibleTasks.map((task, index) => [task.id, index])),
|
|
11467
12288
|
[visibleTasks]
|
|
11468
12289
|
);
|
|
11469
|
-
const forcedRenderedTaskIds = (0,
|
|
12290
|
+
const forcedRenderedTaskIds = (0, import_react18.useMemo)(() => {
|
|
11470
12291
|
const ids = /* @__PURE__ */ new Set();
|
|
11471
12292
|
if (draggedTaskOverride) {
|
|
11472
12293
|
ids.add(draggedTaskOverride.taskId);
|
|
11473
12294
|
}
|
|
11474
12295
|
return ids;
|
|
11475
12296
|
}, [draggedTaskOverride]);
|
|
11476
|
-
const visibleTaskWindowIndices = (0,
|
|
12297
|
+
const visibleTaskWindowIndices = (0, import_react18.useMemo)(() => {
|
|
11477
12298
|
const totalTasks = visibleTasks.length;
|
|
11478
12299
|
if (totalTasks === 0) {
|
|
11479
12300
|
return [];
|
|
@@ -11499,35 +12320,35 @@ function TaskGanttChartInner(props, ref) {
|
|
|
11499
12320
|
}
|
|
11500
12321
|
return Array.from(indices).sort((left, right) => left - right);
|
|
11501
12322
|
}, [effectiveRowHeight, forcedRenderedTaskIds, scrollViewport, visibleTaskIndexMap, visibleTasks.length]);
|
|
11502
|
-
const renderedChartTasks = (0,
|
|
12323
|
+
const renderedChartTasks = (0, import_react18.useMemo)(
|
|
11503
12324
|
() => visibleTaskWindowIndices.map((index) => {
|
|
11504
12325
|
const task = previewVisibleTasks[index];
|
|
11505
12326
|
return task ? { index, task } : null;
|
|
11506
12327
|
}).filter((entry) => entry !== null),
|
|
11507
12328
|
[previewVisibleTasks, visibleTaskWindowIndices]
|
|
11508
12329
|
);
|
|
11509
|
-
const renderedDependencyTasks = (0,
|
|
12330
|
+
const renderedDependencyTasks = (0, import_react18.useMemo)(
|
|
11510
12331
|
() => renderedChartTasks.map(({ task }) => task),
|
|
11511
12332
|
[renderedChartTasks]
|
|
11512
12333
|
);
|
|
11513
|
-
renderedTaskIdsRef.current = (0,
|
|
12334
|
+
renderedTaskIdsRef.current = (0, import_react18.useMemo)(
|
|
11514
12335
|
() => new Set(renderedChartTasks.map(({ task }) => task.id)),
|
|
11515
12336
|
[renderedChartTasks]
|
|
11516
12337
|
);
|
|
11517
|
-
const handleCascade = (0,
|
|
12338
|
+
const handleCascade = (0, import_react18.useCallback)((cascadedTasks) => {
|
|
11518
12339
|
onTasksChange?.(cascadedTasks);
|
|
11519
12340
|
}, [tasks, onTasksChange]);
|
|
11520
|
-
const handleTaskSelect = (0,
|
|
12341
|
+
const handleTaskSelect = (0, import_react18.useCallback)((taskId) => {
|
|
11521
12342
|
setSelectedTaskId(taskId);
|
|
11522
12343
|
}, []);
|
|
11523
|
-
const hoveredRowElementsRef = (0,
|
|
11524
|
-
const clearHoveredRows = (0,
|
|
12344
|
+
const hoveredRowElementsRef = (0, import_react18.useRef)([]);
|
|
12345
|
+
const clearHoveredRows = (0, import_react18.useCallback)(() => {
|
|
11525
12346
|
for (const element of hoveredRowElementsRef.current) {
|
|
11526
|
-
element.classList.remove("gantt-tl-row-hovered", "gantt-tr-row-hovered", "gantt-mx-row-hovered");
|
|
12347
|
+
element.classList.remove("gantt-tl-row-hovered", "gantt-tr-row-hovered", "gantt-mx-row-hovered", "gantt-pf-row-hovered");
|
|
11527
12348
|
}
|
|
11528
12349
|
hoveredRowElementsRef.current = [];
|
|
11529
12350
|
}, []);
|
|
11530
|
-
const applyHoveredRows = (0,
|
|
12351
|
+
const applyHoveredRows = (0, import_react18.useCallback)((taskId) => {
|
|
11531
12352
|
const root = scrollContentRef.current;
|
|
11532
12353
|
if (!root) return;
|
|
11533
12354
|
clearHoveredRows();
|
|
@@ -11544,10 +12365,13 @@ function TaskGanttChartInner(props, ref) {
|
|
|
11544
12365
|
if (element.classList.contains("gantt-mx-row")) {
|
|
11545
12366
|
element.classList.add("gantt-mx-row-hovered");
|
|
11546
12367
|
}
|
|
12368
|
+
if (element.classList.contains("gantt-pf-row")) {
|
|
12369
|
+
element.classList.add("gantt-pf-row-hovered");
|
|
12370
|
+
}
|
|
11547
12371
|
}
|
|
11548
12372
|
hoveredRowElementsRef.current = nextHoveredRows;
|
|
11549
12373
|
}, [clearHoveredRows]);
|
|
11550
|
-
const handleSharedRowHover = (0,
|
|
12374
|
+
const handleSharedRowHover = (0, import_react18.useCallback)((event) => {
|
|
11551
12375
|
const target = event.target;
|
|
11552
12376
|
const row = target.closest("[data-gantt-task-row-id]");
|
|
11553
12377
|
const taskId = row?.dataset.ganttTaskRowId;
|
|
@@ -11557,7 +12381,7 @@ function TaskGanttChartInner(props, ref) {
|
|
|
11557
12381
|
}
|
|
11558
12382
|
applyHoveredRows(taskId);
|
|
11559
12383
|
}, [applyHoveredRows]);
|
|
11560
|
-
const handleToggleCollapse = externalOnToggleCollapse ?? (0,
|
|
12384
|
+
const handleToggleCollapse = externalOnToggleCollapse ?? (0, import_react18.useCallback)((parentId) => {
|
|
11561
12385
|
setInternalCollapsedParentIds((prev) => {
|
|
11562
12386
|
const next = new Set(prev);
|
|
11563
12387
|
if (next.has(parentId)) {
|
|
@@ -11568,20 +12392,20 @@ function TaskGanttChartInner(props, ref) {
|
|
|
11568
12392
|
return next;
|
|
11569
12393
|
});
|
|
11570
12394
|
}, []);
|
|
11571
|
-
const allParentIds = (0,
|
|
12395
|
+
const allParentIds = (0, import_react18.useMemo)(() => {
|
|
11572
12396
|
return new Set(
|
|
11573
12397
|
normalizedTasks.filter((t) => isTaskParent(t.id, normalizedTasks)).map((t) => t.id)
|
|
11574
12398
|
);
|
|
11575
12399
|
}, [normalizedTasks]);
|
|
11576
|
-
const handleCollapseAll = (0,
|
|
12400
|
+
const handleCollapseAll = (0, import_react18.useCallback)(() => {
|
|
11577
12401
|
if (externalCollapsedParentIds) return;
|
|
11578
12402
|
setInternalCollapsedParentIds(allParentIds);
|
|
11579
12403
|
}, [allParentIds, externalCollapsedParentIds]);
|
|
11580
|
-
const handleExpandAll = (0,
|
|
12404
|
+
const handleExpandAll = (0, import_react18.useCallback)(() => {
|
|
11581
12405
|
if (externalCollapsedParentIds) return;
|
|
11582
12406
|
setInternalCollapsedParentIds(/* @__PURE__ */ new Set());
|
|
11583
12407
|
}, [externalCollapsedParentIds]);
|
|
11584
|
-
const exportToPdf = (0,
|
|
12408
|
+
const exportToPdf = (0, import_react18.useCallback)(async (options) => {
|
|
11585
12409
|
const sourceContainer = containerRef.current;
|
|
11586
12410
|
const sourceContent = scrollContentRef.current;
|
|
11587
12411
|
if (!sourceContainer || !sourceContent || typeof window === "undefined" || typeof document === "undefined") {
|
|
@@ -11617,7 +12441,7 @@ function TaskGanttChartInner(props, ref) {
|
|
|
11617
12441
|
orientation: options?.orientation
|
|
11618
12442
|
});
|
|
11619
12443
|
}, [showTaskList, showChart]);
|
|
11620
|
-
(0,
|
|
12444
|
+
(0, import_react18.useImperativeHandle)(
|
|
11621
12445
|
ref,
|
|
11622
12446
|
() => ({
|
|
11623
12447
|
scrollToToday,
|
|
@@ -11640,7 +12464,7 @@ function TaskGanttChartInner(props, ref) {
|
|
|
11640
12464
|
}
|
|
11641
12465
|
return depth;
|
|
11642
12466
|
}
|
|
11643
|
-
const handlePromoteTask = (0,
|
|
12467
|
+
const handlePromoteTask = (0, import_react18.useCallback)((taskId) => {
|
|
11644
12468
|
if (onPromoteTask) {
|
|
11645
12469
|
onPromoteTask(taskId);
|
|
11646
12470
|
return;
|
|
@@ -11672,7 +12496,7 @@ function TaskGanttChartInner(props, ref) {
|
|
|
11672
12496
|
]);
|
|
11673
12497
|
onTasksChange?.(reorderedTasks);
|
|
11674
12498
|
}, [tasks, onTasksChange, onPromoteTask]);
|
|
11675
|
-
const handleDemoteTask = (0,
|
|
12499
|
+
const handleDemoteTask = (0, import_react18.useCallback)((taskId, newParentId) => {
|
|
11676
12500
|
if (onDemoteTask) {
|
|
11677
12501
|
onDemoteTask(taskId, newParentId);
|
|
11678
12502
|
return;
|
|
@@ -11713,7 +12537,7 @@ function TaskGanttChartInner(props, ref) {
|
|
|
11713
12537
|
};
|
|
11714
12538
|
onTasksChange?.([updatedDemotedTask]);
|
|
11715
12539
|
}, [tasks, onTasksChange, onDemoteTask]);
|
|
11716
|
-
const handleUngroupTask = (0,
|
|
12540
|
+
const handleUngroupTask = (0, import_react18.useCallback)((taskId) => {
|
|
11717
12541
|
if (onUngroupTask) {
|
|
11718
12542
|
onUngroupTask(taskId);
|
|
11719
12543
|
return;
|
|
@@ -11738,8 +12562,8 @@ function TaskGanttChartInner(props, ref) {
|
|
|
11738
12562
|
onTasksChange?.(changedTasks);
|
|
11739
12563
|
}
|
|
11740
12564
|
}, [tasks, onTasksChange, onUngroupTask]);
|
|
11741
|
-
const panStateRef = (0,
|
|
11742
|
-
const handlePanStart = (0,
|
|
12565
|
+
const panStateRef = (0, import_react18.useRef)(null);
|
|
12566
|
+
const handlePanStart = (0, import_react18.useCallback)((e) => {
|
|
11743
12567
|
if (e.button !== 0) return;
|
|
11744
12568
|
const target = e.target;
|
|
11745
12569
|
if (target.closest("[data-taskbar]")) return;
|
|
@@ -11760,7 +12584,7 @@ function TaskGanttChartInner(props, ref) {
|
|
|
11760
12584
|
container.style.cursor = "grabbing";
|
|
11761
12585
|
e.preventDefault();
|
|
11762
12586
|
}, []);
|
|
11763
|
-
(0,
|
|
12587
|
+
(0, import_react18.useEffect)(() => {
|
|
11764
12588
|
const handlePanMove = (e) => {
|
|
11765
12589
|
const pan = panStateRef.current;
|
|
11766
12590
|
if (!pan?.active) return;
|
|
@@ -11782,19 +12606,19 @@ function TaskGanttChartInner(props, ref) {
|
|
|
11782
12606
|
window.removeEventListener("mouseup", handlePanEnd);
|
|
11783
12607
|
};
|
|
11784
12608
|
}, []);
|
|
11785
|
-
return /* @__PURE__ */ (0,
|
|
12609
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
11786
12610
|
"div",
|
|
11787
12611
|
{
|
|
11788
12612
|
ref: containerRef,
|
|
11789
|
-
className: isTableMatrixMode ? "gantt-container gantt-container-tableMatrix" : "gantt-container",
|
|
11790
|
-
children: /* @__PURE__ */ (0,
|
|
12613
|
+
className: isTableMatrixMode ? "gantt-container gantt-container-tableMatrix" : isPlanFactMode ? "gantt-container gantt-container-planFact" : "gantt-container",
|
|
12614
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
11791
12615
|
"div",
|
|
11792
12616
|
{
|
|
11793
12617
|
ref: scrollContainerRef,
|
|
11794
12618
|
className: "gantt-scrollContainer",
|
|
11795
12619
|
style: { height: containerHeight ?? "auto", cursor: "grab" },
|
|
11796
12620
|
onMouseDown: handlePanStart,
|
|
11797
|
-
children: /* @__PURE__ */ (0,
|
|
12621
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
|
|
11798
12622
|
"div",
|
|
11799
12623
|
{
|
|
11800
12624
|
ref: scrollContentRef,
|
|
@@ -11802,7 +12626,7 @@ function TaskGanttChartInner(props, ref) {
|
|
|
11802
12626
|
onMouseOver: handleSharedRowHover,
|
|
11803
12627
|
onMouseLeave: clearHoveredRows,
|
|
11804
12628
|
children: [
|
|
11805
|
-
/* @__PURE__ */ (0,
|
|
12629
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
11806
12630
|
TaskList,
|
|
11807
12631
|
{
|
|
11808
12632
|
tasks: normalizedTasks,
|
|
@@ -11855,17 +12679,17 @@ function TaskGanttChartInner(props, ref) {
|
|
|
11855
12679
|
visibleRowIndices: visibleTaskWindowIndices
|
|
11856
12680
|
}
|
|
11857
12681
|
),
|
|
11858
|
-
/* @__PURE__ */ (0,
|
|
12682
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
11859
12683
|
"div",
|
|
11860
12684
|
{
|
|
11861
|
-
className: isTableMatrixMode || showChart ? "gantt-chartSurface" : "gantt-chartSurface gantt-chart-hidden",
|
|
12685
|
+
className: isTableMatrixMode || isPlanFactMode || showChart ? "gantt-chartSurface" : "gantt-chartSurface gantt-chart-hidden",
|
|
11862
12686
|
style: {
|
|
11863
|
-
minWidth: isTableMatrixMode ? matrixWidth !== void 0 ? `${matrixWidth}px` : void 0 : `${gridWidth}px`,
|
|
11864
|
-
width: isTableMatrixMode ? matrixWidth !== void 0 ? `${matrixWidth}px` : "max-content" : void 0,
|
|
11865
|
-
flex: isTableMatrixMode ? "0 0 auto" : 1,
|
|
11866
|
-
display: isTableMatrixMode || showChart ? void 0 : "none"
|
|
12687
|
+
minWidth: isTableMatrixMode ? matrixWidth !== void 0 ? `${matrixWidth}px` : void 0 : isPlanFactMode ? `${gridWidth}px` : `${gridWidth}px`,
|
|
12688
|
+
width: isTableMatrixMode ? matrixWidth !== void 0 ? `${matrixWidth}px` : "max-content" : isPlanFactMode ? `${gridWidth}px` : void 0,
|
|
12689
|
+
flex: isTableMatrixMode || isPlanFactMode ? "0 0 auto" : 1,
|
|
12690
|
+
display: isTableMatrixMode || isPlanFactMode || showChart ? void 0 : "none"
|
|
11867
12691
|
},
|
|
11868
|
-
children: isTableMatrixMode ? /* @__PURE__ */ (0,
|
|
12692
|
+
children: isTableMatrixMode ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
11869
12693
|
TableMatrix,
|
|
11870
12694
|
{
|
|
11871
12695
|
tasks: visibleTasks,
|
|
@@ -11882,14 +12706,31 @@ function TaskGanttChartInner(props, ref) {
|
|
|
11882
12706
|
highlightedTaskIds: taskListHighlightedTaskIds,
|
|
11883
12707
|
filterMode
|
|
11884
12708
|
}
|
|
11885
|
-
) : /* @__PURE__ */ (0,
|
|
11886
|
-
|
|
12709
|
+
) : isPlanFactMode ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
12710
|
+
PlanFactMatrix,
|
|
12711
|
+
{
|
|
12712
|
+
tasks: visibleTasks,
|
|
12713
|
+
allTasks: normalizedTasks,
|
|
12714
|
+
dateRange,
|
|
12715
|
+
dayWidth,
|
|
12716
|
+
rowHeight: effectiveRowHeight,
|
|
12717
|
+
headerHeight: timelineHeaderHeight,
|
|
12718
|
+
bodyMinHeight: tableBodyMinHeight,
|
|
12719
|
+
selectedTaskId,
|
|
12720
|
+
onTaskSelect: handleTaskSelect,
|
|
12721
|
+
onTasksChange: handleTaskChange,
|
|
12722
|
+
onCellCommit: onPlanFactCellCommit,
|
|
12723
|
+
highlightedTaskIds: taskListHighlightedTaskIds,
|
|
12724
|
+
filterMode
|
|
12725
|
+
}
|
|
12726
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(import_jsx_runtime19.Fragment, { children: [
|
|
12727
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
|
|
11887
12728
|
"div",
|
|
11888
12729
|
{
|
|
11889
12730
|
className: "gantt-stickyHeader",
|
|
11890
12731
|
style: { width: `${gridWidth}px`, height: `${timelineHeaderHeight}px` },
|
|
11891
12732
|
children: [
|
|
11892
|
-
/* @__PURE__ */ (0,
|
|
12733
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
11893
12734
|
TimeScaleHeader_default,
|
|
11894
12735
|
{
|
|
11895
12736
|
days: dateRange,
|
|
@@ -11902,7 +12743,7 @@ function TaskGanttChartInner(props, ref) {
|
|
|
11902
12743
|
onTimelineHoverEnd: () => setActiveTimelineTooltip(null)
|
|
11903
12744
|
}
|
|
11904
12745
|
),
|
|
11905
|
-
activeTimelineTooltip && /* @__PURE__ */ (0,
|
|
12746
|
+
activeTimelineTooltip && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { className: "gantt-timelineTooltipLayer", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
11906
12747
|
"div",
|
|
11907
12748
|
{
|
|
11908
12749
|
className: "gantt-timelineTooltip",
|
|
@@ -11916,7 +12757,7 @@ function TaskGanttChartInner(props, ref) {
|
|
|
11916
12757
|
]
|
|
11917
12758
|
}
|
|
11918
12759
|
),
|
|
11919
|
-
/* @__PURE__ */ (0,
|
|
12760
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
|
|
11920
12761
|
"div",
|
|
11921
12762
|
{
|
|
11922
12763
|
className: "gantt-taskArea",
|
|
@@ -11926,7 +12767,7 @@ function TaskGanttChartInner(props, ref) {
|
|
|
11926
12767
|
height: `${totalGridHeight}px`
|
|
11927
12768
|
},
|
|
11928
12769
|
children: [
|
|
11929
|
-
/* @__PURE__ */ (0,
|
|
12770
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
11930
12771
|
GridBackground_default,
|
|
11931
12772
|
{
|
|
11932
12773
|
dateRange,
|
|
@@ -11936,7 +12777,7 @@ function TaskGanttChartInner(props, ref) {
|
|
|
11936
12777
|
isCustomWeekend
|
|
11937
12778
|
}
|
|
11938
12779
|
),
|
|
11939
|
-
todayInRange && /* @__PURE__ */ (0,
|
|
12780
|
+
todayInRange && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
11940
12781
|
TodayIndicator_default,
|
|
11941
12782
|
{
|
|
11942
12783
|
monthStart,
|
|
@@ -11945,7 +12786,7 @@ function TaskGanttChartInner(props, ref) {
|
|
|
11945
12786
|
onHoverEnd: () => setActiveTimelineTooltip(null)
|
|
11946
12787
|
}
|
|
11947
12788
|
),
|
|
11948
|
-
visibleTimelineMarkers.length > 0 && /* @__PURE__ */ (0,
|
|
12789
|
+
visibleTimelineMarkers.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
11949
12790
|
TimelineMarkers_default,
|
|
11950
12791
|
{
|
|
11951
12792
|
rangeStart: monthStart,
|
|
@@ -11956,7 +12797,7 @@ function TaskGanttChartInner(props, ref) {
|
|
|
11956
12797
|
onHoverEnd: () => setActiveTimelineTooltip(null)
|
|
11957
12798
|
}
|
|
11958
12799
|
),
|
|
11959
|
-
/* @__PURE__ */ (0,
|
|
12800
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
11960
12801
|
DependencyLines_default,
|
|
11961
12802
|
{
|
|
11962
12803
|
tasks: renderedDependencyTasks,
|
|
@@ -11974,7 +12815,7 @@ function TaskGanttChartInner(props, ref) {
|
|
|
11974
12815
|
weekendPredicate: isCustomWeekend
|
|
11975
12816
|
}
|
|
11976
12817
|
),
|
|
11977
|
-
dragGuideLines && /* @__PURE__ */ (0,
|
|
12818
|
+
dragGuideLines && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
11978
12819
|
DragGuideLines_default,
|
|
11979
12820
|
{
|
|
11980
12821
|
isDragging: dragGuideLines.isDragging,
|
|
@@ -11984,7 +12825,7 @@ function TaskGanttChartInner(props, ref) {
|
|
|
11984
12825
|
totalHeight: totalGridHeight
|
|
11985
12826
|
}
|
|
11986
12827
|
),
|
|
11987
|
-
renderedChartTasks.map(({ task, index }) => /* @__PURE__ */ (0,
|
|
12828
|
+
renderedChartTasks.map(({ task, index }) => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
11988
12829
|
"div",
|
|
11989
12830
|
{
|
|
11990
12831
|
style: {
|
|
@@ -11994,7 +12835,7 @@ function TaskGanttChartInner(props, ref) {
|
|
|
11994
12835
|
right: 0,
|
|
11995
12836
|
height: `${effectiveRowHeight}px`
|
|
11996
12837
|
},
|
|
11997
|
-
children: /* @__PURE__ */ (0,
|
|
12838
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
11998
12839
|
TaskRow_default,
|
|
11999
12840
|
{
|
|
12000
12841
|
task,
|
|
@@ -12045,14 +12886,14 @@ function TaskGanttChartInner(props, ref) {
|
|
|
12045
12886
|
}
|
|
12046
12887
|
);
|
|
12047
12888
|
}
|
|
12048
|
-
var TaskGanttChart = (0,
|
|
12049
|
-
var GanttChart = (0,
|
|
12889
|
+
var TaskGanttChart = (0, import_react18.forwardRef)(TaskGanttChartInner);
|
|
12890
|
+
var GanttChart = (0, import_react18.forwardRef)(GanttChartInner);
|
|
12050
12891
|
GanttChart.displayName = "GanttChart";
|
|
12051
12892
|
|
|
12052
12893
|
// src/components/ui/Button.tsx
|
|
12053
|
-
var
|
|
12054
|
-
var
|
|
12055
|
-
var Button =
|
|
12894
|
+
var import_react19 = __toESM(require("react"));
|
|
12895
|
+
var import_jsx_runtime20 = require("react/jsx-runtime");
|
|
12896
|
+
var Button = import_react19.default.forwardRef(
|
|
12056
12897
|
({ className, variant = "default", size = "default", children, ...props }, ref) => {
|
|
12057
12898
|
const classes = [
|
|
12058
12899
|
"gantt-btn",
|
|
@@ -12060,7 +12901,7 @@ var Button = import_react18.default.forwardRef(
|
|
|
12060
12901
|
size !== "default" ? `gantt-btn-${size}` : "",
|
|
12061
12902
|
className || ""
|
|
12062
12903
|
].filter(Boolean).join(" ");
|
|
12063
|
-
return /* @__PURE__ */ (0,
|
|
12904
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("button", { ref, className: classes, ...props, children });
|
|
12064
12905
|
}
|
|
12065
12906
|
);
|
|
12066
12907
|
Button.displayName = "Button";
|
|
@@ -12108,6 +12949,7 @@ var nameContains = (substring, caseSensitive = false) => (task) => {
|
|
|
12108
12949
|
GanttChart,
|
|
12109
12950
|
GridBackground,
|
|
12110
12951
|
Input,
|
|
12952
|
+
PlanFactMatrix,
|
|
12111
12953
|
Popover,
|
|
12112
12954
|
PopoverContent,
|
|
12113
12955
|
PopoverTrigger,
|