gantt-lib 0.78.0 → 0.80.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-CZzZrxn-.d.mts → index-DAfJyZbj.d.mts} +14 -1
- package/dist/{index-CZzZrxn-.d.ts → index-DAfJyZbj.d.ts} +14 -1
- package/dist/index.css.map +1 -1
- package/dist/index.d.mts +20 -5
- package/dist/index.d.ts +20 -5
- package/dist/index.js +305 -50
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +317 -62
- package/dist/index.mjs.map +1 -1
- package/dist/styles.css +245 -13
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"use client";
|
|
4
4
|
|
|
5
5
|
// src/components/GanttChart/GanttChart.tsx
|
|
6
|
-
import { useMemo as useMemo10, useCallback as useCallback8, useRef as useRef9, useState as
|
|
6
|
+
import { useMemo as useMemo10, useCallback as useCallback8, useRef as useRef9, useState as useState9, useEffect as useEffect9, useImperativeHandle, forwardRef } from "react";
|
|
7
7
|
|
|
8
8
|
// src/core/scheduling/dateMath.ts
|
|
9
9
|
var DAY_MS = 24 * 60 * 60 * 1e3;
|
|
@@ -2999,7 +2999,7 @@ var arePropsEqual2 = (prevProps, nextProps) => {
|
|
|
2999
2999
|
prevProps.viewMode === nextProps.viewMode && prevProps.isCustomWeekend === nextProps.isCustomWeekend;
|
|
3000
3000
|
};
|
|
3001
3001
|
var GridBackground = React4.memo(
|
|
3002
|
-
({ dateRange, dayWidth, totalHeight, viewMode = "day", isCustomWeekend }) => {
|
|
3002
|
+
({ dateRange, dayWidth, totalHeight, viewMode = "day", isCustomWeekend, className, showWeekendBlocks = true, showGridLines = true }) => {
|
|
3003
3003
|
const weekGridLines = useMemo4(() => {
|
|
3004
3004
|
if (viewMode !== "week") return [];
|
|
3005
3005
|
return calculateWeekGridLines(dateRange, dayWidth);
|
|
@@ -3022,13 +3022,13 @@ var GridBackground = React4.memo(
|
|
|
3022
3022
|
return /* @__PURE__ */ jsxs3(
|
|
3023
3023
|
"div",
|
|
3024
3024
|
{
|
|
3025
|
-
className: "gantt-gb-gridBackground",
|
|
3025
|
+
className: ["gantt-gb-gridBackground", className].filter(Boolean).join(" "),
|
|
3026
3026
|
style: {
|
|
3027
3027
|
width: `${gridWidth}px`,
|
|
3028
3028
|
height: `${totalHeight}px`
|
|
3029
3029
|
},
|
|
3030
3030
|
children: [
|
|
3031
|
-
weekendBlocks.map((block, index) => /* @__PURE__ */ jsx4(
|
|
3031
|
+
showWeekendBlocks && weekendBlocks.map((block, index) => /* @__PURE__ */ jsx4(
|
|
3032
3032
|
"div",
|
|
3033
3033
|
{
|
|
3034
3034
|
className: "gantt-gb-weekendBlock",
|
|
@@ -3039,7 +3039,7 @@ var GridBackground = React4.memo(
|
|
|
3039
3039
|
},
|
|
3040
3040
|
`weekend-${index}`
|
|
3041
3041
|
)),
|
|
3042
|
-
viewMode === "week" ? (
|
|
3042
|
+
showGridLines && (viewMode === "week" ? (
|
|
3043
3043
|
// Week-view: one line per week column boundary
|
|
3044
3044
|
weekGridLines.map((line, index) => {
|
|
3045
3045
|
const lineClass = line.isMonthStart ? "gantt-gb-monthSeparator" : "gantt-gb-weekSeparator";
|
|
@@ -3080,7 +3080,7 @@ var GridBackground = React4.memo(
|
|
|
3080
3080
|
`gridline-${index}`
|
|
3081
3081
|
);
|
|
3082
3082
|
})
|
|
3083
|
-
)
|
|
3083
|
+
))
|
|
3084
3084
|
]
|
|
3085
3085
|
}
|
|
3086
3086
|
);
|
|
@@ -3351,6 +3351,25 @@ var DependencyLines = React5.memo(({
|
|
|
3351
3351
|
}
|
|
3352
3352
|
)
|
|
3353
3353
|
}
|
|
3354
|
+
),
|
|
3355
|
+
/* @__PURE__ */ jsx6(
|
|
3356
|
+
"marker",
|
|
3357
|
+
{
|
|
3358
|
+
id: "arrowhead-hover",
|
|
3359
|
+
markerWidth: "8",
|
|
3360
|
+
markerHeight: "6",
|
|
3361
|
+
markerUnits: "userSpaceOnUse",
|
|
3362
|
+
refX: "7",
|
|
3363
|
+
refY: "3",
|
|
3364
|
+
orient: "auto",
|
|
3365
|
+
children: /* @__PURE__ */ jsx6(
|
|
3366
|
+
"polygon",
|
|
3367
|
+
{
|
|
3368
|
+
points: "0 0, 8 3, 0 6",
|
|
3369
|
+
fill: "var(--gantt-dependency-hover-color, #ef4444)"
|
|
3370
|
+
}
|
|
3371
|
+
)
|
|
3372
|
+
}
|
|
3354
3373
|
)
|
|
3355
3374
|
] }),
|
|
3356
3375
|
lines.map(({ id, path, hasCycle, lag, fromX, toX, fromY, reverseOrder, isVirtual }) => {
|
|
@@ -3365,14 +3384,23 @@ var DependencyLines = React5.memo(({
|
|
|
3365
3384
|
else markerEnd = "url(#arrowhead)";
|
|
3366
3385
|
const lagColor = isSelected ? "#ef4444" : hasCycle ? "var(--gantt-dependency-cycle-color, #ef4444)" : "var(--gantt-dependency-line-color, #666666)";
|
|
3367
3386
|
return /* @__PURE__ */ jsxs5(React5.Fragment, { children: [
|
|
3368
|
-
/* @__PURE__ */
|
|
3369
|
-
|
|
3370
|
-
|
|
3371
|
-
|
|
3372
|
-
|
|
3373
|
-
|
|
3374
|
-
|
|
3375
|
-
|
|
3387
|
+
/* @__PURE__ */ jsxs5("g", { className: "gantt-dependency-line", children: [
|
|
3388
|
+
/* @__PURE__ */ jsx6(
|
|
3389
|
+
"path",
|
|
3390
|
+
{
|
|
3391
|
+
d: path,
|
|
3392
|
+
className: "gantt-dependency-hit-area"
|
|
3393
|
+
}
|
|
3394
|
+
),
|
|
3395
|
+
/* @__PURE__ */ jsx6(
|
|
3396
|
+
"path",
|
|
3397
|
+
{
|
|
3398
|
+
d: path,
|
|
3399
|
+
className: pathClassName,
|
|
3400
|
+
markerEnd
|
|
3401
|
+
}
|
|
3402
|
+
)
|
|
3403
|
+
] }),
|
|
3376
3404
|
lag !== 0 && /* @__PURE__ */ jsx6(
|
|
3377
3405
|
"text",
|
|
3378
3406
|
{
|
|
@@ -4446,12 +4474,20 @@ var DepChip = ({
|
|
|
4446
4474
|
/* @__PURE__ */ jsx12(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxs9(
|
|
4447
4475
|
"span",
|
|
4448
4476
|
{
|
|
4449
|
-
className: `gantt-tl-dep-chip${isSelected ? " gantt-tl-dep-chip-selected" : ""}`,
|
|
4477
|
+
className: `gantt-tl-dep-chip-with-number${isSelected ? " gantt-tl-dep-chip-with-number-selected" : ""}`,
|
|
4450
4478
|
onClick: handleClick,
|
|
4451
|
-
|
|
4479
|
+
"aria-label": `[${LINK_TYPE_LABELS_RU[dep.type]}] ${formatTaskNumberLabel(predecessorTaskNumber)}${depName}`,
|
|
4452
4480
|
children: [
|
|
4453
|
-
/* @__PURE__ */ jsx12(
|
|
4454
|
-
|
|
4481
|
+
predecessorTaskNumber && /* @__PURE__ */ jsx12("span", { className: "gantt-tl-dep-chip-task-number", children: predecessorTaskNumber }),
|
|
4482
|
+
/* @__PURE__ */ jsx12("span", { className: "gantt-tl-dep-chip", children: /* @__PURE__ */ jsx12(Icon, {}) }),
|
|
4483
|
+
effectiveLag !== 0 && /* @__PURE__ */ jsx12("span", { className: "gantt-tl-dep-chip-lag", children: effectiveLag > 0 ? `+${effectiveLag}` : `${effectiveLag}` }),
|
|
4484
|
+
/* @__PURE__ */ jsxs9("span", { className: "gantt-tl-dep-chip-tooltip", role: "tooltip", children: [
|
|
4485
|
+
"[",
|
|
4486
|
+
LINK_TYPE_LABELS_RU[dep.type],
|
|
4487
|
+
"] ",
|
|
4488
|
+
formatTaskNumberLabel(predecessorTaskNumber),
|
|
4489
|
+
depName
|
|
4490
|
+
] })
|
|
4455
4491
|
]
|
|
4456
4492
|
}
|
|
4457
4493
|
) }),
|
|
@@ -6296,7 +6332,7 @@ var BUILT_IN_COLUMN_WIDTHS = {
|
|
|
6296
6332
|
endDate: 90,
|
|
6297
6333
|
duration: 60,
|
|
6298
6334
|
progress: 50,
|
|
6299
|
-
dependencies:
|
|
6335
|
+
dependencies: 128,
|
|
6300
6336
|
actions: 80
|
|
6301
6337
|
};
|
|
6302
6338
|
function createBuiltInColumns(opts) {
|
|
@@ -7206,7 +7242,7 @@ var TaskList = ({
|
|
|
7206
7242
|
};
|
|
7207
7243
|
|
|
7208
7244
|
// src/components/ResourceTimelineChart/ResourceTimelineChart.tsx
|
|
7209
|
-
import { useCallback as useCallback7, useEffect as useEffect8, useMemo as useMemo9, useRef as useRef8 } from "react";
|
|
7245
|
+
import { useCallback as useCallback7, useEffect as useEffect8, useMemo as useMemo9, useRef as useRef8, useState as useState8 } from "react";
|
|
7210
7246
|
|
|
7211
7247
|
// src/utils/resourceTimelineLayout.ts
|
|
7212
7248
|
var isInvalidDate = (date) => Number.isNaN(date.getTime());
|
|
@@ -7297,6 +7333,33 @@ var calculateConflictInfo = (parsedItems) => {
|
|
|
7297
7333
|
}
|
|
7298
7334
|
return result;
|
|
7299
7335
|
};
|
|
7336
|
+
var countConflictOverlaps = (items) => {
|
|
7337
|
+
const conflictsByItemId = new Map(items.map((item) => [item.itemId, item.conflictsWith]));
|
|
7338
|
+
const visited = /* @__PURE__ */ new Set();
|
|
7339
|
+
let overlapCount = 0;
|
|
7340
|
+
for (const item of items) {
|
|
7341
|
+
if (visited.has(item.itemId) || item.conflictsWith.length === 0) {
|
|
7342
|
+
continue;
|
|
7343
|
+
}
|
|
7344
|
+
const stack = [item.itemId];
|
|
7345
|
+
let componentSize = 0;
|
|
7346
|
+
while (stack.length > 0) {
|
|
7347
|
+
const itemId = stack.pop();
|
|
7348
|
+
if (visited.has(itemId)) {
|
|
7349
|
+
continue;
|
|
7350
|
+
}
|
|
7351
|
+
visited.add(itemId);
|
|
7352
|
+
componentSize += 1;
|
|
7353
|
+
for (const conflictId of conflictsByItemId.get(itemId) ?? []) {
|
|
7354
|
+
if (!visited.has(conflictId)) {
|
|
7355
|
+
stack.push(conflictId);
|
|
7356
|
+
}
|
|
7357
|
+
}
|
|
7358
|
+
}
|
|
7359
|
+
overlapCount += Math.max(0, componentSize - 1);
|
|
7360
|
+
}
|
|
7361
|
+
return overlapCount;
|
|
7362
|
+
};
|
|
7300
7363
|
var layoutResourceTimelineItems = (resources, options) => {
|
|
7301
7364
|
const rows = [];
|
|
7302
7365
|
const items = [];
|
|
@@ -7356,7 +7419,7 @@ var layoutResourceTimelineItems = (resources, options) => {
|
|
|
7356
7419
|
}
|
|
7357
7420
|
const laneCount = Math.max(1, laneEndDays.length);
|
|
7358
7421
|
const resourceRowHeight = laneCount * options.laneHeight;
|
|
7359
|
-
const conflictCount = laidOutItems
|
|
7422
|
+
const conflictCount = countConflictOverlaps(laidOutItems);
|
|
7360
7423
|
const row = {
|
|
7361
7424
|
resource,
|
|
7362
7425
|
resourceId: resource.id,
|
|
@@ -7601,7 +7664,8 @@ var DEFAULT_ROW_HEADER_WIDTH = 240;
|
|
|
7601
7664
|
var DEFAULT_RESOURCE_ROW_GAP = 8;
|
|
7602
7665
|
var ITEM_OUTER_VERTICAL_INSET = 2;
|
|
7603
7666
|
var ITEM_INNER_VERTICAL_INSET = 1;
|
|
7604
|
-
var
|
|
7667
|
+
var ITEM_START_HORIZONTAL_INSET = 2;
|
|
7668
|
+
var ITEM_END_HORIZONTAL_INSET = 1;
|
|
7605
7669
|
var isValidDate = (date) => !Number.isNaN(date.getTime());
|
|
7606
7670
|
var collectValidItems = (resources) => {
|
|
7607
7671
|
return resources.flatMap(
|
|
@@ -7623,12 +7687,18 @@ var getVisualItemGeometry = (geometry, laneIndex, laneCount) => {
|
|
|
7623
7687
|
const topInset = laneIndex === 0 ? ITEM_OUTER_VERTICAL_INSET : ITEM_INNER_VERTICAL_INSET;
|
|
7624
7688
|
const bottomInset = laneIndex === laneCount - 1 ? ITEM_OUTER_VERTICAL_INSET : ITEM_INNER_VERTICAL_INSET;
|
|
7625
7689
|
return {
|
|
7626
|
-
left: geometry.left +
|
|
7690
|
+
left: geometry.left + ITEM_START_HORIZONTAL_INSET,
|
|
7627
7691
|
top: geometry.top + topInset,
|
|
7628
|
-
width: Math.max(
|
|
7692
|
+
width: Math.max(1, geometry.width - ITEM_START_HORIZONTAL_INSET - ITEM_END_HORIZONTAL_INSET),
|
|
7629
7693
|
height: Math.max(0, geometry.height - topInset - bottomInset)
|
|
7630
7694
|
};
|
|
7631
7695
|
};
|
|
7696
|
+
var formatOverlapCount = (count) => {
|
|
7697
|
+
const mod10 = count % 10;
|
|
7698
|
+
const mod100 = count % 100;
|
|
7699
|
+
const word = mod10 === 1 && mod100 !== 11 ? "\u043D\u0430\u043B\u043E\u0436\u0435\u043D\u0438\u0435" : mod10 >= 2 && mod10 <= 4 && (mod100 < 12 || mod100 > 14) ? "\u043D\u0430\u043B\u043E\u0436\u0435\u043D\u0438\u044F" : "\u043D\u0430\u043B\u043E\u0436\u0435\u043D\u0438\u0439";
|
|
7700
|
+
return `${count} ${word}`;
|
|
7701
|
+
};
|
|
7632
7702
|
var getWeekendOverlaySegments = (startDate, endDate, dayWidth, weekendPredicate) => {
|
|
7633
7703
|
const segments2 = [];
|
|
7634
7704
|
const current = new Date(Date.UTC(startDate.getUTCFullYear(), startDate.getUTCMonth(), startDate.getUTCDate()));
|
|
@@ -7671,7 +7741,143 @@ var getRangeOverlaySegments = (itemStartDate, ranges, dayWidth) => {
|
|
|
7671
7741
|
};
|
|
7672
7742
|
});
|
|
7673
7743
|
};
|
|
7744
|
+
var clampOverlaySegments = (segments2, maxWidth) => segments2.flatMap((segment) => {
|
|
7745
|
+
const left = Math.max(0, Math.min(segment.left, maxWidth));
|
|
7746
|
+
const right = Math.max(left, Math.min(segment.left + segment.width, maxWidth));
|
|
7747
|
+
const width = right - left;
|
|
7748
|
+
return width > 0 ? [{ left, width }] : [];
|
|
7749
|
+
});
|
|
7674
7750
|
var getDurationValue = (startDate, endDate, businessDays, weekendPredicate) => businessDays ? getBusinessDaysCount(startDate, endDate, weekendPredicate) : Math.max(1, Math.round((endDate.getTime() - startDate.getTime()) / (24 * 60 * 60 * 1e3)) + 1);
|
|
7751
|
+
var ResourceHeader = ({
|
|
7752
|
+
resource,
|
|
7753
|
+
resourceId,
|
|
7754
|
+
conflictCount,
|
|
7755
|
+
height,
|
|
7756
|
+
paddingBottom,
|
|
7757
|
+
menuCommands
|
|
7758
|
+
}) => {
|
|
7759
|
+
const [menuOpen, setMenuOpen] = useState8(false);
|
|
7760
|
+
const visibleCommands = useMemo9(
|
|
7761
|
+
() => menuCommands.filter((command) => command.isVisible?.(resource) ?? true),
|
|
7762
|
+
[menuCommands, resource]
|
|
7763
|
+
);
|
|
7764
|
+
const hasMenu = visibleCommands.length > 0;
|
|
7765
|
+
const handleCommandClick = (command, event) => {
|
|
7766
|
+
event.stopPropagation();
|
|
7767
|
+
if (command.closeOnSelect !== false) {
|
|
7768
|
+
setMenuOpen(false);
|
|
7769
|
+
}
|
|
7770
|
+
command.onSelect(resource);
|
|
7771
|
+
};
|
|
7772
|
+
return /* @__PURE__ */ jsxs12(
|
|
7773
|
+
"div",
|
|
7774
|
+
{
|
|
7775
|
+
className: `gantt-resourceTimeline-resourceHeader${menuOpen ? " gantt-resourceTimeline-resourceHeaderMenuOpen" : ""}`,
|
|
7776
|
+
"data-resource-row-id": resourceId,
|
|
7777
|
+
style: {
|
|
7778
|
+
height: `${height}px`,
|
|
7779
|
+
paddingBottom: `${paddingBottom}px`
|
|
7780
|
+
},
|
|
7781
|
+
children: [
|
|
7782
|
+
/* @__PURE__ */ jsx15("span", { className: "gantt-resourceTimeline-resourceName", children: resource.name }),
|
|
7783
|
+
conflictCount > 0 && /* @__PURE__ */ jsx15(
|
|
7784
|
+
"span",
|
|
7785
|
+
{
|
|
7786
|
+
className: "gantt-resourceTimeline-conflictBadge",
|
|
7787
|
+
"aria-label": formatOverlapCount(conflictCount),
|
|
7788
|
+
title: formatOverlapCount(conflictCount),
|
|
7789
|
+
children: conflictCount
|
|
7790
|
+
}
|
|
7791
|
+
),
|
|
7792
|
+
hasMenu && /* @__PURE__ */ jsxs12(Popover, { open: menuOpen, onOpenChange: setMenuOpen, children: [
|
|
7793
|
+
/* @__PURE__ */ jsx15(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsx15(
|
|
7794
|
+
"button",
|
|
7795
|
+
{
|
|
7796
|
+
className: "gantt-resourceTimeline-resourceMenuButton",
|
|
7797
|
+
type: "button",
|
|
7798
|
+
"aria-label": "\u0414\u0435\u0439\u0441\u0442\u0432\u0438\u044F \u0440\u0435\u0441\u0443\u0440\u0441\u0430",
|
|
7799
|
+
onClick: (event) => {
|
|
7800
|
+
event.stopPropagation();
|
|
7801
|
+
setMenuOpen((open) => !open);
|
|
7802
|
+
},
|
|
7803
|
+
children: /* @__PURE__ */ jsx15("span", { "aria-hidden": "true", children: "\u22EE" })
|
|
7804
|
+
}
|
|
7805
|
+
) }),
|
|
7806
|
+
/* @__PURE__ */ jsx15(PopoverContent, { className: "gantt-resourceTimeline-resourceMenu", portal: true, align: "end", children: visibleCommands.map((command) => /* @__PURE__ */ jsxs12(
|
|
7807
|
+
"button",
|
|
7808
|
+
{
|
|
7809
|
+
type: "button",
|
|
7810
|
+
className: `gantt-resourceTimeline-resourceMenuItem${command.danger ? " gantt-resourceTimeline-resourceMenuItemDanger" : ""}`,
|
|
7811
|
+
disabled: command.isDisabled?.(resource) ?? false,
|
|
7812
|
+
onClick: (event) => handleCommandClick(command, event),
|
|
7813
|
+
children: [
|
|
7814
|
+
command.icon,
|
|
7815
|
+
command.label
|
|
7816
|
+
]
|
|
7817
|
+
},
|
|
7818
|
+
command.id
|
|
7819
|
+
)) })
|
|
7820
|
+
] })
|
|
7821
|
+
]
|
|
7822
|
+
}
|
|
7823
|
+
);
|
|
7824
|
+
};
|
|
7825
|
+
var NewResourceRow = ({ height, onConfirm, onCancel }) => {
|
|
7826
|
+
const [nameValue, setNameValue] = useState8("");
|
|
7827
|
+
const inputRef = useRef8(null);
|
|
7828
|
+
const confirmedRef = useRef8(false);
|
|
7829
|
+
useEffect8(() => {
|
|
7830
|
+
inputRef.current?.focus();
|
|
7831
|
+
inputRef.current?.select();
|
|
7832
|
+
}, []);
|
|
7833
|
+
const handleCancel = () => {
|
|
7834
|
+
confirmedRef.current = true;
|
|
7835
|
+
onCancel();
|
|
7836
|
+
};
|
|
7837
|
+
const handleConfirm = () => {
|
|
7838
|
+
const name = nameValue.trim();
|
|
7839
|
+
if (!name) {
|
|
7840
|
+
handleCancel();
|
|
7841
|
+
return;
|
|
7842
|
+
}
|
|
7843
|
+
confirmedRef.current = true;
|
|
7844
|
+
onConfirm(name);
|
|
7845
|
+
};
|
|
7846
|
+
const handleKeyDown = (event) => {
|
|
7847
|
+
if (event.key === "Enter") {
|
|
7848
|
+
handleConfirm();
|
|
7849
|
+
} else if (event.key === "Escape") {
|
|
7850
|
+
handleCancel();
|
|
7851
|
+
}
|
|
7852
|
+
};
|
|
7853
|
+
const handleBlur = () => {
|
|
7854
|
+
if (!confirmedRef.current) {
|
|
7855
|
+
handleConfirm();
|
|
7856
|
+
}
|
|
7857
|
+
};
|
|
7858
|
+
return /* @__PURE__ */ jsx15(
|
|
7859
|
+
"div",
|
|
7860
|
+
{
|
|
7861
|
+
className: "gantt-resourceTimeline-resourceHeader gantt-resourceTimeline-resourceHeaderNew",
|
|
7862
|
+
style: {
|
|
7863
|
+
height: `${height}px`,
|
|
7864
|
+
paddingBottom: `${DEFAULT_RESOURCE_ROW_GAP}px`
|
|
7865
|
+
},
|
|
7866
|
+
children: /* @__PURE__ */ jsx15(
|
|
7867
|
+
Input,
|
|
7868
|
+
{
|
|
7869
|
+
ref: inputRef,
|
|
7870
|
+
value: nameValue,
|
|
7871
|
+
onChange: (event) => setNameValue(event.target.value),
|
|
7872
|
+
onKeyDown: handleKeyDown,
|
|
7873
|
+
onBlur: handleBlur,
|
|
7874
|
+
placeholder: "\u041D\u0430\u0437\u0432\u0430\u043D\u0438\u0435 \u0440\u0435\u0441\u0443\u0440\u0441\u0430",
|
|
7875
|
+
className: "gantt-resourceTimeline-resourceInput"
|
|
7876
|
+
}
|
|
7877
|
+
)
|
|
7878
|
+
}
|
|
7879
|
+
);
|
|
7880
|
+
};
|
|
7675
7881
|
function ResourceTimelineChart({
|
|
7676
7882
|
resources,
|
|
7677
7883
|
dayWidth = DEFAULT_DAY_WIDTH,
|
|
@@ -7689,11 +7895,15 @@ function ResourceTimelineChart({
|
|
|
7689
7895
|
renderItem,
|
|
7690
7896
|
getItemClassName,
|
|
7691
7897
|
onResourceItemClick,
|
|
7692
|
-
onResourceItemMove
|
|
7898
|
+
onResourceItemMove,
|
|
7899
|
+
onAddResource,
|
|
7900
|
+
enableAddResource = true,
|
|
7901
|
+
resourceMenuCommands = []
|
|
7693
7902
|
}) {
|
|
7694
7903
|
const scrollContainerRef = useRef8(null);
|
|
7695
7904
|
const gridRef = useRef8(null);
|
|
7696
7905
|
const panStateRef = useRef8(null);
|
|
7906
|
+
const [isCreatingResource, setIsCreatingResource] = useState8(false);
|
|
7697
7907
|
const validItems = useMemo9(() => collectValidItems(resources), [resources]);
|
|
7698
7908
|
const dateRange = useMemo9(() => getMultiMonthDays(validItems), [validItems]);
|
|
7699
7909
|
const monthStart = useMemo9(() => {
|
|
@@ -7728,6 +7938,18 @@ function ResourceTimelineChart({
|
|
|
7728
7938
|
}
|
|
7729
7939
|
return map;
|
|
7730
7940
|
}, [layout.items]);
|
|
7941
|
+
const canAddResource = enableAddResource && Boolean(onAddResource);
|
|
7942
|
+
const resourceAddRowHeight = laneHeight + DEFAULT_RESOURCE_ROW_GAP;
|
|
7943
|
+
const displayTotalHeight = layout.totalHeight + (canAddResource ? resourceAddRowHeight : 0);
|
|
7944
|
+
const handleConfirmNewResource = useCallback7((name) => {
|
|
7945
|
+
onAddResource?.({
|
|
7946
|
+
id: crypto.randomUUID(),
|
|
7947
|
+
name,
|
|
7948
|
+
items: []
|
|
7949
|
+
});
|
|
7950
|
+
setIsCreatingResource(false);
|
|
7951
|
+
}, [onAddResource]);
|
|
7952
|
+
const handleCancelNewResource = useCallback7(() => setIsCreatingResource(false), []);
|
|
7731
7953
|
const { preview, startDrag } = useResourceItemDrag({
|
|
7732
7954
|
dayWidth,
|
|
7733
7955
|
monthStart,
|
|
@@ -7822,28 +8044,34 @@ function ResourceTimelineChart({
|
|
|
7822
8044
|
style: { height: `${headerHeight}px` }
|
|
7823
8045
|
}
|
|
7824
8046
|
),
|
|
7825
|
-
layout.rows.map((row) => /* @__PURE__ */
|
|
7826
|
-
|
|
8047
|
+
layout.rows.map((row) => /* @__PURE__ */ jsx15(
|
|
8048
|
+
ResourceHeader,
|
|
7827
8049
|
{
|
|
7828
|
-
|
|
7829
|
-
|
|
7830
|
-
|
|
7831
|
-
|
|
7832
|
-
|
|
7833
|
-
|
|
7834
|
-
children: [
|
|
7835
|
-
/* @__PURE__ */ jsx15("span", { className: "gantt-resourceTimeline-resourceName", children: row.resource.name }),
|
|
7836
|
-
row.conflictCount > 0 && /* @__PURE__ */ jsx15(
|
|
7837
|
-
"span",
|
|
7838
|
-
{
|
|
7839
|
-
className: "gantt-resourceTimeline-conflictBadge",
|
|
7840
|
-
"aria-label": `${row.conflictCount} \u043A\u043E\u043D\u0444\u043B\u0438\u043A\u0442\u043E\u0432`,
|
|
7841
|
-
children: row.conflictCount
|
|
7842
|
-
}
|
|
7843
|
-
)
|
|
7844
|
-
]
|
|
8050
|
+
resource: row.resource,
|
|
8051
|
+
resourceId: row.resourceId,
|
|
8052
|
+
conflictCount: row.conflictCount,
|
|
8053
|
+
height: row.resourceRowHeight + DEFAULT_RESOURCE_ROW_GAP,
|
|
8054
|
+
paddingBottom: DEFAULT_RESOURCE_ROW_GAP,
|
|
8055
|
+
menuCommands: resourceMenuCommands
|
|
7845
8056
|
},
|
|
7846
8057
|
row.resourceId
|
|
8058
|
+
)),
|
|
8059
|
+
canAddResource && (isCreatingResource ? /* @__PURE__ */ jsx15(
|
|
8060
|
+
NewResourceRow,
|
|
8061
|
+
{
|
|
8062
|
+
height: resourceAddRowHeight,
|
|
8063
|
+
onConfirm: handleConfirmNewResource,
|
|
8064
|
+
onCancel: handleCancelNewResource
|
|
8065
|
+
}
|
|
8066
|
+
) : /* @__PURE__ */ jsx15(
|
|
8067
|
+
"button",
|
|
8068
|
+
{
|
|
8069
|
+
className: "gantt-resourceTimeline-addResourceButton",
|
|
8070
|
+
type: "button",
|
|
8071
|
+
style: { height: `${resourceAddRowHeight}px` },
|
|
8072
|
+
onClick: () => setIsCreatingResource(true),
|
|
8073
|
+
children: "+ \u0414\u043E\u0431\u0430\u0432\u0438\u0442\u044C \u0440\u0435\u0441\u0443\u0440\u0441"
|
|
8074
|
+
}
|
|
7847
8075
|
))
|
|
7848
8076
|
]
|
|
7849
8077
|
}
|
|
@@ -7869,14 +8097,14 @@ function ResourceTimelineChart({
|
|
|
7869
8097
|
{
|
|
7870
8098
|
ref: gridRef,
|
|
7871
8099
|
className: "gantt-resourceTimeline-grid",
|
|
7872
|
-
style: { width: `${gridWidth}px`, height: `${
|
|
8100
|
+
style: { width: `${gridWidth}px`, height: `${displayTotalHeight}px` },
|
|
7873
8101
|
children: [
|
|
7874
8102
|
/* @__PURE__ */ jsx15(
|
|
7875
8103
|
GridBackground_default,
|
|
7876
8104
|
{
|
|
7877
8105
|
dateRange,
|
|
7878
8106
|
dayWidth,
|
|
7879
|
-
totalHeight:
|
|
8107
|
+
totalHeight: displayTotalHeight,
|
|
7880
8108
|
viewMode,
|
|
7881
8109
|
isCustomWeekend: weekendPredicate
|
|
7882
8110
|
}
|
|
@@ -7894,6 +8122,17 @@ function ResourceTimelineChart({
|
|
|
7894
8122
|
},
|
|
7895
8123
|
row.resourceId
|
|
7896
8124
|
)),
|
|
8125
|
+
canAddResource && /* @__PURE__ */ jsx15(
|
|
8126
|
+
"div",
|
|
8127
|
+
{
|
|
8128
|
+
className: "gantt-resourceTimeline-row gantt-resourceTimeline-rowNew",
|
|
8129
|
+
"data-resource-add-row": "true",
|
|
8130
|
+
style: {
|
|
8131
|
+
top: `${layout.totalHeight}px`,
|
|
8132
|
+
height: `${resourceAddRowHeight}px`
|
|
8133
|
+
}
|
|
8134
|
+
}
|
|
8135
|
+
),
|
|
7897
8136
|
Array.from(itemsByResourceId.values()).flatMap(
|
|
7898
8137
|
(resourceItems) => resourceItems.map((layoutItem) => {
|
|
7899
8138
|
const customClassName = getItemClassName?.(layoutItem.item);
|
|
@@ -7919,11 +8158,17 @@ function ResourceTimelineChart({
|
|
|
7919
8158
|
}, layoutItem.laneIndex, laneCount);
|
|
7920
8159
|
const overlayStartDate = isDraggingItem ? preview.startDate : layoutItem.startDate;
|
|
7921
8160
|
const overlayEndDate = isDraggingItem ? preview.endDate : layoutItem.endDate;
|
|
7922
|
-
const weekendOverlaySegments = businessDays ?
|
|
7923
|
-
|
|
7924
|
-
|
|
7925
|
-
|
|
7926
|
-
|
|
8161
|
+
const weekendOverlaySegments = businessDays ? clampOverlaySegments(
|
|
8162
|
+
getWeekendOverlaySegments(overlayStartDate, overlayEndDate, dayWidth, weekendPredicate),
|
|
8163
|
+
itemGeometry.width
|
|
8164
|
+
) : [];
|
|
8165
|
+
const conflictOverlaySegments = clampOverlaySegments(
|
|
8166
|
+
getRangeOverlaySegments(
|
|
8167
|
+
overlayStartDate,
|
|
8168
|
+
isDraggingItem ? [] : layoutItem.conflictRanges,
|
|
8169
|
+
dayWidth
|
|
8170
|
+
),
|
|
8171
|
+
itemGeometry.width
|
|
7927
8172
|
);
|
|
7928
8173
|
const durationValue = getDurationValue(
|
|
7929
8174
|
overlayStartDate,
|
|
@@ -7942,6 +8187,7 @@ function ResourceTimelineChart({
|
|
|
7942
8187
|
{
|
|
7943
8188
|
className,
|
|
7944
8189
|
"data-resource-item-id": layoutItem.itemId,
|
|
8190
|
+
"data-resource-item-tooltip": layoutItem.item.title,
|
|
7945
8191
|
onMouseDown: (event) => startDrag(event, layoutItem),
|
|
7946
8192
|
onClick: () => onResourceItemClick?.(layoutItem.item),
|
|
7947
8193
|
onKeyDown: (event) => {
|
|
@@ -8419,20 +8665,20 @@ function TaskGanttChartInner(props, ref) {
|
|
|
8419
8665
|
const containerRef = useRef9(null);
|
|
8420
8666
|
const scrollContainerRef = useRef9(null);
|
|
8421
8667
|
const scrollContentRef = useRef9(null);
|
|
8422
|
-
const [selectedTaskId, setSelectedTaskId] =
|
|
8423
|
-
const [taskListHasRightShadow, setTaskListHasRightShadow] =
|
|
8424
|
-
const [selectedChip, setSelectedChip] =
|
|
8425
|
-
const [internalCollapsedParentIds, setInternalCollapsedParentIds] =
|
|
8668
|
+
const [selectedTaskId, setSelectedTaskId] = useState9(null);
|
|
8669
|
+
const [taskListHasRightShadow, setTaskListHasRightShadow] = useState9(false);
|
|
8670
|
+
const [selectedChip, setSelectedChip] = useState9(null);
|
|
8671
|
+
const [internalCollapsedParentIds, setInternalCollapsedParentIds] = useState9(/* @__PURE__ */ new Set());
|
|
8426
8672
|
const collapsedParentIds = externalCollapsedParentIds ?? internalCollapsedParentIds;
|
|
8427
|
-
const [editingTaskId, setEditingTaskId] =
|
|
8673
|
+
const [editingTaskId, setEditingTaskId] = useState9(null);
|
|
8428
8674
|
const normalizedTasks = useMemo10(() => normalizeHierarchyTasks(tasks), [tasks]);
|
|
8429
8675
|
const isCustomWeekend = useMemo10(
|
|
8430
8676
|
() => createCustomDayPredicate({ customDays, isWeekend: isWeekend3 }),
|
|
8431
8677
|
[customDays, isWeekend3]
|
|
8432
8678
|
);
|
|
8433
8679
|
const dateRange = useMemo10(() => getMultiMonthDays(normalizedTasks), [normalizedTasks]);
|
|
8434
|
-
const [validationResult, setValidationResult] =
|
|
8435
|
-
const [cascadeOverrides, setCascadeOverrides] =
|
|
8680
|
+
const [validationResult, setValidationResult] = useState9(null);
|
|
8681
|
+
const [cascadeOverrides, setCascadeOverrides] = useState9(/* @__PURE__ */ new Map());
|
|
8436
8682
|
const gridWidth = useMemo10(
|
|
8437
8683
|
() => Math.round(dateRange.length * dayWidth),
|
|
8438
8684
|
[dateRange.length, dayWidth]
|
|
@@ -8549,9 +8795,9 @@ function TaskGanttChartInner(props, ref) {
|
|
|
8549
8795
|
setSelectedTaskId(taskId);
|
|
8550
8796
|
container.scrollTo({ top: scrollTop, behavior: "smooth" });
|
|
8551
8797
|
}, [tasks, visibleTasks, rowHeight]);
|
|
8552
|
-
const [dragGuideLines, setDragGuideLines] =
|
|
8553
|
-
const [draggedTaskOverride, setDraggedTaskOverride] =
|
|
8554
|
-
const [previewTasksById, setPreviewTasksById] =
|
|
8798
|
+
const [dragGuideLines, setDragGuideLines] = useState9(null);
|
|
8799
|
+
const [draggedTaskOverride, setDraggedTaskOverride] = useState9(null);
|
|
8800
|
+
const [previewTasksById, setPreviewTasksById] = useState9(/* @__PURE__ */ new Map());
|
|
8555
8801
|
useEffect9(() => {
|
|
8556
8802
|
const result = validateDependencies(tasks);
|
|
8557
8803
|
setValidationResult(result);
|
|
@@ -9078,7 +9324,16 @@ Button.displayName = "Button";
|
|
|
9078
9324
|
var and = (...predicates) => (task) => predicates.every((p) => p(task));
|
|
9079
9325
|
var or = (...predicates) => (task) => predicates.some((p) => p(task));
|
|
9080
9326
|
var not = (predicate) => (task) => !predicate(task);
|
|
9081
|
-
var withoutDeps = () => (task) =>
|
|
9327
|
+
var withoutDeps = (options = {}) => (task) => {
|
|
9328
|
+
if (!task) return false;
|
|
9329
|
+
if (options.onlyChildren && !task.parentId) return false;
|
|
9330
|
+
if (options.onlyLeafTasks) {
|
|
9331
|
+
const isParent = (options.tasks ?? []).some((candidate) => candidate.parentId === task.id);
|
|
9332
|
+
const isRegularTask = task.type == null || task.type === "task";
|
|
9333
|
+
if (isParent || !isRegularTask) return false;
|
|
9334
|
+
}
|
|
9335
|
+
return !task.dependencies || task.dependencies.length === 0;
|
|
9336
|
+
};
|
|
9082
9337
|
var expired = (referenceDate = /* @__PURE__ */ new Date()) => (task) => isTaskExpired(task, referenceDate);
|
|
9083
9338
|
var inDateRange = (rangeStart, rangeEnd) => (task) => {
|
|
9084
9339
|
if (!task) return false;
|