@matsu1321/react-gantt-chart 1.0.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,1996 @@
1
+ import { jsxs, jsx } from "react/jsx-runtime";
2
+ import React, { useMemo, useRef, useState, useEffect, useCallback } from "react";
3
+ import { createPortal } from "react-dom";
4
+ var ViewMode = /* @__PURE__ */ ((ViewMode2) => {
5
+ ViewMode2["Hour"] = "Hour";
6
+ ViewMode2["QuarterDay"] = "Quarter Day";
7
+ ViewMode2["HalfDay"] = "Half Day";
8
+ ViewMode2["Day"] = "Day";
9
+ ViewMode2["Week"] = "Week";
10
+ ViewMode2["Month"] = "Month";
11
+ ViewMode2["Year"] = "Year";
12
+ return ViewMode2;
13
+ })(ViewMode || {});
14
+ const cache = {};
15
+ const getCachedDateTimeFormat = (locString, opts) => {
16
+ const key = JSON.stringify([locString, opts]);
17
+ let format = cache[key];
18
+ if (!format) {
19
+ format = new Intl.DateTimeFormat(locString, opts);
20
+ cache[key] = format;
21
+ }
22
+ return format;
23
+ };
24
+ const addToDate = (date, quantity, scale) => {
25
+ const newDate = new Date(date.getTime());
26
+ switch (scale) {
27
+ case "millisecond":
28
+ newDate.setMilliseconds(newDate.getMilliseconds() + quantity);
29
+ break;
30
+ case "second":
31
+ newDate.setSeconds(newDate.getSeconds() + quantity);
32
+ break;
33
+ case "minute":
34
+ newDate.setMinutes(newDate.getMinutes() + quantity);
35
+ break;
36
+ case "hour":
37
+ newDate.setHours(newDate.getHours() + quantity);
38
+ break;
39
+ case "day":
40
+ newDate.setDate(newDate.getDate() + quantity);
41
+ break;
42
+ case "week":
43
+ newDate.setDate(newDate.getDate() + quantity * 7);
44
+ break;
45
+ case "month":
46
+ newDate.setMonth(newDate.getMonth() + quantity);
47
+ break;
48
+ case "year":
49
+ newDate.setFullYear(newDate.getFullYear() + quantity);
50
+ break;
51
+ }
52
+ return newDate;
53
+ };
54
+ const startOfDate = (date, scale) => {
55
+ const newDate = new Date(date.getTime());
56
+ switch (scale) {
57
+ case "year":
58
+ newDate.setMonth(0, 1);
59
+ newDate.setHours(0, 0, 0, 0);
60
+ break;
61
+ case "month":
62
+ newDate.setDate(1);
63
+ newDate.setHours(0, 0, 0, 0);
64
+ break;
65
+ case "week":
66
+ const day = newDate.getDay();
67
+ const diff = newDate.getDate() - day + (day === 0 ? -6 : 1);
68
+ newDate.setDate(diff);
69
+ newDate.setHours(0, 0, 0, 0);
70
+ break;
71
+ case "day":
72
+ newDate.setHours(0, 0, 0, 0);
73
+ break;
74
+ case "hour":
75
+ newDate.setMinutes(0, 0, 0);
76
+ break;
77
+ case "minute":
78
+ newDate.setSeconds(0, 0);
79
+ break;
80
+ case "second":
81
+ newDate.setMilliseconds(0);
82
+ break;
83
+ }
84
+ return newDate;
85
+ };
86
+ const getWeekNumberISO8601 = (date) => {
87
+ const tempDate = new Date(date.valueOf());
88
+ const dayNum = (date.getDay() + 6) % 7;
89
+ tempDate.setDate(tempDate.getDate() - dayNum + 3);
90
+ const firstThursday = tempDate.valueOf();
91
+ tempDate.setMonth(0, 4);
92
+ const dayNumJan4 = (tempDate.getDay() + 6) % 7;
93
+ tempDate.setDate(tempDate.getDate() - dayNumJan4 + 3);
94
+ const weekNum = 1 + Math.round((firstThursday - tempDate.valueOf()) / 6048e5);
95
+ return weekNum < 10 ? `0${weekNum}` : `${weekNum}`;
96
+ };
97
+ const seedDates = (startDate, endDate, viewMode) => {
98
+ let currentDate = new Date(startDate.getTime());
99
+ const dates = [];
100
+ while (currentDate.getTime() < endDate.getTime()) {
101
+ dates.push(currentDate);
102
+ switch (viewMode) {
103
+ case ViewMode.Hour:
104
+ currentDate = addToDate(currentDate, 1, "hour");
105
+ break;
106
+ case ViewMode.QuarterDay:
107
+ currentDate = addToDate(currentDate, 6, "hour");
108
+ break;
109
+ case ViewMode.HalfDay:
110
+ currentDate = addToDate(currentDate, 12, "hour");
111
+ break;
112
+ case ViewMode.Day:
113
+ currentDate = addToDate(currentDate, 1, "day");
114
+ break;
115
+ case ViewMode.Week:
116
+ currentDate = addToDate(currentDate, 7, "day");
117
+ break;
118
+ case ViewMode.Month:
119
+ currentDate = addToDate(currentDate, 1, "month");
120
+ break;
121
+ case ViewMode.Year:
122
+ currentDate = addToDate(currentDate, 1, "year");
123
+ break;
124
+ }
125
+ }
126
+ return dates;
127
+ };
128
+ const ganttDateRange = (tasks, viewMode, preStepsCount) => {
129
+ let minDate = /* @__PURE__ */ new Date();
130
+ let maxDate = /* @__PURE__ */ new Date();
131
+ if (tasks.length > 0) {
132
+ let min = tasks[0].start.getTime();
133
+ let max = tasks[0].end.getTime();
134
+ for (let i = 1; i < tasks.length; i++) {
135
+ if (tasks[i].start.getTime() < min) min = tasks[i].start.getTime();
136
+ if (tasks[i].end.getTime() > max) max = tasks[i].end.getTime();
137
+ }
138
+ minDate = new Date(min);
139
+ maxDate = new Date(max);
140
+ }
141
+ let start = new Date(minDate.getTime());
142
+ let end = new Date(maxDate.getTime());
143
+ switch (viewMode) {
144
+ case ViewMode.Hour:
145
+ start = startOfDate(start, "day");
146
+ start = addToDate(start, -preStepsCount, "hour");
147
+ end = addToDate(end, 2, "day");
148
+ break;
149
+ case ViewMode.QuarterDay:
150
+ start = startOfDate(start, "day");
151
+ start = addToDate(start, -preStepsCount * 6, "hour");
152
+ end = addToDate(end, 3, "day");
153
+ break;
154
+ case ViewMode.HalfDay:
155
+ start = startOfDate(start, "day");
156
+ start = addToDate(start, -preStepsCount * 12, "hour");
157
+ end = addToDate(end, 5, "day");
158
+ break;
159
+ case ViewMode.Day:
160
+ start = startOfDate(start, "day");
161
+ start = addToDate(start, -preStepsCount, "day");
162
+ end = startOfDate(end, "day");
163
+ end = addToDate(end, 1, "month");
164
+ break;
165
+ case ViewMode.Week:
166
+ start = startOfDate(start, "week");
167
+ start = addToDate(start, -preStepsCount * 7, "day");
168
+ end = addToDate(end, 1.5, "month");
169
+ break;
170
+ case ViewMode.Month:
171
+ start = startOfDate(start, "month");
172
+ start = addToDate(start, -preStepsCount, "month");
173
+ end = startOfDate(end, "month");
174
+ end = addToDate(end, 1, "year");
175
+ break;
176
+ case ViewMode.Year:
177
+ start = startOfDate(start, "year");
178
+ start = addToDate(start, -preStepsCount, "year");
179
+ end = startOfDate(end, "year");
180
+ end = addToDate(end, 1, "year");
181
+ break;
182
+ }
183
+ return seedDates(start, end, viewMode);
184
+ };
185
+ const taskXCoordinate = (date, dates, columnWidth) => {
186
+ const dateVal = date.getTime();
187
+ const startVal = dates[0].getTime();
188
+ if (dateVal <= startVal) return 0;
189
+ const endVal = dates[dates.length - 1].getTime();
190
+ if (dateVal >= endVal) return (dates.length - 1) * columnWidth;
191
+ for (let i = 0; i < dates.length - 1; i++) {
192
+ const d1 = dates[i].getTime();
193
+ const d2 = dates[i + 1].getTime();
194
+ if (dateVal >= d1 && dateVal < d2) {
195
+ const ratio = (dateVal - d1) / (d2 - d1);
196
+ return i * columnWidth + ratio * columnWidth;
197
+ }
198
+ }
199
+ return 0;
200
+ };
201
+ const convertToRenderedTasks = (tasks, dates, columnWidth, rowHeight, taskHeight, barCornerRadius, handleWidth, rtl, barProgressColor, barProgressSelectedColor, barBackgroundColor, barBackgroundSelectedColor, projectProgressColor, projectProgressSelectedColor, projectBackgroundColor, projectBackgroundSelectedColor, milestoneBackgroundColor, milestoneBackgroundSelectedColor) => {
202
+ const renderedTasks = [];
203
+ for (let i = 0; i < tasks.length; i++) {
204
+ const t = tasks[i];
205
+ const y = i * rowHeight + (rowHeight - taskHeight) / 2;
206
+ let x1 = 0;
207
+ let x2 = 0;
208
+ if (t.type === "milestone") {
209
+ const x = taskXCoordinate(t.start, dates, columnWidth);
210
+ x1 = x - taskHeight / 2;
211
+ x2 = x + taskHeight / 2;
212
+ } else {
213
+ x1 = taskXCoordinate(t.start, dates, columnWidth);
214
+ x2 = taskXCoordinate(t.end, dates, columnWidth);
215
+ }
216
+ if (x2 < x1) x2 = x1;
217
+ const width = x2 - x1;
218
+ let typeInternal = t.type;
219
+ if (t.type === "task" && width < 80) {
220
+ typeInternal = "smalltask";
221
+ }
222
+ const [progressWidth, progressX] = calcProgressGeometry(x1, x2, t.progress, rtl);
223
+ const styleDefaults = {
224
+ backgroundColor: barBackgroundColor,
225
+ backgroundSelectedColor: barBackgroundSelectedColor,
226
+ progressColor: barProgressColor,
227
+ progressSelectedColor: barProgressSelectedColor
228
+ };
229
+ if (t.type === "project") {
230
+ styleDefaults.backgroundColor = projectBackgroundColor;
231
+ styleDefaults.backgroundSelectedColor = projectBackgroundSelectedColor;
232
+ styleDefaults.progressColor = projectProgressColor;
233
+ styleDefaults.progressSelectedColor = projectProgressSelectedColor;
234
+ } else if (t.type === "milestone") {
235
+ styleDefaults.backgroundColor = milestoneBackgroundColor;
236
+ styleDefaults.backgroundSelectedColor = milestoneBackgroundSelectedColor;
237
+ styleDefaults.progressColor = "";
238
+ styleDefaults.progressSelectedColor = "";
239
+ }
240
+ const mergedStyles = { ...styleDefaults, ...t.styles };
241
+ const renderedTask = {
242
+ ...t,
243
+ index: i,
244
+ typeInternal,
245
+ x1,
246
+ x2,
247
+ y,
248
+ height: taskHeight,
249
+ progressX,
250
+ progressWidth,
251
+ barCornerRadius,
252
+ handleWidth,
253
+ barChildren: [],
254
+ styles: mergedStyles
255
+ };
256
+ renderedTasks.push(renderedTask);
257
+ }
258
+ for (let i = 0; i < renderedTasks.length; i++) {
259
+ const parent = renderedTasks[i];
260
+ if (parent.type === "project") {
261
+ parent.barChildren = renderedTasks.filter((child) => child.project === parent.id);
262
+ }
263
+ }
264
+ return renderedTasks;
265
+ };
266
+ const calcProgressGeometry = (taskX1, taskX2, progress, rtl) => {
267
+ const width = taskX2 - taskX1;
268
+ const progressWidth = width * (progress / 100);
269
+ const progressX = rtl ? taskX2 - progressWidth : taskX1;
270
+ return [progressWidth, progressX];
271
+ };
272
+ const progressByProgressWidth = (progressWidth, task) => {
273
+ const width = task.x2 - task.x1;
274
+ if (width === 0) return 0;
275
+ const progress = progressWidth / width * 100;
276
+ return Math.min(100, Math.max(0, Math.round(progress)));
277
+ };
278
+ const getProgressHandlePoint = (progressX, taskY, taskHeight) => {
279
+ const y = taskY + taskHeight - 2;
280
+ return `${progressX},${y} ${progressX - 6},${y + 6} ${progressX + 6},${y + 6}`;
281
+ };
282
+ const applyDragToTask = (svgX, action, selectedTask, xStep, timeStep, initEventX1Delta, rtl) => {
283
+ const changedTask = { ...selectedTask };
284
+ let isChanged = false;
285
+ switch (action) {
286
+ case "progress": {
287
+ const progressWidth = svgX - selectedTask.x1;
288
+ const progress = progressByProgressWidth(progressWidth, selectedTask);
289
+ if (progress !== selectedTask.progress) {
290
+ changedTask.progress = progress;
291
+ const [progWidth, progX] = calcProgressGeometry(
292
+ selectedTask.x1,
293
+ selectedTask.x2,
294
+ progress,
295
+ rtl
296
+ );
297
+ changedTask.progressWidth = progWidth;
298
+ changedTask.progressX = progX;
299
+ isChanged = true;
300
+ }
301
+ break;
302
+ }
303
+ case "move": {
304
+ const x1 = svgX - initEventX1Delta;
305
+ const diffX = x1 - selectedTask.x1;
306
+ const steps = Math.round(diffX / xStep);
307
+ if (steps !== 0) {
308
+ const snapX = steps * xStep;
309
+ changedTask.x1 = selectedTask.x1 + snapX;
310
+ changedTask.x2 = selectedTask.x2 + snapX;
311
+ const timeShift = steps * timeStep;
312
+ changedTask.start = new Date(selectedTask.start.getTime() + timeShift);
313
+ changedTask.end = new Date(selectedTask.end.getTime() + timeShift);
314
+ const [progWidth, progX] = calcProgressGeometry(
315
+ changedTask.x1,
316
+ changedTask.x2,
317
+ changedTask.progress,
318
+ rtl
319
+ );
320
+ changedTask.progressWidth = progWidth;
321
+ changedTask.progressX = progX;
322
+ isChanged = true;
323
+ }
324
+ break;
325
+ }
326
+ case "start": {
327
+ const diffX = svgX - selectedTask.x1;
328
+ const steps = Math.round(diffX / xStep);
329
+ if (steps !== 0) {
330
+ const newX1 = selectedTask.x1 + steps * xStep;
331
+ if (newX1 <= selectedTask.x2 - 2 * selectedTask.handleWidth) {
332
+ changedTask.x1 = newX1;
333
+ changedTask.start = new Date(selectedTask.start.getTime() + steps * timeStep);
334
+ const [progWidth, progX] = calcProgressGeometry(
335
+ changedTask.x1,
336
+ changedTask.x2,
337
+ changedTask.progress,
338
+ rtl
339
+ );
340
+ changedTask.progressWidth = progWidth;
341
+ changedTask.progressX = progX;
342
+ const width = changedTask.x2 - changedTask.x1;
343
+ changedTask.typeInternal = changedTask.type === "task" && width < 80 ? "smalltask" : changedTask.type;
344
+ isChanged = true;
345
+ }
346
+ }
347
+ break;
348
+ }
349
+ case "end": {
350
+ const diffX = svgX - selectedTask.x2;
351
+ const steps = Math.round(diffX / xStep);
352
+ if (steps !== 0) {
353
+ const newX2 = selectedTask.x2 + steps * xStep;
354
+ if (newX2 >= selectedTask.x1 + 2 * selectedTask.handleWidth) {
355
+ changedTask.x2 = newX2;
356
+ changedTask.end = new Date(selectedTask.end.getTime() + steps * timeStep);
357
+ const [progWidth, progX] = calcProgressGeometry(
358
+ changedTask.x1,
359
+ changedTask.x2,
360
+ changedTask.progress,
361
+ rtl
362
+ );
363
+ changedTask.progressWidth = progWidth;
364
+ changedTask.progressX = progX;
365
+ const width = changedTask.x2 - changedTask.x1;
366
+ changedTask.typeInternal = changedTask.type === "task" && width < 80 ? "smalltask" : changedTask.type;
367
+ isChanged = true;
368
+ }
369
+ }
370
+ break;
371
+ }
372
+ }
373
+ return { isChanged, changedTask };
374
+ };
375
+ function removeHiddenTasks(tasks) {
376
+ const collapsedProjects = /* @__PURE__ */ new Set();
377
+ tasks.forEach((t) => {
378
+ if (t.type === "project" && t.hideChildren) {
379
+ collapsedProjects.add(t.id);
380
+ }
381
+ });
382
+ const isHidden = (task) => {
383
+ let parentId = task.project;
384
+ while (parentId) {
385
+ if (collapsedProjects.has(parentId)) {
386
+ return true;
387
+ }
388
+ const parent = tasks.find((t) => t.id === parentId);
389
+ parentId = parent == null ? void 0 : parent.project;
390
+ }
391
+ return false;
392
+ };
393
+ return tasks.filter((t) => !isHidden(t));
394
+ }
395
+ const sortTasks = (taskA, taskB) => {
396
+ const orderA = taskA.displayOrder ?? Number.MAX_SAFE_INTEGER;
397
+ const orderB = taskB.displayOrder ?? Number.MAX_SAFE_INTEGER;
398
+ if (orderA > orderB) return 1;
399
+ if (orderA < orderB) return -1;
400
+ return 0;
401
+ };
402
+ const TaskListHeaderDefault = ({ headerHeight, rowWidth, fontFamily, fontSize }) => {
403
+ return /* @__PURE__ */ jsxs(
404
+ "div",
405
+ {
406
+ className: "taskListHeader",
407
+ style: {
408
+ fontFamily,
409
+ fontSize,
410
+ height: headerHeight,
411
+ width: rowWidth,
412
+ display: "flex",
413
+ alignItems: "center",
414
+ boxSizing: "border-box"
415
+ },
416
+ children: [
417
+ /* @__PURE__ */ jsx(
418
+ "div",
419
+ {
420
+ className: "taskListHeaderCell",
421
+ style: {
422
+ flex: 1,
423
+ minWidth: 150,
424
+ paddingLeft: 10,
425
+ fontWeight: "bold",
426
+ boxSizing: "border-box"
427
+ },
428
+ children: "Name"
429
+ }
430
+ ),
431
+ /* @__PURE__ */ jsx(
432
+ "div",
433
+ {
434
+ className: "taskListHeaderCell",
435
+ style: {
436
+ width: 100,
437
+ minWidth: 100,
438
+ paddingLeft: 10,
439
+ fontWeight: "bold",
440
+ borderLeft: "1px solid #e0e0e0",
441
+ boxSizing: "border-box"
442
+ },
443
+ children: "From"
444
+ }
445
+ ),
446
+ /* @__PURE__ */ jsx(
447
+ "div",
448
+ {
449
+ className: "taskListHeaderCell",
450
+ style: {
451
+ width: 100,
452
+ minWidth: 100,
453
+ paddingLeft: 10,
454
+ fontWeight: "bold",
455
+ borderLeft: "1px solid #e0e0e0",
456
+ boxSizing: "border-box"
457
+ },
458
+ children: "To"
459
+ }
460
+ )
461
+ ]
462
+ }
463
+ );
464
+ };
465
+ const TaskListTableDefault = ({
466
+ rowHeight,
467
+ rowWidth,
468
+ fontFamily,
469
+ fontSize,
470
+ locale,
471
+ tasks,
472
+ visibleTasks,
473
+ selectedTaskId,
474
+ setSelectedTask,
475
+ onExpanderClick
476
+ }) => {
477
+ const itemsToRender = visibleTasks || tasks;
478
+ const formatDate = useMemo(() => {
479
+ const formatter = getCachedDateTimeFormat(locale, {
480
+ day: "numeric",
481
+ month: "numeric",
482
+ year: "numeric"
483
+ });
484
+ return (date) => formatter.format(date);
485
+ }, [locale]);
486
+ return /* @__PURE__ */ jsx(
487
+ "div",
488
+ {
489
+ className: "taskListTable",
490
+ style: {
491
+ fontFamily,
492
+ fontSize,
493
+ width: rowWidth,
494
+ height: tasks.length * rowHeight,
495
+ position: "relative"
496
+ },
497
+ children: itemsToRender.map((t) => {
498
+ const renderedTask = t;
499
+ const isSelected = selectedTaskId === t.id;
500
+ let level = 0;
501
+ let parentId = t.project;
502
+ while (parentId) {
503
+ level++;
504
+ const parent = tasks.find((p) => p.id === parentId);
505
+ parentId = parent == null ? void 0 : parent.project;
506
+ }
507
+ return /* @__PURE__ */ jsxs(
508
+ "div",
509
+ {
510
+ className: `taskListTableRow ${isSelected ? "taskListTableRowSelected" : ""}`,
511
+ style: {
512
+ height: rowHeight,
513
+ width: "100%",
514
+ position: "absolute",
515
+ top: renderedTask.index * rowHeight,
516
+ display: "flex",
517
+ alignItems: "center",
518
+ cursor: "pointer",
519
+ boxSizing: "border-box",
520
+ backgroundColor: isSelected ? "#f5f5f5" : void 0,
521
+ borderBottom: "1px solid #ebebeb"
522
+ },
523
+ onClick: () => setSelectedTask(t.id),
524
+ children: [
525
+ /* @__PURE__ */ jsxs(
526
+ "div",
527
+ {
528
+ className: "taskListTableCell",
529
+ style: {
530
+ flex: 1,
531
+ minWidth: 150,
532
+ paddingLeft: 10 + level * 16,
533
+ display: "flex",
534
+ alignItems: "center",
535
+ overflow: "hidden",
536
+ textOverflow: "ellipsis",
537
+ whiteSpace: "nowrap",
538
+ boxSizing: "border-box"
539
+ },
540
+ children: [
541
+ t.type === "project" ? /* @__PURE__ */ jsx(
542
+ "div",
543
+ {
544
+ className: "taskListExpander",
545
+ onClick: (e) => {
546
+ e.stopPropagation();
547
+ onExpanderClick(t);
548
+ },
549
+ style: {
550
+ cursor: "pointer",
551
+ display: "inline-flex",
552
+ alignItems: "center",
553
+ justifyContent: "center",
554
+ width: 16,
555
+ height: 16,
556
+ marginRight: 6,
557
+ userSelect: "none",
558
+ fontSize: "10px",
559
+ color: "#555"
560
+ },
561
+ children: t.hideChildren ? "▶" : "▼"
562
+ }
563
+ ) : /* @__PURE__ */ jsx("div", { style: { width: 22, height: 16, display: "inline-block" } }),
564
+ /* @__PURE__ */ jsx("span", { style: { fontWeight: t.type === "project" ? "bold" : "normal" }, children: t.name })
565
+ ]
566
+ }
567
+ ),
568
+ /* @__PURE__ */ jsx(
569
+ "div",
570
+ {
571
+ className: "taskListTableCell",
572
+ style: {
573
+ width: 100,
574
+ minWidth: 100,
575
+ paddingLeft: 10,
576
+ overflow: "hidden",
577
+ textOverflow: "ellipsis",
578
+ whiteSpace: "nowrap",
579
+ borderLeft: "1px solid #ebebeb",
580
+ boxSizing: "border-box"
581
+ },
582
+ children: formatDate(t.start)
583
+ }
584
+ ),
585
+ /* @__PURE__ */ jsx(
586
+ "div",
587
+ {
588
+ className: "taskListTableCell",
589
+ style: {
590
+ width: 100,
591
+ minWidth: 100,
592
+ paddingLeft: 10,
593
+ overflow: "hidden",
594
+ textOverflow: "ellipsis",
595
+ whiteSpace: "nowrap",
596
+ borderLeft: "1px solid #ebebeb",
597
+ boxSizing: "border-box"
598
+ },
599
+ children: formatDate(t.end)
600
+ }
601
+ )
602
+ ]
603
+ },
604
+ t.id
605
+ );
606
+ })
607
+ }
608
+ );
609
+ };
610
+ const TaskList = ({
611
+ headerHeight,
612
+ rowWidth,
613
+ taskListWidth,
614
+ fontFamily,
615
+ fontSize,
616
+ rowHeight,
617
+ locale,
618
+ tasks,
619
+ visibleTasks,
620
+ selectedTask,
621
+ selectedTaskId,
622
+ setSelectedTask,
623
+ onExpanderClick,
624
+ TaskListHeader = TaskListHeaderDefault,
625
+ TaskListTable = TaskListTableDefault
626
+ }) => {
627
+ const resolvedRowWidth = rowWidth || `${taskListWidth || 250}px`;
628
+ const resolvedSelectedTaskId = selectedTaskId || (selectedTask == null ? void 0 : selectedTask.id) || "";
629
+ return /* @__PURE__ */ jsxs(
630
+ "div",
631
+ {
632
+ className: "taskListWrapper",
633
+ style: {
634
+ fontFamily,
635
+ fontSize,
636
+ flex: "none",
637
+ width: resolvedRowWidth,
638
+ position: "sticky",
639
+ left: 0,
640
+ zIndex: 20,
641
+ backgroundColor: "#fff"
642
+ },
643
+ children: [
644
+ /* @__PURE__ */ jsx("div", { style: { position: "sticky", top: 0, zIndex: 30, backgroundColor: "#fff" }, children: /* @__PURE__ */ jsx(
645
+ TaskListHeader,
646
+ {
647
+ headerHeight,
648
+ rowWidth: resolvedRowWidth,
649
+ fontFamily,
650
+ fontSize
651
+ }
652
+ ) }),
653
+ /* @__PURE__ */ jsx(
654
+ "div",
655
+ {
656
+ className: "taskListContainer",
657
+ children: /* @__PURE__ */ jsx(
658
+ TaskListTable,
659
+ {
660
+ rowHeight,
661
+ rowWidth: resolvedRowWidth,
662
+ fontFamily,
663
+ fontSize,
664
+ locale,
665
+ tasks,
666
+ visibleTasks,
667
+ selectedTaskId: resolvedSelectedTaskId,
668
+ setSelectedTask,
669
+ onExpanderClick
670
+ }
671
+ )
672
+ }
673
+ )
674
+ ]
675
+ }
676
+ );
677
+ };
678
+ const GridBody = ({
679
+ tasks,
680
+ dates,
681
+ svgWidth,
682
+ rowHeight,
683
+ columnWidth,
684
+ todayColor,
685
+ startIndex = 0,
686
+ endIndex = tasks.length - 1,
687
+ svgHeight
688
+ }) => {
689
+ const y1 = startIndex * rowHeight;
690
+ const y2 = (endIndex + 1) * rowHeight;
691
+ const totalHeight = y2 - y1;
692
+ const rowBackgrounds = useMemo(() => {
693
+ const bgs = [];
694
+ for (let i = startIndex; i <= endIndex; i++) {
695
+ const y = i * rowHeight;
696
+ bgs.push(
697
+ /* @__PURE__ */ jsx(
698
+ "rect",
699
+ {
700
+ x: 0,
701
+ y,
702
+ width: svgWidth,
703
+ height: rowHeight,
704
+ fill: i % 2 === 0 ? "transparent" : "#fbfbfb",
705
+ className: "gridRow"
706
+ },
707
+ `bg-${i}`
708
+ )
709
+ );
710
+ }
711
+ return bgs;
712
+ }, [startIndex, endIndex, svgWidth, rowHeight]);
713
+ const rowLines = useMemo(() => {
714
+ const lines = [];
715
+ for (let i = startIndex; i <= endIndex; i++) {
716
+ const y = i * rowHeight + rowHeight;
717
+ lines.push(
718
+ /* @__PURE__ */ jsx(
719
+ "line",
720
+ {
721
+ x1: 0,
722
+ y1: y,
723
+ x2: svgWidth,
724
+ y2: y,
725
+ className: "gridRowLine",
726
+ style: { stroke: "#ebebeb", strokeWidth: 1 }
727
+ },
728
+ `row-line-${i}`
729
+ )
730
+ );
731
+ }
732
+ return lines;
733
+ }, [startIndex, endIndex, svgWidth, rowHeight]);
734
+ const ticks = useMemo(() => {
735
+ const tk = [];
736
+ const height = svgHeight || y2;
737
+ for (let i = 0; i < dates.length; i++) {
738
+ const x = i * columnWidth;
739
+ tk.push(
740
+ /* @__PURE__ */ jsx(
741
+ "line",
742
+ {
743
+ x1: x,
744
+ y1: 0,
745
+ x2: x,
746
+ y2: height,
747
+ className: "gridTick",
748
+ style: { stroke: "#ebebeb", strokeWidth: 1 }
749
+ },
750
+ `tick-${i}`
751
+ )
752
+ );
753
+ }
754
+ return tk;
755
+ }, [dates, columnWidth, svgHeight, y2]);
756
+ const todayHighlight = useMemo(() => {
757
+ var _a, _b;
758
+ const today = /* @__PURE__ */ new Date();
759
+ const startVal = dates[0].getTime();
760
+ const endVal = dates[dates.length - 1].getTime() + (((_a = dates[1]) == null ? void 0 : _a.getTime()) - ((_b = dates[0]) == null ? void 0 : _b.getTime()) || 864e5);
761
+ if (today.getTime() >= startVal && today.getTime() <= endVal) {
762
+ const x = taskXCoordinate(today, dates, columnWidth);
763
+ const colIdx = Math.floor(x / columnWidth);
764
+ const snapX = colIdx * columnWidth;
765
+ return /* @__PURE__ */ jsx(
766
+ "rect",
767
+ {
768
+ x: snapX,
769
+ y: 0,
770
+ width: columnWidth,
771
+ height: svgHeight || totalHeight,
772
+ fill: todayColor,
773
+ className: "gridTodayHighlight"
774
+ }
775
+ );
776
+ }
777
+ return null;
778
+ }, [dates, columnWidth, svgHeight, totalHeight, todayColor]);
779
+ return /* @__PURE__ */ jsxs("g", { className: "gridBody", children: [
780
+ /* @__PURE__ */ jsx("g", { className: "rows", children: rowBackgrounds }),
781
+ /* @__PURE__ */ jsx("g", { className: "ticks", children: ticks }),
782
+ /* @__PURE__ */ jsx("g", { className: "rowLines", children: rowLines }),
783
+ todayHighlight
784
+ ] });
785
+ };
786
+ const Grid = (props) => {
787
+ return /* @__PURE__ */ jsx("g", { className: "grid", children: /* @__PURE__ */ jsx(GridBody, { ...props }) });
788
+ };
789
+ const TopPartOfCalendar = ({
790
+ value,
791
+ x1Line,
792
+ y1Line,
793
+ y2Line,
794
+ xText,
795
+ yText
796
+ }) => {
797
+ return /* @__PURE__ */ jsxs("g", { className: "calendarHeader", children: [
798
+ /* @__PURE__ */ jsx(
799
+ "line",
800
+ {
801
+ x1: x1Line,
802
+ y1: y1Line,
803
+ x2: x1Line,
804
+ y2: y2Line,
805
+ className: "calendarHeaderLine",
806
+ style: { stroke: "#e6e6e6", strokeWidth: 1 }
807
+ }
808
+ ),
809
+ /* @__PURE__ */ jsx(
810
+ "text",
811
+ {
812
+ x: xText,
813
+ y: yText,
814
+ className: "calendarHeaderText",
815
+ style: {
816
+ fill: "#555",
817
+ textAnchor: "middle",
818
+ fontWeight: "bold",
819
+ dominantBaseline: "middle"
820
+ },
821
+ children: value
822
+ }
823
+ )
824
+ ] });
825
+ };
826
+ const Calendar = React.memo(({
827
+ dateSetup,
828
+ locale,
829
+ viewMode,
830
+ headerHeight,
831
+ columnWidth,
832
+ fontFamily,
833
+ fontSize,
834
+ calendarTopHeaderFormat,
835
+ calendarBottomHeaderFormat
836
+ }) => {
837
+ const { dates } = dateSetup;
838
+ const getTopHeaderValue = useMemo(() => {
839
+ return (date) => {
840
+ if (calendarTopHeaderFormat) {
841
+ return calendarTopHeaderFormat(date, viewMode);
842
+ }
843
+ switch (viewMode) {
844
+ case ViewMode.Hour:
845
+ case ViewMode.QuarterDay:
846
+ case ViewMode.HalfDay:
847
+ return getCachedDateTimeFormat(locale, {
848
+ month: "long",
849
+ day: "numeric",
850
+ year: "numeric"
851
+ }).format(date);
852
+ case ViewMode.Day:
853
+ case ViewMode.Week:
854
+ return getCachedDateTimeFormat(locale, {
855
+ month: "long",
856
+ year: "numeric"
857
+ }).format(date);
858
+ case ViewMode.Month:
859
+ return getCachedDateTimeFormat(locale, {
860
+ year: "numeric"
861
+ }).format(date);
862
+ case ViewMode.Year:
863
+ return getCachedDateTimeFormat(locale, {
864
+ year: "numeric"
865
+ }).format(date);
866
+ default:
867
+ return "";
868
+ }
869
+ };
870
+ }, [viewMode, locale, calendarTopHeaderFormat]);
871
+ const getBottomHeaderValue = useMemo(() => {
872
+ return (date) => {
873
+ if (calendarBottomHeaderFormat) {
874
+ return calendarBottomHeaderFormat(date, viewMode);
875
+ }
876
+ switch (viewMode) {
877
+ case ViewMode.Hour:
878
+ return getCachedDateTimeFormat(locale, {
879
+ hour: "numeric",
880
+ hour12: false
881
+ }).format(date);
882
+ case ViewMode.QuarterDay:
883
+ case ViewMode.HalfDay:
884
+ return getCachedDateTimeFormat(locale, {
885
+ hour: "numeric",
886
+ minute: "numeric",
887
+ hour12: false
888
+ }).format(date);
889
+ case ViewMode.Day:
890
+ return getCachedDateTimeFormat(locale, {
891
+ day: "numeric"
892
+ }).format(date);
893
+ case ViewMode.Week:
894
+ return `W${getWeekNumberISO8601(date)}`;
895
+ case ViewMode.Month:
896
+ return getCachedDateTimeFormat(locale, {
897
+ month: "short"
898
+ }).format(date);
899
+ case ViewMode.Year:
900
+ return getCachedDateTimeFormat(locale, {
901
+ year: "numeric"
902
+ }).format(date);
903
+ default:
904
+ return "";
905
+ }
906
+ };
907
+ }, [viewMode, locale, calendarBottomHeaderFormat]);
908
+ const topHeaderCells = useMemo(() => {
909
+ const cells = [];
910
+ let currentCell = null;
911
+ for (let i = 0; i < dates.length; i++) {
912
+ const val = getTopHeaderValue(dates[i]);
913
+ if (!currentCell || currentCell.value !== val) {
914
+ currentCell = {
915
+ value: val,
916
+ colSpan: 1,
917
+ startX: i * columnWidth
918
+ };
919
+ cells.push(currentCell);
920
+ } else {
921
+ currentCell.colSpan++;
922
+ }
923
+ }
924
+ return cells;
925
+ }, [dates, columnWidth, getTopHeaderValue]);
926
+ const topHeaders = useMemo(() => {
927
+ return topHeaderCells.map((cell, idx) => {
928
+ const width = cell.colSpan * columnWidth;
929
+ const xText = cell.startX + width / 2;
930
+ const yText = headerHeight * 0.25;
931
+ return /* @__PURE__ */ jsx(
932
+ TopPartOfCalendar,
933
+ {
934
+ value: cell.value,
935
+ x1Line: cell.startX,
936
+ y1Line: 0,
937
+ y2Line: headerHeight * 0.5,
938
+ xText,
939
+ yText
940
+ },
941
+ `top-hdr-${idx}`
942
+ );
943
+ });
944
+ }, [topHeaderCells, columnWidth, headerHeight]);
945
+ const bottomHeaders = useMemo(() => {
946
+ return dates.map((date, idx) => {
947
+ const x = idx * columnWidth;
948
+ const xText = x + columnWidth / 2;
949
+ const yText = headerHeight * 0.75;
950
+ const val = getBottomHeaderValue(date);
951
+ return /* @__PURE__ */ jsxs("g", { className: "calendarHeader", children: [
952
+ /* @__PURE__ */ jsx(
953
+ "line",
954
+ {
955
+ x1: x,
956
+ y1: headerHeight * 0.5,
957
+ x2: x,
958
+ y2: headerHeight,
959
+ className: "calendarHeaderLine",
960
+ style: { stroke: "#e6e6e6", strokeWidth: 1 }
961
+ }
962
+ ),
963
+ /* @__PURE__ */ jsx(
964
+ "text",
965
+ {
966
+ x: xText,
967
+ y: yText,
968
+ className: "calendarHeaderText",
969
+ style: {
970
+ fill: "#555",
971
+ textAnchor: "middle",
972
+ fontSize: "12px",
973
+ dominantBaseline: "middle"
974
+ },
975
+ children: val
976
+ }
977
+ )
978
+ ] }, `bot-hdr-${idx}`);
979
+ });
980
+ }, [dates, columnWidth, headerHeight, getBottomHeaderValue]);
981
+ return /* @__PURE__ */ jsxs(
982
+ "g",
983
+ {
984
+ className: "calendar",
985
+ style: {
986
+ fontFamily,
987
+ fontSize
988
+ },
989
+ children: [
990
+ /* @__PURE__ */ jsx(
991
+ "rect",
992
+ {
993
+ x: 0,
994
+ y: 0,
995
+ width: dates.length * columnWidth,
996
+ height: headerHeight,
997
+ fill: "#fcfcfc",
998
+ style: { stroke: "#e6e6e6", strokeWidth: 1 }
999
+ }
1000
+ ),
1001
+ /* @__PURE__ */ jsx(
1002
+ "line",
1003
+ {
1004
+ x1: 0,
1005
+ y1: headerHeight * 0.5,
1006
+ x2: dates.length * columnWidth,
1007
+ y2: headerHeight * 0.5,
1008
+ className: "calendarHeaderLine",
1009
+ style: { stroke: "#e6e6e6", strokeWidth: 1 }
1010
+ }
1011
+ ),
1012
+ /* @__PURE__ */ jsx("g", { className: "topHeaders", children: topHeaders }),
1013
+ /* @__PURE__ */ jsx("g", { className: "bottomHeaders", children: bottomHeaders })
1014
+ ]
1015
+ }
1016
+ );
1017
+ });
1018
+ const Bar = ({
1019
+ task,
1020
+ isProgressChangeable,
1021
+ isDateChangeable,
1022
+ isSelected,
1023
+ rtl,
1024
+ onEventStart
1025
+ }) => {
1026
+ const width = task.x2 - task.x1;
1027
+ const isSmall = task.typeInternal === "smalltask";
1028
+ const barBg = isSelected ? task.styles.backgroundSelectedColor : task.styles.backgroundColor;
1029
+ const progBg = isSelected ? task.styles.progressSelectedColor : task.styles.progressColor;
1030
+ return /* @__PURE__ */ jsxs("g", { className: "bar", children: [
1031
+ /* @__PURE__ */ jsx(
1032
+ "rect",
1033
+ {
1034
+ x: task.x1,
1035
+ y: task.y,
1036
+ width,
1037
+ height: task.height,
1038
+ rx: task.barCornerRadius,
1039
+ ry: task.barCornerRadius,
1040
+ fill: barBg,
1041
+ className: "barBackground",
1042
+ style: {
1043
+ cursor: isDateChangeable ? "move" : "default",
1044
+ strokeWidth: isSelected ? 1.5 : 0,
1045
+ stroke: isSelected ? "#333" : void 0
1046
+ },
1047
+ onMouseDown: (e) => {
1048
+ if (isDateChangeable) onEventStart("move", task, e);
1049
+ }
1050
+ }
1051
+ ),
1052
+ /* @__PURE__ */ jsx(
1053
+ "rect",
1054
+ {
1055
+ x: task.progressX,
1056
+ y: task.y,
1057
+ width: task.progressWidth,
1058
+ height: task.height,
1059
+ rx: task.barCornerRadius,
1060
+ ry: task.barCornerRadius,
1061
+ fill: progBg,
1062
+ className: "barProgress",
1063
+ style: { cursor: isDateChangeable ? "move" : "default" },
1064
+ onMouseDown: (e) => {
1065
+ if (isDateChangeable) onEventStart("move", task, e);
1066
+ }
1067
+ }
1068
+ ),
1069
+ isDateChangeable && /* @__PURE__ */ jsxs("g", { className: "handleGroup", children: [
1070
+ /* @__PURE__ */ jsx(
1071
+ "rect",
1072
+ {
1073
+ x: task.x1,
1074
+ y: task.y,
1075
+ width: task.handleWidth,
1076
+ height: task.height,
1077
+ fill: "transparent",
1078
+ style: { cursor: "w-resize" },
1079
+ onMouseDown: (e) => onEventStart("start", task, e)
1080
+ }
1081
+ ),
1082
+ /* @__PURE__ */ jsx(
1083
+ "rect",
1084
+ {
1085
+ x: task.x2 - task.handleWidth,
1086
+ y: task.y,
1087
+ width: task.handleWidth,
1088
+ height: task.height,
1089
+ fill: "transparent",
1090
+ style: { cursor: "e-resize" },
1091
+ onMouseDown: (e) => onEventStart("end", task, e)
1092
+ }
1093
+ )
1094
+ ] }),
1095
+ isProgressChangeable && /* @__PURE__ */ jsx(
1096
+ "polygon",
1097
+ {
1098
+ points: getProgressHandlePoint(
1099
+ task.progressX + (rtl ? 0 : task.progressWidth),
1100
+ task.y,
1101
+ task.height
1102
+ ),
1103
+ className: "barProgressHandle",
1104
+ style: { cursor: "ew-resize", fill: "#333" },
1105
+ onMouseDown: (e) => onEventStart("progress", task, e)
1106
+ }
1107
+ ),
1108
+ /* @__PURE__ */ jsx(
1109
+ "text",
1110
+ {
1111
+ x: isSmall ? task.x2 + 10 : task.x1 + width / 2,
1112
+ y: task.y + task.height / 2,
1113
+ className: "barLabel",
1114
+ style: {
1115
+ textAnchor: isSmall ? "start" : "middle",
1116
+ dominantBaseline: "middle",
1117
+ fill: isSmall ? "#333" : "#fff",
1118
+ fontSize: "12px",
1119
+ userSelect: "none",
1120
+ pointerEvents: "none",
1121
+ fontWeight: isSmall ? "normal" : "500"
1122
+ },
1123
+ children: task.name
1124
+ }
1125
+ )
1126
+ ] });
1127
+ };
1128
+ const Project = ({
1129
+ task,
1130
+ isSelected,
1131
+ onEventStart
1132
+ }) => {
1133
+ const width = task.x2 - task.x1;
1134
+ const projectBg = isSelected ? task.styles.backgroundSelectedColor : task.styles.backgroundColor;
1135
+ const projectProgressBg = isSelected ? task.styles.progressSelectedColor : task.styles.progressColor;
1136
+ return /* @__PURE__ */ jsxs("g", { className: "project", children: [
1137
+ /* @__PURE__ */ jsx(
1138
+ "rect",
1139
+ {
1140
+ x: task.x1,
1141
+ y: task.y,
1142
+ width,
1143
+ height: task.height,
1144
+ rx: task.barCornerRadius,
1145
+ ry: task.barCornerRadius,
1146
+ fill: projectBg,
1147
+ className: "projectBackground",
1148
+ style: {
1149
+ cursor: "pointer",
1150
+ strokeWidth: isSelected ? 1.5 : 0,
1151
+ stroke: isSelected ? "#333" : void 0
1152
+ },
1153
+ onMouseDown: (e) => onEventStart("click", task, e)
1154
+ }
1155
+ ),
1156
+ /* @__PURE__ */ jsx(
1157
+ "rect",
1158
+ {
1159
+ x: task.x1,
1160
+ y: task.y,
1161
+ width: task.progressWidth,
1162
+ height: task.height,
1163
+ rx: task.barCornerRadius,
1164
+ ry: task.barCornerRadius,
1165
+ fill: projectProgressBg,
1166
+ className: "projectProgress",
1167
+ style: { cursor: "pointer" },
1168
+ onMouseDown: (e) => onEventStart("click", task, e)
1169
+ }
1170
+ ),
1171
+ /* @__PURE__ */ jsx(
1172
+ "polygon",
1173
+ {
1174
+ points: `${task.x1},${task.y + task.height} ${task.x1 + 8},${task.y + task.height} ${task.x1},${task.y + task.height - 8}`,
1175
+ fill: projectProgressBg
1176
+ }
1177
+ ),
1178
+ /* @__PURE__ */ jsx(
1179
+ "polygon",
1180
+ {
1181
+ points: `${task.x2},${task.y + task.height} ${task.x2 - 8},${task.y + task.height} ${task.x2},${task.y + task.height - 8}`,
1182
+ fill: projectProgressBg
1183
+ }
1184
+ ),
1185
+ /* @__PURE__ */ jsx(
1186
+ "text",
1187
+ {
1188
+ x: task.x2 + 12,
1189
+ y: task.y + task.height / 2,
1190
+ className: "projectLabel",
1191
+ style: {
1192
+ textAnchor: "start",
1193
+ dominantBaseline: "middle",
1194
+ fill: "#333",
1195
+ fontSize: "12px",
1196
+ fontWeight: "bold",
1197
+ userSelect: "none",
1198
+ pointerEvents: "none"
1199
+ },
1200
+ children: task.name
1201
+ }
1202
+ )
1203
+ ] });
1204
+ };
1205
+ const Milestone = ({
1206
+ task,
1207
+ isDateChangeable,
1208
+ isSelected,
1209
+ onEventStart
1210
+ }) => {
1211
+ const milestoneBg = isSelected ? task.styles.backgroundSelectedColor : task.styles.backgroundColor;
1212
+ const halfHeight = task.height / 2;
1213
+ const cx = task.x1 + halfHeight;
1214
+ const cy = task.y + halfHeight;
1215
+ const points = `
1216
+ ${cx},${cy - halfHeight}
1217
+ ${cx + halfHeight},${cy}
1218
+ ${cx},${cy + halfHeight}
1219
+ ${cx - halfHeight},${cy}
1220
+ `.trim();
1221
+ return /* @__PURE__ */ jsxs("g", { className: "milestone", children: [
1222
+ /* @__PURE__ */ jsx(
1223
+ "polygon",
1224
+ {
1225
+ points,
1226
+ fill: milestoneBg,
1227
+ className: "milestoneBackground",
1228
+ style: {
1229
+ cursor: isDateChangeable ? "move" : "default",
1230
+ strokeWidth: isSelected ? 1.5 : 0,
1231
+ stroke: isSelected ? "#333" : void 0
1232
+ },
1233
+ onMouseDown: (e) => {
1234
+ if (isDateChangeable) onEventStart("move", task, e);
1235
+ }
1236
+ }
1237
+ ),
1238
+ /* @__PURE__ */ jsx(
1239
+ "text",
1240
+ {
1241
+ x: cx + halfHeight + 10,
1242
+ y: cy,
1243
+ className: "milestoneLabel",
1244
+ style: {
1245
+ textAnchor: "start",
1246
+ dominantBaseline: "middle",
1247
+ fill: "#333",
1248
+ fontSize: "12px",
1249
+ userSelect: "none",
1250
+ pointerEvents: "none"
1251
+ },
1252
+ children: task.name
1253
+ }
1254
+ )
1255
+ ] });
1256
+ };
1257
+ const TaskItem = (props) => {
1258
+ const { task } = props;
1259
+ switch (task.type) {
1260
+ case "project":
1261
+ return /* @__PURE__ */ jsx(Project, { ...props });
1262
+ case "milestone":
1263
+ return /* @__PURE__ */ jsx(Milestone, { ...props });
1264
+ default:
1265
+ return /* @__PURE__ */ jsx(Bar, { ...props });
1266
+ }
1267
+ };
1268
+ const DependencyArrow = ({
1269
+ taskFrom,
1270
+ taskTo,
1271
+ taskHeight,
1272
+ arrowIndent,
1273
+ rtl
1274
+ }) => {
1275
+ let path = "";
1276
+ let arrowHeadPoints = "";
1277
+ const y1 = taskFrom.y + taskHeight / 2;
1278
+ const y2 = taskTo.y + taskHeight / 2;
1279
+ if (rtl) {
1280
+ const x1 = taskFrom.x1;
1281
+ const x2 = taskTo.x2;
1282
+ if (x1 - arrowIndent > x2) {
1283
+ const midX = x1 - arrowIndent;
1284
+ path = `M ${x1} ${y1} H ${midX} V ${y2} H ${x2}`;
1285
+ } else {
1286
+ const midX1 = x1 - arrowIndent;
1287
+ const midX2 = x2 + arrowIndent;
1288
+ const midY = y1 + (y2 - y1) / 2;
1289
+ path = `M ${x1} ${y1} H ${midX1} V ${midY} H ${midX2} V ${y2} H ${x2}`;
1290
+ }
1291
+ arrowHeadPoints = `${x2},${y2} ${x2 + 5},${y2 - 3} ${x2 + 5},${y2 + 3}`;
1292
+ } else {
1293
+ const x1 = taskFrom.x2;
1294
+ const x2 = taskTo.x1;
1295
+ if (x1 + arrowIndent < x2) {
1296
+ const midX = x1 + arrowIndent;
1297
+ path = `M ${x1} ${y1} H ${midX} V ${y2} H ${x2}`;
1298
+ } else {
1299
+ const midX1 = x1 + arrowIndent;
1300
+ const midX2 = x2 - arrowIndent;
1301
+ const midY = y1 + (y2 - y1) / 2;
1302
+ path = `M ${x1} ${y1} H ${midX1} V ${midY} H ${midX2} V ${y2} H ${x2}`;
1303
+ }
1304
+ arrowHeadPoints = `${x2},${y2} ${x2 - 5},${y2 - 3} ${x2 - 5},${y2 + 3}`;
1305
+ }
1306
+ return /* @__PURE__ */ jsxs("g", { className: "dependencyArrow", children: [
1307
+ /* @__PURE__ */ jsx(
1308
+ "path",
1309
+ {
1310
+ d: path,
1311
+ fill: "transparent",
1312
+ stroke: "#fcb32c",
1313
+ strokeWidth: 1.5,
1314
+ className: "arrowPath"
1315
+ }
1316
+ ),
1317
+ /* @__PURE__ */ jsx(
1318
+ "polygon",
1319
+ {
1320
+ points: arrowHeadPoints,
1321
+ fill: "#fcb32c",
1322
+ className: "arrowHead"
1323
+ }
1324
+ )
1325
+ ] });
1326
+ };
1327
+ const DefaultTooltipContent = ({ task, fontSize, fontFamily }) => {
1328
+ const duration = Math.round((task.end.getTime() - task.start.getTime()) / 864e5);
1329
+ return /* @__PURE__ */ jsxs(
1330
+ "div",
1331
+ {
1332
+ style: {
1333
+ padding: "10px 12px",
1334
+ backgroundColor: "rgba(255, 255, 255, 0.98)",
1335
+ border: "1px solid #ebebeb",
1336
+ borderRadius: "6px",
1337
+ boxShadow: "0 4px 12px rgba(0, 0, 0, 0.08)",
1338
+ color: "#333",
1339
+ fontFamily,
1340
+ fontSize,
1341
+ lineHeight: "1.5em",
1342
+ pointerEvents: "none",
1343
+ minWidth: 180
1344
+ },
1345
+ children: [
1346
+ /* @__PURE__ */ jsx("div", { style: { fontWeight: "bold", color: "#111", marginBottom: 6 }, children: task.name }),
1347
+ /* @__PURE__ */ jsxs("div", { style: { color: "#666", fontSize: "11px", marginBottom: 2 }, children: [
1348
+ "開始: ",
1349
+ task.start.toLocaleDateString("ja-JP")
1350
+ ] }),
1351
+ /* @__PURE__ */ jsxs("div", { style: { color: "#666", fontSize: "11px", marginBottom: 4 }, children: [
1352
+ "終了: ",
1353
+ task.end.toLocaleDateString("ja-JP")
1354
+ ] }),
1355
+ task.type !== "milestone" && /* @__PURE__ */ jsxs("div", { style: { display: "flex", justifyContent: "space-between", marginTop: 6, paddingTop: 6, borderTop: "1px solid #f0f0f0", fontSize: "11px" }, children: [
1356
+ /* @__PURE__ */ jsxs("span", { children: [
1357
+ "期間: ",
1358
+ /* @__PURE__ */ jsxs("strong", { children: [
1359
+ duration,
1360
+ " 日間"
1361
+ ] })
1362
+ ] }),
1363
+ /* @__PURE__ */ jsxs("span", { children: [
1364
+ "進捗: ",
1365
+ /* @__PURE__ */ jsxs("strong", { children: [
1366
+ task.progress,
1367
+ "%"
1368
+ ] })
1369
+ ] })
1370
+ ] })
1371
+ ]
1372
+ }
1373
+ );
1374
+ };
1375
+ const TaskTooltip = ({
1376
+ task,
1377
+ rtl,
1378
+ fontSize,
1379
+ fontFamily,
1380
+ TooltipContent,
1381
+ mousePos = { x: 0, y: 0 }
1382
+ }) => {
1383
+ const tooltipRef = useRef(null);
1384
+ const [coords, setCoords] = useState({ x: 0, y: 0 });
1385
+ useEffect(() => {
1386
+ if (tooltipRef.current) {
1387
+ const width = tooltipRef.current.clientWidth || 200;
1388
+ let finalX = mousePos.x + 15;
1389
+ let finalY = mousePos.y + 15;
1390
+ if (rtl) {
1391
+ finalX = mousePos.x - width - 15;
1392
+ }
1393
+ setCoords({ x: finalX, y: finalY });
1394
+ }
1395
+ }, [mousePos, rtl]);
1396
+ return /* @__PURE__ */ jsx(
1397
+ "div",
1398
+ {
1399
+ ref: tooltipRef,
1400
+ style: {
1401
+ position: "fixed",
1402
+ left: coords.x,
1403
+ top: coords.y,
1404
+ zIndex: 1e3,
1405
+ pointerEvents: "none"
1406
+ },
1407
+ className: "ganttTooltip",
1408
+ children: !!(coords == null ? void 0 : coords.x) && !!(coords == null ? void 0 : coords.y) && /* @__PURE__ */ jsx(TooltipContent, { task, fontSize, fontFamily })
1409
+ }
1410
+ );
1411
+ };
1412
+ const TimelineContent = ({
1413
+ tasks,
1414
+ allTasks = [],
1415
+ interactionState,
1416
+ selectedTask,
1417
+ rowHeight,
1418
+ columnWidth,
1419
+ timeStep,
1420
+ svg,
1421
+ svgWidth,
1422
+ taskHeight,
1423
+ arrowIndent,
1424
+ fontSize,
1425
+ fontFamily,
1426
+ rtl,
1427
+ setInteractionState,
1428
+ setSelectedTask,
1429
+ mousePos = { x: 0, y: 0 },
1430
+ TooltipContent = DefaultTooltipContent,
1431
+ onDoubleClick,
1432
+ onClick,
1433
+ onDateChange,
1434
+ onProgressChange,
1435
+ onDelete
1436
+ }) => {
1437
+ const [hoveredTask, setHoveredTask] = useState(void 0);
1438
+ const dragX1DeltaRef = useRef(0);
1439
+ useEffect(() => {
1440
+ const handleMouseMove = async (event) => {
1441
+ if (!interactionState.action || !interactionState.originalSelectedTask || !(svg == null ? void 0 : svg.current)) {
1442
+ return;
1443
+ }
1444
+ event.preventDefault();
1445
+ const rect = svg.current.getBoundingClientRect();
1446
+ const svgX = event.clientX - rect.left;
1447
+ const { isChanged, changedTask } = applyDragToTask(
1448
+ svgX,
1449
+ interactionState.action,
1450
+ interactionState.originalSelectedTask,
1451
+ columnWidth,
1452
+ timeStep,
1453
+ dragX1DeltaRef.current,
1454
+ rtl
1455
+ );
1456
+ if (isChanged) {
1457
+ setInteractionState({ ...interactionState, changedTask });
1458
+ }
1459
+ };
1460
+ const handleMouseUp = async (event) => {
1461
+ if (!interactionState.action || !interactionState.originalSelectedTask) {
1462
+ return;
1463
+ }
1464
+ event.preventDefault();
1465
+ const { changedTask, originalSelectedTask, action } = interactionState;
1466
+ if (changedTask && changedTask !== originalSelectedTask) {
1467
+ try {
1468
+ if (action === "progress" && onProgressChange) {
1469
+ await onProgressChange(changedTask, changedTask.barChildren);
1470
+ } else if ((action === "move" || action === "start" || action === "end") && onDateChange) {
1471
+ await onDateChange(changedTask, changedTask.barChildren);
1472
+ }
1473
+ } catch (err) {
1474
+ console.error("Gantt action callback failed:", err);
1475
+ }
1476
+ }
1477
+ setInteractionState({ action: "" });
1478
+ };
1479
+ if (interactionState.action !== "") {
1480
+ window.addEventListener("mousemove", handleMouseMove);
1481
+ window.addEventListener("mouseup", handleMouseUp);
1482
+ }
1483
+ return () => {
1484
+ window.removeEventListener("mousemove", handleMouseMove);
1485
+ window.removeEventListener("mouseup", handleMouseUp);
1486
+ };
1487
+ }, [interactionState, svg, columnWidth, timeStep, rtl, onProgressChange, onDateChange, setInteractionState]);
1488
+ const handleEventStart = (action, task, event) => {
1489
+ if (event) {
1490
+ event.preventDefault();
1491
+ if ("clientX" in event && (svg == null ? void 0 : svg.current)) {
1492
+ const rect = svg.current.getBoundingClientRect();
1493
+ const svgX = event.clientX - rect.left;
1494
+ dragX1DeltaRef.current = svgX - task.x1;
1495
+ }
1496
+ }
1497
+ if (action === "click") {
1498
+ setSelectedTask(task.id);
1499
+ if (onClick) onClick(task);
1500
+ } else if (action === "dblclick") {
1501
+ if (onDoubleClick) onDoubleClick(task);
1502
+ } else if (action === "delete") {
1503
+ if (onDelete) onDelete(task);
1504
+ } else {
1505
+ setInteractionState({
1506
+ action,
1507
+ originalSelectedTask: task,
1508
+ changedTask: task
1509
+ });
1510
+ }
1511
+ };
1512
+ const arrows = useMemo(() => {
1513
+ const list = [];
1514
+ const tasksLookupList = allTasks.length > 0 ? allTasks : tasks;
1515
+ tasks.forEach((taskTo) => {
1516
+ if (taskTo.dependencies) {
1517
+ taskTo.dependencies.forEach((depId) => {
1518
+ const taskFrom = tasksLookupList.find((t) => t.id === depId);
1519
+ if (taskFrom) {
1520
+ list.push(
1521
+ /* @__PURE__ */ jsx(
1522
+ DependencyArrow,
1523
+ {
1524
+ taskFrom,
1525
+ taskTo,
1526
+ rowHeight,
1527
+ taskHeight,
1528
+ arrowIndent,
1529
+ rtl
1530
+ },
1531
+ `arrow-${taskFrom.id}-${taskTo.id}`
1532
+ )
1533
+ );
1534
+ }
1535
+ });
1536
+ }
1537
+ });
1538
+ return list;
1539
+ }, [tasks, allTasks, rowHeight, taskHeight, arrowIndent, rtl]);
1540
+ const isDateChangeable = (task) => !task.isDisabled;
1541
+ const isProgressChangeable = (task) => !task.isDisabled && task.type === "task";
1542
+ return /* @__PURE__ */ jsxs("g", { className: "timelineContent", children: [
1543
+ /* @__PURE__ */ jsx("g", { className: "dependencyArrows", children: arrows }),
1544
+ /* @__PURE__ */ jsx("g", { className: "taskBars", children: tasks.map((task) => {
1545
+ const renderTask = interactionState.action !== "" && interactionState.changedTask && interactionState.changedTask.id === task.id ? interactionState.changedTask : task;
1546
+ const isSelected = (selectedTask == null ? void 0 : selectedTask.id) === task.id;
1547
+ return /* @__PURE__ */ jsx(
1548
+ "g",
1549
+ {
1550
+ className: "taskItemWrapper",
1551
+ onMouseEnter: () => setHoveredTask(task),
1552
+ onMouseLeave: () => setHoveredTask(void 0),
1553
+ children: /* @__PURE__ */ jsx(
1554
+ TaskItem,
1555
+ {
1556
+ task: renderTask,
1557
+ arrowIndent,
1558
+ taskHeight,
1559
+ isProgressChangeable: isProgressChangeable(task),
1560
+ isDateChangeable: isDateChangeable(task),
1561
+ isDelete: true,
1562
+ isSelected,
1563
+ rtl,
1564
+ onEventStart: handleEventStart
1565
+ }
1566
+ )
1567
+ },
1568
+ task.id
1569
+ );
1570
+ }) }),
1571
+ hoveredTask && createPortal(
1572
+ /* @__PURE__ */ jsx(
1573
+ TaskTooltip,
1574
+ {
1575
+ task: hoveredTask,
1576
+ arrowIndent,
1577
+ rtl,
1578
+ svgWidth,
1579
+ fontSize,
1580
+ fontFamily,
1581
+ TooltipContent,
1582
+ mousePos
1583
+ }
1584
+ ),
1585
+ document.body
1586
+ )
1587
+ ] });
1588
+ };
1589
+ const TimelinePanel = ({
1590
+ gridProps,
1591
+ calendarProps,
1592
+ contentProps
1593
+ }) => {
1594
+ const { svgWidth } = gridProps;
1595
+ const { headerHeight } = calendarProps;
1596
+ const svgRef = useRef(null);
1597
+ return /* @__PURE__ */ jsxs(
1598
+ "div",
1599
+ {
1600
+ className: "ganttTimeline",
1601
+ style: {
1602
+ width: svgWidth,
1603
+ position: "relative"
1604
+ },
1605
+ children: [
1606
+ /* @__PURE__ */ jsx(
1607
+ "div",
1608
+ {
1609
+ className: "ganttCalendarHeader",
1610
+ style: {
1611
+ position: "sticky",
1612
+ top: 0,
1613
+ zIndex: 10,
1614
+ width: svgWidth,
1615
+ height: headerHeight,
1616
+ backgroundColor: "#fcfcfc",
1617
+ borderBottom: "1px solid #e6e6e6"
1618
+ },
1619
+ children: /* @__PURE__ */ jsx(
1620
+ "svg",
1621
+ {
1622
+ width: svgWidth,
1623
+ height: headerHeight,
1624
+ className: "calendarSvg",
1625
+ children: /* @__PURE__ */ jsx(Calendar, { ...calendarProps })
1626
+ }
1627
+ )
1628
+ }
1629
+ ),
1630
+ /* @__PURE__ */ jsx(
1631
+ "div",
1632
+ {
1633
+ style: {
1634
+ width: svgWidth,
1635
+ height: contentProps.svgHeight,
1636
+ position: "relative"
1637
+ },
1638
+ children: /* @__PURE__ */ jsxs(
1639
+ "svg",
1640
+ {
1641
+ width: svgWidth,
1642
+ height: contentProps.svgHeight,
1643
+ className: "ganttSvg",
1644
+ ref: svgRef,
1645
+ children: [
1646
+ /* @__PURE__ */ jsx(Grid, { ...gridProps }),
1647
+ /* @__PURE__ */ jsx(
1648
+ TimelineContent,
1649
+ {
1650
+ ...contentProps,
1651
+ svg: svgRef
1652
+ }
1653
+ )
1654
+ ]
1655
+ }
1656
+ )
1657
+ }
1658
+ )
1659
+ ]
1660
+ }
1661
+ );
1662
+ };
1663
+ const Gantt = ({
1664
+ tasks,
1665
+ viewMode = ViewMode.Day,
1666
+ viewDate,
1667
+ preStepsCount = 1,
1668
+ locale = "en-GB",
1669
+ rtl = false,
1670
+ calendarTopHeaderFormat,
1671
+ calendarBottomHeaderFormat,
1672
+ headerHeight = 50,
1673
+ columnWidth,
1674
+ listCellWidth = "360px",
1675
+ rowHeight = 50,
1676
+ ganttHeight = 0,
1677
+ barCornerRadius = 3,
1678
+ handleWidth = 8,
1679
+ fontFamily = "Arial, Roboto, sans-serif",
1680
+ fontSize = "14px",
1681
+ barFill = 60,
1682
+ barProgressColor = "#a3a3ff",
1683
+ barProgressSelectedColor = "#8282ff",
1684
+ barBackgroundColor = "#b8c2cc",
1685
+ barBackgroundSelectedColor = "#a3aebe",
1686
+ projectProgressColor = "#7db3e8",
1687
+ projectProgressSelectedColor = "#5492d6",
1688
+ projectBackgroundColor = "#facfc3",
1689
+ projectBackgroundSelectedColor = "#f1b3a2",
1690
+ milestoneBackgroundColor = "#f1c40f",
1691
+ milestoneBackgroundSelectedColor = "#f39c12",
1692
+ arrowColor = "#fcb32c",
1693
+ arrowIndent = 20,
1694
+ todayColor = "rgba(252, 75, 113, 0.3)",
1695
+ TooltipContent,
1696
+ TaskListHeader,
1697
+ TaskListTable,
1698
+ timeStep = 36e5 * 24,
1699
+ onSelect,
1700
+ onDoubleClick,
1701
+ onClick,
1702
+ onDateChange,
1703
+ onProgressChange,
1704
+ onDelete,
1705
+ onExpanderClick
1706
+ }) => {
1707
+ const resolvedColumnWidth = useMemo(() => {
1708
+ if (columnWidth) return columnWidth;
1709
+ switch (viewMode) {
1710
+ case ViewMode.Hour:
1711
+ return 60;
1712
+ case ViewMode.QuarterDay:
1713
+ return 65;
1714
+ case ViewMode.HalfDay:
1715
+ return 80;
1716
+ case ViewMode.Day:
1717
+ return 60;
1718
+ case ViewMode.Week:
1719
+ return 250;
1720
+ case ViewMode.Month:
1721
+ return 300;
1722
+ case ViewMode.Year:
1723
+ return 350;
1724
+ default:
1725
+ return 60;
1726
+ }
1727
+ }, [columnWidth, viewMode]);
1728
+ const filteredTasks = useMemo(
1729
+ () => removeHiddenTasks(tasks).sort(sortTasks),
1730
+ [tasks]
1731
+ );
1732
+ const dates = useMemo(
1733
+ () => ganttDateRange(filteredTasks, viewMode, preStepsCount),
1734
+ [filteredTasks, viewMode, preStepsCount]
1735
+ );
1736
+ const renderedTasks = useMemo(
1737
+ () => convertToRenderedTasks(
1738
+ filteredTasks,
1739
+ dates,
1740
+ resolvedColumnWidth,
1741
+ rowHeight,
1742
+ rowHeight * (barFill / 100),
1743
+ barCornerRadius,
1744
+ handleWidth,
1745
+ rtl,
1746
+ barProgressColor,
1747
+ barProgressSelectedColor,
1748
+ barBackgroundColor,
1749
+ barBackgroundSelectedColor,
1750
+ projectProgressColor,
1751
+ projectProgressSelectedColor,
1752
+ projectBackgroundColor,
1753
+ projectBackgroundSelectedColor,
1754
+ milestoneBackgroundColor,
1755
+ milestoneBackgroundSelectedColor
1756
+ ),
1757
+ [
1758
+ filteredTasks,
1759
+ dates,
1760
+ resolvedColumnWidth,
1761
+ rowHeight,
1762
+ barFill,
1763
+ barCornerRadius,
1764
+ handleWidth,
1765
+ rtl,
1766
+ barProgressColor,
1767
+ barProgressSelectedColor,
1768
+ barBackgroundColor,
1769
+ barBackgroundSelectedColor,
1770
+ projectProgressColor,
1771
+ projectProgressSelectedColor,
1772
+ projectBackgroundColor,
1773
+ projectBackgroundSelectedColor,
1774
+ milestoneBackgroundColor,
1775
+ milestoneBackgroundSelectedColor
1776
+ ]
1777
+ );
1778
+ const [scrollTopState, setScrollTopState] = useState(0);
1779
+ const [mousePos, setMousePos] = useState({ x: 0, y: 0 });
1780
+ const [selectedTask, setSelectedTaskState] = useState(void 0);
1781
+ const [interactionState, setInteractionState] = useState({ action: "" });
1782
+ const [, setFailedTask] = useState(null);
1783
+ const ganttFullHeight = renderedTasks.length * rowHeight;
1784
+ const viewHeight = ganttHeight && ganttHeight > 0 ? ganttHeight : 500;
1785
+ const startIndex = Math.max(0, Math.floor(scrollTopState / rowHeight) - 3);
1786
+ const endIndex = Math.min(
1787
+ renderedTasks.length - 1,
1788
+ Math.ceil((scrollTopState + viewHeight) / rowHeight) + 3
1789
+ );
1790
+ const visibleRenderedTasks = useMemo(
1791
+ () => renderedTasks.slice(startIndex, endIndex + 1),
1792
+ [renderedTasks, startIndex, endIndex]
1793
+ );
1794
+ const taskListWidthNumber = useMemo(() => {
1795
+ const val = parseInt(listCellWidth, 10);
1796
+ return isNaN(val) ? 250 : val;
1797
+ }, [listCellWidth]);
1798
+ const [taskListWidth, setTaskListWidth] = useState(taskListWidthNumber);
1799
+ useEffect(() => {
1800
+ setTaskListWidth(taskListWidthNumber);
1801
+ }, [taskListWidthNumber]);
1802
+ const [isResizing, setIsResizing] = useState(false);
1803
+ const resizerRef = useRef(null);
1804
+ const handleResizerMouseDown = useCallback((e) => {
1805
+ resizerRef.current = { startX: e.clientX, startWidth: taskListWidth };
1806
+ setIsResizing(true);
1807
+ e.preventDefault();
1808
+ }, [taskListWidth]);
1809
+ useEffect(() => {
1810
+ const handleGlobalMouseMove = (e) => {
1811
+ if (!isResizing || !resizerRef.current) return;
1812
+ const diff = e.clientX - resizerRef.current.startX;
1813
+ setTaskListWidth(Math.max(0, resizerRef.current.startWidth + diff));
1814
+ };
1815
+ const handleGlobalMouseUp = () => {
1816
+ setIsResizing(false);
1817
+ resizerRef.current = null;
1818
+ };
1819
+ if (isResizing) {
1820
+ window.addEventListener("mousemove", handleGlobalMouseMove);
1821
+ window.addEventListener("mouseup", handleGlobalMouseUp);
1822
+ document.body.style.cursor = "col-resize";
1823
+ } else {
1824
+ document.body.style.cursor = "";
1825
+ }
1826
+ return () => {
1827
+ window.removeEventListener("mousemove", handleGlobalMouseMove);
1828
+ window.removeEventListener("mouseup", handleGlobalMouseUp);
1829
+ document.body.style.cursor = "";
1830
+ };
1831
+ }, [isResizing]);
1832
+ const svgWidth = dates.length * resolvedColumnWidth;
1833
+ const containerRef = useRef(null);
1834
+ useEffect(() => {
1835
+ if (viewDate && dates.length > 0 && containerRef.current) {
1836
+ const x = taskXCoordinate(viewDate, dates, resolvedColumnWidth);
1837
+ const targetLeft = Math.max(0, x - resolvedColumnWidth * 2);
1838
+ containerRef.current.scrollLeft = targetLeft;
1839
+ }
1840
+ }, [viewDate, dates, resolvedColumnWidth]);
1841
+ const handleScroll = useCallback((e) => {
1842
+ setScrollTopState(e.currentTarget.scrollTop);
1843
+ }, []);
1844
+ const handleMouseMove = useCallback((e) => {
1845
+ setMousePos({ x: e.clientX, y: e.clientY });
1846
+ }, []);
1847
+ const handleExpanderClick = useCallback(
1848
+ (task) => {
1849
+ if (onExpanderClick) onExpanderClick(task);
1850
+ },
1851
+ [onExpanderClick]
1852
+ );
1853
+ const setSelectedTask = useCallback(
1854
+ (taskId) => {
1855
+ const newTask = renderedTasks.find((t) => t.id === taskId);
1856
+ setSelectedTaskState(newTask);
1857
+ if (onSelect) onSelect(newTask, !!newTask);
1858
+ },
1859
+ [renderedTasks, onSelect]
1860
+ );
1861
+ const gridProps = {
1862
+ columnWidth: resolvedColumnWidth,
1863
+ svgWidth,
1864
+ svgHeight: ganttFullHeight,
1865
+ dates,
1866
+ rowHeight,
1867
+ rtl,
1868
+ todayColor,
1869
+ tasks: visibleRenderedTasks,
1870
+ startIndex,
1871
+ endIndex
1872
+ };
1873
+ const dateSetup = useMemo(() => ({ dates, viewMode }), [dates, viewMode]);
1874
+ const calendarProps = {
1875
+ dateSetup,
1876
+ locale,
1877
+ rtl,
1878
+ headerHeight,
1879
+ columnWidth: resolvedColumnWidth,
1880
+ fontFamily,
1881
+ fontSize,
1882
+ viewMode,
1883
+ calendarTopHeaderFormat,
1884
+ calendarBottomHeaderFormat
1885
+ };
1886
+ const contentProps = {
1887
+ tasks: visibleRenderedTasks,
1888
+ allTasks: renderedTasks,
1889
+ dates,
1890
+ interactionState,
1891
+ selectedTask,
1892
+ rowHeight,
1893
+ columnWidth: resolvedColumnWidth,
1894
+ timeStep,
1895
+ svgWidth,
1896
+ svgHeight: ganttFullHeight,
1897
+ taskHeight: rowHeight * (barFill / 100),
1898
+ arrowColor,
1899
+ arrowIndent,
1900
+ fontSize,
1901
+ fontFamily,
1902
+ rtl,
1903
+ setInteractionState,
1904
+ setFailedTask,
1905
+ setSelectedTask,
1906
+ onSelect,
1907
+ onDoubleClick,
1908
+ onClick,
1909
+ onDateChange,
1910
+ onProgressChange,
1911
+ onDelete,
1912
+ onExpanderClick: handleExpanderClick,
1913
+ TooltipContent,
1914
+ mousePos,
1915
+ ganttHeight: viewHeight,
1916
+ headerHeight
1917
+ };
1918
+ return /* @__PURE__ */ jsx(
1919
+ "div",
1920
+ {
1921
+ ref: containerRef,
1922
+ className: "ganttOuterWrapper",
1923
+ onScroll: handleScroll,
1924
+ onMouseMove: handleMouseMove,
1925
+ style: {
1926
+ fontFamily,
1927
+ fontSize,
1928
+ height: viewHeight,
1929
+ width: "100%",
1930
+ overflow: "auto",
1931
+ position: "relative"
1932
+ },
1933
+ children: /* @__PURE__ */ jsxs(
1934
+ "div",
1935
+ {
1936
+ className: "ganttWrapper",
1937
+ style: {
1938
+ display: "flex",
1939
+ width: taskListWidth + svgWidth + 6,
1940
+ // リサイザーの幅分追加
1941
+ height: ganttFullHeight + headerHeight,
1942
+ position: "relative",
1943
+ userSelect: isResizing ? "none" : "auto"
1944
+ },
1945
+ children: [
1946
+ /* @__PURE__ */ jsx(
1947
+ TaskList,
1948
+ {
1949
+ tasks: renderedTasks,
1950
+ visibleTasks: visibleRenderedTasks,
1951
+ rowWidth: `${taskListWidth}px`,
1952
+ taskListWidth,
1953
+ rowHeight,
1954
+ headerHeight,
1955
+ fontFamily,
1956
+ fontSize,
1957
+ locale,
1958
+ selectedTaskId: (selectedTask == null ? void 0 : selectedTask.id) || "",
1959
+ setSelectedTask,
1960
+ onExpanderClick: handleExpanderClick,
1961
+ TaskListHeader,
1962
+ TaskListTable
1963
+ }
1964
+ ),
1965
+ /* @__PURE__ */ jsx(
1966
+ "div",
1967
+ {
1968
+ className: "ganttResizer",
1969
+ onMouseDown: handleResizerMouseDown,
1970
+ style: {
1971
+ width: "6px",
1972
+ cursor: "col-resize",
1973
+ zIndex: 30,
1974
+ flexShrink: 0,
1975
+ transition: "background-color 0.2s"
1976
+ }
1977
+ }
1978
+ ),
1979
+ /* @__PURE__ */ jsx("div", { style: { pointerEvents: isResizing ? "none" : "auto" }, children: /* @__PURE__ */ jsx(
1980
+ TimelinePanel,
1981
+ {
1982
+ gridProps,
1983
+ calendarProps,
1984
+ contentProps
1985
+ }
1986
+ ) })
1987
+ ]
1988
+ }
1989
+ )
1990
+ }
1991
+ );
1992
+ };
1993
+ export {
1994
+ Gantt,
1995
+ ViewMode
1996
+ };