iris-gantt 1.4.11 → 1.5.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 +231 -103
- package/dist/Gantt/Gantt.d.ts +2 -1
- package/dist/Gantt/Gantt.d.ts.map +1 -1
- package/dist/Gantt/Timeline.d.ts.map +1 -1
- package/dist/Gantt/Toolbar.d.ts +7 -1
- package/dist/Gantt/Toolbar.d.ts.map +1 -1
- package/dist/Gantt/types.d.ts +7 -0
- package/dist/Gantt/types.d.ts.map +1 -1
- package/dist/gantt.css +1 -1
- package/dist/iris-gantt.js +2302 -2135
- package/dist/iris-gantt.umd.cjs +16 -16
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -2,27 +2,36 @@
|
|
|
2
2
|
|
|
3
3
|
A comprehensive, production-ready Gantt chart component built with React and TypeScript. Easy to install, simple to use, fully customizable, and responsive.
|
|
4
4
|
|
|
5
|
-
## 🆕 Version 1.
|
|
5
|
+
## 🆕 Version 1.5.0 (Latest)
|
|
6
6
|
|
|
7
7
|
### Bug Fixes
|
|
8
|
+
- **On-Hold correctly renders over completed tasks** — The grey hatched on-hold overlay now correctly sits *above* the task bar in the DOM tree. Previously, the `status-completed` blue background colour overrode it.
|
|
9
|
+
- **On-Hold overlay stays visible on hover** — Raised the CSS `z-index` of `.gantt-on-hold-period` to `101 !important`. The task bar hover state elevates to `z-index: 100`, so the hold pattern will no longer disappear when you mouse over a task.
|
|
10
|
+
|
|
8
11
|
- **OnHold grey lines now render with project API data** — Fixed a bug where on-hold grey bars were not visible when tasks used API field names (`workGroupName`, `plannedStartDate`, `plannedEndDate`). The normalizer now recognises these aliases, so dates are correctly resolved and the hold period overlap is detected.
|
|
9
12
|
|
|
13
|
+
### Improvements
|
|
14
|
+
- **Prop-driven day/week/month timeline switcher** — You can now expose a calendar view switcher in the toolbar and control the available `day`, `week`, and `month` views through props.
|
|
15
|
+
|
|
10
16
|
### New API Field Aliases
|
|
17
|
+
|
|
11
18
|
The `tasks` prop now accepts the following additional field names used by common project APIs:
|
|
12
19
|
|
|
13
|
-
| New alias
|
|
14
|
-
|
|
15
|
-
| `workGroupName`
|
|
20
|
+
| New alias | Maps to |
|
|
21
|
+
| ------------------ | ------------------- |
|
|
22
|
+
| `workGroupName` | Task display name |
|
|
16
23
|
| `plannedStartDate` | Task bar start date |
|
|
17
|
-
| `plannedEndDate`
|
|
24
|
+
| `plannedEndDate` | Task bar end date |
|
|
18
25
|
|
|
19
26
|
## 🔖 Version 1.4.6
|
|
20
27
|
|
|
21
28
|
### Bug Fixes
|
|
29
|
+
|
|
22
30
|
- **Baselines now show by default** — Fixed a critical bug where baselines were not rendering because the `config` spread was overriding the default `baselines: true` with `undefined`. Baselines are now always enabled unless you explicitly pass `config={{ baselines: false }}`.
|
|
23
31
|
- **`on_hold_periods` snake_case prop supported** — The Gantt component now accepts both `onHoldPeriods` (camelCase) and `on_hold_periods` (snake_case) as a top-level prop for project-level on-hold periods. Previously only the camelCase variant was recognized, causing the feature to silently fail for API-style payloads.
|
|
24
32
|
|
|
25
33
|
### Improvements
|
|
34
|
+
|
|
26
35
|
- **Project-level OnHold applied to all tasks** — The `onHoldPeriods` / `on_hold_periods` prop now propagates the grey hatched on-hold bar to **all** task rows including `project`-type tasks. Previously, only child/standalone tasks showed the hold bar; now the entire project hierarchy displays it consistently.
|
|
27
36
|
- **Same-height on-hold bars** — The grey on-hold period bar is now the same height (28px) as the task bar.
|
|
28
37
|
- **Tasks continue after hold period** — When a project resumes after an on-hold period, all affected tasks continue in sequence after the hold, and remaining days are extended automatically.
|
|
@@ -31,6 +40,7 @@ The `tasks` prop now accepts the following additional field names used by common
|
|
|
31
40
|
## 🔖 Version 1.4.2
|
|
32
41
|
|
|
33
42
|
### Included Changes
|
|
43
|
+
|
|
34
44
|
- **Per-task tooltip config** — Each task can now carry its own `tooltipConfig` to override global tooltip settings (show/hide fields, labels, accessors, formatters).
|
|
35
45
|
- **Unified `onTaskDragUpdate` callback** — Single callback for all drag operations: task bar move/resize AND row reorder (grip icon drag-and-drop).
|
|
36
46
|
- **Row reorder API integration** — `onTaskDragUpdate` now fires with `dragType: 'reorder'` and `reorderMeta` (sequence IDs, stage ID) when tasks are reordered via grip icon.
|
|
@@ -51,6 +61,7 @@ The `tasks` prop now accepts the following additional field names used by common
|
|
|
51
61
|
## ✨ Features
|
|
52
62
|
|
|
53
63
|
### Core Features
|
|
64
|
+
|
|
54
65
|
- ✅ Interactive task management
|
|
55
66
|
- ✅ Drag & drop task bars
|
|
56
67
|
- ✅ Task dependencies with 4 link types (end-to-start, start-to-start, end-to-end, start-to-end)
|
|
@@ -61,6 +72,7 @@ The `tasks` prop now accepts the following additional field names used by common
|
|
|
61
72
|
- ✅ Light & dark themes
|
|
62
73
|
|
|
63
74
|
### Advanced Features
|
|
75
|
+
|
|
64
76
|
- ✅ Auto-scheduling
|
|
65
77
|
- ✅ Critical path analysis
|
|
66
78
|
- ✅ **Baselines (always visible, automatically created)**
|
|
@@ -69,7 +81,8 @@ The `tasks` prop now accepts the following additional field names used by common
|
|
|
69
81
|
- ✅ Filtering & search
|
|
70
82
|
- ✅ Resource leveling
|
|
71
83
|
- ✅ **Fully responsive** (desktop, tablet, mobile)
|
|
72
|
-
- ✅ **Fully customizable** (all text, buttons, colors, fonts)
|
|
84
|
+
- ✅ **Fully customizable** (all text, buttons, colors, fonts, icons)
|
|
85
|
+
- ✅ **Vertical Marker Lines** (Today & Project Start)
|
|
73
86
|
|
|
74
87
|
## 📦 Installation
|
|
75
88
|
|
|
@@ -93,31 +106,31 @@ npm install @fortawesome/react-fontawesome@^3.1.0
|
|
|
93
106
|
## 🚀 Quick Start
|
|
94
107
|
|
|
95
108
|
```tsx
|
|
96
|
-
import { Gantt } from
|
|
97
|
-
import
|
|
109
|
+
import { Gantt } from "iris-gantt";
|
|
110
|
+
import "iris-gantt/gantt.css";
|
|
98
111
|
|
|
99
112
|
function MyGantt() {
|
|
100
113
|
const tasks = [
|
|
101
114
|
{
|
|
102
|
-
id:
|
|
103
|
-
text:
|
|
115
|
+
id: "1",
|
|
116
|
+
text: "Project Planning",
|
|
104
117
|
start: new Date(2024, 0, 1),
|
|
105
118
|
end: new Date(2024, 0, 15),
|
|
106
119
|
duration: 14,
|
|
107
120
|
progress: 100,
|
|
108
|
-
type:
|
|
121
|
+
type: "project",
|
|
109
122
|
},
|
|
110
123
|
{
|
|
111
|
-
id:
|
|
112
|
-
text:
|
|
124
|
+
id: "2",
|
|
125
|
+
text: "Development",
|
|
113
126
|
start: new Date(2024, 0, 15),
|
|
114
127
|
end: new Date(2024, 1, 15),
|
|
115
128
|
duration: 31,
|
|
116
129
|
progress: 60,
|
|
117
130
|
},
|
|
118
|
-
]
|
|
131
|
+
];
|
|
119
132
|
|
|
120
|
-
return <Gantt tasks={tasks}
|
|
133
|
+
return <Gantt tasks={tasks} />;
|
|
121
134
|
}
|
|
122
135
|
```
|
|
123
136
|
|
|
@@ -133,19 +146,25 @@ function MyGantt() {
|
|
|
133
146
|
|
|
134
147
|
```tsx
|
|
135
148
|
// Main component (named import - recommended)
|
|
136
|
-
import { Gantt } from
|
|
149
|
+
import { Gantt } from "iris-gantt";
|
|
137
150
|
|
|
138
151
|
// Main component (default import - also works)
|
|
139
|
-
import Gantt from
|
|
152
|
+
import Gantt from "iris-gantt";
|
|
140
153
|
|
|
141
154
|
// Types
|
|
142
155
|
import type {
|
|
143
|
-
Task,
|
|
144
|
-
|
|
145
|
-
|
|
156
|
+
Task,
|
|
157
|
+
Link,
|
|
158
|
+
GanttConfig,
|
|
159
|
+
GanttUIConfig,
|
|
160
|
+
GanttStyleConfig,
|
|
161
|
+
TaskTooltipConfig,
|
|
162
|
+
TaskDragUpdatePayload,
|
|
163
|
+
TaskReorderMeta,
|
|
164
|
+
} from "iris-gantt";
|
|
146
165
|
|
|
147
166
|
// CSS (required!)
|
|
148
|
-
import
|
|
167
|
+
import "iris-gantt/gantt.css";
|
|
149
168
|
```
|
|
150
169
|
|
|
151
170
|
## 🔧 Basic Configuration
|
|
@@ -155,12 +174,112 @@ import 'iris-gantt/gantt.css'
|
|
|
155
174
|
tasks={tasks}
|
|
156
175
|
links={links}
|
|
157
176
|
config={{
|
|
158
|
-
theme:
|
|
177
|
+
theme: "light",
|
|
159
178
|
weekends: true,
|
|
160
|
-
containerHeight:
|
|
161
|
-
containerMinHeight:
|
|
179
|
+
containerHeight: "100%",
|
|
180
|
+
containerMinHeight: "400px",
|
|
181
|
+
timelineView: "day",
|
|
182
|
+
timelineViews: ["day", "week", "month"],
|
|
183
|
+
}}
|
|
184
|
+
uiConfig={{
|
|
185
|
+
timelineViewLabels: {
|
|
186
|
+
day: "Days",
|
|
187
|
+
week: "Weeks",
|
|
188
|
+
month: "Months",
|
|
189
|
+
},
|
|
190
|
+
}}
|
|
191
|
+
onTaskUpdate={(task) => console.log("Updated:", task)}
|
|
192
|
+
/>
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
## View Switcher
|
|
196
|
+
|
|
197
|
+
Use the toolbar switcher to toggle the calendar between day, week, and month views.
|
|
198
|
+
|
|
199
|
+
```tsx
|
|
200
|
+
<Gantt
|
|
201
|
+
tasks={tasks}
|
|
202
|
+
config={{
|
|
203
|
+
timelineView: "week",
|
|
204
|
+
timelineViews: ["day", "week", "month"],
|
|
205
|
+
timelineViewScales: {
|
|
206
|
+
day: [
|
|
207
|
+
{ unit: "month", step: 1, format: "MMM YYYY" },
|
|
208
|
+
{ unit: "day", step: 1, format: "D" },
|
|
209
|
+
],
|
|
210
|
+
week: [
|
|
211
|
+
{ unit: "month", step: 1, format: "MMM YYYY" },
|
|
212
|
+
{ unit: "week", step: 1, format: "Week W" },
|
|
213
|
+
],
|
|
214
|
+
month: [
|
|
215
|
+
{ unit: "year", step: 1, format: "YYYY" },
|
|
216
|
+
{ unit: "month", step: 1, format: "MMM" },
|
|
217
|
+
],
|
|
218
|
+
},
|
|
219
|
+
}}
|
|
220
|
+
uiConfig={{
|
|
221
|
+
timelineViewLabels: {
|
|
222
|
+
day: "Days",
|
|
223
|
+
week: "Weeks",
|
|
224
|
+
month: "Months",
|
|
225
|
+
},
|
|
226
|
+
}}
|
|
227
|
+
/>
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
## 📍 Vertical Marker Lines
|
|
231
|
+
|
|
232
|
+
The Gantt chart supports vertical indicator lines for the current date (Today) and the project start date. Both are enabled by default and come with customizable markers and labels.
|
|
233
|
+
|
|
234
|
+
```tsx
|
|
235
|
+
<Gantt
|
|
236
|
+
tasks={tasks}
|
|
237
|
+
config={{
|
|
238
|
+
// Today Line
|
|
239
|
+
showTodayLine: true,
|
|
240
|
+
todayLineColor: "#ff4d4f",
|
|
241
|
+
todayLineLabel: "Today",
|
|
242
|
+
todayLineStyle: "solid", // 'solid' | 'dashed' | 'dotted'
|
|
243
|
+
todayLineWidth: 1,
|
|
244
|
+
todayLineOpacity: 1,
|
|
245
|
+
showTodayLineMarker: true, // Triangle marker at the top
|
|
246
|
+
todayLineMarkerStyle: "triangle", // 'triangle' | 'arrow' | 'dot'
|
|
247
|
+
|
|
248
|
+
// Project Start Line
|
|
249
|
+
showProjectStartLine: true,
|
|
250
|
+
projectStartDate: new Date(2024, 0, 1), // Optional: defaults to earliest task
|
|
251
|
+
projectStartLineColor: "#40a9ff",
|
|
252
|
+
projectStartLineLabel: "Kick-off",
|
|
253
|
+
projectStartLineStyle: "dashed",
|
|
254
|
+
showProjectStartLineMarker: true,
|
|
255
|
+
}}
|
|
256
|
+
/>
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
## 🎨 Custom Icons
|
|
260
|
+
|
|
261
|
+
You can replace any UI icon by passing a React component or a string (for font-icon classes) to the `iconConfig` prop. This allows you to match your project's icon library (e.g., Ant Design, Lucide, FontAwesome).
|
|
262
|
+
|
|
263
|
+
```tsx
|
|
264
|
+
<Gantt
|
|
265
|
+
tasks={tasks}
|
|
266
|
+
iconConfig={{
|
|
267
|
+
// Toolbar
|
|
268
|
+
addTask: <PlusCircleOutlined />, // React node
|
|
269
|
+
zoomIn: "fas fa-search-plus", // Font-icon string
|
|
270
|
+
zoomOut: "fas fa-search-minus",
|
|
271
|
+
exportPDF: <FilePdfOutlined />,
|
|
272
|
+
|
|
273
|
+
// Grid
|
|
274
|
+
gripVertical: <HolderOutlined />,
|
|
275
|
+
chevronRight: <RightOutlined />,
|
|
276
|
+
chevronDown: <DownOutlined />,
|
|
277
|
+
|
|
278
|
+
// Context Menu
|
|
279
|
+
edit: <EditOutlined />,
|
|
280
|
+
delete: <DeleteOutlined />,
|
|
281
|
+
copy: <CopyOutlined />,
|
|
162
282
|
}}
|
|
163
|
-
onTaskUpdate={(task) => console.log('Updated:', task)}
|
|
164
283
|
/>
|
|
165
284
|
```
|
|
166
285
|
|
|
@@ -178,17 +297,18 @@ All task hover fields are configurable via props and can be mapped from API valu
|
|
|
178
297
|
showStatus: true,
|
|
179
298
|
showDependencyRule: true,
|
|
180
299
|
showProgress: true,
|
|
181
|
-
plannedLabel:
|
|
182
|
-
actualLabel:
|
|
183
|
-
statusLabel:
|
|
184
|
-
dependencyRuleLabel:
|
|
185
|
-
progressLabel:
|
|
186
|
-
ownerLabel:
|
|
187
|
-
dateFormat:
|
|
300
|
+
plannedLabel: "Planned start/end",
|
|
301
|
+
actualLabel: "Actual start/end",
|
|
302
|
+
statusLabel: "Current status",
|
|
303
|
+
dependencyRuleLabel: "Dependency rule",
|
|
304
|
+
progressLabel: "Progress",
|
|
305
|
+
ownerLabel: "Owner",
|
|
306
|
+
dateFormat: "MMM D, YYYY",
|
|
188
307
|
taskNameAccessor: (task) => task.text,
|
|
189
308
|
statusAccessor: (task) => task.status,
|
|
190
309
|
progressAccessor: (task) => task.progress,
|
|
191
|
-
dependencyRuleAccessor: (task, generatedRules) =>
|
|
310
|
+
dependencyRuleAccessor: (task, generatedRules) =>
|
|
311
|
+
task.dependencyRule || generatedRules,
|
|
192
312
|
}}
|
|
193
313
|
/>
|
|
194
314
|
```
|
|
@@ -202,9 +322,9 @@ Each task can override the global `taskTooltipConfig` with its own `tooltipConfi
|
|
|
202
322
|
tasks={[
|
|
203
323
|
{
|
|
204
324
|
id: 1,
|
|
205
|
-
text:
|
|
206
|
-
start:
|
|
207
|
-
end:
|
|
325
|
+
text: "Task with custom tooltip",
|
|
326
|
+
start: "2026-01-01",
|
|
327
|
+
end: "2026-01-10",
|
|
208
328
|
duration: 9,
|
|
209
329
|
progress: 50,
|
|
210
330
|
tooltipConfig: {
|
|
@@ -212,7 +332,8 @@ Each task can override the global `taskTooltipConfig` with its own `tooltipConfi
|
|
|
212
332
|
showDependencyRule: false,
|
|
213
333
|
showProgress: true,
|
|
214
334
|
showActualDates: true,
|
|
215
|
-
plannedStartAccessor: (task) =>
|
|
335
|
+
plannedStartAccessor: (task) =>
|
|
336
|
+
customDataMap.get(task.id)?.plannedStart,
|
|
216
337
|
plannedEndAccessor: (task) => customDataMap.get(task.id)?.plannedEnd,
|
|
217
338
|
actualStartAccessor: (task) => customDataMap.get(task.id)?.actualStart,
|
|
218
339
|
actualEndAccessor: (task) => customDataMap.get(task.id)?.actualEnd,
|
|
@@ -220,9 +341,9 @@ Each task can override the global `taskTooltipConfig` with its own `tooltipConfi
|
|
|
220
341
|
},
|
|
221
342
|
{
|
|
222
343
|
id: 2,
|
|
223
|
-
text:
|
|
224
|
-
start:
|
|
225
|
-
end:
|
|
344
|
+
text: "Task using global tooltip config",
|
|
345
|
+
start: "2026-01-05",
|
|
346
|
+
end: "2026-01-15",
|
|
226
347
|
duration: 10,
|
|
227
348
|
progress: 30,
|
|
228
349
|
// No tooltipConfig — uses global taskTooltipConfig
|
|
@@ -233,6 +354,7 @@ Each task can override the global `taskTooltipConfig` with its own `tooltipConfi
|
|
|
233
354
|
```
|
|
234
355
|
|
|
235
356
|
API-friendly task aliases accepted in `tasks`:
|
|
357
|
+
|
|
236
358
|
- Name: `text`, `name`, `title`, `taskName`, `task_name`, `workGroupName`
|
|
237
359
|
- Drag/resize handles: `ShowHandle` (boolean), `showHandle` (boolean)
|
|
238
360
|
- OnHold periods: `onHoldPeriods`, `on_hold_periods`, `onHold`, `on_hold`, `onhold`
|
|
@@ -248,11 +370,13 @@ API-friendly task aliases accepted in `tasks`:
|
|
|
248
370
|
## ⏸️ OnHold In `tasks` Props
|
|
249
371
|
|
|
250
372
|
You can pass paused periods directly inside each task using either:
|
|
373
|
+
|
|
251
374
|
- `onHoldPeriods` (camelCase)
|
|
252
375
|
- `on_hold_periods` (snake_case API style)
|
|
253
376
|
- `onHold`, `on_hold`, `onhold` (additional API aliases)
|
|
254
377
|
|
|
255
378
|
Each alias accepts either:
|
|
379
|
+
|
|
256
380
|
- An array of periods: `[{ start, end }, ...]`
|
|
257
381
|
- A single period object: `{ start, end }`
|
|
258
382
|
|
|
@@ -263,14 +387,14 @@ Date values can be `Date`, ISO date string, or timestamp number.
|
|
|
263
387
|
tasks={[
|
|
264
388
|
{
|
|
265
389
|
id: 1,
|
|
266
|
-
text:
|
|
267
|
-
start:
|
|
268
|
-
end:
|
|
390
|
+
text: "Development",
|
|
391
|
+
start: "2026-02-01",
|
|
392
|
+
end: "2026-02-20",
|
|
269
393
|
duration: 19,
|
|
270
394
|
progress: 45,
|
|
271
395
|
on_hold_periods: [
|
|
272
|
-
{ start:
|
|
273
|
-
{ start:
|
|
396
|
+
{ start: "2026-02-06", end: "2026-02-09" },
|
|
397
|
+
{ start: "2026-02-12", end: "2026-02-13" },
|
|
274
398
|
],
|
|
275
399
|
},
|
|
276
400
|
]}
|
|
@@ -286,16 +410,16 @@ Date values can be `Date`, ISO date string, or timestamp number.
|
|
|
286
410
|
tasks={tasks}
|
|
287
411
|
uiConfig={{
|
|
288
412
|
// Header
|
|
289
|
-
headerTitle:
|
|
413
|
+
headerTitle: "My Project Gantt",
|
|
290
414
|
showHeader: true,
|
|
291
|
-
|
|
415
|
+
|
|
292
416
|
// Toolbar Buttons
|
|
293
417
|
showAddTaskButton: true,
|
|
294
418
|
showZoomButtons: true,
|
|
295
419
|
showExportButtons: true,
|
|
296
420
|
showFilterSearch: true,
|
|
297
|
-
addTaskButtonText:
|
|
298
|
-
|
|
421
|
+
addTaskButtonText: "Add New Task",
|
|
422
|
+
|
|
299
423
|
// All labels, placeholders, tooltips are configurable
|
|
300
424
|
// See USAGE.md for complete list
|
|
301
425
|
}}
|
|
@@ -309,17 +433,17 @@ Date values can be `Date`, ISO date string, or timestamp number.
|
|
|
309
433
|
tasks={tasks}
|
|
310
434
|
styleConfig={{
|
|
311
435
|
// Colors - Match your brand
|
|
312
|
-
primary:
|
|
313
|
-
success:
|
|
314
|
-
warning:
|
|
315
|
-
danger:
|
|
316
|
-
background:
|
|
317
|
-
fontColor:
|
|
318
|
-
|
|
436
|
+
primary: "#37a9ef",
|
|
437
|
+
success: "#77d257",
|
|
438
|
+
warning: "#fcba2e",
|
|
439
|
+
danger: "#fe6158",
|
|
440
|
+
background: "#ffffff",
|
|
441
|
+
fontColor: "#333333",
|
|
442
|
+
|
|
319
443
|
// Fonts - Use your project fonts
|
|
320
|
-
fontFamily:
|
|
321
|
-
fontSize:
|
|
322
|
-
|
|
444
|
+
fontFamily: "Inter, sans-serif",
|
|
445
|
+
fontSize: "14px",
|
|
446
|
+
|
|
323
447
|
// See USAGE.md for complete list
|
|
324
448
|
}}
|
|
325
449
|
/>
|
|
@@ -332,11 +456,11 @@ Date values can be `Date`, ISO date string, or timestamp number.
|
|
|
332
456
|
tasks={tasks}
|
|
333
457
|
config={{
|
|
334
458
|
// Responsive container
|
|
335
|
-
containerHeight:
|
|
336
|
-
containerMinHeight:
|
|
337
|
-
|
|
459
|
+
containerHeight: "100%",
|
|
460
|
+
containerMinHeight: "400px",
|
|
461
|
+
|
|
338
462
|
// Responsive grid width
|
|
339
|
-
gridWidth:
|
|
463
|
+
gridWidth: "clamp(280px, 30vw, 720px)", // Adapts to viewport
|
|
340
464
|
}}
|
|
341
465
|
/>
|
|
342
466
|
```
|
|
@@ -350,10 +474,10 @@ Date values can be `Date`, ISO date string, or timestamp number.
|
|
|
350
474
|
--wx-gantt-primary: #your-brand-color;
|
|
351
475
|
--wx-gantt-background: var(--your-bg-color);
|
|
352
476
|
--wx-gantt-font-color: var(--your-text-color);
|
|
353
|
-
|
|
477
|
+
|
|
354
478
|
/* Use your project fonts */
|
|
355
|
-
--wx-gantt-font-family:
|
|
356
|
-
|
|
479
|
+
--wx-gantt-font-family: "Your Font", sans-serif;
|
|
480
|
+
|
|
357
481
|
/* Responsive sizing */
|
|
358
482
|
--gantt-grid-width: clamp(280px, 30vw, 720px);
|
|
359
483
|
}
|
|
@@ -362,6 +486,7 @@ Date values can be `Date`, ISO date string, or timestamp number.
|
|
|
362
486
|
## 📱 Responsive
|
|
363
487
|
|
|
364
488
|
The component is fully responsive and adapts to:
|
|
489
|
+
|
|
365
490
|
- ✅ Desktop (1024px+)
|
|
366
491
|
- ✅ Tablet (768px - 1024px)
|
|
367
492
|
- ✅ Mobile Landscape (480px - 768px)
|
|
@@ -394,12 +519,12 @@ A single callback for **all** drag operations: task bar move/resize AND row reor
|
|
|
394
519
|
// task.rawId preserves the original API ID (before string normalization)
|
|
395
520
|
const taskId = task.rawId ?? task.id;
|
|
396
521
|
|
|
397
|
-
if (dragType ===
|
|
522
|
+
if (dragType === "reorder" && reorderMeta) {
|
|
398
523
|
// Row reorder — task was dragged to a new position via grip icon
|
|
399
524
|
await api.reorderTask(taskId, {
|
|
400
525
|
current_sequence_id: reorderMeta.currentSequenceId,
|
|
401
526
|
target_sequence_id: reorderMeta.targetSequenceId,
|
|
402
|
-
target_stage_id: reorderMeta.targetStageId,
|
|
527
|
+
target_stage_id: reorderMeta.targetStageId, // parent task ID or null for root
|
|
403
528
|
});
|
|
404
529
|
} else {
|
|
405
530
|
// Task bar drag — move or resize on the timeline
|
|
@@ -419,12 +544,12 @@ A single callback for **all** drag operations: task bar move/resize AND row reor
|
|
|
419
544
|
|
|
420
545
|
**`TaskDragUpdatePayload` fields:**
|
|
421
546
|
|
|
422
|
-
| Field
|
|
423
|
-
|
|
424
|
-
| `task`
|
|
425
|
-
| `previousTask` | `Task`
|
|
426
|
-
| `dragType`
|
|
427
|
-
| `reorderMeta`
|
|
547
|
+
| Field | Type | Description |
|
|
548
|
+
| -------------- | -------------------------------------------------------- | ------------------------------------------------------------------------------------------------ |
|
|
549
|
+
| `task` | `Task` | The updated task (after drag/reorder) |
|
|
550
|
+
| `previousTask` | `Task` | The task state before the operation |
|
|
551
|
+
| `dragType` | `'move' \| 'resize-left' \| 'resize-right' \| 'reorder'` | What kind of drag was performed |
|
|
552
|
+
| `reorderMeta` | `TaskReorderMeta \| undefined` | Only present for `'reorder'` — contains `currentSequenceId`, `targetSequenceId`, `targetStageId` |
|
|
428
553
|
|
|
429
554
|
### Other Event Handlers
|
|
430
555
|
|
|
@@ -456,10 +581,11 @@ A single callback for **all** drag operations: task bar move/resize AND row reor
|
|
|
456
581
|
If you get: `Module not found: Error: Package path ./dist/gantt.css is not exported`
|
|
457
582
|
|
|
458
583
|
**Solution:**
|
|
584
|
+
|
|
459
585
|
```tsx
|
|
460
|
-
import
|
|
586
|
+
import "iris-gantt/gantt.css";
|
|
461
587
|
// or
|
|
462
|
-
import
|
|
588
|
+
import "iris-gantt/dist/gantt.css";
|
|
463
589
|
```
|
|
464
590
|
|
|
465
591
|
### Default Import Error
|
|
@@ -467,9 +593,10 @@ import 'iris-gantt/dist/gantt.css'
|
|
|
467
593
|
If you get: `export 'default' was not found`
|
|
468
594
|
|
|
469
595
|
**Solution:**
|
|
596
|
+
|
|
470
597
|
```tsx
|
|
471
598
|
// Use named import instead
|
|
472
|
-
import { Gantt } from
|
|
599
|
+
import { Gantt } from "iris-gantt";
|
|
473
600
|
```
|
|
474
601
|
|
|
475
602
|
### Runtime Error: recentlyCreatedOwnerStacks
|
|
@@ -477,6 +604,7 @@ import { Gantt } from 'iris-gantt'
|
|
|
477
604
|
This is a **cached code issue** in your project, not the package.
|
|
478
605
|
|
|
479
606
|
**Solution:**
|
|
607
|
+
|
|
480
608
|
```bash
|
|
481
609
|
# In your project directory
|
|
482
610
|
rm -rf node_modules package-lock.json .next .cache dist build
|
|
@@ -488,69 +616,69 @@ npm start
|
|
|
488
616
|
## 📖 Complete Example
|
|
489
617
|
|
|
490
618
|
```tsx
|
|
491
|
-
import React, { useState } from
|
|
492
|
-
import { Gantt } from
|
|
493
|
-
import
|
|
494
|
-
import type { Task, Link } from
|
|
619
|
+
import React, { useState } from "react";
|
|
620
|
+
import { Gantt } from "iris-gantt";
|
|
621
|
+
import "iris-gantt/gantt.css";
|
|
622
|
+
import type { Task, Link } from "iris-gantt";
|
|
495
623
|
|
|
496
624
|
function ProjectGantt() {
|
|
497
625
|
const [tasks, setTasks] = useState<Task[]>([
|
|
498
626
|
{
|
|
499
|
-
id:
|
|
500
|
-
text:
|
|
627
|
+
id: "1",
|
|
628
|
+
text: "Project Planning",
|
|
501
629
|
start: new Date(2024, 0, 1),
|
|
502
630
|
end: new Date(2024, 0, 15),
|
|
503
631
|
duration: 14,
|
|
504
632
|
progress: 100,
|
|
505
|
-
type:
|
|
633
|
+
type: "project",
|
|
506
634
|
},
|
|
507
|
-
])
|
|
635
|
+
]);
|
|
508
636
|
|
|
509
637
|
const [links, setLinks] = useState<Link[]>([
|
|
510
|
-
{ id:
|
|
511
|
-
])
|
|
638
|
+
{ id: "l1", source: "1", target: "2", type: "e2s" },
|
|
639
|
+
]);
|
|
512
640
|
|
|
513
641
|
return (
|
|
514
|
-
<div style={{ width:
|
|
642
|
+
<div style={{ width: "100%", height: "100vh" }}>
|
|
515
643
|
<Gantt
|
|
516
644
|
tasks={tasks}
|
|
517
645
|
links={links}
|
|
518
646
|
config={{
|
|
519
|
-
theme:
|
|
647
|
+
theme: "light",
|
|
520
648
|
weekends: true,
|
|
521
|
-
containerHeight:
|
|
522
|
-
containerMinHeight:
|
|
523
|
-
gridWidth:
|
|
649
|
+
containerHeight: "100%",
|
|
650
|
+
containerMinHeight: "500px",
|
|
651
|
+
gridWidth: "clamp(300px, 35vw, 800px)",
|
|
524
652
|
}}
|
|
525
653
|
uiConfig={{
|
|
526
|
-
headerTitle:
|
|
527
|
-
addTaskButtonText:
|
|
654
|
+
headerTitle: "My Project Timeline",
|
|
655
|
+
addTaskButtonText: "New Task",
|
|
528
656
|
}}
|
|
529
657
|
styleConfig={{
|
|
530
|
-
primary:
|
|
531
|
-
fontFamily:
|
|
658
|
+
primary: "#6366f1",
|
|
659
|
+
fontFamily: "Inter, sans-serif",
|
|
532
660
|
}}
|
|
533
661
|
onTaskUpdate={(task) => {
|
|
534
|
-
setTasks(tasks.map(t => t.id === task.id ? task : t))
|
|
662
|
+
setTasks(tasks.map((t) => (t.id === task.id ? task : t)));
|
|
535
663
|
}}
|
|
536
664
|
onTaskCreate={(task) => {
|
|
537
|
-
setTasks([...tasks, task])
|
|
665
|
+
setTasks([...tasks, task]);
|
|
538
666
|
}}
|
|
539
667
|
onTaskDelete={(taskId) => {
|
|
540
|
-
setTasks(tasks.filter(t => t.id !== taskId))
|
|
668
|
+
setTasks(tasks.filter((t) => t.id !== taskId));
|
|
541
669
|
}}
|
|
542
670
|
onLinkCreate={(link) => {
|
|
543
|
-
setLinks([...links, link])
|
|
671
|
+
setLinks([...links, link]);
|
|
544
672
|
}}
|
|
545
673
|
onLinkDelete={(linkId) => {
|
|
546
|
-
setLinks(links.filter(l => l.id !== linkId))
|
|
674
|
+
setLinks(links.filter((l) => l.id !== linkId));
|
|
547
675
|
}}
|
|
548
676
|
/>
|
|
549
677
|
</div>
|
|
550
|
-
)
|
|
678
|
+
);
|
|
551
679
|
}
|
|
552
680
|
|
|
553
|
-
export default ProjectGantt
|
|
681
|
+
export default ProjectGantt;
|
|
554
682
|
```
|
|
555
683
|
|
|
556
684
|
## 📝 TypeScript Support
|
package/dist/Gantt/Gantt.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import type { GanttConfig, Baseline, GanttUIConfig, GanttStyleConfig, GanttIconConfig } from './types';
|
|
2
|
+
import type { GanttConfig, Baseline, GanttUIConfig, GanttStyleConfig, GanttIconConfig, TimelineView } from './types';
|
|
3
3
|
import type { Task, TaskInput, Link, TaskReorderMeta, OnHoldPeriodInput, TaskTooltipConfig, TaskDragUpdatePayload } from './types';
|
|
4
4
|
import './gantt.css';
|
|
5
5
|
export interface GanttProps {
|
|
@@ -21,6 +21,7 @@ export interface GanttProps {
|
|
|
21
21
|
onTaskDelete?: (taskId: string) => void;
|
|
22
22
|
onLinkCreate?: (link: Link) => void;
|
|
23
23
|
onLinkDelete?: (linkId: string) => void;
|
|
24
|
+
onTimelineViewChange?: (view: TimelineView) => void;
|
|
24
25
|
cellWidth?: number;
|
|
25
26
|
cellHeight?: number;
|
|
26
27
|
scaleHeight?: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Gantt.d.ts","sourceRoot":"","sources":["../../src/components/Gantt/Gantt.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAsC,MAAM,OAAO,CAAC;AAQ3D,OAAO,KAAK,EAAE,WAAW,EAA4B,QAAQ,EAAiB,aAAa,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"Gantt.d.ts","sourceRoot":"","sources":["../../src/components/Gantt/Gantt.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAsC,MAAM,OAAO,CAAC;AAQ3D,OAAO,KAAK,EAAE,WAAW,EAA4B,QAAQ,EAAiB,aAAa,EAAE,gBAAgB,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAQ9J,OAAO,KAAK,EAEV,IAAI,EACJ,SAAS,EACT,IAAI,EACJ,eAAe,EACf,iBAAiB,EAEjB,iBAAiB,EACjB,qBAAqB,EAEtB,MAAM,SAAS,CAAC;AACjB,OAAO,aAAa,CAAC;AAErB,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,SAAS,EAAE,CAAC;IACnB,KAAK,CAAC,EAAE,IAAI,EAAE,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC;IAC9B,QAAQ,CAAC,EAAE,OAAO,CAAC,aAAa,CAAC,CAAC;IAClC,WAAW,CAAC,EAAE,OAAO,CAAC,gBAAgB,CAAC,CAAC;IACxC,UAAU,CAAC,EAAE,OAAO,CAAC,eAAe,CAAC,CAAC;IACtC,iBAAiB,CAAC,EAAE,OAAO,CAAC,iBAAiB,CAAC,CAAC;IAC/C,aAAa,CAAC,EAAE,iBAAiB,EAAE,CAAC;IACpC,eAAe,CAAC,EAAE,iBAAiB,EAAE,CAAC;IACtC,MAAM,CAAC,EAAE,iBAAiB,EAAE,GAAG,iBAAiB,CAAC;IACjD,OAAO,CAAC,EAAE,iBAAiB,EAAE,GAAG,iBAAiB,CAAC;IAClD,MAAM,CAAC,EAAE,iBAAiB,EAAE,GAAG,iBAAiB,CAAC;IACjD,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,WAAW,CAAC,EAAE,eAAe,KAAK,IAAI,CAAC;IACnE,gBAAgB,CAAC,EAAE,CAAC,OAAO,EAAE,qBAAqB,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5E,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,IAAI,CAAC;IACpC,YAAY,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,IAAI,CAAC;IACpC,YAAY,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,oBAAoB,CAAC,EAAE,CAAC,IAAI,EAAE,YAAY,KAAK,IAAI,CAAC;IAGpD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,SAAS,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;CACnC;AA6bD,eAAO,MAAM,KAAK,EAAE,KAAK,CAAC,EAAE,CAAC,UAAU,CAo2BtC,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Timeline.d.ts","sourceRoot":"","sources":["../../src/components/Gantt/Timeline.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA4C,MAAM,OAAO,CAAC;AACjE,OAAO,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"Timeline.d.ts","sourceRoot":"","sources":["../../src/components/Gantt/Timeline.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA4C,MAAM,OAAO,CAAC;AACjE,OAAO,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AA4E/G,UAAU,aAAa;IACrB,KAAK,EAAE,IAAI,EAAE,CAAC;IACd,KAAK,EAAE,IAAI,EAAE,CAAC;IACd,KAAK,EAAE;QAAE,KAAK,EAAE,IAAI,CAAC;QAAC,GAAG,EAAE,IAAI,CAAA;KAAE,CAAC;IAClC,MAAM,EAAE,KAAK,EAAE,CAAC;IAChB,MAAM,EAAE,WAAW,CAAC;IACpB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,WAAW,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACtC,eAAe,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5E,aAAa,EAAE,MAAM,IAAI,CAAC;IAC1B,YAAY,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,EAAE,kBAAkB,KAAK,IAAI,CAAC;IACvF,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IAClC,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,iBAAiB,CAAC,EAAE,iBAAiB,CAAC;CACvC;AAED,eAAO,MAAM,QAAQ,sFAi1BpB,CAAC"}
|
package/dist/Gantt/Toolbar.d.ts
CHANGED
|
@@ -1,9 +1,15 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import type { FilterOptions } from './features/filterUtils';
|
|
3
|
-
import type { GanttUIConfig, GanttIconConfig, GanttStyleConfig } from './types';
|
|
3
|
+
import type { GanttUIConfig, GanttIconConfig, GanttStyleConfig, TimelineView } from './types';
|
|
4
4
|
interface ToolbarProps {
|
|
5
5
|
zoomLevel: number;
|
|
6
6
|
setZoomLevel: (zoom: number) => void;
|
|
7
|
+
timelineView?: TimelineView;
|
|
8
|
+
timelineViewOptions?: Array<{
|
|
9
|
+
value: TimelineView;
|
|
10
|
+
label: string;
|
|
11
|
+
}>;
|
|
12
|
+
onTimelineViewChange?: (view: TimelineView) => void;
|
|
7
13
|
onBaselineToggle?: () => void;
|
|
8
14
|
showBaselines?: boolean;
|
|
9
15
|
onExport: (type: 'csv' | 'excel' | 'json' | 'pdf') => void;
|