iris-gantt 1.0.1 → 1.0.2
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 +183 -215
- package/USAGE.md +838 -0
- package/dist/Gantt/Chart.d.ts +22 -0
- package/dist/Gantt/Chart.d.ts.map +1 -0
- package/dist/Gantt/ContextMenu.d.ts +19 -0
- package/dist/Gantt/ContextMenu.d.ts.map +1 -0
- package/dist/Gantt/DependencyEditor.d.ts +13 -0
- package/dist/Gantt/DependencyEditor.d.ts.map +1 -0
- package/dist/Gantt/DependencyPopover.d.ts +12 -0
- package/dist/Gantt/DependencyPopover.d.ts.map +1 -0
- package/dist/Gantt/DragDrop.d.ts +18 -0
- package/dist/Gantt/DragDrop.d.ts.map +1 -0
- package/dist/Gantt/Gantt.d.ts +35 -0
- package/dist/Gantt/Gantt.d.ts.map +1 -0
- package/dist/Gantt/GanttPro.d.ts +16 -0
- package/dist/Gantt/GanttPro.d.ts.map +1 -0
- package/dist/Gantt/Grid.d.ts +29 -0
- package/dist/Gantt/Grid.d.ts.map +1 -0
- package/dist/Gantt/LinkRenderer.d.ts +15 -0
- package/dist/Gantt/LinkRenderer.d.ts.map +1 -0
- package/dist/Gantt/TaskBar.d.ts +19 -0
- package/dist/Gantt/TaskBar.d.ts.map +1 -0
- package/dist/Gantt/TaskCreator.d.ts +8 -0
- package/dist/Gantt/TaskCreator.d.ts.map +1 -0
- package/dist/Gantt/TaskEditor.d.ts +10 -0
- package/dist/Gantt/TaskEditor.d.ts.map +1 -0
- package/dist/Gantt/Timeline.d.ts +23 -0
- package/dist/Gantt/Timeline.d.ts.map +1 -0
- package/dist/Gantt/Toolbar.d.ts +15 -0
- package/dist/Gantt/Toolbar.d.ts.map +1 -0
- package/dist/Gantt/UndoRedo.d.ts +27 -0
- package/dist/Gantt/UndoRedo.d.ts.map +1 -0
- package/dist/Gantt/exports.d.ts +21 -0
- package/dist/Gantt/exports.d.ts.map +1 -0
- package/dist/Gantt/features/AutoScheduler.d.ts +10 -0
- package/dist/Gantt/features/AutoScheduler.d.ts.map +1 -0
- package/dist/Gantt/features/Baselines.d.ts +27 -0
- package/dist/Gantt/features/Baselines.d.ts.map +1 -0
- package/dist/Gantt/features/CriticalPath.d.ts +10 -0
- package/dist/Gantt/features/CriticalPath.d.ts.map +1 -0
- package/dist/Gantt/features/ExportUtils.d.ts +11 -0
- package/dist/Gantt/features/ExportUtils.d.ts.map +1 -0
- package/dist/Gantt/features/FilterSearch.d.ts +20 -0
- package/dist/Gantt/features/FilterSearch.d.ts.map +1 -0
- package/dist/Gantt/types.d.ts +80 -0
- package/dist/Gantt/types.d.ts.map +1 -0
- package/dist/Gantt/utils/dateUtils.d.ts +11 -0
- package/dist/Gantt/utils/dateUtils.d.ts.map +1 -0
- package/dist/Gantt/utils/dependencyParser.d.ts +26 -0
- package/dist/Gantt/utils/dependencyParser.d.ts.map +1 -0
- package/dist/gantt.css +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/iris-gantt.js +1232 -1500
- package/dist/iris-gantt.umd.cjs +8 -8
- package/dist/types.d.ts +2 -0
- package/dist/types.d.ts.map +1 -0
- package/package.json +42 -7
- package/dist/iris-gantt.css +0 -1
- package/src/components/Gantt/gantt.css +0 -2167
package/USAGE.md
ADDED
|
@@ -0,0 +1,838 @@
|
|
|
1
|
+
# iris-gantt Usage Documentation
|
|
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)
|
|
18
|
+
|
|
19
|
+
## Installation
|
|
20
|
+
|
|
21
|
+
### Install the Package
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
npm install iris-gantt
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
### Install Peer Dependencies
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
npm install react react-dom antd dayjs @fortawesome/react-fontawesome @fortawesome/fontawesome-svg-core @fortawesome/free-solid-svg-icons
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
**Note:** These are required peer dependencies. Make sure they're installed in your project.
|
|
34
|
+
|
|
35
|
+
## Quick Start
|
|
36
|
+
|
|
37
|
+
```tsx
|
|
38
|
+
import React from 'react'
|
|
39
|
+
import { Gantt } from 'iris-gantt'
|
|
40
|
+
import 'iris-gantt/gantt.css'
|
|
41
|
+
import type { Task, Link } from 'iris-gantt'
|
|
42
|
+
|
|
43
|
+
function App() {
|
|
44
|
+
const tasks: Task[] = [
|
|
45
|
+
{
|
|
46
|
+
id: '1',
|
|
47
|
+
text: 'Project Planning',
|
|
48
|
+
start: new Date(2024, 0, 1),
|
|
49
|
+
end: new Date(2024, 0, 15),
|
|
50
|
+
duration: 14,
|
|
51
|
+
progress: 100,
|
|
52
|
+
},
|
|
53
|
+
]
|
|
54
|
+
|
|
55
|
+
return <Gantt tasks={tasks} />
|
|
56
|
+
}
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
**Important:** Don't forget to import the CSS file: `import 'iris-gantt/gantt.css'`
|
|
60
|
+
|
|
61
|
+
## Basic Usage
|
|
62
|
+
|
|
63
|
+
### Minimal Example
|
|
64
|
+
|
|
65
|
+
```tsx
|
|
66
|
+
import { Gantt } from 'iris-gantt'
|
|
67
|
+
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
|
+
```
|
|
84
|
+
|
|
85
|
+
### With Event Handlers
|
|
86
|
+
|
|
87
|
+
```tsx
|
|
88
|
+
import { Gantt } from 'iris-gantt'
|
|
89
|
+
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
|
+
```
|
|
125
|
+
|
|
126
|
+
## Task Management
|
|
127
|
+
|
|
128
|
+
### Creating Tasks
|
|
129
|
+
|
|
130
|
+
Tasks are created through the built-in task creator (click the "+ Add Task" button) or programmatically:
|
|
131
|
+
|
|
132
|
+
```tsx
|
|
133
|
+
const newTask: Task = {
|
|
134
|
+
id: 'unique-id',
|
|
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)
|
|
169
|
+
|
|
170
|
+
```tsx
|
|
171
|
+
const tasks: Task[] = [
|
|
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
|
+
]
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
### Task Types
|
|
204
|
+
|
|
205
|
+
```tsx
|
|
206
|
+
// Regular task
|
|
207
|
+
{ type: 'task', ... }
|
|
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:
|
|
219
|
+
|
|
220
|
+
```tsx
|
|
221
|
+
const task: Task = {
|
|
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: [
|
|
229
|
+
{
|
|
230
|
+
start: new Date(2024, 0, 1),
|
|
231
|
+
end: new Date(2024, 0, 10),
|
|
232
|
+
duration: 9,
|
|
233
|
+
},
|
|
234
|
+
{
|
|
235
|
+
start: new Date(2024, 0, 15),
|
|
236
|
+
end: new Date(2024, 0, 20),
|
|
237
|
+
duration: 5,
|
|
238
|
+
},
|
|
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
|
|
287
|
+
|
|
288
|
+
Add delays or lead time to dependencies:
|
|
289
|
+
|
|
290
|
+
```tsx
|
|
291
|
+
const links: Link[] = [
|
|
292
|
+
{
|
|
293
|
+
id: 'l1',
|
|
294
|
+
source: '1',
|
|
295
|
+
target: '2',
|
|
296
|
+
type: 'e2s',
|
|
297
|
+
lag: 2, // 2 days delay
|
|
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
|
+
]
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
## Configuration
|
|
312
|
+
|
|
313
|
+
### Basic Configuration
|
|
314
|
+
|
|
315
|
+
```tsx
|
|
316
|
+
<Gantt
|
|
317
|
+
tasks={tasks}
|
|
318
|
+
config={{
|
|
319
|
+
theme: 'light', // or 'dark'
|
|
320
|
+
weekends: true,
|
|
321
|
+
readonly: false,
|
|
322
|
+
editable: true,
|
|
323
|
+
}}
|
|
324
|
+
/>
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
### Timeline Scales
|
|
328
|
+
|
|
329
|
+
Customize the timeline display:
|
|
330
|
+
|
|
331
|
+
```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
|
+
<Gantt
|
|
341
|
+
tasks={tasks}
|
|
342
|
+
config={{ scales }}
|
|
343
|
+
/>
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
Available units: `'hour'`, `'day'`, `'week'`, `'month'`, `'quarter'`, `'year'`
|
|
347
|
+
|
|
348
|
+
### Custom Columns
|
|
349
|
+
|
|
350
|
+
```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
|
+
<Gantt
|
|
361
|
+
tasks={tasks}
|
|
362
|
+
config={{ columns }}
|
|
363
|
+
/>
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
### Custom Column Templates
|
|
367
|
+
|
|
368
|
+
```tsx
|
|
369
|
+
const columns: Column[] = [
|
|
370
|
+
{
|
|
371
|
+
name: 'status',
|
|
372
|
+
label: 'Status',
|
|
373
|
+
width: 120,
|
|
374
|
+
template: (task) => {
|
|
375
|
+
if (task.progress === 100) return '✅ Complete'
|
|
376
|
+
if (task.progress > 0) return '🔄 In Progress'
|
|
377
|
+
return '⏳ Not Started'
|
|
378
|
+
},
|
|
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
|
+
}}
|
|
395
|
+
/>
|
|
396
|
+
```
|
|
397
|
+
|
|
398
|
+
### Markers
|
|
399
|
+
|
|
400
|
+
Add vertical markers to highlight important dates:
|
|
401
|
+
|
|
402
|
+
```tsx
|
|
403
|
+
import type { Marker } from 'iris-gantt'
|
|
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
|
+
]
|
|
413
|
+
|
|
414
|
+
<Gantt
|
|
415
|
+
tasks={tasks}
|
|
416
|
+
config={{ markers }}
|
|
417
|
+
/>
|
|
418
|
+
```
|
|
419
|
+
|
|
420
|
+
### Sizing
|
|
421
|
+
|
|
422
|
+
```tsx
|
|
423
|
+
<Gantt
|
|
424
|
+
tasks={tasks}
|
|
425
|
+
config={{
|
|
426
|
+
taskHeight: 30, // Height of task bars
|
|
427
|
+
rowHeight: 44, // Height of each row
|
|
428
|
+
scaleHeight: 28, // Height of timeline scales
|
|
429
|
+
columnWidth: 50, // Width of timeline columns
|
|
430
|
+
minColumnWidth: 30, // Minimum column width
|
|
431
|
+
}}
|
|
432
|
+
/>
|
|
433
|
+
```
|
|
434
|
+
|
|
435
|
+
## Advanced Features
|
|
436
|
+
|
|
437
|
+
### Auto-Scheduling
|
|
438
|
+
|
|
439
|
+
Automatically schedule tasks based on dependencies:
|
|
440
|
+
|
|
441
|
+
```tsx
|
|
442
|
+
<Gantt
|
|
443
|
+
tasks={tasks}
|
|
444
|
+
links={links}
|
|
445
|
+
config={{
|
|
446
|
+
autoSchedule: true,
|
|
447
|
+
}}
|
|
448
|
+
/>
|
|
449
|
+
```
|
|
450
|
+
|
|
451
|
+
The toolbar includes an "Auto-Schedule" button that recalculates task dates based on dependencies.
|
|
452
|
+
|
|
453
|
+
### Critical Path
|
|
454
|
+
|
|
455
|
+
Highlight the critical path (longest path through dependencies):
|
|
456
|
+
|
|
457
|
+
```tsx
|
|
458
|
+
<Gantt
|
|
459
|
+
tasks={tasks}
|
|
460
|
+
links={links}
|
|
461
|
+
config={{
|
|
462
|
+
criticalPath: true,
|
|
463
|
+
}}
|
|
464
|
+
/>
|
|
465
|
+
```
|
|
466
|
+
|
|
467
|
+
Critical tasks are highlighted in red.
|
|
468
|
+
|
|
469
|
+
### Baselines
|
|
470
|
+
|
|
471
|
+
Track original plans vs. current state:
|
|
472
|
+
|
|
473
|
+
```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
|
+
<Gantt
|
|
481
|
+
tasks={currentTasks}
|
|
482
|
+
config={{
|
|
483
|
+
baselines: true,
|
|
484
|
+
// Baselines are stored internally
|
|
485
|
+
}}
|
|
486
|
+
/>
|
|
487
|
+
```
|
|
488
|
+
|
|
489
|
+
### Undo/Redo
|
|
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
|
|
620
|
+
|
|
621
|
+
```tsx
|
|
622
|
+
import React, { useState } from 'react'
|
|
623
|
+
import { Gantt } from 'iris-gantt'
|
|
624
|
+
import 'iris-gantt/gantt.css'
|
|
625
|
+
import type { Task, Link } from 'iris-gantt'
|
|
626
|
+
|
|
627
|
+
function ProjectGantt() {
|
|
628
|
+
const [tasks, setTasks] = useState<Task[]>([
|
|
629
|
+
{
|
|
630
|
+
id: '1',
|
|
631
|
+
text: 'Project Setup',
|
|
632
|
+
start: new Date(2024, 0, 1),
|
|
633
|
+
end: new Date(2024, 0, 5),
|
|
634
|
+
duration: 4,
|
|
635
|
+
progress: 100,
|
|
636
|
+
type: 'project',
|
|
637
|
+
open: true,
|
|
638
|
+
},
|
|
639
|
+
{
|
|
640
|
+
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
|
+
text: 'Development',
|
|
653
|
+
start: new Date(2024, 0, 21),
|
|
654
|
+
end: new Date(2024, 1, 15),
|
|
655
|
+
duration: 25,
|
|
656
|
+
progress: 30,
|
|
657
|
+
parent: '1',
|
|
658
|
+
owner: 'Bob',
|
|
659
|
+
priority: 'high',
|
|
660
|
+
},
|
|
661
|
+
])
|
|
662
|
+
|
|
663
|
+
const [links, setLinks] = useState<Link[]>([
|
|
664
|
+
{ id: 'l1', source: '2', target: '3', type: 'e2s' },
|
|
665
|
+
])
|
|
666
|
+
|
|
667
|
+
return (
|
|
668
|
+
<div style={{ height: '600px' }}>
|
|
669
|
+
<Gantt
|
|
670
|
+
tasks={tasks}
|
|
671
|
+
links={links}
|
|
672
|
+
config={{
|
|
673
|
+
theme: 'light',
|
|
674
|
+
weekends: true,
|
|
675
|
+
criticalPath: true,
|
|
676
|
+
autoSchedule: true,
|
|
677
|
+
}}
|
|
678
|
+
onTaskUpdate={(task) => {
|
|
679
|
+
setTasks(prev => prev.map(t => t.id === task.id ? task : t))
|
|
680
|
+
}}
|
|
681
|
+
onTaskCreate={(task) => {
|
|
682
|
+
setTasks(prev => [...prev, task])
|
|
683
|
+
}}
|
|
684
|
+
onTaskDelete={(id) => {
|
|
685
|
+
setTasks(prev => prev.filter(t => t.id !== id))
|
|
686
|
+
setLinks(prev => prev.filter(l => l.source !== id && l.target !== id))
|
|
687
|
+
}}
|
|
688
|
+
onLinkCreate={(link) => {
|
|
689
|
+
setLinks(prev => [...prev, link])
|
|
690
|
+
}}
|
|
691
|
+
onLinkDelete={(id) => {
|
|
692
|
+
setLinks(prev => prev.filter(l => l.id !== id))
|
|
693
|
+
}}
|
|
694
|
+
/>
|
|
695
|
+
</div>
|
|
696
|
+
)
|
|
697
|
+
}
|
|
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
|
+
|
|
730
|
+
return (
|
|
731
|
+
<Gantt
|
|
732
|
+
tasks={tasks}
|
|
733
|
+
links={links}
|
|
734
|
+
onTaskUpdate={(task) => updateTask.mutate(task)}
|
|
735
|
+
/>
|
|
736
|
+
)
|
|
737
|
+
}
|
|
738
|
+
```
|
|
739
|
+
|
|
740
|
+
## Common Patterns
|
|
741
|
+
|
|
742
|
+
### Controlled Component Pattern
|
|
743
|
+
|
|
744
|
+
```tsx
|
|
745
|
+
const [tasks, setTasks] = useState(initialTasks)
|
|
746
|
+
|
|
747
|
+
<Gantt
|
|
748
|
+
tasks={tasks}
|
|
749
|
+
onTaskUpdate={(task) => {
|
|
750
|
+
// Update local state
|
|
751
|
+
setTasks(prev => prev.map(t => t.id === task.id ? task : t))
|
|
752
|
+
// Sync with backend
|
|
753
|
+
updateTaskInBackend(task)
|
|
754
|
+
}}
|
|
755
|
+
/>
|
|
756
|
+
```
|
|
757
|
+
|
|
758
|
+
### Read-Only Mode
|
|
759
|
+
|
|
760
|
+
```tsx
|
|
761
|
+
<Gantt
|
|
762
|
+
tasks={tasks}
|
|
763
|
+
config={{ readonly: true }}
|
|
764
|
+
/>
|
|
765
|
+
```
|
|
766
|
+
|
|
767
|
+
### Custom Styling
|
|
768
|
+
|
|
769
|
+
The component uses CSS variables that you can override:
|
|
770
|
+
|
|
771
|
+
```css
|
|
772
|
+
.gantt-container {
|
|
773
|
+
--wx-gantt-primary: #your-color;
|
|
774
|
+
--gantt-row-height: 50px;
|
|
775
|
+
/* etc. */
|
|
776
|
+
}
|
|
777
|
+
```
|
|
778
|
+
|
|
779
|
+
## Troubleshooting
|
|
780
|
+
|
|
781
|
+
### CSS Not Loading
|
|
782
|
+
|
|
783
|
+
**Problem:** Styles are not applied.
|
|
784
|
+
|
|
785
|
+
**Solution:** Make sure you import the CSS:
|
|
786
|
+
```tsx
|
|
787
|
+
import 'iris-gantt/gantt.css'
|
|
788
|
+
```
|
|
789
|
+
|
|
790
|
+
### Tasks Not Rendering
|
|
791
|
+
|
|
792
|
+
**Problem:** Tasks don't appear on the chart.
|
|
793
|
+
|
|
794
|
+
**Solution:**
|
|
795
|
+
- Check that `start` and `end` are `Date` objects, not strings
|
|
796
|
+
- Verify `duration` is a positive number
|
|
797
|
+
- Ensure tasks are within the visible date range
|
|
798
|
+
|
|
799
|
+
### TypeScript Errors
|
|
800
|
+
|
|
801
|
+
**Problem:** Type errors when using the component.
|
|
802
|
+
|
|
803
|
+
**Solution:** Import types explicitly:
|
|
804
|
+
```tsx
|
|
805
|
+
import type { Task, Link, GanttProps } from 'iris-gantt'
|
|
806
|
+
```
|
|
807
|
+
|
|
808
|
+
### Dependencies Not Showing
|
|
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.
|
|
820
|
+
|
|
821
|
+
**Solution:** Always use `Date` objects, not strings:
|
|
822
|
+
```tsx
|
|
823
|
+
// ✅ Correct
|
|
824
|
+
start: new Date(2024, 0, 1)
|
|
825
|
+
|
|
826
|
+
// ❌ Wrong
|
|
827
|
+
start: '2024-01-01'
|
|
828
|
+
```
|
|
829
|
+
|
|
830
|
+
## Additional Resources
|
|
831
|
+
|
|
832
|
+
- [GitHub Repository](https://github.com/TimJerry725/ganttchart)
|
|
833
|
+
- [API Reference](./README.md)
|
|
834
|
+
- [Publishing Guide](./PUBLISHING.md)
|
|
835
|
+
|
|
836
|
+
---
|
|
837
|
+
|
|
838
|
+
**Need Help?** Open an issue on GitHub or check the examples in the Storybook demos.
|