gantt-task-react-v 1.5.27 → 1.6.1
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/README.md +659 -103
- package/dist/components/task-item/bar/bar-display.d.ts +1 -0
- package/dist/components/task-list/task-list-table-columns/assignees-column.d.ts +3 -0
- package/dist/components/task-list/task-list-table-columns/use-task-list-columns-builder.d.ts +6 -0
- package/dist/gantt-task-react.es.js +112 -7
- package/dist/gantt-task-react.umd.js +112 -7
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,133 +1,689 @@
|
|
|
1
|
-
#
|
|
1
|
+
# gantt-task-react-v
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Interactive Gantt Chart for React with TypeScript.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install gantt-task-react-v
|
|
9
|
+
```
|
|
6
10
|
|
|
7
|
-
|
|
8
|
-
- Fixed sticky gantt header on drag
|
|
9
|
-
- Fixed Tooltip should show only on gantt section current view boundaries
|
|
10
|
-
- Added Tooltip for comparison bars
|
|
11
|
-
- Show Custom Data Date Line
|
|
12
|
-
- Customize Data Date Line and Today Line Color and Label
|
|
13
|
-
- Show/Hide Task Table Column
|
|
14
|
-
- Improved staggered and rounded arrows
|
|
15
|
-
- RightClick ContextMenu option for Tasklist and Gantt
|
|
16
|
-
- Custom Drawer on click taskbar and arrow, callback to get taskdata
|
|
11
|
+
## Quick Start
|
|
17
12
|
|
|
18
|
-
|
|
13
|
+
```tsx
|
|
14
|
+
import { Gantt, Task, ViewMode } from "gantt-task-react-v";
|
|
15
|
+
import "gantt-task-react-v/dist/style.css";
|
|
19
16
|
|
|
20
|
-
|
|
17
|
+
const tasks: Task[] = [
|
|
18
|
+
{
|
|
19
|
+
id: "task-1",
|
|
20
|
+
type: "task",
|
|
21
|
+
name: "Design",
|
|
22
|
+
start: new Date(2026, 0, 1),
|
|
23
|
+
end: new Date(2026, 0, 10),
|
|
24
|
+
progress: 60,
|
|
25
|
+
assignees: ["Alice"],
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
id: "task-2",
|
|
29
|
+
type: "task",
|
|
30
|
+
name: "Development",
|
|
31
|
+
start: new Date(2026, 0, 11),
|
|
32
|
+
end: new Date(2026, 1, 15),
|
|
33
|
+
progress: 20,
|
|
34
|
+
dependencies: [
|
|
35
|
+
{
|
|
36
|
+
sourceId: "task-1",
|
|
37
|
+
sourceTarget: "endOfTask",
|
|
38
|
+
ownTarget: "startOfTask",
|
|
39
|
+
},
|
|
40
|
+
],
|
|
41
|
+
assignees: ["Bob", "Carol"],
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
id: "milestone-1",
|
|
45
|
+
type: "milestone",
|
|
46
|
+
name: "MVP Release",
|
|
47
|
+
start: new Date(2026, 1, 15),
|
|
48
|
+
end: new Date(2026, 1, 15),
|
|
49
|
+
progress: 0,
|
|
50
|
+
dependencies: [
|
|
51
|
+
{
|
|
52
|
+
sourceId: "task-2",
|
|
53
|
+
sourceTarget: "endOfTask",
|
|
54
|
+
ownTarget: "startOfTask",
|
|
55
|
+
},
|
|
56
|
+
],
|
|
57
|
+
},
|
|
58
|
+
];
|
|
21
59
|
|
|
60
|
+
function App() {
|
|
61
|
+
return <Gantt tasks={tasks} viewMode={ViewMode.Day} />;
|
|
62
|
+
}
|
|
22
63
|
```
|
|
23
|
-
|
|
64
|
+
|
|
65
|
+
## Core Features
|
|
66
|
+
|
|
67
|
+
### 1. Task List (WBS)
|
|
68
|
+
|
|
69
|
+
Hierarchical work breakdown structure with expand/collapse, nested numbering, drag-and-drop reordering, and resizable columns.
|
|
70
|
+
|
|
71
|
+
```tsx
|
|
72
|
+
<Gantt
|
|
73
|
+
tasks={tasks}
|
|
74
|
+
taskList={{
|
|
75
|
+
isShowTaskNumbers: true,
|
|
76
|
+
canReorderTasks: true,
|
|
77
|
+
canResizeColumns: true,
|
|
78
|
+
canToggleColumns: true,
|
|
79
|
+
}}
|
|
80
|
+
/>
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### 2. Timeline
|
|
84
|
+
|
|
85
|
+
Horizontal time scale supporting multiple view modes.
|
|
86
|
+
|
|
87
|
+
```tsx
|
|
88
|
+
<Gantt tasks={tasks} viewMode={ViewMode.Week} viewDate={new Date()} />
|
|
24
89
|
```
|
|
25
90
|
|
|
26
|
-
|
|
91
|
+
**ViewMode values:** `Hour`, `QuarterDay`, `HalfDay`, `Day`, `Week`, `Month`, `Year`
|
|
92
|
+
|
|
93
|
+
### 3. Task Bars
|
|
27
94
|
|
|
28
|
-
|
|
29
|
-
import { Gantt, Task, EventOption, StylingOption, ViewMode, DisplayOption } from 'gantt-task-react';
|
|
30
|
-
import "gantt-task-react/dist/index.css";
|
|
95
|
+
Bars represent duration and are drag-resizable. Hold **Ctrl** to show start/end drag handles.
|
|
31
96
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
97
|
+
Progress is displayed as a filled overlay with a percentage label on the bar. The progress drag handle allows interactive editing.
|
|
98
|
+
|
|
99
|
+
```tsx
|
|
100
|
+
<Gantt
|
|
101
|
+
tasks={tasks}
|
|
102
|
+
showProgress={true}
|
|
103
|
+
progressColor="#4dabf7"
|
|
104
|
+
taskBar={{
|
|
105
|
+
isProgressChangeable: task => !task.isDisabled,
|
|
106
|
+
isDateChangeable: task => !task.isDisabled,
|
|
107
|
+
allowMoveTaskBar: (action, task) => true,
|
|
108
|
+
}}
|
|
109
|
+
/>
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### 4. Dependencies (Arrows)
|
|
113
|
+
|
|
114
|
+
Arrows link tasks to define execution order. Supports four relation kinds.
|
|
115
|
+
|
|
116
|
+
```tsx
|
|
117
|
+
<Gantt
|
|
118
|
+
tasks={tasks}
|
|
119
|
+
authorizedRelations={["endToStart", "startToStart", "endToEnd", "startToEnd"]}
|
|
120
|
+
taskBar={{
|
|
121
|
+
isRelationChangeable: task => true,
|
|
122
|
+
isDeleteDependencyOnDoubleClick: true,
|
|
123
|
+
onArrowDoubleClick: (taskFrom, taskTo, event) => {
|
|
124
|
+
/* handle */
|
|
42
125
|
},
|
|
43
|
-
|
|
126
|
+
onArrowClick: (taskFrom, taskTo) => {
|
|
127
|
+
/* handle */
|
|
128
|
+
},
|
|
129
|
+
}}
|
|
130
|
+
/>
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
**RelationKind values:** `"startToStart"`, `"startToEnd"`, `"endToStart"`, `"endToEnd"`
|
|
134
|
+
|
|
135
|
+
### 5. Milestones
|
|
136
|
+
|
|
137
|
+
Rendered as diamonds. Set `type: "milestone"` on a task.
|
|
138
|
+
|
|
139
|
+
```tsx
|
|
140
|
+
const milestone: Task = {
|
|
141
|
+
id: "m1",
|
|
142
|
+
type: "milestone",
|
|
143
|
+
name: "Go-Live",
|
|
144
|
+
start: new Date(2026, 3, 1),
|
|
145
|
+
end: new Date(2026, 3, 1),
|
|
146
|
+
progress: 0,
|
|
147
|
+
};
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### 6. Progress Tracking
|
|
151
|
+
|
|
152
|
+
Progress is shown as a filled bar overlay with a percentage label. Tasks have a `progress` field (0–100). The progress drag handle is enabled when `isProgressChangeable` returns true.
|
|
153
|
+
|
|
154
|
+
```tsx
|
|
155
|
+
<Gantt
|
|
156
|
+
tasks={tasks}
|
|
157
|
+
showProgress={true}
|
|
158
|
+
taskBar={{ isProgressChangeable: task => !task.isDisabled }}
|
|
159
|
+
/>
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
### 7. Resource Allocation (Assignees)
|
|
163
|
+
|
|
164
|
+
Tasks support an `assignees` field. Use the built-in `AssigneesColumn` via the columns builder.
|
|
165
|
+
|
|
166
|
+
```tsx
|
|
167
|
+
import { Gantt, useTaskListColumnsBuilder } from "gantt-task-react-v";
|
|
168
|
+
|
|
169
|
+
function App() {
|
|
170
|
+
const {
|
|
171
|
+
createNameColumn,
|
|
172
|
+
createStartDateColumn,
|
|
173
|
+
createEndDateColumn,
|
|
174
|
+
createAssigneesColumn,
|
|
175
|
+
} = useTaskListColumnsBuilder();
|
|
176
|
+
|
|
177
|
+
const columns = [
|
|
178
|
+
createNameColumn("Name", 200),
|
|
179
|
+
createStartDateColumn("Start", 100),
|
|
180
|
+
createEndDateColumn("End", 100),
|
|
181
|
+
createAssigneesColumn("Assignees", 150),
|
|
182
|
+
];
|
|
183
|
+
|
|
184
|
+
return <Gantt tasks={tasks} columns={columns} />;
|
|
185
|
+
}
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
### 8. Critical Path
|
|
189
|
+
|
|
190
|
+
Highlight the longest chain of dependent tasks that determines project duration.
|
|
191
|
+
|
|
192
|
+
```tsx
|
|
193
|
+
<Gantt tasks={tasks} taskBar={{ isShowCriticalPath: true }} />
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
### 9. Today Line & Data Date Line
|
|
197
|
+
|
|
198
|
+
Vertical markers for the current date and a custom data date.
|
|
199
|
+
|
|
200
|
+
```tsx
|
|
201
|
+
<Gantt
|
|
202
|
+
tasks={tasks}
|
|
203
|
+
showTodayLine={true}
|
|
204
|
+
todayColor="#ff6b6b"
|
|
205
|
+
todayLabel="Today"
|
|
206
|
+
showDataDateLine={true}
|
|
207
|
+
dataDate={new Date(2026, 2, 15)}
|
|
208
|
+
dataDateColor="#4dabf7"
|
|
209
|
+
dataDateLabel="Data Date"
|
|
210
|
+
/>
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
---
|
|
214
|
+
|
|
215
|
+
## Drawer Panel
|
|
216
|
+
|
|
217
|
+
A slide-in panel for viewing task/arrow details with built-in "Go to" navigation.
|
|
218
|
+
|
|
219
|
+
```tsx
|
|
220
|
+
<Gantt
|
|
221
|
+
tasks={tasks}
|
|
222
|
+
drawer={{
|
|
223
|
+
enableDrawer: true,
|
|
224
|
+
drawerWidth: 400,
|
|
225
|
+
renderDrawerContent: (data, goToTask) => {
|
|
226
|
+
if (data.type === "task") {
|
|
227
|
+
return (
|
|
228
|
+
<div>
|
|
229
|
+
<h3>{data.task.name}</h3>
|
|
230
|
+
<p>Progress: {data.task.progress}%</p>
|
|
231
|
+
{data.task.dependencies?.map(dep => (
|
|
232
|
+
<button key={dep.sourceId} onClick={() => goToTask(dep.sourceId)}>
|
|
233
|
+
Go to {dep.sourceId}
|
|
234
|
+
</button>
|
|
235
|
+
))}
|
|
236
|
+
</div>
|
|
237
|
+
);
|
|
238
|
+
}
|
|
239
|
+
if (data.type === "arrow") {
|
|
240
|
+
return (
|
|
241
|
+
<div>
|
|
242
|
+
<button onClick={() => goToTask(data.taskFrom.id)}>
|
|
243
|
+
Go to {data.taskFrom.name}
|
|
244
|
+
</button>
|
|
245
|
+
<button onClick={() => goToTask(data.taskTo.id)}>
|
|
246
|
+
Go to {data.taskTo.name}
|
|
247
|
+
</button>
|
|
248
|
+
</div>
|
|
249
|
+
);
|
|
250
|
+
}
|
|
251
|
+
return null;
|
|
252
|
+
},
|
|
253
|
+
}}
|
|
254
|
+
/>
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
The `goToTask(taskId)` function scrolls both horizontally and vertically to center the target task and selects it. Built-in "Go to" buttons also appear automatically in the drawer header for arrow-type panels and task-type panels.
|
|
258
|
+
|
|
259
|
+
## Scroll To Task
|
|
260
|
+
|
|
261
|
+
Programmatically scroll to and select any task by id.
|
|
262
|
+
|
|
263
|
+
```tsx
|
|
264
|
+
const [targetId, setTargetId] = useState<string | undefined>();
|
|
265
|
+
|
|
266
|
+
<Gantt tasks={tasks} scrollToTaskId={targetId} />
|
|
267
|
+
<button onClick={() => setTargetId("task-2")}>Go to Task 2</button>
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
---
|
|
271
|
+
|
|
272
|
+
## Task List Callbacks
|
|
273
|
+
|
|
274
|
+
Row click and double-click callbacks are inside the `taskList` prop.
|
|
275
|
+
|
|
276
|
+
```tsx
|
|
277
|
+
<Gantt
|
|
278
|
+
tasks={tasks}
|
|
279
|
+
taskList={{
|
|
280
|
+
onClickTaskRow: task => console.log("Clicked:", task.id),
|
|
281
|
+
onDoubleClickTaskRow: task => console.log("Double-clicked:", task.id),
|
|
282
|
+
}}
|
|
283
|
+
/>
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
---
|
|
287
|
+
|
|
288
|
+
## Custom Columns
|
|
289
|
+
|
|
290
|
+
Build columns with the hook or provide fully custom ones.
|
|
291
|
+
|
|
292
|
+
```tsx
|
|
293
|
+
import {
|
|
294
|
+
Gantt,
|
|
295
|
+
useTaskListColumnsBuilder,
|
|
296
|
+
Column,
|
|
297
|
+
ColumnProps,
|
|
298
|
+
} from "gantt-task-react-v";
|
|
299
|
+
|
|
300
|
+
// Custom column component
|
|
301
|
+
const ProgressColumn: React.FC<ColumnProps> = ({ data: { task } }) => {
|
|
302
|
+
if (task.type === "empty") return null;
|
|
303
|
+
return <>{task.progress}%</>;
|
|
304
|
+
};
|
|
305
|
+
|
|
306
|
+
function App() {
|
|
307
|
+
const { createNameColumn, createDeleteActionColumn, createEditActionColumn } =
|
|
308
|
+
useTaskListColumnsBuilder();
|
|
309
|
+
|
|
310
|
+
const columns: Column[] = [
|
|
311
|
+
createNameColumn("Task", 200),
|
|
312
|
+
{ id: "progress", component: ProgressColumn, width: 80, title: "Progress" },
|
|
313
|
+
createEditActionColumn(40),
|
|
314
|
+
createDeleteActionColumn(40),
|
|
315
|
+
];
|
|
316
|
+
|
|
317
|
+
return <Gantt tasks={tasks} columns={columns} />;
|
|
318
|
+
}
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
### Column Pinning
|
|
322
|
+
|
|
323
|
+
Pin columns so they stay visible while scrolling.
|
|
324
|
+
|
|
325
|
+
```tsx
|
|
326
|
+
const columns: Column[] = [
|
|
327
|
+
{ ...createNameColumn("Task", 200), pinned: "left" },
|
|
328
|
+
createStartDateColumn("Start", 100),
|
|
329
|
+
createEndDateColumn("End", 100),
|
|
330
|
+
{ ...createDeleteActionColumn(40), pinned: "right" },
|
|
44
331
|
];
|
|
45
|
-
<Gantt tasks={tasks} />
|
|
46
332
|
```
|
|
47
333
|
|
|
48
|
-
|
|
334
|
+
### Column Visibility
|
|
49
335
|
|
|
50
|
-
|
|
336
|
+
Columns can be hidden and toggled by the user.
|
|
337
|
+
|
|
338
|
+
```tsx
|
|
51
339
|
<Gantt
|
|
52
340
|
tasks={tasks}
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
341
|
+
columns={[
|
|
342
|
+
createNameColumn("Task", 200),
|
|
343
|
+
{ ...createStartDateColumn("Start"), hidden: true },
|
|
344
|
+
]}
|
|
345
|
+
taskList={{
|
|
346
|
+
canToggleColumns: true,
|
|
347
|
+
onColumnVisibilityChange: columns => console.log(columns),
|
|
348
|
+
}}
|
|
59
349
|
/>
|
|
60
350
|
```
|
|
61
351
|
|
|
62
|
-
|
|
352
|
+
### Built-in Columns Builder Methods
|
|
353
|
+
|
|
354
|
+
| Method | Description |
|
|
355
|
+
| ----------------------------------------- | ------------------------------ |
|
|
356
|
+
| `createNameColumn(title, width?)` | Task name with expand/collapse |
|
|
357
|
+
| `createStartDateColumn(title, width?)` | Start date |
|
|
358
|
+
| `createEndDateColumn(title, width?)` | End date |
|
|
359
|
+
| `createDependenciesColumn(title, width?)` | Dependency names |
|
|
360
|
+
| `createAssigneesColumn(title, width?)` | Assignees list |
|
|
361
|
+
| `createEditActionColumn(width?)` | Edit button |
|
|
362
|
+
| `createDeleteActionColumn(width?)` | Delete button |
|
|
363
|
+
| `createAddActionColumn(width?)` | Add task button |
|
|
364
|
+
|
|
365
|
+
---
|
|
366
|
+
|
|
367
|
+
## Context Menu
|
|
368
|
+
|
|
369
|
+
Right-click context menus for the task list and chart area.
|
|
63
370
|
|
|
64
|
-
```
|
|
65
|
-
|
|
371
|
+
```tsx
|
|
372
|
+
import {
|
|
373
|
+
Gantt,
|
|
374
|
+
createCopyOption,
|
|
375
|
+
createCutOption,
|
|
376
|
+
createPasteOption,
|
|
377
|
+
createDeleteOption,
|
|
378
|
+
createEditOption,
|
|
379
|
+
} from "gantt-task-react-v";
|
|
380
|
+
|
|
381
|
+
<Gantt
|
|
382
|
+
tasks={tasks}
|
|
383
|
+
taskList={{
|
|
384
|
+
enableTableListContextMenu: 1, // right-click trigger
|
|
385
|
+
contextMenuOptions: [
|
|
386
|
+
createEditOption(),
|
|
387
|
+
createCopyOption(),
|
|
388
|
+
createCutOption(),
|
|
389
|
+
createPasteOption(),
|
|
390
|
+
createDeleteOption(),
|
|
391
|
+
],
|
|
392
|
+
}}
|
|
393
|
+
onRowContextMenu={task => console.log("Right-clicked:", task.id)}
|
|
394
|
+
/>;
|
|
395
|
+
```
|
|
396
|
+
|
|
397
|
+
---
|
|
398
|
+
|
|
399
|
+
## Theming
|
|
400
|
+
|
|
401
|
+
Customize colors, typography, shapes, distances, and date formats.
|
|
402
|
+
|
|
403
|
+
```tsx
|
|
404
|
+
<Gantt
|
|
405
|
+
tasks={tasks}
|
|
406
|
+
theme={{
|
|
407
|
+
rtl: false,
|
|
408
|
+
colors: {
|
|
409
|
+
barProgressColor: "#4dabf7",
|
|
410
|
+
barBackgroundColor: "#e3f2fd",
|
|
411
|
+
barBackgroundSelectedColor: "#bbdefb",
|
|
412
|
+
milestoneBackgroundColor: "#7c4dff",
|
|
413
|
+
arrowColor: "#90a4ae",
|
|
414
|
+
calendarTodayColor: "#ff6b6b",
|
|
415
|
+
tableSelectedTaskBackgroundColor: "#e3f2fd",
|
|
416
|
+
},
|
|
417
|
+
typography: {
|
|
418
|
+
fontFamily: "'Inter', sans-serif",
|
|
419
|
+
fontSize: "13px",
|
|
420
|
+
},
|
|
421
|
+
shape: {
|
|
422
|
+
borderRadius: "4px",
|
|
423
|
+
},
|
|
424
|
+
distances: {
|
|
425
|
+
rowHeight: 40,
|
|
426
|
+
},
|
|
427
|
+
dateFormats: {
|
|
428
|
+
dateColumnFormat: "dd/MM/yyyy",
|
|
429
|
+
},
|
|
430
|
+
}}
|
|
431
|
+
/>
|
|
66
432
|
```
|
|
67
433
|
|
|
68
|
-
|
|
434
|
+
### Color Reference
|
|
435
|
+
|
|
436
|
+
| Group | Keys |
|
|
437
|
+
| -------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
438
|
+
| **Bar** | `barProgressColor`, `barProgressCriticalColor`, `barProgressSelectedColor`, `barProgressSelectedCriticalColor`, `barBackgroundColor`, `barBackgroundCriticalColor`, `barBackgroundSelectedColor`, `barBackgroundSelectedCriticalColor`, `barHandleColor` |
|
|
439
|
+
| **Group** | `groupProgressColor`, `groupProgressCriticalColor`, `groupProgressSelectedColor`, `groupProgressSelectedCriticalColor`, `groupBackgroundColor`, `groupBackgroundCriticalColor`, `groupBackgroundSelectedColor`, `groupBackgroundSelectedCriticalColor` |
|
|
440
|
+
| **Project** | `projectProgressColor`, `projectProgressCriticalColor`, `projectProgressSelectedColor`, `projectProgressSelectedCriticalColor`, `projectBackgroundColor`, `projectBackgroundCriticalColor`, `projectBackgroundSelectedColor`, `projectBackgroundSelectedCriticalColor` |
|
|
441
|
+
| **Milestone** | `milestoneBackgroundColor`, `milestoneBackgroundCriticalColor`, `milestoneBackgroundSelectedColor`, `milestoneBackgroundSelectedCriticalColor` |
|
|
442
|
+
| **Comparison** | `barComparisonDefaultColor`, `barComparisonPlanColor`, `barComparisonWarningColor`, `barComparisonCriticalColor` |
|
|
443
|
+
| **Arrow** | `arrowColor`, `arrowCriticalColor`, `arrowRelationColor`, `arrowHoverColor` |
|
|
444
|
+
| **Calendar** | `calendarHolidayColor`, `calendarTodayColor`, `calendarStrokeColor` |
|
|
445
|
+
| **Table** | `tableDragTaskBackgroundColor`, `tableSelectedTaskBackgroundColor`, `tableActionColor`, `tableDragIndicatorColor`, `tableHoverActionColor`, `tableEvenBackgroundColor` |
|
|
446
|
+
| **UI** | `backgroundColor`, `dividerColor`, `hoverFilter`, `loadingPrimaryColor`, `loadingSecondaryColor`, `contextMenuBoxShadow`, `contextMenuBgColor`, `contextMenuTextColor`, `tooltipBoxShadow`, `scrollbarThumbColor`, `primaryTextColor`, `secondaryTextColor` |
|
|
447
|
+
|
|
448
|
+
---
|
|
449
|
+
|
|
450
|
+
## Locale
|
|
451
|
+
|
|
452
|
+
```tsx
|
|
453
|
+
import { Gantt, GanttLocale } from "gantt-task-react-v";
|
|
454
|
+
import { enUS } from "date-fns/locale";
|
|
455
|
+
|
|
456
|
+
const locale: GanttLocale = {
|
|
457
|
+
dateLocale: enUS,
|
|
458
|
+
suffix: { days: "days" },
|
|
459
|
+
tooltip: { duration: "Duration", progress: "Progress" },
|
|
460
|
+
table: {
|
|
461
|
+
columns: {
|
|
462
|
+
name: "Task",
|
|
463
|
+
startDate: "Start",
|
|
464
|
+
endDate: "End",
|
|
465
|
+
dependencies: "Dependencies",
|
|
466
|
+
progress: "Progress",
|
|
467
|
+
},
|
|
468
|
+
},
|
|
469
|
+
context: {
|
|
470
|
+
edit: "Edit",
|
|
471
|
+
copy: "Copy",
|
|
472
|
+
cut: "Cut",
|
|
473
|
+
paste: "Paste",
|
|
474
|
+
delete: "Delete",
|
|
475
|
+
},
|
|
476
|
+
};
|
|
477
|
+
|
|
478
|
+
<Gantt tasks={tasks} locale={locale} />;
|
|
479
|
+
```
|
|
480
|
+
|
|
481
|
+
---
|
|
482
|
+
|
|
483
|
+
## Task Lifecycle Callbacks
|
|
484
|
+
|
|
485
|
+
```tsx
|
|
486
|
+
<Gantt
|
|
487
|
+
tasks={tasks}
|
|
488
|
+
onCommitTasks={async (nextTasks, action) => {
|
|
489
|
+
// Persist changes — return { tasks } to confirm or throw to revert
|
|
490
|
+
await saveTasks(nextTasks);
|
|
491
|
+
return {};
|
|
492
|
+
}}
|
|
493
|
+
onAddTaskAction={async parentTask => {
|
|
494
|
+
// Return new task data or null to cancel
|
|
495
|
+
return {
|
|
496
|
+
id: "new-1",
|
|
497
|
+
type: "task",
|
|
498
|
+
name: "New",
|
|
499
|
+
start: new Date(),
|
|
500
|
+
end: new Date(),
|
|
501
|
+
progress: 0,
|
|
502
|
+
};
|
|
503
|
+
}}
|
|
504
|
+
onEditTaskAction={async task => {
|
|
505
|
+
// Return edited task or null to cancel
|
|
506
|
+
return { ...task, name: "Edited" };
|
|
507
|
+
}}
|
|
508
|
+
onSelectTaskIds={ids => console.log("Selected:", ids)}
|
|
509
|
+
/>
|
|
510
|
+
```
|
|
511
|
+
|
|
512
|
+
---
|
|
513
|
+
|
|
514
|
+
## Comparison Mode
|
|
515
|
+
|
|
516
|
+
Overlay plan vs actual dates by providing `comparisonDates` on tasks.
|
|
517
|
+
|
|
518
|
+
```tsx
|
|
519
|
+
const tasks: Task[] = [
|
|
520
|
+
{
|
|
521
|
+
id: "1",
|
|
522
|
+
type: "task",
|
|
523
|
+
name: "Feature A",
|
|
524
|
+
start: new Date(2026, 0, 5), // actual
|
|
525
|
+
end: new Date(2026, 0, 20),
|
|
526
|
+
progress: 50,
|
|
527
|
+
comparisonDates: {
|
|
528
|
+
start: new Date(2026, 0, 1), // planned
|
|
529
|
+
end: new Date(2026, 0, 15),
|
|
530
|
+
},
|
|
531
|
+
},
|
|
532
|
+
];
|
|
533
|
+
|
|
534
|
+
<Gantt tasks={tasks} comparisonLevels={2} />;
|
|
535
|
+
```
|
|
536
|
+
|
|
537
|
+
---
|
|
538
|
+
|
|
539
|
+
## Full API Reference
|
|
69
540
|
|
|
70
541
|
### GanttProps
|
|
71
542
|
|
|
72
|
-
|
|
|
73
|
-
|
|
|
74
|
-
| tasks
|
|
75
|
-
|
|
|
76
|
-
|
|
|
77
|
-
| [
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
|
82
|
-
|
|
|
83
|
-
|
|
|
84
|
-
|
|
|
85
|
-
|
|
|
86
|
-
|
|
|
87
|
-
|
|
|
88
|
-
|
|
|
89
|
-
|
|
|
90
|
-
|
|
|
91
|
-
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
|
98
|
-
|
|
|
99
|
-
|
|
|
100
|
-
|
|
|
101
|
-
|
|
|
102
|
-
|
|
|
103
|
-
|
|
|
104
|
-
|
|
|
105
|
-
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
|
110
|
-
|
|
|
111
|
-
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
|
116
|
-
|
|
|
117
|
-
|
|
|
118
|
-
|
|
|
119
|
-
|
|
|
120
|
-
|
|
|
121
|
-
|
|
|
122
|
-
|
|
|
123
|
-
|
|
|
124
|
-
|
|
|
125
|
-
|
|
|
126
|
-
|
|
|
127
|
-
|
|
|
128
|
-
|
|
|
129
|
-
|
|
|
130
|
-
|
|
|
543
|
+
| Prop | Type | Default | Description |
|
|
544
|
+
| --------------------------------- | --------------------------------------- | ------------- | ------------------------------- |
|
|
545
|
+
| `tasks` | `RenderTask[]` | **required** | Array of tasks to display |
|
|
546
|
+
| `viewMode` | `ViewMode` | `Day` | Time scale |
|
|
547
|
+
| `viewDate` | `Date` | — | Scroll to this date on mount |
|
|
548
|
+
| `columns` | `Column[]` | — | Custom table columns |
|
|
549
|
+
| `language` | `string` | — | Language code |
|
|
550
|
+
| `locale` | `GanttLocale` | English | Localization strings |
|
|
551
|
+
| `theme` | `GanttPartialTheme` | — | Theme overrides |
|
|
552
|
+
| `taskBar` | `GanttTaskBarProps` | — | Chart bar options |
|
|
553
|
+
| `taskList` | `GanttTaskListProps` | — | Task list options |
|
|
554
|
+
| `drawer` | `GanttDrawerProps` | — | Drawer panel options |
|
|
555
|
+
| `authorizedRelations` | `RelationKind[]` | all four | Allowed dependency types |
|
|
556
|
+
| `timeStep` | `number` | `300000` | Snap interval in ms |
|
|
557
|
+
| `comparisonLevels` | `number` | `1` | Number of comparison levels |
|
|
558
|
+
| `rowHeight` | `number` | theme default | Row height in pixels |
|
|
559
|
+
| `showTodayLine` | `boolean` | `true` | Show today marker |
|
|
560
|
+
| `showDataDateLine` | `boolean` | `false` | Show data-date marker |
|
|
561
|
+
| `dataDate` | `Date \| null` | `null` | Data date value |
|
|
562
|
+
| `todayColor` | `string` | theme default | Today line color |
|
|
563
|
+
| `dataDateColor` | `string` | theme default | Data date line color |
|
|
564
|
+
| `todayLabel` | `string` | `"Today"` | Today marker label |
|
|
565
|
+
| `dataDateLabel` | `string` | `"Data Date"` | Data date marker label |
|
|
566
|
+
| `showProgress` | `boolean` | `true` | Show progress fill on bars |
|
|
567
|
+
| `progressColor` | `string` | theme default | Custom progress color |
|
|
568
|
+
| `scrollToTaskId` | `TaskId` | — | Scroll to and select this task |
|
|
569
|
+
| `isMoveChildsWithParent` | `boolean` | `true` | Move children when parent moves |
|
|
570
|
+
| `isUpdateDisabledParentsOnChange` | `boolean` | `true` | Recompute parents on commit |
|
|
571
|
+
| `isUnknownDates` | `boolean` | `false` | Show offsets instead of dates |
|
|
572
|
+
| `isAdjustToWorkingDates` | `boolean` | `true` | Snap to working days |
|
|
573
|
+
| `checkIsHoliday` | `CheckIsHoliday` | — | Holiday check function |
|
|
574
|
+
| `getCopiedTaskId` | `GetCopiedTaskId` | — | ID generator for paste |
|
|
575
|
+
| `roundStartDate` | `(date, viewMode) => Date` | — | Round start after drag |
|
|
576
|
+
| `roundEndDate` | `(date, viewMode) => Date` | — | Round end after drag |
|
|
577
|
+
| `onCommitTasks` | `OnCommitTasks` | — | Task change callback |
|
|
578
|
+
| `onAddTaskAction` | `(task) => Promise<RenderTask \| null>` | — | Add task handler |
|
|
579
|
+
| `onEditTaskAction` | `(task) => Promise<RenderTask \| null>` | — | Edit task handler |
|
|
580
|
+
| `onSelectTaskIds` | `(ids: TaskId[]) => void` | — | Selection change |
|
|
581
|
+
| `onWheel` | `(event: WheelEvent) => void` | — | Wheel event |
|
|
582
|
+
| `onRowContextMenu` | `(task: RenderTask) => void` | — | Row right-click |
|
|
583
|
+
|
|
584
|
+
### Task
|
|
585
|
+
|
|
586
|
+
| Field | Type | Description |
|
|
587
|
+
| ----------------- | ------------------------------------ | ----------------------------- |
|
|
588
|
+
| `id` | `string` | Unique identifier |
|
|
589
|
+
| `type` | `"task" \| "milestone" \| "project"` | Task type |
|
|
590
|
+
| `name` | `string` | Display name |
|
|
591
|
+
| `start` | `Date` | Start date |
|
|
592
|
+
| `end` | `Date` | End date |
|
|
593
|
+
| `progress` | `number` | Completion percentage (0–100) |
|
|
594
|
+
| `assignees` | `string[]` | Assigned resources |
|
|
595
|
+
| `parent` | `string` | Parent task id for hierarchy |
|
|
596
|
+
| `dependencies` | `Dependency[]` | Task dependencies |
|
|
597
|
+
| `comparisonDates` | `{ start, end }` | Plan dates for comparison |
|
|
598
|
+
| `hideChildren` | `boolean` | Collapse children |
|
|
599
|
+
| `isDisabled` | `boolean` | Disable interactions |
|
|
600
|
+
| `displayOrder` | `number` | Sort order |
|
|
601
|
+
| `comparisonLevel` | `number` | Comparison level index |
|
|
602
|
+
| `style` | `CSSProperties` | Custom bar styles |
|
|
603
|
+
| `payload` | `Record<string, string>` | Custom data |
|
|
604
|
+
|
|
605
|
+
### GanttTaskListProps
|
|
606
|
+
|
|
607
|
+
| Prop | Type | Default | Description |
|
|
608
|
+
| ---------------------------- | -------------------------------- | ------------ | ----------------------------- |
|
|
609
|
+
| `isShowTaskNumbers` | `boolean` | `true` | Show row numbers |
|
|
610
|
+
| `canReorderTasks` | `boolean` | `true` | Enable drag reorder |
|
|
611
|
+
| `canResizeColumns` | `boolean` | `true` | Enable column resize |
|
|
612
|
+
| `canToggleColumns` | `boolean` | `false` | Show column visibility toggle |
|
|
613
|
+
| `allowReorderTask` | `AllowReorderTask` | `() => true` | Per-task reorder guard |
|
|
614
|
+
| `enableTableListContextMenu` | `number` | `1` | Context menu trigger |
|
|
615
|
+
| `contextMenuOptions` | `ContextMenuOptionType[]` | — | Menu options |
|
|
616
|
+
| `icons` | `Partial<GanttRenderIconsProps>` | — | Custom icons |
|
|
617
|
+
| `onResizeColumn` | `OnResizeColumn` | — | Column resize callback |
|
|
618
|
+
| `onColumnVisibilityChange` | `OnColumnVisibilityChange` | — | Visibility change callback |
|
|
619
|
+
| `tableBottom` | `TableRenderBottomProps` | — | Footer render |
|
|
620
|
+
| `onClickTaskRow` | `(task: RenderTask) => void` | — | Row click |
|
|
621
|
+
| `onDoubleClickTaskRow` | `(task: RenderTask) => void` | — | Row double-click |
|
|
622
|
+
|
|
623
|
+
### GanttTaskBarProps
|
|
624
|
+
|
|
625
|
+
| Prop | Type | Default | Description |
|
|
626
|
+
| --------------------------------- | ---------------------------- | ------------------ | ------------------------------- |
|
|
627
|
+
| `isShowCriticalPath` | `boolean` | `false` | Show critical path |
|
|
628
|
+
| `isProgressChangeable` | `(task) => boolean` | `!task.isDisabled` | Allow progress drag |
|
|
629
|
+
| `isDateChangeable` | `(task) => boolean` | `!task.isDisabled` | Allow date drag |
|
|
630
|
+
| `isRelationChangeable` | `(task) => boolean` | — | Allow relation draw |
|
|
631
|
+
| `isDeleteDependencyOnDoubleClick` | `boolean` | `true` | Delete deps on dblclick |
|
|
632
|
+
| `preStepsCount` | `number` | `1` | Empty columns before first task |
|
|
633
|
+
| `allowMoveTaskBar` | `(action, task) => boolean` | — | Per-action move guard |
|
|
634
|
+
| `renderBottomHeader` | `RenderBottomHeader` | — | Custom bottom header |
|
|
635
|
+
| `renderTopHeader` | `RenderTopHeader` | — | Custom top header |
|
|
636
|
+
| `renderCustomLabel` | `RenderCustomLabel` | — | Custom bar label |
|
|
637
|
+
| `TooltipContent` | `ComponentType<{ task }>` | built-in | Custom tooltip |
|
|
638
|
+
| `taskGanttContextMenuOption` | `ContextMenuOptionType[]` | — | Chart context menu |
|
|
639
|
+
| `onClick` | `(task: RenderTask) => void` | — | Bar click |
|
|
640
|
+
| `onDoubleClick` | `(task: Task) => void` | — | Bar double-click |
|
|
641
|
+
| `onArrowClick` | `(from, to) => void` | — | Arrow click |
|
|
642
|
+
| `onArrowDoubleClick` | `OnArrowDoubleClick` | — | Arrow double-click |
|
|
643
|
+
|
|
644
|
+
### GanttDrawerProps
|
|
645
|
+
|
|
646
|
+
| Prop | Type | Default | Description |
|
|
647
|
+
| --------------------- | --------------------- | ------- | ----------------------- |
|
|
648
|
+
| `enableDrawer` | `boolean` | `false` | Enable drawer panel |
|
|
649
|
+
| `drawerWidth` | `number` | `360` | Panel width in px |
|
|
650
|
+
| `renderDrawerContent` | `RenderDrawerContent` | — | Custom content renderer |
|
|
651
|
+
|
|
652
|
+
`RenderDrawerContent = (data: GanttDrawerData, goToTask: (taskId: string) => void) => ReactNode`
|
|
653
|
+
|
|
654
|
+
### Column
|
|
655
|
+
|
|
656
|
+
| Field | Type | Description |
|
|
657
|
+
| ----------- | ---------------------------- | ------------------ |
|
|
658
|
+
| `id` | `string` | Unique column id |
|
|
659
|
+
| `component` | `ComponentType<ColumnProps>` | Render component |
|
|
660
|
+
| `width` | `number` | Column width in px |
|
|
661
|
+
| `title` | `ReactNode` | Header text |
|
|
662
|
+
| `canResize` | `boolean` | Allow resize |
|
|
663
|
+
| `pinned` | `"left" \| "right"` | Sticky pinning |
|
|
664
|
+
| `hidden` | `boolean` | Hide column |
|
|
665
|
+
|
|
666
|
+
---
|
|
667
|
+
|
|
668
|
+
## Running Storybook
|
|
669
|
+
|
|
670
|
+
```bash
|
|
671
|
+
npm run storybook
|
|
672
|
+
```
|
|
673
|
+
|
|
674
|
+
## License
|
|
675
|
+
|
|
676
|
+
MIT
|
|
677
|
+
| barProgressColor | string | Specifies the taskbar progress fill color globally. |
|
|
678
|
+
| barProgressSelectedColor | string | Specifies the taskbar progress fill color globally on select. |
|
|
679
|
+
| barBackgroundColor | string | Specifies the taskbar background fill color globally. |
|
|
680
|
+
| barBackgroundSelectedColor | string | Specifies the taskbar background fill color globally on select. |
|
|
681
|
+
| arrowColor | string | Specifies the relationship arrow fill color. |
|
|
682
|
+
| arrowIndent | number | Specifies the relationship arrow right indent. Sets in px |
|
|
683
|
+
| todayColor | string | Specifies the current period column fill color. |
|
|
684
|
+
| TooltipContent | | Specifies the Tooltip view for selected taskbar. |
|
|
685
|
+
| TaskListHeader | | Specifies the task list Header view |
|
|
686
|
+
| TaskListTable | | Specifies the task list Table view |
|
|
131
687
|
|
|
132
688
|
- TooltipContent: [`React.FC<{ task: Task; fontSize: string; fontFamily: string; }>;`](https://github.com/MaTeMaTuK/gantt-task-react/blob/main/src/components/other/tooltip.tsx#L56)
|
|
133
689
|
- TaskListHeader: `React.FC<{ headerHeight: number; rowWidth: string; fontFamily: string; fontSize: string;}>;`
|
package/dist/components/task-list/task-list-table-columns/use-task-list-columns-builder.d.ts
CHANGED
|
@@ -42,4 +42,10 @@ export declare function useTaskListColumnsBuilder(): {
|
|
|
42
42
|
width: number;
|
|
43
43
|
canResize: boolean;
|
|
44
44
|
};
|
|
45
|
+
createAssigneesColumn: (title: React.ReactNode | null, width?: number) => {
|
|
46
|
+
id: string;
|
|
47
|
+
component: React.FC<import("../../..").ColumnProps>;
|
|
48
|
+
width: number;
|
|
49
|
+
title: React.ReactNode;
|
|
50
|
+
};
|
|
45
51
|
};
|
|
@@ -5017,6 +5017,16 @@ const AddColumn = ({
|
|
|
5017
5017
|
}
|
|
5018
5018
|
);
|
|
5019
5019
|
};
|
|
5020
|
+
const AssigneesColumn = ({ data: { task } }) => {
|
|
5021
|
+
if (task.type === "empty") {
|
|
5022
|
+
return null;
|
|
5023
|
+
}
|
|
5024
|
+
const assignees = task.assignees;
|
|
5025
|
+
if (!assignees || assignees.length === 0) {
|
|
5026
|
+
return null;
|
|
5027
|
+
}
|
|
5028
|
+
return /* @__PURE__ */ jsx(Fragment, { children: assignees.join(", ") });
|
|
5029
|
+
};
|
|
5020
5030
|
function useTaskListColumnsBuilder() {
|
|
5021
5031
|
const createNameColumn = useCallback(
|
|
5022
5032
|
(title2, width) => {
|
|
@@ -5086,6 +5096,17 @@ function useTaskListColumnsBuilder() {
|
|
|
5086
5096
|
canResize: false
|
|
5087
5097
|
};
|
|
5088
5098
|
}, []);
|
|
5099
|
+
const createAssigneesColumn = useCallback(
|
|
5100
|
+
(title2, width) => {
|
|
5101
|
+
return {
|
|
5102
|
+
id: "AssigneesColumn",
|
|
5103
|
+
component: AssigneesColumn,
|
|
5104
|
+
width: width || 120,
|
|
5105
|
+
title: title2
|
|
5106
|
+
};
|
|
5107
|
+
},
|
|
5108
|
+
[]
|
|
5109
|
+
);
|
|
5089
5110
|
return {
|
|
5090
5111
|
createNameColumn,
|
|
5091
5112
|
createStartDateColumn,
|
|
@@ -5093,7 +5114,8 @@ function useTaskListColumnsBuilder() {
|
|
|
5093
5114
|
createDependenciesColumn,
|
|
5094
5115
|
createDeleteActionColumn,
|
|
5095
5116
|
createEditActionColumn,
|
|
5096
|
-
createAddActionColumn
|
|
5117
|
+
createAddActionColumn,
|
|
5118
|
+
createAssigneesColumn
|
|
5097
5119
|
};
|
|
5098
5120
|
}
|
|
5099
5121
|
const DEFAULT_THEME = {
|
|
@@ -12176,6 +12198,17 @@ const progressWithByParams = (taskX1, taskX2, progress, rtl) => {
|
|
|
12176
12198
|
}
|
|
12177
12199
|
return [progressWidth, progressX];
|
|
12178
12200
|
};
|
|
12201
|
+
const getProgressPoint = (progressX, taskY, taskHeight) => {
|
|
12202
|
+
const point = [
|
|
12203
|
+
progressX - 5,
|
|
12204
|
+
taskY + taskHeight,
|
|
12205
|
+
progressX + 5,
|
|
12206
|
+
taskY + taskHeight,
|
|
12207
|
+
progressX,
|
|
12208
|
+
taskY + taskHeight - 8.66
|
|
12209
|
+
];
|
|
12210
|
+
return point.join(",");
|
|
12211
|
+
};
|
|
12179
12212
|
const dateByX = (x, taskX, taskDate, xStep, timeStep) => {
|
|
12180
12213
|
const safeX = isNaN(x) || !isFinite(x) ? 0 : x;
|
|
12181
12214
|
const safeTaskX = isNaN(taskX) || !isFinite(taskX) ? 0 : taskX;
|
|
@@ -12355,6 +12388,7 @@ const BarDisplay = ({
|
|
|
12355
12388
|
height,
|
|
12356
12389
|
progressWidth,
|
|
12357
12390
|
progressX,
|
|
12391
|
+
progress,
|
|
12358
12392
|
startMoveFullTask,
|
|
12359
12393
|
width,
|
|
12360
12394
|
x,
|
|
@@ -12455,6 +12489,24 @@ const BarDisplay = ({
|
|
|
12455
12489
|
rx: barCornerRadius,
|
|
12456
12490
|
fill: processColor
|
|
12457
12491
|
}
|
|
12492
|
+
),
|
|
12493
|
+
showProgress && width > 40 && /* @__PURE__ */ jsxs(
|
|
12494
|
+
"text",
|
|
12495
|
+
{
|
|
12496
|
+
x: x + width / 2,
|
|
12497
|
+
y: y + height / 2,
|
|
12498
|
+
dominantBaseline: "central",
|
|
12499
|
+
textAnchor: "middle",
|
|
12500
|
+
fill: "#fff",
|
|
12501
|
+
fontSize: 11,
|
|
12502
|
+
fontWeight: 600,
|
|
12503
|
+
pointerEvents: "none",
|
|
12504
|
+
style: { userSelect: "none" },
|
|
12505
|
+
children: [
|
|
12506
|
+
Math.round(progress),
|
|
12507
|
+
"%"
|
|
12508
|
+
]
|
|
12509
|
+
}
|
|
12458
12510
|
)
|
|
12459
12511
|
]
|
|
12460
12512
|
}
|
|
@@ -12495,6 +12547,31 @@ const BarDateHandle = ({
|
|
|
12495
12547
|
}
|
|
12496
12548
|
);
|
|
12497
12549
|
};
|
|
12550
|
+
const BarProgressHandle = ({
|
|
12551
|
+
taskId,
|
|
12552
|
+
progressPoint,
|
|
12553
|
+
startMoveProgress,
|
|
12554
|
+
className
|
|
12555
|
+
}) => {
|
|
12556
|
+
return /* @__PURE__ */ jsx(
|
|
12557
|
+
"polygon",
|
|
12558
|
+
{
|
|
12559
|
+
"data-testid": `bar-progress-handle-${taskId}`,
|
|
12560
|
+
className,
|
|
12561
|
+
points: progressPoint,
|
|
12562
|
+
onMouseDown: (e) => {
|
|
12563
|
+
e.stopPropagation();
|
|
12564
|
+
startMoveProgress(e.clientX);
|
|
12565
|
+
},
|
|
12566
|
+
onTouchStart: (e) => {
|
|
12567
|
+
const firstTouch = e.touches[0];
|
|
12568
|
+
if (firstTouch) {
|
|
12569
|
+
startMoveProgress(firstTouch.clientX);
|
|
12570
|
+
}
|
|
12571
|
+
}
|
|
12572
|
+
}
|
|
12573
|
+
);
|
|
12574
|
+
};
|
|
12498
12575
|
const projectWrapper = "_projectWrapper_1maxt_1";
|
|
12499
12576
|
const projectBackground = "_projectBackground_1maxt_11";
|
|
12500
12577
|
const projectTop = "_projectTop_1maxt_21";
|
|
@@ -12706,7 +12783,7 @@ const Bar = (props) => {
|
|
|
12706
12783
|
showProgress = true,
|
|
12707
12784
|
progressColor
|
|
12708
12785
|
} = props;
|
|
12709
|
-
useMemo(() => width < 30, [width]);
|
|
12786
|
+
const isSmallWidth = useMemo(() => width < 30, [width]);
|
|
12710
12787
|
const handleHeight = useMemo(() => taskHeight - 2, [taskHeight]);
|
|
12711
12788
|
const rootRef = useRef();
|
|
12712
12789
|
const [ctrlPressed, setCtrlPressed] = useState(true);
|
|
@@ -12740,12 +12817,17 @@ const Bar = (props) => {
|
|
|
12740
12817
|
},
|
|
12741
12818
|
[onTaskEventStart]
|
|
12742
12819
|
);
|
|
12743
|
-
useCallback(
|
|
12820
|
+
const startMoveProgress = useCallback(
|
|
12744
12821
|
(clientX) => {
|
|
12745
12822
|
onTaskEventStart("progress", clientX);
|
|
12746
12823
|
},
|
|
12747
12824
|
[onTaskEventStart]
|
|
12748
12825
|
);
|
|
12826
|
+
const progressPoint = getProgressPoint(
|
|
12827
|
+
+!rtl * progressWidth + progressX,
|
|
12828
|
+
taskYOffset,
|
|
12829
|
+
taskHeight
|
|
12830
|
+
);
|
|
12749
12831
|
const renderBarDisplay = () => {
|
|
12750
12832
|
if (task.type === "project") {
|
|
12751
12833
|
return /* @__PURE__ */ jsx(
|
|
@@ -12782,6 +12864,7 @@ const Bar = (props) => {
|
|
|
12782
12864
|
height: taskHeight,
|
|
12783
12865
|
progressX,
|
|
12784
12866
|
progressWidth,
|
|
12867
|
+
progress: task.progress,
|
|
12785
12868
|
barCornerRadius,
|
|
12786
12869
|
isSelected,
|
|
12787
12870
|
isCritical,
|
|
@@ -12845,7 +12928,15 @@ const Bar = (props) => {
|
|
|
12845
12928
|
}
|
|
12846
12929
|
),
|
|
12847
12930
|
relationHandles,
|
|
12848
|
-
|
|
12931
|
+
isProgressChangeable(task) && /* @__PURE__ */ jsx(
|
|
12932
|
+
BarProgressHandle,
|
|
12933
|
+
{
|
|
12934
|
+
className: `${styles$9.barHandle} ${isMovingProgress ? styles$9.barHandleImportantVisible : ""} ${isSmallWidth || isMovingDate || isRelationDrawMode ? styles$9.barHandleImportantHidden : ""}`,
|
|
12935
|
+
taskId: task.id,
|
|
12936
|
+
progressPoint,
|
|
12937
|
+
startMoveProgress
|
|
12938
|
+
}
|
|
12939
|
+
)
|
|
12849
12940
|
] });
|
|
12850
12941
|
};
|
|
12851
12942
|
const milestoneWrapper = "_milestoneWrapper_vcirf_1";
|
|
@@ -20818,11 +20909,11 @@ const Gantt = (props) => {
|
|
|
20818
20909
|
if (enableDrawer) {
|
|
20819
20910
|
setActiveArrowKey(null);
|
|
20820
20911
|
setActiveTaskId(task.id);
|
|
20912
|
+
selectTask(task.id);
|
|
20821
20913
|
if ((drawerData == null ? void 0 : drawerData.type) === "task") {
|
|
20822
20914
|
setDrawerData({ type: "task", task });
|
|
20823
20915
|
}
|
|
20824
20916
|
}
|
|
20825
|
-
selectTask(task.id);
|
|
20826
20917
|
if (taskBar.onClick) {
|
|
20827
20918
|
taskBar.onClick(task);
|
|
20828
20919
|
}
|
|
@@ -20832,6 +20923,10 @@ const Gantt = (props) => {
|
|
|
20832
20923
|
const handleTaskDoubleClick = useCallback(
|
|
20833
20924
|
(task) => {
|
|
20834
20925
|
if (enableDrawer && drawerData) {
|
|
20926
|
+
selectTask(task.id);
|
|
20927
|
+
setActiveArrowKey(null);
|
|
20928
|
+
setActiveTaskId(task.id);
|
|
20929
|
+
setDrawerData({ type: "task", task });
|
|
20835
20930
|
return;
|
|
20836
20931
|
}
|
|
20837
20932
|
selectTask(task.id);
|
|
@@ -21137,6 +21232,16 @@ const Gantt = (props) => {
|
|
|
21137
21232
|
language
|
|
21138
21233
|
]
|
|
21139
21234
|
);
|
|
21235
|
+
const drawerAwareSelectOnMouseDown = useCallback(
|
|
21236
|
+
(taskId, event) => {
|
|
21237
|
+
if (enableDrawer && drawerData) {
|
|
21238
|
+
selectTask(taskId);
|
|
21239
|
+
return;
|
|
21240
|
+
}
|
|
21241
|
+
selectTaskOnMouseDown(taskId, event);
|
|
21242
|
+
},
|
|
21243
|
+
[enableDrawer, drawerData, selectTask, selectTaskOnMouseDown]
|
|
21244
|
+
);
|
|
21140
21245
|
const renderTaskBarProps = useMemo(
|
|
21141
21246
|
() => ({
|
|
21142
21247
|
...taskBar,
|
|
@@ -21173,7 +21278,7 @@ const Gantt = (props) => {
|
|
|
21173
21278
|
activeTaskId,
|
|
21174
21279
|
renderedRowIndexes,
|
|
21175
21280
|
rtl,
|
|
21176
|
-
selectTaskOnMouseDown,
|
|
21281
|
+
selectTaskOnMouseDown: drawerAwareSelectOnMouseDown,
|
|
21177
21282
|
selectedIdsMirror,
|
|
21178
21283
|
startColumnIndex,
|
|
21179
21284
|
taskHalfHeight,
|
|
@@ -21215,7 +21320,7 @@ const Gantt = (props) => {
|
|
|
21215
21320
|
handleTaskClick,
|
|
21216
21321
|
renderedRowIndexes,
|
|
21217
21322
|
rtl,
|
|
21218
|
-
|
|
21323
|
+
drawerAwareSelectOnMouseDown,
|
|
21219
21324
|
selectedIdsMirror,
|
|
21220
21325
|
startColumnIndex,
|
|
21221
21326
|
taskHalfHeight,
|
|
@@ -5034,6 +5034,16 @@
|
|
|
5034
5034
|
}
|
|
5035
5035
|
);
|
|
5036
5036
|
};
|
|
5037
|
+
const AssigneesColumn = ({ data: { task } }) => {
|
|
5038
|
+
if (task.type === "empty") {
|
|
5039
|
+
return null;
|
|
5040
|
+
}
|
|
5041
|
+
const assignees = task.assignees;
|
|
5042
|
+
if (!assignees || assignees.length === 0) {
|
|
5043
|
+
return null;
|
|
5044
|
+
}
|
|
5045
|
+
return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: assignees.join(", ") });
|
|
5046
|
+
};
|
|
5037
5047
|
function useTaskListColumnsBuilder() {
|
|
5038
5048
|
const createNameColumn = React.useCallback(
|
|
5039
5049
|
(title2, width) => {
|
|
@@ -5103,6 +5113,17 @@
|
|
|
5103
5113
|
canResize: false
|
|
5104
5114
|
};
|
|
5105
5115
|
}, []);
|
|
5116
|
+
const createAssigneesColumn = React.useCallback(
|
|
5117
|
+
(title2, width) => {
|
|
5118
|
+
return {
|
|
5119
|
+
id: "AssigneesColumn",
|
|
5120
|
+
component: AssigneesColumn,
|
|
5121
|
+
width: width || 120,
|
|
5122
|
+
title: title2
|
|
5123
|
+
};
|
|
5124
|
+
},
|
|
5125
|
+
[]
|
|
5126
|
+
);
|
|
5106
5127
|
return {
|
|
5107
5128
|
createNameColumn,
|
|
5108
5129
|
createStartDateColumn,
|
|
@@ -5110,7 +5131,8 @@
|
|
|
5110
5131
|
createDependenciesColumn,
|
|
5111
5132
|
createDeleteActionColumn,
|
|
5112
5133
|
createEditActionColumn,
|
|
5113
|
-
createAddActionColumn
|
|
5134
|
+
createAddActionColumn,
|
|
5135
|
+
createAssigneesColumn
|
|
5114
5136
|
};
|
|
5115
5137
|
}
|
|
5116
5138
|
const DEFAULT_THEME = {
|
|
@@ -12193,6 +12215,17 @@
|
|
|
12193
12215
|
}
|
|
12194
12216
|
return [progressWidth, progressX];
|
|
12195
12217
|
};
|
|
12218
|
+
const getProgressPoint = (progressX, taskY, taskHeight) => {
|
|
12219
|
+
const point = [
|
|
12220
|
+
progressX - 5,
|
|
12221
|
+
taskY + taskHeight,
|
|
12222
|
+
progressX + 5,
|
|
12223
|
+
taskY + taskHeight,
|
|
12224
|
+
progressX,
|
|
12225
|
+
taskY + taskHeight - 8.66
|
|
12226
|
+
];
|
|
12227
|
+
return point.join(",");
|
|
12228
|
+
};
|
|
12196
12229
|
const dateByX = (x, taskX, taskDate, xStep, timeStep) => {
|
|
12197
12230
|
const safeX = isNaN(x) || !isFinite(x) ? 0 : x;
|
|
12198
12231
|
const safeTaskX = isNaN(taskX) || !isFinite(taskX) ? 0 : taskX;
|
|
@@ -12372,6 +12405,7 @@
|
|
|
12372
12405
|
height,
|
|
12373
12406
|
progressWidth,
|
|
12374
12407
|
progressX,
|
|
12408
|
+
progress,
|
|
12375
12409
|
startMoveFullTask,
|
|
12376
12410
|
width,
|
|
12377
12411
|
x,
|
|
@@ -12472,6 +12506,24 @@
|
|
|
12472
12506
|
rx: barCornerRadius,
|
|
12473
12507
|
fill: processColor
|
|
12474
12508
|
}
|
|
12509
|
+
),
|
|
12510
|
+
showProgress && width > 40 && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
12511
|
+
"text",
|
|
12512
|
+
{
|
|
12513
|
+
x: x + width / 2,
|
|
12514
|
+
y: y + height / 2,
|
|
12515
|
+
dominantBaseline: "central",
|
|
12516
|
+
textAnchor: "middle",
|
|
12517
|
+
fill: "#fff",
|
|
12518
|
+
fontSize: 11,
|
|
12519
|
+
fontWeight: 600,
|
|
12520
|
+
pointerEvents: "none",
|
|
12521
|
+
style: { userSelect: "none" },
|
|
12522
|
+
children: [
|
|
12523
|
+
Math.round(progress),
|
|
12524
|
+
"%"
|
|
12525
|
+
]
|
|
12526
|
+
}
|
|
12475
12527
|
)
|
|
12476
12528
|
]
|
|
12477
12529
|
}
|
|
@@ -12512,6 +12564,31 @@
|
|
|
12512
12564
|
}
|
|
12513
12565
|
);
|
|
12514
12566
|
};
|
|
12567
|
+
const BarProgressHandle = ({
|
|
12568
|
+
taskId,
|
|
12569
|
+
progressPoint,
|
|
12570
|
+
startMoveProgress,
|
|
12571
|
+
className
|
|
12572
|
+
}) => {
|
|
12573
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
12574
|
+
"polygon",
|
|
12575
|
+
{
|
|
12576
|
+
"data-testid": `bar-progress-handle-${taskId}`,
|
|
12577
|
+
className,
|
|
12578
|
+
points: progressPoint,
|
|
12579
|
+
onMouseDown: (e) => {
|
|
12580
|
+
e.stopPropagation();
|
|
12581
|
+
startMoveProgress(e.clientX);
|
|
12582
|
+
},
|
|
12583
|
+
onTouchStart: (e) => {
|
|
12584
|
+
const firstTouch = e.touches[0];
|
|
12585
|
+
if (firstTouch) {
|
|
12586
|
+
startMoveProgress(firstTouch.clientX);
|
|
12587
|
+
}
|
|
12588
|
+
}
|
|
12589
|
+
}
|
|
12590
|
+
);
|
|
12591
|
+
};
|
|
12515
12592
|
const projectWrapper = "_projectWrapper_1maxt_1";
|
|
12516
12593
|
const projectBackground = "_projectBackground_1maxt_11";
|
|
12517
12594
|
const projectTop = "_projectTop_1maxt_21";
|
|
@@ -12723,7 +12800,7 @@
|
|
|
12723
12800
|
showProgress = true,
|
|
12724
12801
|
progressColor
|
|
12725
12802
|
} = props;
|
|
12726
|
-
React.useMemo(() => width < 30, [width]);
|
|
12803
|
+
const isSmallWidth = React.useMemo(() => width < 30, [width]);
|
|
12727
12804
|
const handleHeight = React.useMemo(() => taskHeight - 2, [taskHeight]);
|
|
12728
12805
|
const rootRef = React.useRef();
|
|
12729
12806
|
const [ctrlPressed, setCtrlPressed] = React.useState(true);
|
|
@@ -12757,12 +12834,17 @@
|
|
|
12757
12834
|
},
|
|
12758
12835
|
[onTaskEventStart]
|
|
12759
12836
|
);
|
|
12760
|
-
React.useCallback(
|
|
12837
|
+
const startMoveProgress = React.useCallback(
|
|
12761
12838
|
(clientX) => {
|
|
12762
12839
|
onTaskEventStart("progress", clientX);
|
|
12763
12840
|
},
|
|
12764
12841
|
[onTaskEventStart]
|
|
12765
12842
|
);
|
|
12843
|
+
const progressPoint = getProgressPoint(
|
|
12844
|
+
+!rtl * progressWidth + progressX,
|
|
12845
|
+
taskYOffset,
|
|
12846
|
+
taskHeight
|
|
12847
|
+
);
|
|
12766
12848
|
const renderBarDisplay = () => {
|
|
12767
12849
|
if (task.type === "project") {
|
|
12768
12850
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -12799,6 +12881,7 @@
|
|
|
12799
12881
|
height: taskHeight,
|
|
12800
12882
|
progressX,
|
|
12801
12883
|
progressWidth,
|
|
12884
|
+
progress: task.progress,
|
|
12802
12885
|
barCornerRadius,
|
|
12803
12886
|
isSelected,
|
|
12804
12887
|
isCritical,
|
|
@@ -12862,7 +12945,15 @@
|
|
|
12862
12945
|
}
|
|
12863
12946
|
),
|
|
12864
12947
|
relationHandles,
|
|
12865
|
-
|
|
12948
|
+
isProgressChangeable(task) && /* @__PURE__ */ jsxRuntime.jsx(
|
|
12949
|
+
BarProgressHandle,
|
|
12950
|
+
{
|
|
12951
|
+
className: `${styles$9.barHandle} ${isMovingProgress ? styles$9.barHandleImportantVisible : ""} ${isSmallWidth || isMovingDate || isRelationDrawMode ? styles$9.barHandleImportantHidden : ""}`,
|
|
12952
|
+
taskId: task.id,
|
|
12953
|
+
progressPoint,
|
|
12954
|
+
startMoveProgress
|
|
12955
|
+
}
|
|
12956
|
+
)
|
|
12866
12957
|
] });
|
|
12867
12958
|
};
|
|
12868
12959
|
const milestoneWrapper = "_milestoneWrapper_vcirf_1";
|
|
@@ -20835,11 +20926,11 @@
|
|
|
20835
20926
|
if (enableDrawer) {
|
|
20836
20927
|
setActiveArrowKey(null);
|
|
20837
20928
|
setActiveTaskId(task.id);
|
|
20929
|
+
selectTask(task.id);
|
|
20838
20930
|
if ((drawerData == null ? void 0 : drawerData.type) === "task") {
|
|
20839
20931
|
setDrawerData({ type: "task", task });
|
|
20840
20932
|
}
|
|
20841
20933
|
}
|
|
20842
|
-
selectTask(task.id);
|
|
20843
20934
|
if (taskBar.onClick) {
|
|
20844
20935
|
taskBar.onClick(task);
|
|
20845
20936
|
}
|
|
@@ -20849,6 +20940,10 @@
|
|
|
20849
20940
|
const handleTaskDoubleClick = React.useCallback(
|
|
20850
20941
|
(task) => {
|
|
20851
20942
|
if (enableDrawer && drawerData) {
|
|
20943
|
+
selectTask(task.id);
|
|
20944
|
+
setActiveArrowKey(null);
|
|
20945
|
+
setActiveTaskId(task.id);
|
|
20946
|
+
setDrawerData({ type: "task", task });
|
|
20852
20947
|
return;
|
|
20853
20948
|
}
|
|
20854
20949
|
selectTask(task.id);
|
|
@@ -21154,6 +21249,16 @@
|
|
|
21154
21249
|
language
|
|
21155
21250
|
]
|
|
21156
21251
|
);
|
|
21252
|
+
const drawerAwareSelectOnMouseDown = React.useCallback(
|
|
21253
|
+
(taskId, event) => {
|
|
21254
|
+
if (enableDrawer && drawerData) {
|
|
21255
|
+
selectTask(taskId);
|
|
21256
|
+
return;
|
|
21257
|
+
}
|
|
21258
|
+
selectTaskOnMouseDown(taskId, event);
|
|
21259
|
+
},
|
|
21260
|
+
[enableDrawer, drawerData, selectTask, selectTaskOnMouseDown]
|
|
21261
|
+
);
|
|
21157
21262
|
const renderTaskBarProps = React.useMemo(
|
|
21158
21263
|
() => ({
|
|
21159
21264
|
...taskBar,
|
|
@@ -21190,7 +21295,7 @@
|
|
|
21190
21295
|
activeTaskId,
|
|
21191
21296
|
renderedRowIndexes,
|
|
21192
21297
|
rtl,
|
|
21193
|
-
selectTaskOnMouseDown,
|
|
21298
|
+
selectTaskOnMouseDown: drawerAwareSelectOnMouseDown,
|
|
21194
21299
|
selectedIdsMirror,
|
|
21195
21300
|
startColumnIndex,
|
|
21196
21301
|
taskHalfHeight,
|
|
@@ -21232,7 +21337,7 @@
|
|
|
21232
21337
|
handleTaskClick,
|
|
21233
21338
|
renderedRowIndexes,
|
|
21234
21339
|
rtl,
|
|
21235
|
-
|
|
21340
|
+
drawerAwareSelectOnMouseDown,
|
|
21236
21341
|
selectedIdsMirror,
|
|
21237
21342
|
startColumnIndex,
|
|
21238
21343
|
taskHalfHeight,
|
package/package.json
CHANGED