gantt-lib 0.79.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 +13 -3
- package/dist/index.d.ts +13 -3
- package/dist/index.js +250 -36
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +262 -48
- package/dist/index.mjs.map +1 -1
- package/dist/styles.css +113 -2
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React$1, { ReactNode } from 'react';
|
|
2
|
-
import { T as Task$1, R as ResourceTimelineItem, V as ValidationResult, a as ResourcePlannerChartProps, b as ResourceTimelineResource } from './index-
|
|
3
|
-
export { D as DAY_MS, c as DependencyError, G as GanttChartMode, d as GanttDateRange, e as GridConfig, f as GridLine, L as LinkType, M as MonthSpan, g as ResourceTimelineMove, h as TaskBarGeometry, W as WeekendBlock,
|
|
2
|
+
import { T as Task$1, R as ResourceTimelineItem, V as ValidationResult, a as ResourcePlannerChartProps, b as ResourceTimelineResource } from './index-DAfJyZbj.mjs';
|
|
3
|
+
export { D as DAY_MS, c as DependencyError, G as GanttChartMode, d as GanttDateRange, e as GridConfig, f as GridLine, L as LinkType, M as MonthSpan, g as ResourceTimelineMove, h as ResourceTimelineResourceMenuCommand, i as TaskBarGeometry, W as WeekendBlock, j as alignToWorkingDay, k as areTasksHierarchicallyRelated, l as buildAdjacencyList, m as buildTaskRangeFromEnd, n as buildTaskRangeFromStart, o as calculateSuccessorDate, p as cascadeByLinks, q as clampTaskRangeForIncomingFS, r as computeLagFromDates, s as computeParentDates, t as computeParentProgress, u as detectCycles, v as findParentId, w as getAllDependencyEdges, x as getAllDescendants, y as getBusinessDayOffset, z as getChildren, A as getDependencyLag, B as getSuccessorChain, C as getTaskDuration, E as getTransitiveCascadeChain, F as isAncestorTask, H as isTaskParent, I as moveTaskRange, J as moveTaskWithCascade, K as normalizeDependencyLag, N as normalizePredecessorDates, O as normalizeUTCDate, P as parseDateOnly, Q as recalculateIncomingLags, S as recalculateProjectSchedule, U as recalculateTaskFromDependencies, X as reflowTasksOnModeSwitch, Y as removeDependenciesBetweenTasks, Z as resizeTaskWithCascade, _ as shiftBusinessDayOffset, $ as universalCascade, a0 as validateDependencies } from './index-DAfJyZbj.mjs';
|
|
4
4
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
5
5
|
import * as RadixPopover from '@radix-ui/react-popover';
|
|
6
6
|
|
|
@@ -263,6 +263,10 @@ declare const not: (predicate: TaskPredicate) => TaskPredicate;
|
|
|
263
263
|
interface WithoutDepsOptions {
|
|
264
264
|
/** If true, only child tasks (tasks with parentId) can match. */
|
|
265
265
|
onlyChildren?: boolean;
|
|
266
|
+
/** Full task list, required when excluding parent rows. */
|
|
267
|
+
tasks?: Task$1[];
|
|
268
|
+
/** If true, only non-parent regular tasks can match. Requires tasks. */
|
|
269
|
+
onlyLeafTasks?: boolean;
|
|
266
270
|
}
|
|
267
271
|
/**
|
|
268
272
|
* Filter tasks that have no dependencies
|
|
@@ -545,7 +549,7 @@ declare const GanttChart: <TTask extends Task = Task, TItem extends ResourceTime
|
|
|
545
549
|
ref?: React$1.Ref<GanttChartHandle>;
|
|
546
550
|
}) => React$1.ReactElement;
|
|
547
551
|
|
|
548
|
-
declare function ResourceTimelineChart<TItem extends ResourceTimelineItem = ResourceTimelineItem>({ resources, dayWidth, viewMode, rowHeaderWidth, laneHeight, headerHeight, containerHeight, allowVerticalPan, customDays, isWeekend, businessDays, readonly, disableResourceReassignment, renderItem, getItemClassName, onResourceItemClick, onResourceItemMove, }: ResourcePlannerChartProps<TItem>): react_jsx_runtime.JSX.Element;
|
|
552
|
+
declare function ResourceTimelineChart<TItem extends ResourceTimelineItem = ResourceTimelineItem>({ resources, dayWidth, viewMode, rowHeaderWidth, laneHeight, headerHeight, containerHeight, allowVerticalPan, customDays, isWeekend, businessDays, readonly, disableResourceReassignment, renderItem, getItemClassName, onResourceItemClick, onResourceItemMove, onAddResource, enableAddResource, resourceMenuCommands, }: ResourcePlannerChartProps<TItem>): react_jsx_runtime.JSX.Element;
|
|
549
553
|
|
|
550
554
|
interface TaskRowProps {
|
|
551
555
|
/** Task data to render */
|
|
@@ -648,6 +652,12 @@ interface GridBackgroundProps {
|
|
|
648
652
|
viewMode?: 'day' | 'week' | 'month';
|
|
649
653
|
/** Optional predicate for custom weekend logic (e.g., holidays, shift patterns) */
|
|
650
654
|
isCustomWeekend?: (date: Date) => boolean;
|
|
655
|
+
/** Optional extra class for layered rendering contexts. */
|
|
656
|
+
className?: string;
|
|
657
|
+
/** Whether to render weekend background blocks. */
|
|
658
|
+
showWeekendBlocks?: boolean;
|
|
659
|
+
/** Whether to render vertical grid lines. */
|
|
660
|
+
showGridLines?: boolean;
|
|
651
661
|
}
|
|
652
662
|
/**
|
|
653
663
|
* GridBackground component - renders vertical grid lines and weekend background highlighting
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React$1, { ReactNode } from 'react';
|
|
2
|
-
import { T as Task$1, R as ResourceTimelineItem, V as ValidationResult, a as ResourcePlannerChartProps, b as ResourceTimelineResource } from './index-
|
|
3
|
-
export { D as DAY_MS, c as DependencyError, G as GanttChartMode, d as GanttDateRange, e as GridConfig, f as GridLine, L as LinkType, M as MonthSpan, g as ResourceTimelineMove, h as TaskBarGeometry, W as WeekendBlock,
|
|
2
|
+
import { T as Task$1, R as ResourceTimelineItem, V as ValidationResult, a as ResourcePlannerChartProps, b as ResourceTimelineResource } from './index-DAfJyZbj.js';
|
|
3
|
+
export { D as DAY_MS, c as DependencyError, G as GanttChartMode, d as GanttDateRange, e as GridConfig, f as GridLine, L as LinkType, M as MonthSpan, g as ResourceTimelineMove, h as ResourceTimelineResourceMenuCommand, i as TaskBarGeometry, W as WeekendBlock, j as alignToWorkingDay, k as areTasksHierarchicallyRelated, l as buildAdjacencyList, m as buildTaskRangeFromEnd, n as buildTaskRangeFromStart, o as calculateSuccessorDate, p as cascadeByLinks, q as clampTaskRangeForIncomingFS, r as computeLagFromDates, s as computeParentDates, t as computeParentProgress, u as detectCycles, v as findParentId, w as getAllDependencyEdges, x as getAllDescendants, y as getBusinessDayOffset, z as getChildren, A as getDependencyLag, B as getSuccessorChain, C as getTaskDuration, E as getTransitiveCascadeChain, F as isAncestorTask, H as isTaskParent, I as moveTaskRange, J as moveTaskWithCascade, K as normalizeDependencyLag, N as normalizePredecessorDates, O as normalizeUTCDate, P as parseDateOnly, Q as recalculateIncomingLags, S as recalculateProjectSchedule, U as recalculateTaskFromDependencies, X as reflowTasksOnModeSwitch, Y as removeDependenciesBetweenTasks, Z as resizeTaskWithCascade, _ as shiftBusinessDayOffset, $ as universalCascade, a0 as validateDependencies } from './index-DAfJyZbj.js';
|
|
4
4
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
5
5
|
import * as RadixPopover from '@radix-ui/react-popover';
|
|
6
6
|
|
|
@@ -263,6 +263,10 @@ declare const not: (predicate: TaskPredicate) => TaskPredicate;
|
|
|
263
263
|
interface WithoutDepsOptions {
|
|
264
264
|
/** If true, only child tasks (tasks with parentId) can match. */
|
|
265
265
|
onlyChildren?: boolean;
|
|
266
|
+
/** Full task list, required when excluding parent rows. */
|
|
267
|
+
tasks?: Task$1[];
|
|
268
|
+
/** If true, only non-parent regular tasks can match. Requires tasks. */
|
|
269
|
+
onlyLeafTasks?: boolean;
|
|
266
270
|
}
|
|
267
271
|
/**
|
|
268
272
|
* Filter tasks that have no dependencies
|
|
@@ -545,7 +549,7 @@ declare const GanttChart: <TTask extends Task = Task, TItem extends ResourceTime
|
|
|
545
549
|
ref?: React$1.Ref<GanttChartHandle>;
|
|
546
550
|
}) => React$1.ReactElement;
|
|
547
551
|
|
|
548
|
-
declare function ResourceTimelineChart<TItem extends ResourceTimelineItem = ResourceTimelineItem>({ resources, dayWidth, viewMode, rowHeaderWidth, laneHeight, headerHeight, containerHeight, allowVerticalPan, customDays, isWeekend, businessDays, readonly, disableResourceReassignment, renderItem, getItemClassName, onResourceItemClick, onResourceItemMove, }: ResourcePlannerChartProps<TItem>): react_jsx_runtime.JSX.Element;
|
|
552
|
+
declare function ResourceTimelineChart<TItem extends ResourceTimelineItem = ResourceTimelineItem>({ resources, dayWidth, viewMode, rowHeaderWidth, laneHeight, headerHeight, containerHeight, allowVerticalPan, customDays, isWeekend, businessDays, readonly, disableResourceReassignment, renderItem, getItemClassName, onResourceItemClick, onResourceItemMove, onAddResource, enableAddResource, resourceMenuCommands, }: ResourcePlannerChartProps<TItem>): react_jsx_runtime.JSX.Element;
|
|
549
553
|
|
|
550
554
|
interface TaskRowProps {
|
|
551
555
|
/** Task data to render */
|
|
@@ -648,6 +652,12 @@ interface GridBackgroundProps {
|
|
|
648
652
|
viewMode?: 'day' | 'week' | 'month';
|
|
649
653
|
/** Optional predicate for custom weekend logic (e.g., holidays, shift patterns) */
|
|
650
654
|
isCustomWeekend?: (date: Date) => boolean;
|
|
655
|
+
/** Optional extra class for layered rendering contexts. */
|
|
656
|
+
className?: string;
|
|
657
|
+
/** Whether to render weekend background blocks. */
|
|
658
|
+
showWeekendBlocks?: boolean;
|
|
659
|
+
/** Whether to render vertical grid lines. */
|
|
660
|
+
showGridLines?: boolean;
|
|
651
661
|
}
|
|
652
662
|
/**
|
|
653
663
|
* GridBackground component - renders vertical grid lines and weekend background highlighting
|
package/dist/index.js
CHANGED
|
@@ -3137,7 +3137,7 @@ var arePropsEqual2 = (prevProps, nextProps) => {
|
|
|
3137
3137
|
prevProps.viewMode === nextProps.viewMode && prevProps.isCustomWeekend === nextProps.isCustomWeekend;
|
|
3138
3138
|
};
|
|
3139
3139
|
var GridBackground = import_react5.default.memo(
|
|
3140
|
-
({ dateRange, dayWidth, totalHeight, viewMode = "day", isCustomWeekend }) => {
|
|
3140
|
+
({ dateRange, dayWidth, totalHeight, viewMode = "day", isCustomWeekend, className, showWeekendBlocks = true, showGridLines = true }) => {
|
|
3141
3141
|
const weekGridLines = (0, import_react5.useMemo)(() => {
|
|
3142
3142
|
if (viewMode !== "week") return [];
|
|
3143
3143
|
return calculateWeekGridLines(dateRange, dayWidth);
|
|
@@ -3160,13 +3160,13 @@ var GridBackground = import_react5.default.memo(
|
|
|
3160
3160
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
3161
3161
|
"div",
|
|
3162
3162
|
{
|
|
3163
|
-
className: "gantt-gb-gridBackground",
|
|
3163
|
+
className: ["gantt-gb-gridBackground", className].filter(Boolean).join(" "),
|
|
3164
3164
|
style: {
|
|
3165
3165
|
width: `${gridWidth}px`,
|
|
3166
3166
|
height: `${totalHeight}px`
|
|
3167
3167
|
},
|
|
3168
3168
|
children: [
|
|
3169
|
-
weekendBlocks.map((block, index) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
3169
|
+
showWeekendBlocks && weekendBlocks.map((block, index) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
3170
3170
|
"div",
|
|
3171
3171
|
{
|
|
3172
3172
|
className: "gantt-gb-weekendBlock",
|
|
@@ -3177,7 +3177,7 @@ var GridBackground = import_react5.default.memo(
|
|
|
3177
3177
|
},
|
|
3178
3178
|
`weekend-${index}`
|
|
3179
3179
|
)),
|
|
3180
|
-
viewMode === "week" ? (
|
|
3180
|
+
showGridLines && (viewMode === "week" ? (
|
|
3181
3181
|
// Week-view: one line per week column boundary
|
|
3182
3182
|
weekGridLines.map((line, index) => {
|
|
3183
3183
|
const lineClass = line.isMonthStart ? "gantt-gb-monthSeparator" : "gantt-gb-weekSeparator";
|
|
@@ -3218,7 +3218,7 @@ var GridBackground = import_react5.default.memo(
|
|
|
3218
3218
|
`gridline-${index}`
|
|
3219
3219
|
);
|
|
3220
3220
|
})
|
|
3221
|
-
)
|
|
3221
|
+
))
|
|
3222
3222
|
]
|
|
3223
3223
|
}
|
|
3224
3224
|
);
|
|
@@ -7447,6 +7447,33 @@ var calculateConflictInfo = (parsedItems) => {
|
|
|
7447
7447
|
}
|
|
7448
7448
|
return result;
|
|
7449
7449
|
};
|
|
7450
|
+
var countConflictOverlaps = (items) => {
|
|
7451
|
+
const conflictsByItemId = new Map(items.map((item) => [item.itemId, item.conflictsWith]));
|
|
7452
|
+
const visited = /* @__PURE__ */ new Set();
|
|
7453
|
+
let overlapCount = 0;
|
|
7454
|
+
for (const item of items) {
|
|
7455
|
+
if (visited.has(item.itemId) || item.conflictsWith.length === 0) {
|
|
7456
|
+
continue;
|
|
7457
|
+
}
|
|
7458
|
+
const stack = [item.itemId];
|
|
7459
|
+
let componentSize = 0;
|
|
7460
|
+
while (stack.length > 0) {
|
|
7461
|
+
const itemId = stack.pop();
|
|
7462
|
+
if (visited.has(itemId)) {
|
|
7463
|
+
continue;
|
|
7464
|
+
}
|
|
7465
|
+
visited.add(itemId);
|
|
7466
|
+
componentSize += 1;
|
|
7467
|
+
for (const conflictId of conflictsByItemId.get(itemId) ?? []) {
|
|
7468
|
+
if (!visited.has(conflictId)) {
|
|
7469
|
+
stack.push(conflictId);
|
|
7470
|
+
}
|
|
7471
|
+
}
|
|
7472
|
+
}
|
|
7473
|
+
overlapCount += Math.max(0, componentSize - 1);
|
|
7474
|
+
}
|
|
7475
|
+
return overlapCount;
|
|
7476
|
+
};
|
|
7450
7477
|
var layoutResourceTimelineItems = (resources, options) => {
|
|
7451
7478
|
const rows = [];
|
|
7452
7479
|
const items = [];
|
|
@@ -7506,7 +7533,7 @@ var layoutResourceTimelineItems = (resources, options) => {
|
|
|
7506
7533
|
}
|
|
7507
7534
|
const laneCount = Math.max(1, laneEndDays.length);
|
|
7508
7535
|
const resourceRowHeight = laneCount * options.laneHeight;
|
|
7509
|
-
const conflictCount = laidOutItems
|
|
7536
|
+
const conflictCount = countConflictOverlaps(laidOutItems);
|
|
7510
7537
|
const row = {
|
|
7511
7538
|
resource,
|
|
7512
7539
|
resourceId: resource.id,
|
|
@@ -7751,7 +7778,8 @@ var DEFAULT_ROW_HEADER_WIDTH = 240;
|
|
|
7751
7778
|
var DEFAULT_RESOURCE_ROW_GAP = 8;
|
|
7752
7779
|
var ITEM_OUTER_VERTICAL_INSET = 2;
|
|
7753
7780
|
var ITEM_INNER_VERTICAL_INSET = 1;
|
|
7754
|
-
var
|
|
7781
|
+
var ITEM_START_HORIZONTAL_INSET = 2;
|
|
7782
|
+
var ITEM_END_HORIZONTAL_INSET = 1;
|
|
7755
7783
|
var isValidDate = (date) => !Number.isNaN(date.getTime());
|
|
7756
7784
|
var collectValidItems = (resources) => {
|
|
7757
7785
|
return resources.flatMap(
|
|
@@ -7773,12 +7801,18 @@ var getVisualItemGeometry = (geometry, laneIndex, laneCount) => {
|
|
|
7773
7801
|
const topInset = laneIndex === 0 ? ITEM_OUTER_VERTICAL_INSET : ITEM_INNER_VERTICAL_INSET;
|
|
7774
7802
|
const bottomInset = laneIndex === laneCount - 1 ? ITEM_OUTER_VERTICAL_INSET : ITEM_INNER_VERTICAL_INSET;
|
|
7775
7803
|
return {
|
|
7776
|
-
left: geometry.left +
|
|
7804
|
+
left: geometry.left + ITEM_START_HORIZONTAL_INSET,
|
|
7777
7805
|
top: geometry.top + topInset,
|
|
7778
|
-
width: Math.max(
|
|
7806
|
+
width: Math.max(1, geometry.width - ITEM_START_HORIZONTAL_INSET - ITEM_END_HORIZONTAL_INSET),
|
|
7779
7807
|
height: Math.max(0, geometry.height - topInset - bottomInset)
|
|
7780
7808
|
};
|
|
7781
7809
|
};
|
|
7810
|
+
var formatOverlapCount = (count) => {
|
|
7811
|
+
const mod10 = count % 10;
|
|
7812
|
+
const mod100 = count % 100;
|
|
7813
|
+
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";
|
|
7814
|
+
return `${count} ${word}`;
|
|
7815
|
+
};
|
|
7782
7816
|
var getWeekendOverlaySegments = (startDate, endDate, dayWidth, weekendPredicate) => {
|
|
7783
7817
|
const segments2 = [];
|
|
7784
7818
|
const current = new Date(Date.UTC(startDate.getUTCFullYear(), startDate.getUTCMonth(), startDate.getUTCDate()));
|
|
@@ -7821,7 +7855,143 @@ var getRangeOverlaySegments = (itemStartDate, ranges, dayWidth) => {
|
|
|
7821
7855
|
};
|
|
7822
7856
|
});
|
|
7823
7857
|
};
|
|
7858
|
+
var clampOverlaySegments = (segments2, maxWidth) => segments2.flatMap((segment) => {
|
|
7859
|
+
const left = Math.max(0, Math.min(segment.left, maxWidth));
|
|
7860
|
+
const right = Math.max(left, Math.min(segment.left + segment.width, maxWidth));
|
|
7861
|
+
const width = right - left;
|
|
7862
|
+
return width > 0 ? [{ left, width }] : [];
|
|
7863
|
+
});
|
|
7824
7864
|
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);
|
|
7865
|
+
var ResourceHeader = ({
|
|
7866
|
+
resource,
|
|
7867
|
+
resourceId,
|
|
7868
|
+
conflictCount,
|
|
7869
|
+
height,
|
|
7870
|
+
paddingBottom,
|
|
7871
|
+
menuCommands
|
|
7872
|
+
}) => {
|
|
7873
|
+
const [menuOpen, setMenuOpen] = (0, import_react14.useState)(false);
|
|
7874
|
+
const visibleCommands = (0, import_react14.useMemo)(
|
|
7875
|
+
() => menuCommands.filter((command) => command.isVisible?.(resource) ?? true),
|
|
7876
|
+
[menuCommands, resource]
|
|
7877
|
+
);
|
|
7878
|
+
const hasMenu = visibleCommands.length > 0;
|
|
7879
|
+
const handleCommandClick = (command, event) => {
|
|
7880
|
+
event.stopPropagation();
|
|
7881
|
+
if (command.closeOnSelect !== false) {
|
|
7882
|
+
setMenuOpen(false);
|
|
7883
|
+
}
|
|
7884
|
+
command.onSelect(resource);
|
|
7885
|
+
};
|
|
7886
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
|
|
7887
|
+
"div",
|
|
7888
|
+
{
|
|
7889
|
+
className: `gantt-resourceTimeline-resourceHeader${menuOpen ? " gantt-resourceTimeline-resourceHeaderMenuOpen" : ""}`,
|
|
7890
|
+
"data-resource-row-id": resourceId,
|
|
7891
|
+
style: {
|
|
7892
|
+
height: `${height}px`,
|
|
7893
|
+
paddingBottom: `${paddingBottom}px`
|
|
7894
|
+
},
|
|
7895
|
+
children: [
|
|
7896
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "gantt-resourceTimeline-resourceName", children: resource.name }),
|
|
7897
|
+
conflictCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
7898
|
+
"span",
|
|
7899
|
+
{
|
|
7900
|
+
className: "gantt-resourceTimeline-conflictBadge",
|
|
7901
|
+
"aria-label": formatOverlapCount(conflictCount),
|
|
7902
|
+
title: formatOverlapCount(conflictCount),
|
|
7903
|
+
children: conflictCount
|
|
7904
|
+
}
|
|
7905
|
+
),
|
|
7906
|
+
hasMenu && /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(Popover, { open: menuOpen, onOpenChange: setMenuOpen, children: [
|
|
7907
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
7908
|
+
"button",
|
|
7909
|
+
{
|
|
7910
|
+
className: "gantt-resourceTimeline-resourceMenuButton",
|
|
7911
|
+
type: "button",
|
|
7912
|
+
"aria-label": "\u0414\u0435\u0439\u0441\u0442\u0432\u0438\u044F \u0440\u0435\u0441\u0443\u0440\u0441\u0430",
|
|
7913
|
+
onClick: (event) => {
|
|
7914
|
+
event.stopPropagation();
|
|
7915
|
+
setMenuOpen((open) => !open);
|
|
7916
|
+
},
|
|
7917
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { "aria-hidden": "true", children: "\u22EE" })
|
|
7918
|
+
}
|
|
7919
|
+
) }),
|
|
7920
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(PopoverContent, { className: "gantt-resourceTimeline-resourceMenu", portal: true, align: "end", children: visibleCommands.map((command) => /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
|
|
7921
|
+
"button",
|
|
7922
|
+
{
|
|
7923
|
+
type: "button",
|
|
7924
|
+
className: `gantt-resourceTimeline-resourceMenuItem${command.danger ? " gantt-resourceTimeline-resourceMenuItemDanger" : ""}`,
|
|
7925
|
+
disabled: command.isDisabled?.(resource) ?? false,
|
|
7926
|
+
onClick: (event) => handleCommandClick(command, event),
|
|
7927
|
+
children: [
|
|
7928
|
+
command.icon,
|
|
7929
|
+
command.label
|
|
7930
|
+
]
|
|
7931
|
+
},
|
|
7932
|
+
command.id
|
|
7933
|
+
)) })
|
|
7934
|
+
] })
|
|
7935
|
+
]
|
|
7936
|
+
}
|
|
7937
|
+
);
|
|
7938
|
+
};
|
|
7939
|
+
var NewResourceRow = ({ height, onConfirm, onCancel }) => {
|
|
7940
|
+
const [nameValue, setNameValue] = (0, import_react14.useState)("");
|
|
7941
|
+
const inputRef = (0, import_react14.useRef)(null);
|
|
7942
|
+
const confirmedRef = (0, import_react14.useRef)(false);
|
|
7943
|
+
(0, import_react14.useEffect)(() => {
|
|
7944
|
+
inputRef.current?.focus();
|
|
7945
|
+
inputRef.current?.select();
|
|
7946
|
+
}, []);
|
|
7947
|
+
const handleCancel = () => {
|
|
7948
|
+
confirmedRef.current = true;
|
|
7949
|
+
onCancel();
|
|
7950
|
+
};
|
|
7951
|
+
const handleConfirm = () => {
|
|
7952
|
+
const name = nameValue.trim();
|
|
7953
|
+
if (!name) {
|
|
7954
|
+
handleCancel();
|
|
7955
|
+
return;
|
|
7956
|
+
}
|
|
7957
|
+
confirmedRef.current = true;
|
|
7958
|
+
onConfirm(name);
|
|
7959
|
+
};
|
|
7960
|
+
const handleKeyDown = (event) => {
|
|
7961
|
+
if (event.key === "Enter") {
|
|
7962
|
+
handleConfirm();
|
|
7963
|
+
} else if (event.key === "Escape") {
|
|
7964
|
+
handleCancel();
|
|
7965
|
+
}
|
|
7966
|
+
};
|
|
7967
|
+
const handleBlur = () => {
|
|
7968
|
+
if (!confirmedRef.current) {
|
|
7969
|
+
handleConfirm();
|
|
7970
|
+
}
|
|
7971
|
+
};
|
|
7972
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
7973
|
+
"div",
|
|
7974
|
+
{
|
|
7975
|
+
className: "gantt-resourceTimeline-resourceHeader gantt-resourceTimeline-resourceHeaderNew",
|
|
7976
|
+
style: {
|
|
7977
|
+
height: `${height}px`,
|
|
7978
|
+
paddingBottom: `${DEFAULT_RESOURCE_ROW_GAP}px`
|
|
7979
|
+
},
|
|
7980
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
7981
|
+
Input,
|
|
7982
|
+
{
|
|
7983
|
+
ref: inputRef,
|
|
7984
|
+
value: nameValue,
|
|
7985
|
+
onChange: (event) => setNameValue(event.target.value),
|
|
7986
|
+
onKeyDown: handleKeyDown,
|
|
7987
|
+
onBlur: handleBlur,
|
|
7988
|
+
placeholder: "\u041D\u0430\u0437\u0432\u0430\u043D\u0438\u0435 \u0440\u0435\u0441\u0443\u0440\u0441\u0430",
|
|
7989
|
+
className: "gantt-resourceTimeline-resourceInput"
|
|
7990
|
+
}
|
|
7991
|
+
)
|
|
7992
|
+
}
|
|
7993
|
+
);
|
|
7994
|
+
};
|
|
7825
7995
|
function ResourceTimelineChart({
|
|
7826
7996
|
resources,
|
|
7827
7997
|
dayWidth = DEFAULT_DAY_WIDTH,
|
|
@@ -7839,11 +8009,15 @@ function ResourceTimelineChart({
|
|
|
7839
8009
|
renderItem,
|
|
7840
8010
|
getItemClassName,
|
|
7841
8011
|
onResourceItemClick,
|
|
7842
|
-
onResourceItemMove
|
|
8012
|
+
onResourceItemMove,
|
|
8013
|
+
onAddResource,
|
|
8014
|
+
enableAddResource = true,
|
|
8015
|
+
resourceMenuCommands = []
|
|
7843
8016
|
}) {
|
|
7844
8017
|
const scrollContainerRef = (0, import_react14.useRef)(null);
|
|
7845
8018
|
const gridRef = (0, import_react14.useRef)(null);
|
|
7846
8019
|
const panStateRef = (0, import_react14.useRef)(null);
|
|
8020
|
+
const [isCreatingResource, setIsCreatingResource] = (0, import_react14.useState)(false);
|
|
7847
8021
|
const validItems = (0, import_react14.useMemo)(() => collectValidItems(resources), [resources]);
|
|
7848
8022
|
const dateRange = (0, import_react14.useMemo)(() => getMultiMonthDays(validItems), [validItems]);
|
|
7849
8023
|
const monthStart = (0, import_react14.useMemo)(() => {
|
|
@@ -7878,6 +8052,18 @@ function ResourceTimelineChart({
|
|
|
7878
8052
|
}
|
|
7879
8053
|
return map;
|
|
7880
8054
|
}, [layout.items]);
|
|
8055
|
+
const canAddResource = enableAddResource && Boolean(onAddResource);
|
|
8056
|
+
const resourceAddRowHeight = laneHeight + DEFAULT_RESOURCE_ROW_GAP;
|
|
8057
|
+
const displayTotalHeight = layout.totalHeight + (canAddResource ? resourceAddRowHeight : 0);
|
|
8058
|
+
const handleConfirmNewResource = (0, import_react14.useCallback)((name) => {
|
|
8059
|
+
onAddResource?.({
|
|
8060
|
+
id: crypto.randomUUID(),
|
|
8061
|
+
name,
|
|
8062
|
+
items: []
|
|
8063
|
+
});
|
|
8064
|
+
setIsCreatingResource(false);
|
|
8065
|
+
}, [onAddResource]);
|
|
8066
|
+
const handleCancelNewResource = (0, import_react14.useCallback)(() => setIsCreatingResource(false), []);
|
|
7881
8067
|
const { preview, startDrag } = useResourceItemDrag({
|
|
7882
8068
|
dayWidth,
|
|
7883
8069
|
monthStart,
|
|
@@ -7972,28 +8158,34 @@ function ResourceTimelineChart({
|
|
|
7972
8158
|
style: { height: `${headerHeight}px` }
|
|
7973
8159
|
}
|
|
7974
8160
|
),
|
|
7975
|
-
layout.rows.map((row) => /* @__PURE__ */ (0, import_jsx_runtime15.
|
|
7976
|
-
|
|
8161
|
+
layout.rows.map((row) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
8162
|
+
ResourceHeader,
|
|
7977
8163
|
{
|
|
7978
|
-
|
|
7979
|
-
|
|
7980
|
-
|
|
7981
|
-
|
|
7982
|
-
|
|
7983
|
-
|
|
7984
|
-
children: [
|
|
7985
|
-
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "gantt-resourceTimeline-resourceName", children: row.resource.name }),
|
|
7986
|
-
row.conflictCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
7987
|
-
"span",
|
|
7988
|
-
{
|
|
7989
|
-
className: "gantt-resourceTimeline-conflictBadge",
|
|
7990
|
-
"aria-label": `${row.conflictCount} \u043A\u043E\u043D\u0444\u043B\u0438\u043A\u0442\u043E\u0432`,
|
|
7991
|
-
children: row.conflictCount
|
|
7992
|
-
}
|
|
7993
|
-
)
|
|
7994
|
-
]
|
|
8164
|
+
resource: row.resource,
|
|
8165
|
+
resourceId: row.resourceId,
|
|
8166
|
+
conflictCount: row.conflictCount,
|
|
8167
|
+
height: row.resourceRowHeight + DEFAULT_RESOURCE_ROW_GAP,
|
|
8168
|
+
paddingBottom: DEFAULT_RESOURCE_ROW_GAP,
|
|
8169
|
+
menuCommands: resourceMenuCommands
|
|
7995
8170
|
},
|
|
7996
8171
|
row.resourceId
|
|
8172
|
+
)),
|
|
8173
|
+
canAddResource && (isCreatingResource ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
8174
|
+
NewResourceRow,
|
|
8175
|
+
{
|
|
8176
|
+
height: resourceAddRowHeight,
|
|
8177
|
+
onConfirm: handleConfirmNewResource,
|
|
8178
|
+
onCancel: handleCancelNewResource
|
|
8179
|
+
}
|
|
8180
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
8181
|
+
"button",
|
|
8182
|
+
{
|
|
8183
|
+
className: "gantt-resourceTimeline-addResourceButton",
|
|
8184
|
+
type: "button",
|
|
8185
|
+
style: { height: `${resourceAddRowHeight}px` },
|
|
8186
|
+
onClick: () => setIsCreatingResource(true),
|
|
8187
|
+
children: "+ \u0414\u043E\u0431\u0430\u0432\u0438\u0442\u044C \u0440\u0435\u0441\u0443\u0440\u0441"
|
|
8188
|
+
}
|
|
7997
8189
|
))
|
|
7998
8190
|
]
|
|
7999
8191
|
}
|
|
@@ -8019,14 +8211,14 @@ function ResourceTimelineChart({
|
|
|
8019
8211
|
{
|
|
8020
8212
|
ref: gridRef,
|
|
8021
8213
|
className: "gantt-resourceTimeline-grid",
|
|
8022
|
-
style: { width: `${gridWidth}px`, height: `${
|
|
8214
|
+
style: { width: `${gridWidth}px`, height: `${displayTotalHeight}px` },
|
|
8023
8215
|
children: [
|
|
8024
8216
|
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
8025
8217
|
GridBackground_default,
|
|
8026
8218
|
{
|
|
8027
8219
|
dateRange,
|
|
8028
8220
|
dayWidth,
|
|
8029
|
-
totalHeight:
|
|
8221
|
+
totalHeight: displayTotalHeight,
|
|
8030
8222
|
viewMode,
|
|
8031
8223
|
isCustomWeekend: weekendPredicate
|
|
8032
8224
|
}
|
|
@@ -8044,6 +8236,17 @@ function ResourceTimelineChart({
|
|
|
8044
8236
|
},
|
|
8045
8237
|
row.resourceId
|
|
8046
8238
|
)),
|
|
8239
|
+
canAddResource && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
8240
|
+
"div",
|
|
8241
|
+
{
|
|
8242
|
+
className: "gantt-resourceTimeline-row gantt-resourceTimeline-rowNew",
|
|
8243
|
+
"data-resource-add-row": "true",
|
|
8244
|
+
style: {
|
|
8245
|
+
top: `${layout.totalHeight}px`,
|
|
8246
|
+
height: `${resourceAddRowHeight}px`
|
|
8247
|
+
}
|
|
8248
|
+
}
|
|
8249
|
+
),
|
|
8047
8250
|
Array.from(itemsByResourceId.values()).flatMap(
|
|
8048
8251
|
(resourceItems) => resourceItems.map((layoutItem) => {
|
|
8049
8252
|
const customClassName = getItemClassName?.(layoutItem.item);
|
|
@@ -8069,11 +8272,17 @@ function ResourceTimelineChart({
|
|
|
8069
8272
|
}, layoutItem.laneIndex, laneCount);
|
|
8070
8273
|
const overlayStartDate = isDraggingItem ? preview.startDate : layoutItem.startDate;
|
|
8071
8274
|
const overlayEndDate = isDraggingItem ? preview.endDate : layoutItem.endDate;
|
|
8072
|
-
const weekendOverlaySegments = businessDays ?
|
|
8073
|
-
|
|
8074
|
-
|
|
8075
|
-
|
|
8076
|
-
|
|
8275
|
+
const weekendOverlaySegments = businessDays ? clampOverlaySegments(
|
|
8276
|
+
getWeekendOverlaySegments(overlayStartDate, overlayEndDate, dayWidth, weekendPredicate),
|
|
8277
|
+
itemGeometry.width
|
|
8278
|
+
) : [];
|
|
8279
|
+
const conflictOverlaySegments = clampOverlaySegments(
|
|
8280
|
+
getRangeOverlaySegments(
|
|
8281
|
+
overlayStartDate,
|
|
8282
|
+
isDraggingItem ? [] : layoutItem.conflictRanges,
|
|
8283
|
+
dayWidth
|
|
8284
|
+
),
|
|
8285
|
+
itemGeometry.width
|
|
8077
8286
|
);
|
|
8078
8287
|
const durationValue = getDurationValue(
|
|
8079
8288
|
overlayStartDate,
|
|
@@ -9232,6 +9441,11 @@ var not = (predicate) => (task) => !predicate(task);
|
|
|
9232
9441
|
var withoutDeps = (options = {}) => (task) => {
|
|
9233
9442
|
if (!task) return false;
|
|
9234
9443
|
if (options.onlyChildren && !task.parentId) return false;
|
|
9444
|
+
if (options.onlyLeafTasks) {
|
|
9445
|
+
const isParent = (options.tasks ?? []).some((candidate) => candidate.parentId === task.id);
|
|
9446
|
+
const isRegularTask = task.type == null || task.type === "task";
|
|
9447
|
+
if (isParent || !isRegularTask) return false;
|
|
9448
|
+
}
|
|
9235
9449
|
return !task.dependencies || task.dependencies.length === 0;
|
|
9236
9450
|
};
|
|
9237
9451
|
var expired = (referenceDate = /* @__PURE__ */ new Date()) => (task) => isTaskExpired(task, referenceDate);
|