iris-gantt 1.0.5 → 1.0.6
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/PACKAGE_SETUP.md +197 -0
- package/QUICK_START.md +188 -0
- package/README.md +281 -141
- package/USAGE.md +430 -634
- package/dist/Gantt/ContextMenu.d.ts +1 -0
- package/dist/Gantt/ContextMenu.d.ts.map +1 -1
- package/dist/Gantt/Gantt.d.ts +4 -1
- package/dist/Gantt/Gantt.d.ts.map +1 -1
- package/dist/Gantt/Grid.d.ts +2 -1
- package/dist/Gantt/Grid.d.ts.map +1 -1
- package/dist/Gantt/LinkRenderer.d.ts.map +1 -1
- package/dist/Gantt/TaskCreator.d.ts +5 -2
- package/dist/Gantt/TaskCreator.d.ts.map +1 -1
- package/dist/Gantt/TaskEditor.d.ts +2 -1
- package/dist/Gantt/TaskEditor.d.ts.map +1 -1
- package/dist/Gantt/Timeline.d.ts.map +1 -1
- package/dist/Gantt/Toolbar.d.ts +6 -3
- package/dist/Gantt/Toolbar.d.ts.map +1 -1
- package/dist/Gantt/exports.d.ts +2 -0
- package/dist/Gantt/exports.d.ts.map +1 -1
- package/dist/Gantt/features/FilterSearch.d.ts +2 -1
- package/dist/Gantt/features/FilterSearch.d.ts.map +1 -1
- package/dist/Gantt/types.d.ts +147 -0
- package/dist/Gantt/types.d.ts.map +1 -1
- package/dist/gantt.css +1 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/iris-gantt.js +2170 -1820
- package/dist/iris-gantt.umd.cjs +19 -19
- package/package.json +13 -3
package/USAGE.md
CHANGED
|
@@ -1,54 +1,26 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
3
|
-
Complete guide to using the iris-gantt React component library.
|
|
4
|
-
|
|
5
|
-
## Table of Contents
|
|
6
|
-
|
|
7
|
-
- [Installation](#installation)
|
|
8
|
-
- [Quick Start](#quick-start)
|
|
9
|
-
- [Basic Usage](#basic-usage)
|
|
10
|
-
- [Task Management](#task-management)
|
|
11
|
-
- [Dependencies](#dependencies)
|
|
12
|
-
- [Configuration](#configuration)
|
|
13
|
-
- [Advanced Features](#advanced-features)
|
|
14
|
-
- [API Reference](#api-reference)
|
|
15
|
-
- [Examples](#examples)
|
|
16
|
-
- [Common Patterns](#common-patterns)
|
|
17
|
-
- [Troubleshooting](#troubleshooting)
|
|
1
|
+
# Iris Gantt - Complete Usage Guide
|
|
18
2
|
|
|
19
3
|
## Installation
|
|
20
4
|
|
|
21
|
-
### Install the Package
|
|
22
|
-
|
|
23
5
|
```bash
|
|
24
6
|
npm install iris-gantt
|
|
25
7
|
```
|
|
26
8
|
|
|
27
|
-
### Install Peer Dependencies
|
|
28
|
-
|
|
29
|
-
```bash
|
|
30
|
-
npm install react react-dom antd@^5.29.3 dayjs @fortawesome/react-fontawesome@^3.1.0 @fortawesome/fontawesome-svg-core@^7.1.0 @fortawesome/free-solid-svg-icons@^7.1.0
|
|
31
|
-
```
|
|
32
|
-
|
|
33
|
-
**Note:** These are required peer dependencies. Make sure they're installed in your project.
|
|
34
|
-
|
|
35
9
|
## Quick Start
|
|
36
10
|
|
|
37
11
|
```tsx
|
|
38
|
-
import React from 'react'
|
|
39
12
|
import { Gantt } from 'iris-gantt'
|
|
40
13
|
import 'iris-gantt/gantt.css'
|
|
41
|
-
import type { Task, Link } from 'iris-gantt'
|
|
42
14
|
|
|
43
|
-
function
|
|
44
|
-
const tasks
|
|
15
|
+
function MyGantt() {
|
|
16
|
+
const tasks = [
|
|
45
17
|
{
|
|
46
18
|
id: '1',
|
|
47
|
-
text: '
|
|
19
|
+
text: 'My Task',
|
|
48
20
|
start: new Date(2024, 0, 1),
|
|
49
|
-
end: new Date(2024, 0,
|
|
50
|
-
duration:
|
|
51
|
-
progress:
|
|
21
|
+
end: new Date(2024, 0, 10),
|
|
22
|
+
duration: 9,
|
|
23
|
+
progress: 50,
|
|
52
24
|
},
|
|
53
25
|
]
|
|
54
26
|
|
|
@@ -56,567 +28,415 @@ function App() {
|
|
|
56
28
|
}
|
|
57
29
|
```
|
|
58
30
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
## Basic Usage
|
|
62
|
-
|
|
63
|
-
### Minimal Example
|
|
31
|
+
## Import Options
|
|
64
32
|
|
|
33
|
+
### Named Import (Recommended)
|
|
65
34
|
```tsx
|
|
66
35
|
import { Gantt } from 'iris-gantt'
|
|
67
36
|
import 'iris-gantt/gantt.css'
|
|
68
|
-
|
|
69
|
-
const tasks = [
|
|
70
|
-
{
|
|
71
|
-
id: '1',
|
|
72
|
-
text: 'Task 1',
|
|
73
|
-
start: new Date(2024, 0, 1),
|
|
74
|
-
end: new Date(2024, 0, 10),
|
|
75
|
-
duration: 9,
|
|
76
|
-
progress: 50,
|
|
77
|
-
},
|
|
78
|
-
]
|
|
79
|
-
|
|
80
|
-
function MyGantt() {
|
|
81
|
-
return <Gantt tasks={tasks} />
|
|
82
|
-
}
|
|
83
37
|
```
|
|
84
38
|
|
|
85
|
-
###
|
|
86
|
-
|
|
39
|
+
### Default Import
|
|
87
40
|
```tsx
|
|
88
|
-
import
|
|
41
|
+
import Gantt from 'iris-gantt'
|
|
89
42
|
import 'iris-gantt/gantt.css'
|
|
90
|
-
import type { Task, Link } from 'iris-gantt'
|
|
91
|
-
|
|
92
|
-
function MyGantt() {
|
|
93
|
-
const [tasks, setTasks] = useState<Task[]>([])
|
|
94
|
-
const [links, setLinks] = useState<Link[]>([])
|
|
95
|
-
|
|
96
|
-
const handleTaskUpdate = (task: Task) => {
|
|
97
|
-
setTasks(prev => prev.map(t => t.id === task.id ? task : t))
|
|
98
|
-
// Or sync with your backend
|
|
99
|
-
// await updateTask(task)
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
const handleTaskCreate = (task: Task) => {
|
|
103
|
-
setTasks(prev => [...prev, task])
|
|
104
|
-
// await createTask(task)
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
const handleTaskDelete = (taskId: string) => {
|
|
108
|
-
setTasks(prev => prev.filter(t => t.id !== taskId))
|
|
109
|
-
// await deleteTask(taskId)
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
return (
|
|
113
|
-
<Gantt
|
|
114
|
-
tasks={tasks}
|
|
115
|
-
links={links}
|
|
116
|
-
onTaskUpdate={handleTaskUpdate}
|
|
117
|
-
onTaskCreate={handleTaskCreate}
|
|
118
|
-
onTaskDelete={handleTaskDelete}
|
|
119
|
-
onLinkCreate={(link) => setLinks(prev => [...prev, link])}
|
|
120
|
-
onLinkDelete={(linkId) => setLinks(prev => prev.filter(l => l.id !== linkId))}
|
|
121
|
-
/>
|
|
122
|
-
)
|
|
123
|
-
}
|
|
124
43
|
```
|
|
125
44
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
### Creating Tasks
|
|
129
|
-
|
|
130
|
-
Tasks are created through the built-in task creator (click the "+ Add Task" button) or programmatically:
|
|
131
|
-
|
|
45
|
+
### CSS Import
|
|
132
46
|
```tsx
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
text: 'Task Name',
|
|
136
|
-
start: new Date(2024, 0, 1),
|
|
137
|
-
end: new Date(2024, 0, 10),
|
|
138
|
-
duration: 9, // days
|
|
139
|
-
progress: 0, // 0-100
|
|
140
|
-
type: 'task', // 'task' | 'milestone' | 'project'
|
|
141
|
-
color: '#4A90E2',
|
|
142
|
-
owner: 'John Doe',
|
|
143
|
-
priority: 'high', // 'low' | 'medium' | 'high'
|
|
144
|
-
details: 'Task description',
|
|
145
|
-
}
|
|
146
|
-
```
|
|
147
|
-
|
|
148
|
-
### Task Properties
|
|
149
|
-
|
|
150
|
-
| Property | Type | Required | Description |
|
|
151
|
-
|----------|------|----------|-------------|
|
|
152
|
-
| `id` | `string` | ✅ | Unique identifier |
|
|
153
|
-
| `text` | `string` | ✅ | Task name/label |
|
|
154
|
-
| `start` | `Date` | ✅ | Start date |
|
|
155
|
-
| `end` | `Date` | ✅ | End date |
|
|
156
|
-
| `duration` | `number` | ✅ | Duration in days |
|
|
157
|
-
| `progress` | `number` | ✅ | Progress 0-100 |
|
|
158
|
-
| `type` | `'task' \| 'milestone' \| 'project'` | ❌ | Task type |
|
|
159
|
-
| `parent` | `string` | ❌ | Parent task ID (for hierarchy) |
|
|
160
|
-
| `open` | `boolean` | ❌ | Whether parent is expanded |
|
|
161
|
-
| `color` | `string` | ❌ | Hex color code |
|
|
162
|
-
| `owner` | `string` | ❌ | Assigned person |
|
|
163
|
-
| `priority` | `'low' \| 'medium' \| 'high'` | ❌ | Priority level |
|
|
164
|
-
| `details` | `string` | ❌ | Task description |
|
|
165
|
-
| `dependencies` | `string[]` | ❌ | Array of task IDs this depends on |
|
|
166
|
-
| `segments` | `TaskSegment[]` | ❌ | For split tasks |
|
|
167
|
-
|
|
168
|
-
### Hierarchical Tasks (Parent/Child)
|
|
47
|
+
// Option 1 (preferred)
|
|
48
|
+
import 'iris-gantt/gantt.css'
|
|
169
49
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
{
|
|
173
|
-
id: '1',
|
|
174
|
-
text: 'Project',
|
|
175
|
-
start: new Date(2024, 0, 1),
|
|
176
|
-
end: new Date(2024, 2, 31),
|
|
177
|
-
duration: 90,
|
|
178
|
-
progress: 30,
|
|
179
|
-
type: 'project',
|
|
180
|
-
open: true, // Expanded by default
|
|
181
|
-
},
|
|
182
|
-
{
|
|
183
|
-
id: '2',
|
|
184
|
-
text: 'Phase 1',
|
|
185
|
-
start: new Date(2024, 0, 1),
|
|
186
|
-
end: new Date(2024, 1, 15),
|
|
187
|
-
duration: 45,
|
|
188
|
-
progress: 50,
|
|
189
|
-
parent: '1', // Child of task '1'
|
|
190
|
-
},
|
|
191
|
-
{
|
|
192
|
-
id: '3',
|
|
193
|
-
text: 'Phase 2',
|
|
194
|
-
start: new Date(2024, 1, 16),
|
|
195
|
-
end: new Date(2024, 2, 31),
|
|
196
|
-
duration: 45,
|
|
197
|
-
progress: 10,
|
|
198
|
-
parent: '1', // Child of task '1'
|
|
199
|
-
},
|
|
200
|
-
]
|
|
50
|
+
// Option 2 (if Option 1 doesn't work)
|
|
51
|
+
import 'iris-gantt/dist/gantt.css'
|
|
201
52
|
```
|
|
202
53
|
|
|
203
|
-
|
|
54
|
+
## Basic Usage
|
|
204
55
|
|
|
205
56
|
```tsx
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
// Milestone (rendered as a diamond)
|
|
210
|
-
{ type: 'milestone', ... }
|
|
211
|
-
|
|
212
|
-
// Project (summary task, can have children)
|
|
213
|
-
{ type: 'project', ... }
|
|
214
|
-
```
|
|
215
|
-
|
|
216
|
-
### Split Tasks
|
|
217
|
-
|
|
218
|
-
Tasks can be split into multiple segments:
|
|
57
|
+
import { Gantt } from 'iris-gantt'
|
|
58
|
+
import 'iris-gantt/gantt.css'
|
|
59
|
+
import type { Task, Link } from 'iris-gantt'
|
|
219
60
|
|
|
220
|
-
|
|
221
|
-
const
|
|
222
|
-
id: '1',
|
|
223
|
-
text: 'Split Task',
|
|
224
|
-
start: new Date(2024, 0, 1),
|
|
225
|
-
end: new Date(2024, 0, 20),
|
|
226
|
-
duration: 20,
|
|
227
|
-
progress: 50,
|
|
228
|
-
segments: [
|
|
61
|
+
function MyGantt() {
|
|
62
|
+
const tasks: Task[] = [
|
|
229
63
|
{
|
|
64
|
+
id: '1',
|
|
65
|
+
text: 'Project Planning',
|
|
230
66
|
start: new Date(2024, 0, 1),
|
|
231
|
-
end: new Date(2024, 0,
|
|
232
|
-
duration:
|
|
67
|
+
end: new Date(2024, 0, 15),
|
|
68
|
+
duration: 14,
|
|
69
|
+
progress: 100,
|
|
70
|
+
type: 'project',
|
|
233
71
|
},
|
|
234
72
|
{
|
|
73
|
+
id: '2',
|
|
74
|
+
text: 'Development',
|
|
235
75
|
start: new Date(2024, 0, 15),
|
|
236
|
-
end: new Date(2024,
|
|
237
|
-
duration:
|
|
76
|
+
end: new Date(2024, 1, 15),
|
|
77
|
+
duration: 31,
|
|
78
|
+
progress: 60,
|
|
79
|
+
type: 'task',
|
|
238
80
|
},
|
|
239
|
-
]
|
|
240
|
-
}
|
|
241
|
-
```
|
|
242
|
-
|
|
243
|
-
## Dependencies
|
|
244
|
-
|
|
245
|
-
### Creating Links
|
|
246
|
-
|
|
247
|
-
Links define relationships between tasks:
|
|
248
|
-
|
|
249
|
-
```tsx
|
|
250
|
-
const links: Link[] = [
|
|
251
|
-
{
|
|
252
|
-
id: 'l1',
|
|
253
|
-
source: '1', // Source task ID
|
|
254
|
-
target: '2', // Target task ID
|
|
255
|
-
type: 'e2s', // Dependency type
|
|
256
|
-
lag: 0, // Optional lag time
|
|
257
|
-
lagUnit: 'day', // 'day' | 'hour' | 'week' | 'month'
|
|
258
|
-
},
|
|
259
|
-
]
|
|
260
|
-
```
|
|
261
|
-
|
|
262
|
-
### Dependency Types
|
|
263
|
-
|
|
264
|
-
| Type | Code | Description |
|
|
265
|
-
|------|------|-------------|
|
|
266
|
-
| End-to-Start | `'e2s'` | Task B starts when Task A ends (most common) |
|
|
267
|
-
| Start-to-Start | `'s2s'` | Tasks start together |
|
|
268
|
-
| End-to-End | `'e2e'` | Tasks end together |
|
|
269
|
-
| Start-to-End | `'s2e'` | Task B ends when Task A starts |
|
|
270
|
-
|
|
271
|
-
### Example with Dependencies
|
|
272
|
-
|
|
273
|
-
```tsx
|
|
274
|
-
const tasks: Task[] = [
|
|
275
|
-
{ id: '1', text: 'Design', start: new Date(2024, 0, 1), end: new Date(2024, 0, 10), duration: 9, progress: 100 },
|
|
276
|
-
{ id: '2', text: 'Development', start: new Date(2024, 0, 11), end: new Date(2024, 0, 25), duration: 14, progress: 50 },
|
|
277
|
-
{ id: '3', text: 'Testing', start: new Date(2024, 0, 26), end: new Date(2024, 1, 5), duration: 10, progress: 0 },
|
|
278
|
-
]
|
|
279
|
-
|
|
280
|
-
const links: Link[] = [
|
|
281
|
-
{ id: 'l1', source: '1', target: '2', type: 'e2s' }, // Development starts after Design
|
|
282
|
-
{ id: 'l2', source: '2', target: '3', type: 'e2s' }, // Testing starts after Development
|
|
283
|
-
]
|
|
284
|
-
```
|
|
285
|
-
|
|
286
|
-
### Lag Time
|
|
81
|
+
]
|
|
287
82
|
|
|
288
|
-
|
|
83
|
+
const links: Link[] = [
|
|
84
|
+
{ id: 'l1', source: '1', target: '2', type: 'e2s' },
|
|
85
|
+
]
|
|
289
86
|
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
lagUnit: 'day',
|
|
299
|
-
},
|
|
300
|
-
{
|
|
301
|
-
id: 'l2',
|
|
302
|
-
source: '2',
|
|
303
|
-
target: '3',
|
|
304
|
-
type: 'e2s',
|
|
305
|
-
lag: -1, // 1 day lead time (negative = starts early)
|
|
306
|
-
lagUnit: 'day',
|
|
307
|
-
},
|
|
308
|
-
]
|
|
87
|
+
return (
|
|
88
|
+
<Gantt
|
|
89
|
+
tasks={tasks}
|
|
90
|
+
links={links}
|
|
91
|
+
onTaskUpdate={(task) => console.log('Updated:', task)}
|
|
92
|
+
/>
|
|
93
|
+
)
|
|
94
|
+
}
|
|
309
95
|
```
|
|
310
96
|
|
|
311
|
-
## Configuration
|
|
97
|
+
## Complete Props Configuration
|
|
312
98
|
|
|
313
|
-
###
|
|
99
|
+
### Main Props
|
|
314
100
|
|
|
315
101
|
```tsx
|
|
316
102
|
<Gantt
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
}
|
|
103
|
+
// Required
|
|
104
|
+
tasks={Task[]}
|
|
105
|
+
|
|
106
|
+
// Optional
|
|
107
|
+
links={Link[]}
|
|
108
|
+
config={GanttConfig}
|
|
109
|
+
uiConfig={GanttUIConfig}
|
|
110
|
+
styleConfig={GanttStyleConfig}
|
|
111
|
+
iconConfig={GanttIconConfig}
|
|
112
|
+
|
|
113
|
+
// Event Handlers
|
|
114
|
+
onTaskUpdate={(task: Task) => void}
|
|
115
|
+
onTaskCreate={(task: Task) => void}
|
|
116
|
+
onTaskDelete={(taskId: string) => void}
|
|
117
|
+
onLinkCreate={(link: Link) => void}
|
|
118
|
+
onLinkDelete={(linkId: string) => void}
|
|
324
119
|
/>
|
|
325
120
|
```
|
|
326
121
|
|
|
327
|
-
|
|
122
|
+
## UI Configuration (uiConfig)
|
|
328
123
|
|
|
329
|
-
|
|
124
|
+
All text, labels, and button visibility can be customized:
|
|
330
125
|
|
|
331
126
|
```tsx
|
|
332
|
-
import type { Scale } from 'iris-gantt'
|
|
333
|
-
|
|
334
|
-
const scales: Scale[] = [
|
|
335
|
-
{ unit: 'month', step: 1, format: 'MMM YYYY' },
|
|
336
|
-
{ unit: 'week', step: 1, format: 'W' },
|
|
337
|
-
{ unit: 'day', step: 1, format: 'D' },
|
|
338
|
-
]
|
|
339
|
-
|
|
340
127
|
<Gantt
|
|
341
128
|
tasks={tasks}
|
|
342
|
-
|
|
129
|
+
uiConfig={{
|
|
130
|
+
// Header
|
|
131
|
+
headerTitle: 'My Project Gantt',
|
|
132
|
+
showHeader: true,
|
|
133
|
+
|
|
134
|
+
// Toolbar Buttons Visibility
|
|
135
|
+
showAddTaskButton: true,
|
|
136
|
+
showBaselineButton: false, // Baselines are always visible, no button needed
|
|
137
|
+
showZoomButtons: true,
|
|
138
|
+
showExportButtons: true,
|
|
139
|
+
showFilterSearch: true,
|
|
140
|
+
|
|
141
|
+
// Toolbar Button Labels
|
|
142
|
+
addTaskButtonText: 'Add New Task',
|
|
143
|
+
zoomOutTooltip: 'Zoom Out',
|
|
144
|
+
zoomInTooltip: 'Zoom In',
|
|
145
|
+
resetZoomTooltip: 'Reset Zoom',
|
|
146
|
+
exportCSVTooltip: 'Export to CSV',
|
|
147
|
+
exportExcelTooltip: 'Export to Excel',
|
|
148
|
+
exportJSONTooltip: 'Export to JSON',
|
|
149
|
+
exportPDFTooltip: 'Export to PDF',
|
|
150
|
+
|
|
151
|
+
// Task Creator Modal
|
|
152
|
+
taskCreatorTitle: 'Create New Task',
|
|
153
|
+
taskCreatorOkText: 'Create',
|
|
154
|
+
taskCreatorCancelText: 'Cancel',
|
|
155
|
+
taskNameLabel: 'Task Name',
|
|
156
|
+
taskNamePlaceholder: 'Enter task name',
|
|
157
|
+
typeLabel: 'Type',
|
|
158
|
+
priorityLabel: 'Priority',
|
|
159
|
+
startDateLabel: 'Start Date',
|
|
160
|
+
durationLabel: 'Duration (days)',
|
|
161
|
+
colorLabel: 'Color',
|
|
162
|
+
progressLabel: 'Progress (%)',
|
|
163
|
+
ownerLabel: 'Owner',
|
|
164
|
+
ownerPlaceholder: 'Assign to...',
|
|
165
|
+
detailsLabel: 'Details',
|
|
166
|
+
detailsPlaceholder: 'Add task description...',
|
|
167
|
+
taskTypeOptions: {
|
|
168
|
+
task: 'Task',
|
|
169
|
+
milestone: 'Milestone',
|
|
170
|
+
project: 'Project',
|
|
171
|
+
},
|
|
172
|
+
priorityOptions: {
|
|
173
|
+
low: 'Low',
|
|
174
|
+
medium: 'Medium',
|
|
175
|
+
high: 'High',
|
|
176
|
+
},
|
|
177
|
+
|
|
178
|
+
// Task Editor Modal
|
|
179
|
+
taskEditorTitle: 'Edit Task',
|
|
180
|
+
taskEditorSaveText: 'Save',
|
|
181
|
+
taskEditorCancelText: 'Cancel',
|
|
182
|
+
taskEditorDeleteText: 'Delete',
|
|
183
|
+
deleteConfirmTitle: 'Delete Task',
|
|
184
|
+
deleteConfirmContent: 'This action cannot be undone.',
|
|
185
|
+
deleteConfirmOkText: 'Yes, Delete',
|
|
186
|
+
deleteConfirmCancelText: 'No',
|
|
187
|
+
|
|
188
|
+
// Filter Search
|
|
189
|
+
searchPlaceholder: 'Search tasks...',
|
|
190
|
+
allOwnersText: 'All Owners',
|
|
191
|
+
allStatusText: 'All Status',
|
|
192
|
+
allPriorityText: 'All Priority',
|
|
193
|
+
clearFiltersText: 'Clear',
|
|
194
|
+
statusOptions: {
|
|
195
|
+
all: 'All Status',
|
|
196
|
+
notStarted: 'Not Started',
|
|
197
|
+
inProgress: 'In Progress',
|
|
198
|
+
completed: 'Completed',
|
|
199
|
+
},
|
|
200
|
+
priorityFilterOptions: {
|
|
201
|
+
all: 'All Priority',
|
|
202
|
+
low: 'Low',
|
|
203
|
+
medium: 'Medium',
|
|
204
|
+
high: 'High',
|
|
205
|
+
},
|
|
206
|
+
|
|
207
|
+
// Column Labels
|
|
208
|
+
columnLabels: {
|
|
209
|
+
name: 'Name',
|
|
210
|
+
dependsOn: 'Depends on',
|
|
211
|
+
duration: 'Duration',
|
|
212
|
+
start: 'Start',
|
|
213
|
+
},
|
|
214
|
+
|
|
215
|
+
// Validation
|
|
216
|
+
taskNameRequired: 'Please enter task name',
|
|
217
|
+
}}
|
|
343
218
|
/>
|
|
344
219
|
```
|
|
345
220
|
|
|
346
|
-
|
|
221
|
+
## Style Configuration (styleConfig)
|
|
347
222
|
|
|
348
|
-
|
|
223
|
+
Customize colors, fonts, and spacing to match your project:
|
|
349
224
|
|
|
350
225
|
```tsx
|
|
351
|
-
import type { Column } from 'iris-gantt'
|
|
352
|
-
|
|
353
|
-
const columns: Column[] = [
|
|
354
|
-
{ name: 'text', label: 'Task', width: 300, align: 'left', resize: true },
|
|
355
|
-
{ name: 'owner', label: 'Owner', width: 150, align: 'left' },
|
|
356
|
-
{ name: 'priority', label: 'Priority', width: 100, align: 'center' },
|
|
357
|
-
{ name: 'duration', label: 'Duration', width: 100, align: 'right' },
|
|
358
|
-
]
|
|
359
|
-
|
|
360
226
|
<Gantt
|
|
361
227
|
tasks={tasks}
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
228
|
+
styleConfig={{
|
|
229
|
+
// Colors
|
|
230
|
+
primary: '#37a9ef',
|
|
231
|
+
primarySelected: '#d5eaf7',
|
|
232
|
+
success: '#77d257',
|
|
233
|
+
warning: '#fcba2e',
|
|
234
|
+
danger: '#fe6158',
|
|
235
|
+
background: '#ffffff',
|
|
236
|
+
backgroundAlt: '#f2f3f7',
|
|
237
|
+
backgroundHover: '#eaedf5',
|
|
238
|
+
selectColor: '#eaedf5',
|
|
239
|
+
taskColor: '#37a9ef',
|
|
240
|
+
taskFillColor: 'rgba(0, 0, 0, 0.15)',
|
|
241
|
+
projectColor: '#81C784',
|
|
242
|
+
milestoneColor: '#9c27b0',
|
|
243
|
+
fontColor: '#333333',
|
|
244
|
+
fontColorAlt: '#9fa1ae',
|
|
245
|
+
iconColor: '#9fa1ae',
|
|
246
|
+
borderColor: '#e6e6e6',
|
|
247
|
+
|
|
248
|
+
// Fonts
|
|
249
|
+
fontFamily: 'Inter, sans-serif',
|
|
250
|
+
fontMono: 'Fira Code, monospace',
|
|
251
|
+
fontSize: '14px',
|
|
252
|
+
fontWeight: '400',
|
|
253
|
+
lineHeight: '1.5',
|
|
254
|
+
|
|
255
|
+
// Spacing
|
|
256
|
+
spacingXS: '4px',
|
|
257
|
+
spacingSM: '8px',
|
|
258
|
+
spacingMD: '12px',
|
|
259
|
+
spacingLG: '16px',
|
|
260
|
+
|
|
261
|
+
// Custom CSS Variables (advanced)
|
|
262
|
+
customCSSVariables: {
|
|
263
|
+
'--my-custom-var': 'value',
|
|
378
264
|
},
|
|
379
|
-
},
|
|
380
|
-
]
|
|
381
|
-
```
|
|
382
|
-
|
|
383
|
-
### Holidays
|
|
384
|
-
|
|
385
|
-
```tsx
|
|
386
|
-
<Gantt
|
|
387
|
-
tasks={tasks}
|
|
388
|
-
config={{
|
|
389
|
-
holidays: [
|
|
390
|
-
new Date(2024, 0, 1), // New Year
|
|
391
|
-
new Date(2024, 6, 4), // Independence Day
|
|
392
|
-
new Date(2024, 11, 25), // Christmas
|
|
393
|
-
],
|
|
394
265
|
}}
|
|
395
266
|
/>
|
|
396
267
|
```
|
|
397
268
|
|
|
398
|
-
|
|
269
|
+
## Icon Configuration (iconConfig)
|
|
399
270
|
|
|
400
|
-
|
|
271
|
+
Customize icons throughout the component:
|
|
401
272
|
|
|
402
273
|
```tsx
|
|
403
|
-
import
|
|
404
|
-
|
|
405
|
-
const markers: Marker[] = [
|
|
406
|
-
{
|
|
407
|
-
id: 'm1',
|
|
408
|
-
date: new Date(2024, 2, 15),
|
|
409
|
-
text: 'Release Date',
|
|
410
|
-
css: 'border-left: 2px solid red;',
|
|
411
|
-
},
|
|
412
|
-
]
|
|
274
|
+
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
|
275
|
+
import { faPlus, faSearch } from '@fortawesome/free-solid-svg-icons'
|
|
413
276
|
|
|
414
277
|
<Gantt
|
|
415
278
|
tasks={tasks}
|
|
416
|
-
|
|
279
|
+
iconConfig={{
|
|
280
|
+
// Toolbar icons
|
|
281
|
+
addTask: <FontAwesomeIcon icon={faPlus} />,
|
|
282
|
+
zoomIn: 'search-plus', // FontAwesome icon name
|
|
283
|
+
zoomOut: <CustomIcon />, // Custom React component
|
|
284
|
+
resetZoom: faRotateLeft,
|
|
285
|
+
exportCSV: faFileCsv,
|
|
286
|
+
exportExcel: faFileExcel,
|
|
287
|
+
exportJSON: faFileCode,
|
|
288
|
+
exportPDF: faFilePdf,
|
|
289
|
+
|
|
290
|
+
// Grid icons
|
|
291
|
+
gripVertical: faGripVertical,
|
|
292
|
+
chevronRight: faChevronRight,
|
|
293
|
+
chevronDown: faChevronDown,
|
|
294
|
+
plus: faPlus,
|
|
295
|
+
|
|
296
|
+
// Context menu icons
|
|
297
|
+
edit: faEdit,
|
|
298
|
+
delete: faTrash,
|
|
299
|
+
copy: faCopy,
|
|
300
|
+
link: faLink,
|
|
301
|
+
flag: faFlag,
|
|
302
|
+
folder: faFolder,
|
|
303
|
+
tasks: faTasks,
|
|
304
|
+
rotateLeft: faRotateLeft,
|
|
305
|
+
}}
|
|
417
306
|
/>
|
|
418
307
|
```
|
|
419
308
|
|
|
420
|
-
|
|
309
|
+
## Configuration (config)
|
|
421
310
|
|
|
422
311
|
```tsx
|
|
423
312
|
<Gantt
|
|
424
313
|
tasks={tasks}
|
|
425
314
|
config={{
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
315
|
+
// Layout
|
|
316
|
+
columns: Column[], // Custom columns
|
|
317
|
+
scales: Scale[], // Timeline scales
|
|
318
|
+
readonly: false,
|
|
319
|
+
editable: true,
|
|
320
|
+
|
|
321
|
+
// Sizing
|
|
322
|
+
taskHeight: 28,
|
|
323
|
+
rowHeight: 44,
|
|
324
|
+
scaleHeight: 28,
|
|
325
|
+
columnWidth: 80,
|
|
326
|
+
minColumnWidth: 60,
|
|
327
|
+
|
|
328
|
+
// Features
|
|
329
|
+
autoSchedule: false,
|
|
330
|
+
criticalPath: false,
|
|
331
|
+
baselines: true, // Always enabled - automatically created
|
|
332
|
+
weekends: true,
|
|
333
|
+
holidays: [],
|
|
334
|
+
|
|
335
|
+
// Theme
|
|
336
|
+
theme: 'light' | 'dark',
|
|
337
|
+
locale: 'en',
|
|
338
|
+
|
|
339
|
+
// Responsive
|
|
340
|
+
containerHeight: '100%', // or '600px', '50vh', etc.
|
|
341
|
+
containerMinHeight: '400px',
|
|
342
|
+
gridWidth: 'clamp(280px, 30vw, 720px)', // Responsive width
|
|
431
343
|
}}
|
|
432
344
|
/>
|
|
433
345
|
```
|
|
434
346
|
|
|
435
|
-
##
|
|
347
|
+
## Responsive Design
|
|
436
348
|
|
|
437
|
-
|
|
349
|
+
The component is fully responsive and adapts to:
|
|
350
|
+
- ✅ Desktop (1024px+)
|
|
351
|
+
- ✅ Tablet (768px - 1024px)
|
|
352
|
+
- ✅ Mobile Landscape (480px - 768px)
|
|
353
|
+
- ✅ Mobile Portrait (< 480px)
|
|
438
354
|
|
|
439
|
-
|
|
355
|
+
### Responsive Configuration
|
|
440
356
|
|
|
441
357
|
```tsx
|
|
442
358
|
<Gantt
|
|
443
359
|
tasks={tasks}
|
|
444
|
-
links={links}
|
|
445
360
|
config={{
|
|
446
|
-
|
|
361
|
+
// Responsive container
|
|
362
|
+
containerHeight: '100%',
|
|
363
|
+
containerMinHeight: '400px',
|
|
364
|
+
|
|
365
|
+
// Responsive grid width
|
|
366
|
+
gridWidth: 'clamp(280px, 30vw, 720px)', // Adapts to viewport
|
|
367
|
+
// or fixed: '720px'
|
|
368
|
+
// or percentage: '30vw'
|
|
447
369
|
}}
|
|
448
370
|
/>
|
|
449
371
|
```
|
|
450
372
|
|
|
451
|
-
|
|
373
|
+
### Style Integration
|
|
374
|
+
|
|
375
|
+
Override CSS variables to match your project:
|
|
452
376
|
|
|
453
|
-
|
|
377
|
+
```css
|
|
378
|
+
/* In your project's CSS */
|
|
379
|
+
.my-gantt-wrapper {
|
|
380
|
+
/* Colors - Match your brand */
|
|
381
|
+
--wx-gantt-primary: #your-brand-color;
|
|
382
|
+
--wx-gantt-background: var(--your-bg-color, #ffffff);
|
|
383
|
+
--wx-gantt-font-color: var(--your-text-color, #333);
|
|
384
|
+
|
|
385
|
+
/* Fonts - Use your project fonts */
|
|
386
|
+
--wx-gantt-font-family: 'Your Font', -apple-system, sans-serif;
|
|
387
|
+
--wx-gantt-font-size: 14px;
|
|
388
|
+
|
|
389
|
+
/* Layout - Responsive sizing */
|
|
390
|
+
--gantt-container-height: 100%;
|
|
391
|
+
--gantt-container-min-height: 400px;
|
|
392
|
+
--gantt-grid-width: clamp(280px, 30vw, 720px);
|
|
393
|
+
--gantt-row-height: 44px;
|
|
394
|
+
}
|
|
395
|
+
```
|
|
454
396
|
|
|
455
|
-
|
|
397
|
+
## Baselines
|
|
398
|
+
|
|
399
|
+
Baselines are **always visible** and **automatically created** when tasks are set or updated. No button is needed - baselines are automatically generated from the current task state.
|
|
456
400
|
|
|
457
401
|
```tsx
|
|
402
|
+
// Baselines are automatically created and displayed
|
|
458
403
|
<Gantt
|
|
459
404
|
tasks={tasks}
|
|
460
|
-
links={links}
|
|
461
405
|
config={{
|
|
462
|
-
|
|
406
|
+
baselines: true, // Always enabled
|
|
463
407
|
}}
|
|
464
408
|
/>
|
|
465
409
|
```
|
|
466
410
|
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
### Baselines
|
|
470
|
-
|
|
471
|
-
Track original plans vs. current state:
|
|
411
|
+
## Event Handlers
|
|
472
412
|
|
|
473
413
|
```tsx
|
|
474
|
-
import { createBaseline } from 'iris-gantt'
|
|
475
|
-
|
|
476
|
-
// Create baseline from current tasks
|
|
477
|
-
const baseline = createBaseline(tasks)
|
|
478
|
-
|
|
479
|
-
// Later, compare current tasks to baseline
|
|
480
414
|
<Gantt
|
|
481
|
-
tasks={
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
//
|
|
415
|
+
tasks={tasks}
|
|
416
|
+
onTaskUpdate={(task) => {
|
|
417
|
+
console.log('Task updated:', task)
|
|
418
|
+
// Save to your backend
|
|
419
|
+
}}
|
|
420
|
+
onTaskCreate={(task) => {
|
|
421
|
+
console.log('Task created:', task)
|
|
422
|
+
// Add to your backend
|
|
423
|
+
}}
|
|
424
|
+
onTaskDelete={(taskId) => {
|
|
425
|
+
console.log('Task deleted:', taskId)
|
|
426
|
+
// Remove from your backend
|
|
427
|
+
}}
|
|
428
|
+
onLinkCreate={(link) => {
|
|
429
|
+
console.log('Link created:', link)
|
|
430
|
+
// Save dependency to your backend
|
|
431
|
+
}}
|
|
432
|
+
onLinkDelete={(linkId) => {
|
|
433
|
+
console.log('Link deleted:', linkId)
|
|
434
|
+
// Remove dependency from your backend
|
|
485
435
|
}}
|
|
486
436
|
/>
|
|
487
437
|
```
|
|
488
438
|
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
Built-in undo/redo system (Ctrl+Z / Ctrl+Y):
|
|
492
|
-
|
|
493
|
-
```tsx
|
|
494
|
-
// No configuration needed - works automatically
|
|
495
|
-
<Gantt tasks={tasks} />
|
|
496
|
-
```
|
|
497
|
-
|
|
498
|
-
The toolbar includes undo/redo buttons.
|
|
499
|
-
|
|
500
|
-
### Export
|
|
501
|
-
|
|
502
|
-
Export your Gantt chart data:
|
|
503
|
-
|
|
504
|
-
```tsx
|
|
505
|
-
import * as ExportUtils from 'iris-gantt'
|
|
506
|
-
|
|
507
|
-
// Export to CSV
|
|
508
|
-
const csv = ExportUtils.exportToCSV(tasks, links)
|
|
509
|
-
|
|
510
|
-
// Export to JSON
|
|
511
|
-
const json = ExportUtils.exportToJSON(tasks, links)
|
|
512
|
-
|
|
513
|
-
// Export to Excel
|
|
514
|
-
const excel = ExportUtils.exportToExcel(tasks, links)
|
|
515
|
-
```
|
|
516
|
-
|
|
517
|
-
The toolbar includes an export button with a dropdown menu.
|
|
518
|
-
|
|
519
|
-
### Filtering and Search
|
|
520
|
-
|
|
521
|
-
```tsx
|
|
522
|
-
import { FilterSearch, applyFilters, type FilterOptions } from 'iris-gantt'
|
|
523
|
-
|
|
524
|
-
const [filteredTasks, setFilteredTasks] = useState(tasks)
|
|
525
|
-
const [filters, setFilters] = useState<FilterOptions>({
|
|
526
|
-
search: '',
|
|
527
|
-
status: 'all',
|
|
528
|
-
priority: 'all',
|
|
529
|
-
owner: '',
|
|
530
|
-
})
|
|
531
|
-
|
|
532
|
-
// Apply filters
|
|
533
|
-
useEffect(() => {
|
|
534
|
-
const filtered = applyFilters(tasks, filters)
|
|
535
|
-
setFilteredTasks(filtered)
|
|
536
|
-
}, [tasks, filters])
|
|
537
|
-
|
|
538
|
-
<Gantt tasks={filteredTasks} />
|
|
539
|
-
```
|
|
540
|
-
|
|
541
|
-
## API Reference
|
|
542
|
-
|
|
543
|
-
### Gantt Component Props
|
|
544
|
-
|
|
545
|
-
```tsx
|
|
546
|
-
interface GanttProps {
|
|
547
|
-
tasks: Task[] // Required: Array of tasks
|
|
548
|
-
links?: Link[] // Optional: Array of dependency links
|
|
549
|
-
config?: Partial<GanttConfig> // Optional: Configuration object
|
|
550
|
-
onTaskUpdate?: (task: Task) => void
|
|
551
|
-
onTaskCreate?: (task: Task) => void
|
|
552
|
-
onTaskDelete?: (taskId: string) => void
|
|
553
|
-
onLinkCreate?: (link: Link) => void
|
|
554
|
-
onLinkDelete?: (linkId: string) => void
|
|
555
|
-
}
|
|
556
|
-
```
|
|
557
|
-
|
|
558
|
-
### GanttConfig
|
|
559
|
-
|
|
560
|
-
```tsx
|
|
561
|
-
interface GanttConfig {
|
|
562
|
-
columns?: Column[]
|
|
563
|
-
scales?: Scale[]
|
|
564
|
-
readonly?: boolean
|
|
565
|
-
editable?: boolean
|
|
566
|
-
taskHeight?: number
|
|
567
|
-
rowHeight?: number
|
|
568
|
-
scaleHeight?: number
|
|
569
|
-
columnWidth?: number
|
|
570
|
-
minColumnWidth?: number
|
|
571
|
-
autoSchedule?: boolean
|
|
572
|
-
criticalPath?: boolean
|
|
573
|
-
baselines?: boolean
|
|
574
|
-
markers?: Marker[]
|
|
575
|
-
weekends?: boolean
|
|
576
|
-
holidays?: Date[]
|
|
577
|
-
theme?: 'light' | 'dark'
|
|
578
|
-
locale?: string
|
|
579
|
-
}
|
|
580
|
-
```
|
|
581
|
-
|
|
582
|
-
### Task
|
|
583
|
-
|
|
584
|
-
```tsx
|
|
585
|
-
interface Task {
|
|
586
|
-
id: string
|
|
587
|
-
text: string
|
|
588
|
-
start: Date
|
|
589
|
-
end: Date
|
|
590
|
-
duration: number
|
|
591
|
-
progress: number
|
|
592
|
-
type?: 'task' | 'milestone' | 'project'
|
|
593
|
-
parent?: string
|
|
594
|
-
open?: boolean
|
|
595
|
-
color?: string
|
|
596
|
-
details?: string
|
|
597
|
-
owner?: string
|
|
598
|
-
priority?: 'low' | 'medium' | 'high'
|
|
599
|
-
dependencies?: string[]
|
|
600
|
-
segments?: TaskSegment[]
|
|
601
|
-
}
|
|
602
|
-
```
|
|
603
|
-
|
|
604
|
-
### Link
|
|
605
|
-
|
|
606
|
-
```tsx
|
|
607
|
-
interface Link {
|
|
608
|
-
id: string
|
|
609
|
-
source: string
|
|
610
|
-
target: string
|
|
611
|
-
type: 'e2s' | 's2s' | 'e2e' | 's2e'
|
|
612
|
-
lag?: number
|
|
613
|
-
lagUnit?: 'day' | 'hour' | 'week' | 'month'
|
|
614
|
-
}
|
|
615
|
-
```
|
|
616
|
-
|
|
617
|
-
## Examples
|
|
618
|
-
|
|
619
|
-
### Complete Example with State Management
|
|
439
|
+
## Complete Example
|
|
620
440
|
|
|
621
441
|
```tsx
|
|
622
442
|
import React, { useState } from 'react'
|
|
@@ -628,211 +448,187 @@ function ProjectGantt() {
|
|
|
628
448
|
const [tasks, setTasks] = useState<Task[]>([
|
|
629
449
|
{
|
|
630
450
|
id: '1',
|
|
631
|
-
text: 'Project
|
|
451
|
+
text: 'Project Planning',
|
|
632
452
|
start: new Date(2024, 0, 1),
|
|
633
|
-
end: new Date(2024, 0,
|
|
634
|
-
duration:
|
|
453
|
+
end: new Date(2024, 0, 15),
|
|
454
|
+
duration: 14,
|
|
635
455
|
progress: 100,
|
|
636
456
|
type: 'project',
|
|
637
|
-
|
|
457
|
+
color: '#81C784',
|
|
638
458
|
},
|
|
639
459
|
{
|
|
640
460
|
id: '2',
|
|
641
|
-
text: 'Design Phase',
|
|
642
|
-
start: new Date(2024, 0, 6),
|
|
643
|
-
end: new Date(2024, 0, 20),
|
|
644
|
-
duration: 14,
|
|
645
|
-
progress: 75,
|
|
646
|
-
parent: '1',
|
|
647
|
-
owner: 'Alice',
|
|
648
|
-
priority: 'high',
|
|
649
|
-
},
|
|
650
|
-
{
|
|
651
|
-
id: '3',
|
|
652
461
|
text: 'Development',
|
|
653
|
-
start: new Date(2024, 0,
|
|
462
|
+
start: new Date(2024, 0, 15),
|
|
654
463
|
end: new Date(2024, 1, 15),
|
|
655
|
-
duration:
|
|
656
|
-
progress:
|
|
657
|
-
|
|
658
|
-
|
|
464
|
+
duration: 31,
|
|
465
|
+
progress: 60,
|
|
466
|
+
type: 'task',
|
|
467
|
+
color: '#37a9ef',
|
|
468
|
+
owner: 'John Doe',
|
|
659
469
|
priority: 'high',
|
|
660
470
|
},
|
|
661
471
|
])
|
|
662
472
|
|
|
663
473
|
const [links, setLinks] = useState<Link[]>([
|
|
664
|
-
{ id: 'l1', source: '
|
|
474
|
+
{ id: 'l1', source: '1', target: '2', type: 'e2s' },
|
|
665
475
|
])
|
|
666
476
|
|
|
667
477
|
return (
|
|
668
|
-
<div style={{ height: '
|
|
478
|
+
<div style={{ width: '100%', height: '100vh' }}>
|
|
669
479
|
<Gantt
|
|
670
480
|
tasks={tasks}
|
|
671
481
|
links={links}
|
|
672
482
|
config={{
|
|
673
483
|
theme: 'light',
|
|
674
484
|
weekends: true,
|
|
675
|
-
|
|
676
|
-
|
|
485
|
+
containerHeight: '100%',
|
|
486
|
+
containerMinHeight: '500px',
|
|
487
|
+
gridWidth: 'clamp(300px, 35vw, 800px)',
|
|
488
|
+
}}
|
|
489
|
+
uiConfig={{
|
|
490
|
+
headerTitle: 'My Project Timeline',
|
|
491
|
+
addTaskButtonText: 'New Task',
|
|
492
|
+
showHeader: true,
|
|
493
|
+
}}
|
|
494
|
+
styleConfig={{
|
|
495
|
+
primary: '#6366f1',
|
|
496
|
+
fontFamily: 'Inter, sans-serif',
|
|
677
497
|
}}
|
|
678
498
|
onTaskUpdate={(task) => {
|
|
679
|
-
setTasks(
|
|
499
|
+
setTasks(tasks.map(t => t.id === task.id ? task : t))
|
|
680
500
|
}}
|
|
681
501
|
onTaskCreate={(task) => {
|
|
682
|
-
setTasks(
|
|
502
|
+
setTasks([...tasks, task])
|
|
683
503
|
}}
|
|
684
|
-
onTaskDelete={(
|
|
685
|
-
setTasks(
|
|
686
|
-
setLinks(prev => prev.filter(l => l.source !== id && l.target !== id))
|
|
504
|
+
onTaskDelete={(taskId) => {
|
|
505
|
+
setTasks(tasks.filter(t => t.id !== taskId))
|
|
687
506
|
}}
|
|
688
507
|
onLinkCreate={(link) => {
|
|
689
|
-
setLinks(
|
|
508
|
+
setLinks([...links, link])
|
|
690
509
|
}}
|
|
691
|
-
onLinkDelete={(
|
|
692
|
-
setLinks(
|
|
510
|
+
onLinkDelete={(linkId) => {
|
|
511
|
+
setLinks(links.filter(l => l.id !== linkId))
|
|
693
512
|
}}
|
|
694
513
|
/>
|
|
695
514
|
</div>
|
|
696
515
|
)
|
|
697
516
|
}
|
|
698
|
-
```
|
|
699
|
-
|
|
700
|
-
### With React Query
|
|
701
|
-
|
|
702
|
-
```tsx
|
|
703
|
-
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'
|
|
704
|
-
import { Gantt } from 'iris-gantt'
|
|
705
|
-
import 'iris-gantt/gantt.css'
|
|
706
|
-
|
|
707
|
-
function GanttWithBackend() {
|
|
708
|
-
const queryClient = useQueryClient()
|
|
709
|
-
|
|
710
|
-
const { data: tasks = [] } = useQuery({
|
|
711
|
-
queryKey: ['tasks'],
|
|
712
|
-
queryFn: () => fetch('/api/tasks').then(r => r.json()),
|
|
713
|
-
})
|
|
714
|
-
|
|
715
|
-
const { data: links = [] } = useQuery({
|
|
716
|
-
queryKey: ['links'],
|
|
717
|
-
queryFn: () => fetch('/api/links').then(r => r.json()),
|
|
718
|
-
})
|
|
719
|
-
|
|
720
|
-
const updateTask = useMutation({
|
|
721
|
-
mutationFn: (task) => fetch(`/api/tasks/${task.id}`, {
|
|
722
|
-
method: 'PUT',
|
|
723
|
-
body: JSON.stringify(task),
|
|
724
|
-
}),
|
|
725
|
-
onSuccess: () => {
|
|
726
|
-
queryClient.invalidateQueries({ queryKey: ['tasks'] })
|
|
727
|
-
},
|
|
728
|
-
})
|
|
729
517
|
|
|
730
|
-
|
|
731
|
-
<Gantt
|
|
732
|
-
tasks={tasks}
|
|
733
|
-
links={links}
|
|
734
|
-
onTaskUpdate={(task) => updateTask.mutate(task)}
|
|
735
|
-
/>
|
|
736
|
-
)
|
|
737
|
-
}
|
|
518
|
+
export default ProjectGantt
|
|
738
519
|
```
|
|
739
520
|
|
|
740
|
-
##
|
|
521
|
+
## Troubleshooting
|
|
741
522
|
|
|
742
|
-
###
|
|
523
|
+
### CSS Import Error
|
|
743
524
|
|
|
744
|
-
|
|
745
|
-
const [tasks, setTasks] = useState(initialTasks)
|
|
525
|
+
If you get: `Module not found: Error: Package path ./dist/gantt.css is not exported`
|
|
746
526
|
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
updateTaskInBackend(task)
|
|
754
|
-
}}
|
|
755
|
-
/>
|
|
527
|
+
**Solution:**
|
|
528
|
+
```tsx
|
|
529
|
+
// Try this instead
|
|
530
|
+
import 'iris-gantt/gantt.css'
|
|
531
|
+
// or
|
|
532
|
+
import 'iris-gantt/dist/gantt.css'
|
|
756
533
|
```
|
|
757
534
|
|
|
758
|
-
###
|
|
535
|
+
### Default Import Error
|
|
536
|
+
|
|
537
|
+
If you get: `export 'default' was not found`
|
|
759
538
|
|
|
539
|
+
**Solution:**
|
|
760
540
|
```tsx
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
config={{ readonly: true }}
|
|
764
|
-
/>
|
|
541
|
+
// Use named import instead
|
|
542
|
+
import { Gantt } from 'iris-gantt'
|
|
765
543
|
```
|
|
766
544
|
|
|
767
|
-
###
|
|
545
|
+
### Runtime Error: recentlyCreatedOwnerStacks
|
|
768
546
|
|
|
769
|
-
|
|
547
|
+
This is a **cached code issue** in your project, not the package.
|
|
770
548
|
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
549
|
+
**Solution:**
|
|
550
|
+
```bash
|
|
551
|
+
# In your project directory
|
|
552
|
+
rm -rf node_modules package-lock.json .next .cache dist build
|
|
553
|
+
npm cache clean --force
|
|
554
|
+
npm install
|
|
555
|
+
npm start
|
|
777
556
|
```
|
|
778
557
|
|
|
779
|
-
##
|
|
780
|
-
|
|
781
|
-
### CSS Not Loading
|
|
558
|
+
## TypeScript Support
|
|
782
559
|
|
|
783
|
-
|
|
560
|
+
Full TypeScript support is included:
|
|
784
561
|
|
|
785
|
-
**Solution:** Make sure you import the CSS:
|
|
786
562
|
```tsx
|
|
787
|
-
import 'iris-gantt
|
|
563
|
+
import { Gantt } from 'iris-gantt'
|
|
564
|
+
import type { Task, Link, GanttConfig, GanttUIConfig, GanttStyleConfig } from 'iris-gantt'
|
|
565
|
+
|
|
566
|
+
const tasks: Task[] = [...]
|
|
567
|
+
const config: GanttConfig = {...}
|
|
568
|
+
const uiConfig: GanttUIConfig = {...}
|
|
569
|
+
const styleConfig: GanttStyleConfig = {...}
|
|
788
570
|
```
|
|
789
571
|
|
|
790
|
-
|
|
572
|
+
## Peer Dependencies
|
|
791
573
|
|
|
792
|
-
|
|
574
|
+
Make sure you have these installed:
|
|
793
575
|
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
576
|
+
```bash
|
|
577
|
+
npm install react@^18.3.1 react-dom@^18.3.1
|
|
578
|
+
npm install antd@^5.29.3
|
|
579
|
+
npm install dayjs@^1.11.0
|
|
580
|
+
npm install @fortawesome/fontawesome-svg-core@^7.1.0
|
|
581
|
+
npm install @fortawesome/free-solid-svg-icons@^7.1.0
|
|
582
|
+
npm install @fortawesome/react-fontawesome@^3.1.0
|
|
583
|
+
```
|
|
798
584
|
|
|
799
|
-
|
|
585
|
+
## API Reference
|
|
800
586
|
|
|
801
|
-
|
|
587
|
+
### Task Interface
|
|
802
588
|
|
|
803
|
-
**Solution:** Import types explicitly:
|
|
804
589
|
```tsx
|
|
805
|
-
|
|
590
|
+
interface Task {
|
|
591
|
+
id: string
|
|
592
|
+
text: string
|
|
593
|
+
start: Date
|
|
594
|
+
end: Date
|
|
595
|
+
duration: number
|
|
596
|
+
progress: number
|
|
597
|
+
type?: 'task' | 'milestone' | 'project'
|
|
598
|
+
parent?: string
|
|
599
|
+
open?: boolean
|
|
600
|
+
color?: string
|
|
601
|
+
details?: string
|
|
602
|
+
owner?: string
|
|
603
|
+
priority?: 'low' | 'medium' | 'high'
|
|
604
|
+
dependencies?: string[]
|
|
605
|
+
segments?: TaskSegment[]
|
|
606
|
+
}
|
|
806
607
|
```
|
|
807
608
|
|
|
808
|
-
###
|
|
809
|
-
|
|
810
|
-
**Problem:** Dependency arrows don't appear.
|
|
811
|
-
|
|
812
|
-
**Solution:**
|
|
813
|
-
- Ensure `links` array is provided
|
|
814
|
-
- Check that `source` and `target` IDs match task IDs
|
|
815
|
-
- Verify tasks exist for all link references
|
|
816
|
-
|
|
817
|
-
### Date Format Issues
|
|
818
|
-
|
|
819
|
-
**Problem:** Dates are incorrect or not displaying.
|
|
609
|
+
### Link Interface
|
|
820
610
|
|
|
821
|
-
**Solution:** Always use `Date` objects, not strings:
|
|
822
611
|
```tsx
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
612
|
+
interface Link {
|
|
613
|
+
id: string
|
|
614
|
+
source: string
|
|
615
|
+
target: string
|
|
616
|
+
type: 'e2s' | 's2s' | 'e2e' | 's2e'
|
|
617
|
+
lag?: number
|
|
618
|
+
lagUnit?: 'day' | 'hour' | 'week' | 'month'
|
|
619
|
+
}
|
|
828
620
|
```
|
|
829
621
|
|
|
830
|
-
##
|
|
622
|
+
## Best Practices
|
|
831
623
|
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
624
|
+
1. **Always import CSS**: `import 'iris-gantt/gantt.css'`
|
|
625
|
+
2. **Use TypeScript**: Full type support is available
|
|
626
|
+
3. **Handle events**: Use `onTaskUpdate`, `onTaskCreate`, etc. to sync with your backend
|
|
627
|
+
4. **Customize styles**: Use `styleConfig` and CSS variables to match your project
|
|
628
|
+
5. **Responsive design**: Use `clamp()` for truly responsive widths
|
|
629
|
+
6. **Test on mobile**: The component is responsive, test on all devices
|
|
835
630
|
|
|
836
|
-
|
|
631
|
+
## Support
|
|
837
632
|
|
|
838
|
-
|
|
633
|
+
For issues, questions, or contributions, please visit:
|
|
634
|
+
- GitHub: https://github.com/TimJerry725/ganttchart.git
|