gantt-lib 0.6.0 → 0.6.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -492,6 +492,55 @@ function findParentId(taskId, tasks) {
492
492
  return task?.parentId;
493
493
  }
494
494
 
495
+ // src/utils/hierarchyOrder.ts
496
+ function flattenHierarchy(tasks) {
497
+ const byId = new Map(tasks.map((task) => [task.id, task]));
498
+ const byParent = /* @__PURE__ */ new Map();
499
+ for (const task of tasks) {
500
+ const normalizedParentId = task.parentId && byId.has(task.parentId) ? task.parentId : void 0;
501
+ const siblings = byParent.get(normalizedParentId) ?? [];
502
+ siblings.push(task);
503
+ byParent.set(normalizedParentId, siblings);
504
+ }
505
+ const result = [];
506
+ const visited = /* @__PURE__ */ new Set();
507
+ const walk = (parentId) => {
508
+ const children = byParent.get(parentId) ?? [];
509
+ for (const task of children) {
510
+ if (visited.has(task.id)) continue;
511
+ visited.add(task.id);
512
+ result.push(task);
513
+ walk(task.id);
514
+ }
515
+ };
516
+ walk(void 0);
517
+ for (const task of tasks) {
518
+ if (!visited.has(task.id)) {
519
+ result.push(task);
520
+ }
521
+ }
522
+ return result;
523
+ }
524
+ function normalizeHierarchyTasks(tasks) {
525
+ const orderedTasks = flattenHierarchy(tasks).map((task) => ({ ...task }));
526
+ for (const task of [...orderedTasks].reverse()) {
527
+ if (!isTaskParent(task.id, orderedTasks)) continue;
528
+ const { startDate, endDate } = computeParentDates(task.id, orderedTasks);
529
+ const progress = computeParentProgress(task.id, orderedTasks);
530
+ const normalizedStartDate = startDate.toISOString().split("T")[0];
531
+ const normalizedEndDate = endDate.toISOString().split("T")[0];
532
+ const parentIndex = orderedTasks.findIndex((candidate) => candidate.id === task.id);
533
+ if (parentIndex === -1) continue;
534
+ orderedTasks[parentIndex] = {
535
+ ...orderedTasks[parentIndex],
536
+ startDate: normalizedStartDate,
537
+ endDate: normalizedEndDate,
538
+ progress
539
+ };
540
+ }
541
+ return orderedTasks;
542
+ }
543
+
495
544
  // src/components/TimeScaleHeader/TimeScaleHeader.tsx
496
545
  import { useMemo } from "react";
497
546
  import { format } from "date-fns";
@@ -3080,13 +3129,14 @@ var TaskList = ({
3080
3129
  return next;
3081
3130
  });
3082
3131
  }, []);
3132
+ const orderedTasks = useMemo8(() => normalizeHierarchyTasks(tasks), [tasks]);
3083
3133
  const visibleTasks = useMemo8(() => {
3084
- return tasks.filter((task) => {
3134
+ return orderedTasks.filter((task) => {
3085
3135
  if (!task.parentId) return true;
3086
3136
  const parentCollapsed = collapsedParentIds.has(task.parentId);
3087
3137
  return !parentCollapsed;
3088
3138
  });
3089
- }, [tasks, collapsedParentIds]);
3139
+ }, [orderedTasks, collapsedParentIds]);
3090
3140
  const totalHeight = useMemo8(
3091
3141
  () => visibleTasks.length * rowHeight,
3092
3142
  [visibleTasks.length, rowHeight]
@@ -3208,9 +3258,9 @@ var TaskList = ({
3208
3258
  dragOriginIndexRef.current = null;
3209
3259
  return;
3210
3260
  }
3211
- const reordered = [...tasks];
3261
+ const reordered = [...orderedTasks];
3212
3262
  const [moved] = reordered.splice(originIndex, 1);
3213
- const insertIndex = dropIndex === tasks.length ? tasks.length - 1 : originIndex < dropIndex ? dropIndex - 1 : dropIndex;
3263
+ const insertIndex = dropIndex === visibleTasks.length ? visibleTasks.length - 1 : originIndex < dropIndex ? dropIndex - 1 : dropIndex;
3214
3264
  const isChild = !!moved.parentId;
3215
3265
  const isParent = tasks.some((t) => t.parentId === moved.id);
3216
3266
  const taskType = isParent ? "PARENT" : isChild ? "CHILD" : "ROOT";
@@ -3225,7 +3275,7 @@ var TaskList = ({
3225
3275
  insertIndex,
3226
3276
  direction: originIndex < dropIndex ? "DOWN" : "UP"
3227
3277
  });
3228
- console.log("[TASKS ARRAY LENGTH]", tasks.length);
3278
+ console.log("[TASKS ARRAY LENGTH]", orderedTasks.length);
3229
3279
  let inferredParentId;
3230
3280
  if (moved.parentId) {
3231
3281
  const parentIndex = reordered.findIndex((t) => t.id === moved.parentId);
@@ -3310,7 +3360,7 @@ var TaskList = ({
3310
3360
  setDraggingIndex(null);
3311
3361
  setDragOverIndex(null);
3312
3362
  dragOriginIndexRef.current = null;
3313
- }, [tasks, onReorder, onTaskSelect]);
3363
+ }, [orderedTasks, visibleTasks.length, onReorder, onTaskSelect]);
3314
3364
  const handleDragEnd = useCallback5(() => {
3315
3365
  setDraggingIndex(null);
3316
3366
  setDragOverIndex(null);
@@ -3433,16 +3483,16 @@ var TaskList = ({
3433
3483
  enableAddTask && onAdd && !isCreating && /* @__PURE__ */ jsx14(
3434
3484
  "button",
3435
3485
  {
3436
- className: `gantt-tl-add-btn${dragOverIndex === tasks.length ? " gantt-tl-add-btn-drag-over" : ""}`,
3486
+ className: `gantt-tl-add-btn${dragOverIndex === visibleTasks.length ? " gantt-tl-add-btn-drag-over" : ""}`,
3437
3487
  onClick: () => setIsCreating(true),
3438
3488
  onDragEnter: (e) => {
3439
3489
  e.preventDefault();
3440
- setDragOverIndex(tasks.length);
3490
+ setDragOverIndex(visibleTasks.length);
3441
3491
  },
3442
3492
  onDragOver: (e) => {
3443
3493
  e.preventDefault();
3444
3494
  e.dataTransfer.dropEffect = "move";
3445
- setDragOverIndex(tasks.length);
3495
+ setDragOverIndex(visibleTasks.length);
3446
3496
  },
3447
3497
  onDragLeave: (e) => {
3448
3498
  e.preventDefault();
@@ -3450,7 +3500,7 @@ var TaskList = ({
3450
3500
  },
3451
3501
  onDrop: (e) => {
3452
3502
  e.preventDefault();
3453
- handleDrop(tasks.length, e);
3503
+ handleDrop(visibleTasks.length, e);
3454
3504
  },
3455
3505
  type: "button",
3456
3506
  children: "+ \u0414\u043E\u0431\u0430\u0432\u0438\u0442\u044C \u0437\u0430\u0434\u0430\u0447\u0443"
@@ -3490,7 +3540,8 @@ var GanttChart = forwardRef(({
3490
3540
  const [selectedChip, setSelectedChip] = useState7(null);
3491
3541
  const [collapsedParentIds, setCollapsedParentIds] = useState7(/* @__PURE__ */ new Set());
3492
3542
  const [editingTaskId, setEditingTaskId] = useState7(null);
3493
- const dateRange = useMemo9(() => getMultiMonthDays(tasks), [tasks]);
3543
+ const normalizedTasks = useMemo9(() => normalizeHierarchyTasks(tasks), [tasks]);
3544
+ const dateRange = useMemo9(() => getMultiMonthDays(normalizedTasks), [normalizedTasks]);
3494
3545
  const [validationResult, setValidationResult] = useState7(null);
3495
3546
  const [cascadeOverrides, setCascadeOverrides] = useState7(/* @__PURE__ */ new Map());
3496
3547
  const gridWidth = useMemo9(
@@ -3498,12 +3549,12 @@ var GanttChart = forwardRef(({
3498
3549
  [dateRange.length, dayWidth]
3499
3550
  );
3500
3551
  const filteredTasks = useMemo9(() => {
3501
- return tasks.filter((task) => {
3552
+ return normalizedTasks.filter((task) => {
3502
3553
  if (!task.parentId) return true;
3503
3554
  const parentCollapsed = collapsedParentIds.has(task.parentId);
3504
3555
  return !parentCollapsed;
3505
3556
  });
3506
- }, [tasks, collapsedParentIds]);
3557
+ }, [normalizedTasks, collapsedParentIds]);
3507
3558
  const totalGridHeight = useMemo9(
3508
3559
  () => filteredTasks.length * rowHeight,
3509
3560
  [filteredTasks.length, rowHeight]
@@ -3749,9 +3800,9 @@ var GanttChart = forwardRef(({
3749
3800
  updatedCount: updated.length
3750
3801
  });
3751
3802
  console.log("=== GANTT CHART handleReorder END ===\n");
3752
- return updated;
3803
+ return normalizeHierarchyTasks(updated);
3753
3804
  });
3754
- onReorder?.(reorderedTasks, movedTaskId, inferredParentId);
3805
+ onReorder?.(normalizeHierarchyTasks(reorderedTasks), movedTaskId, inferredParentId);
3755
3806
  }, [onChange, onReorder]);
3756
3807
  const dependencyOverrides = useMemo9(() => {
3757
3808
  const map = new Map(cascadeOverrides);
@@ -3818,15 +3869,15 @@ var GanttChart = forwardRef(({
3818
3869
  const parentId = taskToPromote.parentId;
3819
3870
  const siblings = currentTasks.filter((t) => t.parentId === parentId);
3820
3871
  if (siblings.length <= 1) {
3821
- return currentTasks.map(
3872
+ return normalizeHierarchyTasks(currentTasks.map(
3822
3873
  (t) => t.id === taskId ? { ...t, parentId: void 0 } : t
3823
- );
3874
+ ));
3824
3875
  }
3825
3876
  const lastSiblingIndex = currentTasks.map((t, i) => ({ task: t, index: i })).filter(({ task }) => task.parentId === parentId).sort((a, b) => b.index - a.index)[0];
3826
3877
  if (!lastSiblingIndex) {
3827
- return currentTasks.map(
3878
+ return normalizeHierarchyTasks(currentTasks.map(
3828
3879
  (t) => t.id === taskId ? { ...t, parentId: void 0 } : t
3829
- );
3880
+ ));
3830
3881
  }
3831
3882
  const withoutPromotedTask = currentTasks.filter((t) => t.id !== taskId);
3832
3883
  const insertIndex = lastSiblingIndex.index + 1;
@@ -3836,7 +3887,7 @@ var GanttChart = forwardRef(({
3836
3887
  promotedTask,
3837
3888
  ...withoutPromotedTask.slice(insertIndex)
3838
3889
  ];
3839
- return newTasks;
3890
+ return normalizeHierarchyTasks(newTasks);
3840
3891
  });
3841
3892
  }, [onChange]);
3842
3893
  const handleDemoteTask = useCallback6((taskId, newParentId) => {
@@ -3869,7 +3920,7 @@ var GanttChart = forwardRef(({
3869
3920
  updatedTasks = updatedTasks.map(
3870
3921
  (t) => t.id === newParentId ? { ...t, startDate: parentDates.startDate.toISOString().split("T")[0], endDate: parentDates.endDate.toISOString().split("T")[0], progress: parentProgress } : t
3871
3922
  );
3872
- return updatedTasks;
3923
+ return normalizeHierarchyTasks(updatedTasks);
3873
3924
  });
3874
3925
  }, [onChange]);
3875
3926
  const panStateRef = useRef6(null);
@@ -3927,7 +3978,7 @@ var GanttChart = forwardRef(({
3927
3978
  /* @__PURE__ */ jsx15(
3928
3979
  TaskList,
3929
3980
  {
3930
- tasks,
3981
+ tasks: normalizedTasks,
3931
3982
  rowHeight,
3932
3983
  headerHeight,
3933
3984
  taskListWidth,
@@ -3982,7 +4033,7 @@ var GanttChart = forwardRef(({
3982
4033
  DependencyLines_default,
3983
4034
  {
3984
4035
  tasks: filteredTasks,
3985
- allTasks: tasks,
4036
+ allTasks: normalizedTasks,
3986
4037
  collapsedParentIds,
3987
4038
  monthStart,
3988
4039
  dayWidth,
@@ -4020,7 +4071,7 @@ var GanttChart = forwardRef(({
4020
4071
  }
4021
4072
  },
4022
4073
  rowIndex: index,
4023
- allTasks: tasks,
4074
+ allTasks: normalizedTasks,
4024
4075
  enableAutoSchedule: enableAutoSchedule ?? false,
4025
4076
  disableConstraints: disableConstraints ?? false,
4026
4077
  overridePosition: cascadeOverrides.get(task.id),
@@ -4086,6 +4137,7 @@ export {
4086
4137
  detectCycles,
4087
4138
  detectEdgeZone,
4088
4139
  findParentId,
4140
+ flattenHierarchy,
4089
4141
  formatDateLabel,
4090
4142
  getAllDependencyEdges,
4091
4143
  getChildren,
@@ -4099,6 +4151,7 @@ export {
4099
4151
  isTaskParent,
4100
4152
  isToday,
4101
4153
  isWeekend,
4154
+ normalizeHierarchyTasks,
4102
4155
  parseUTCDate,
4103
4156
  pixelsToDate,
4104
4157
  recalculateIncomingLags,