apexgantt 3.2.0 → 3.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,341 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>ApexGantt - Drag & Resize Events Demo</title>
7
+ <link href="https://fonts.googleapis.com/css2?family=Quicksand:wght@400;600&display=swap" rel="stylesheet" />
8
+ <script src="../apexgantt.min.js"></script>
9
+ <style>
10
+ body {
11
+ font-family: 'Quicksand', sans-serif;
12
+ margin: 0;
13
+ padding: 20px;
14
+ background: #f5f5f5;
15
+ }
16
+
17
+ .demo-container {
18
+ max-width: 1400px;
19
+ margin: 0 auto;
20
+ }
21
+
22
+ .demo-header {
23
+ background: white;
24
+ padding: 20px;
25
+ border-radius: 8px;
26
+ margin-bottom: 20px;
27
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
28
+ }
29
+
30
+ .demo-header h1 {
31
+ margin: 0 0 10px 0;
32
+ color: #333;
33
+ }
34
+
35
+ .demo-header p {
36
+ margin: 0;
37
+ color: #666;
38
+ }
39
+
40
+ #svg-gantt {
41
+ background: white;
42
+ border-radius: 8px;
43
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
44
+ padding: 20px;
45
+ height: 400px;
46
+ }
47
+
48
+ .event-log {
49
+ background: white;
50
+ border-radius: 8px;
51
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
52
+ padding: 20px;
53
+ margin-top: 20px;
54
+ max-height: 300px;
55
+ overflow-y: auto;
56
+ }
57
+
58
+ .event-log h2 {
59
+ margin-top: 0;
60
+ color: #333;
61
+ font-size: 18px;
62
+ }
63
+
64
+ .event-log-header {
65
+ display: flex;
66
+ justify-content: space-between;
67
+ align-items: center;
68
+ margin-bottom: 15px;
69
+ }
70
+
71
+ .clear-log {
72
+ background: #f44336;
73
+ color: white;
74
+ border: none;
75
+ padding: 6px 12px;
76
+ border-radius: 4px;
77
+ cursor: pointer;
78
+ font-size: 12px;
79
+ font-family: 'Quicksand', sans-serif;
80
+ font-weight: 600;
81
+ }
82
+
83
+ .clear-log:hover {
84
+ background: #d32f2f;
85
+ }
86
+
87
+ .event-item {
88
+ border-left: 3px solid #2196f3;
89
+ padding: 10px;
90
+ margin-bottom: 10px;
91
+ background: #f8f9fa;
92
+ border-radius: 0 4px 4px 0;
93
+ font-size: 13px;
94
+ }
95
+
96
+ .event-item.drag {
97
+ border-left-color: #4caf50;
98
+ }
99
+
100
+ .event-item.resize {
101
+ border-left-color: #ff9800;
102
+ }
103
+
104
+ .event-item.update {
105
+ border-left-color: #9c27b0;
106
+ }
107
+
108
+ .event-time {
109
+ color: #999;
110
+ font-size: 11px;
111
+ margin-bottom: 5px;
112
+ }
113
+
114
+ .event-type {
115
+ font-weight: 600;
116
+ color: #333;
117
+ margin-bottom: 5px;
118
+ }
119
+
120
+ .event-details {
121
+ color: #666;
122
+ line-height: 1.4;
123
+ }
124
+
125
+ .event-details strong {
126
+ color: #333;
127
+ }
128
+
129
+ .no-events {
130
+ color: #999;
131
+ text-align: center;
132
+ padding: 40px;
133
+ font-style: italic;
134
+ }
135
+
136
+ .instructions {
137
+ background: #e3f2fd;
138
+ border: 1px solid #90caf9;
139
+ border-radius: 4px;
140
+ padding: 15px;
141
+ margin-bottom: 20px;
142
+ color: #1565c0;
143
+ }
144
+
145
+ .instructions ul {
146
+ margin: 10px 0 0 0;
147
+ padding-left: 20px;
148
+ }
149
+
150
+ .instructions li {
151
+ margin: 5px 0;
152
+ }
153
+ </style>
154
+ </head>
155
+ <body>
156
+ <div class="demo-container">
157
+ <div class="demo-header">
158
+ <h1>ApexGantt - Drag & Resize Events Demo</h1>
159
+ <p>Interactive demo showing task drag and resize events</p>
160
+ </div>
161
+
162
+ <div class="instructions">
163
+ <strong>Instructions:</strong>
164
+ <ul>
165
+ <li>Drag any task bar horizontally to move it to a new date</li>
166
+ <li>Hover over task edges and drag the handles to resize (change duration)</li>
167
+ <li>Double-click a task to edit it via the dialog</li>
168
+ <li>Watch the event log below to see all emitted events</li>
169
+ </ul>
170
+ </div>
171
+
172
+ <div id="svg-gantt"></div>
173
+
174
+ <div class="event-log">
175
+ <div class="event-log-header">
176
+ <h2>Event Log</h2>
177
+ <button class="clear-log" onclick="clearEventLog()">Clear Log</button>
178
+ </div>
179
+ <div id="event-log-content">
180
+ <div class="no-events">No events yet. Try dragging or resizing a task!</div>
181
+ </div>
182
+ </div>
183
+ </div>
184
+
185
+ <script>
186
+ // event log management
187
+ let eventCount = 0;
188
+ const maxEvents = 50;
189
+
190
+ function clearEventLog() {
191
+ document.getElementById('event-log-content').innerHTML =
192
+ '<div class="no-events">No events yet. Try dragging or resizing a task!</div>';
193
+ eventCount = 0;
194
+ }
195
+
196
+ function logEvent(type, detail) {
197
+ const logContent = document.getElementById('event-log-content');
198
+
199
+ // remove "no events" message
200
+ const noEventsMsg = logContent.querySelector('.no-events');
201
+ if (noEventsMsg) {
202
+ noEventsMsg.remove();
203
+ }
204
+
205
+ // format timestamp
206
+ const timestamp = new Date(detail.timestamp).toLocaleTimeString();
207
+
208
+ // create event item
209
+ const eventItem = document.createElement('div');
210
+ eventItem.className = `event-item ${type}`;
211
+
212
+ let eventHTML = `
213
+ <div class="event-time">${timestamp}</div>
214
+ <div class="event-type">${type.toUpperCase()} EVENT</div>
215
+ <div class="event-details">
216
+ `;
217
+
218
+ // format details based on event type
219
+ if (type === 'drag') {
220
+ eventHTML += `
221
+ <strong>Task ID:</strong> ${detail.taskId}<br>
222
+ <strong>Days Moved:</strong> ${detail.daysMoved}<br>
223
+ <strong>Old Dates:</strong> ${detail.oldStartTime} → ${detail.oldEndTime}<br>
224
+ <strong>New Dates:</strong> ${detail.newStartTime} → ${detail.newEndTime}
225
+ `;
226
+
227
+ if (detail.affectedChildTasks && detail.affectedChildTasks.length > 0) {
228
+ eventHTML += `<br><strong>Affected Children:</strong> ${detail.affectedChildTasks.length} task(s)`;
229
+ }
230
+ } else if (type === 'resize') {
231
+ eventHTML += `
232
+ <strong>Task ID:</strong> ${detail.taskId}<br>
233
+ <strong>Handle:</strong> ${detail.resizeHandle}<br>
234
+ <strong>Duration Change:</strong> ${detail.durationChange > 0 ? '+' : ''}${detail.durationChange} days<br>
235
+ <strong>Old Dates:</strong> ${detail.oldStartTime} → ${detail.oldEndTime}<br>
236
+ <strong>New Dates:</strong> ${detail.newStartTime} → ${detail.newEndTime}
237
+ `;
238
+ } else if (type === 'update') {
239
+ eventHTML += `
240
+ <strong>Task ID:</strong> ${detail.taskId}<br>
241
+ <strong>Updated Fields:</strong> ${Object.keys(detail.updates).join(', ')}
242
+ `;
243
+ }
244
+
245
+ eventHTML += '</div>';
246
+ eventItem.innerHTML = eventHTML;
247
+
248
+ // add to log (prepend for newest first)
249
+ logContent.insertBefore(eventItem, logContent.firstChild);
250
+
251
+ // limit number of events shown
252
+ eventCount++;
253
+ if (eventCount > maxEvents) {
254
+ logContent.removeChild(logContent.lastChild);
255
+ }
256
+ }
257
+
258
+ // gantt initialization
259
+ const ganttOptions = {
260
+ enableTaskDrag: true,
261
+ enableTaskResize: true,
262
+ enableTaskEdit: true,
263
+ viewMode: 'week',
264
+ series: [
265
+ {
266
+ id: 'task-1',
267
+ startTime: '11-01-2024',
268
+ endTime: '11-08-2024',
269
+ name: 'Project Planning',
270
+ progress: 75,
271
+ },
272
+ {
273
+ id: 'task-2',
274
+ startTime: '11-04-2024',
275
+ endTime: '11-12-2024',
276
+ name: 'Development Phase',
277
+ progress: 50,
278
+ },
279
+ {
280
+ id: 'task-2.1',
281
+ startTime: '11-04-2024',
282
+ endTime: '11-07-2024',
283
+ name: 'Backend Development',
284
+ parentId: 'task-2',
285
+ progress: 60,
286
+ },
287
+ {
288
+ id: 'task-2.2',
289
+ startTime: '11-08-2024',
290
+ endTime: '11-12-2024',
291
+ name: 'Frontend Development',
292
+ parentId: 'task-2',
293
+ dependency: 'task-2.1',
294
+ progress: 40,
295
+ },
296
+ {
297
+ id: 'task-3',
298
+ startTime: '11-13-2024',
299
+ endTime: '11-15-2024',
300
+ name: 'Testing & QA',
301
+ dependency: 'task-2',
302
+ progress: 25,
303
+ },
304
+ {
305
+ id: 'task-4',
306
+ startTime: '11-16-2024',
307
+ endTime: '11-20-2024',
308
+ name: 'Deployment',
309
+ progress: 0,
310
+ },
311
+ {
312
+ id: 'milestone-1',
313
+ startTime: '11-21-2024',
314
+ name: 'Project Launch',
315
+ type: 'milestone',
316
+ dependency: 'task-4',
317
+ },
318
+ ],
319
+ };
320
+
321
+ const container = document.getElementById('svg-gantt');
322
+ const gantt = new ApexGantt(container, ganttOptions);
323
+ gantt.render();
324
+
325
+ container.addEventListener('taskDragged', (e) => {
326
+ console.log('Task Dragged:', e.detail);
327
+ logEvent('drag', e.detail);
328
+ });
329
+
330
+ container.addEventListener('taskResized', (e) => {
331
+ console.log('Task Resized:', e.detail);
332
+ logEvent('resize', e.detail);
333
+ });
334
+
335
+ container.addEventListener('taskUpdateSuccess', (e) => {
336
+ console.log('Task Updated:', e.detail);
337
+ logEvent('update', e.detail);
338
+ });
339
+ </script>
340
+ </body>
341
+ </html>
package/index.d.ts CHANGED
@@ -9,6 +9,6 @@ export { ViewMode } from './lib/util/gantt.util';
9
9
  export type { ThemeMode, GanttTheme } from './lib/models/Theme';
10
10
  export { LightTheme, DarkTheme, getTheme } from './lib/models/Theme';
11
11
  export { GanttEvents } from './lib/types/events';
12
- export type { TaskUpdateEventDetail, TaskValidationErrorEventDetail, TaskUpdateSuccessEventDetail, TaskUpdateErrorEventDetail, } from './lib/types/events';
12
+ export type { TaskUpdateEventDetail, TaskValidationErrorEventDetail, TaskUpdateSuccessEventDetail, TaskUpdateErrorEventDetail, TaskDraggedEventDetail, TaskResizedEventDetail, } from './lib/types/events';
13
13
  export type { ParsingConfig, ParsingValue } from './lib/models/DataParser';
14
14
  export { DataParser } from './lib/models/DataParser';
package/lib/gantt.d.ts CHANGED
@@ -16,6 +16,7 @@ export declare class ApexGantt extends BaseChart {
16
16
  private stateManager;
17
17
  private containerResizeObserver;
18
18
  private lastKnownWidth;
19
+ private lastKnownHeight;
19
20
  private resizeDebounceTimer;
20
21
  constructor(element: HTMLElement, options?: GanttUserOptions);
21
22
  static setLicense(key: string): void;
@@ -82,7 +83,7 @@ export declare class ApexGantt extends BaseChart {
82
83
  */
83
84
  private normalizeDimension;
84
85
  /**
85
- * resize observer for container to handle responsive width changes
86
+ * resize observer for container to handle responsive width and height changes
86
87
  */
87
88
  private setupContainerResizeObserver;
88
89
  private handleContainerResize;
@@ -17,6 +17,7 @@ export declare class BarDragManager {
17
17
  private createMouseDownHandler;
18
18
  private createMouseMoveHandler;
19
19
  private createMouseUpHandler;
20
+ private emitTaskDraggedEvent;
20
21
  private isOutOfBounds;
21
22
  private moveBar;
22
23
  private moveChildBars;
@@ -15,6 +15,7 @@ export declare class BarResizeManager {
15
15
  constructor(taskId: string, options: GanttOptions, viewMode: ViewMode, chartContext: ChartContext, dataManager: DataManager);
16
16
  private createMouseMoveHandler;
17
17
  private createMouseUpHandler;
18
+ private emitTaskResizedEvent;
18
19
  private createResizeMouseDownHandler;
19
20
  makeResizable(barElement: HTMLDivElement, onUpdate?: onUpdateBarCallback): () => void;
20
21
  }
@@ -35,6 +35,30 @@ export interface TaskUpdateErrorEventDetail {
35
35
  error: Error;
36
36
  timestamp: number;
37
37
  }
38
+ export interface TaskDraggedEventDetail {
39
+ taskId: string;
40
+ oldStartTime: string;
41
+ oldEndTime: string;
42
+ newStartTime: string;
43
+ newEndTime: string;
44
+ daysMoved: number;
45
+ affectedChildTasks: Array<{
46
+ taskId: string;
47
+ newStartTime: string;
48
+ newEndTime: string;
49
+ }>;
50
+ timestamp: number;
51
+ }
52
+ export interface TaskResizedEventDetail {
53
+ taskId: string;
54
+ resizeHandle: 'left' | 'right';
55
+ oldStartTime: string;
56
+ oldEndTime: string;
57
+ newStartTime: string;
58
+ newEndTime: string;
59
+ durationChange: number;
60
+ timestamp: number;
61
+ }
38
62
  /**
39
63
  * chart event names
40
64
  * use these constants to attach event listeners like below
@@ -60,4 +84,12 @@ export declare const GanttEvents: {
60
84
  * emits when a task update fails
61
85
  */
62
86
  readonly TASK_UPDATE_ERROR: "taskUpdateError";
87
+ /**
88
+ * emits when a task bar is dragged to a new position
89
+ */
90
+ readonly TASK_DRAGGED: "taskDragged";
91
+ /**
92
+ * emits when a task bar is resized via handles
93
+ */
94
+ readonly TASK_RESIZED: "taskResized";
63
95
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "apexgantt",
3
- "version": "3.2.0",
3
+ "version": "3.4.0",
4
4
  "dependencies": {
5
5
  "dayjs": "^1.11.13",
6
6
  "lodash": "^4.17.21"