ct-gantt-core 1.0.12 → 1.0.14

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.cjs CHANGED
@@ -22,12 +22,15 @@ var index_exports = {};
22
22
  __export(index_exports, {
23
23
  DAY_MS: () => DAY_MS,
24
24
  DEFAULT_HOUR_COLORS: () => DEFAULT_HOUR_COLORS,
25
+ DEFAULT_RESOURCE_COLORS: () => DEFAULT_RESOURCE_COLORS,
25
26
  DEFAULT_TASK_COLORS: () => DEFAULT_TASK_COLORS,
27
+ DEFAULT_WORKLOAD_COLORS: () => DEFAULT_WORKLOAD_COLORS,
26
28
  EDITOR_COLOR_OPTIONS: () => EDITOR_COLOR_OPTIONS,
27
29
  GanttEngine: () => GanttEngine,
28
30
  HOUR_MS: () => HOUR_MS,
29
31
  OWNER_COLOR_PALETTE: () => OWNER_COLOR_PALETTE,
30
32
  RESOURCE_COLOR_PALETTE: () => RESOURCE_COLOR_PALETTE,
33
+ RESOURCE_EDITOR_COLOR_OPTIONS: () => RESOURCE_EDITOR_COLOR_OPTIONS,
31
34
  addDays: () => addDays,
32
35
  addHours: () => addHours,
33
36
  addPlannedDuration: () => addPlannedDuration,
@@ -38,8 +41,10 @@ __export(index_exports, {
38
41
  computeLayout: () => computeLayout,
39
42
  computeResourceLayout: () => computeResourceLayout,
40
43
  computeTimeScale: () => computeTimeScale,
44
+ computeVisibleWindow: () => computeVisibleWindow,
41
45
  computeWorkload: () => computeWorkload,
42
46
  createGanttEngine: () => createGanttEngine,
47
+ dateExtent: () => dateExtent,
43
48
  defaultConfig: () => defaultConfig,
44
49
  diffDays: () => diffDays,
45
50
  diffHours: () => diffHours,
@@ -49,15 +54,18 @@ __export(index_exports, {
49
54
  hasTimeComponent: () => hasTimeComponent,
50
55
  inclusiveDays: () => inclusiveDays,
51
56
  isValidDate: () => isValidDate,
57
+ mergeGanttConfig: () => mergeGanttConfig,
52
58
  mergeTaskPatch: () => mergeTaskPatch,
53
59
  normalizeLinks: () => normalizeLinks,
54
60
  plannedDurationBetween: () => plannedDurationBetween,
61
+ resolveGanttConfig: () => resolveGanttConfig,
55
62
  resolveResourceColor: () => resolveResourceColor,
56
63
  resolveUsageColor: () => resolveUsageColor,
57
64
  resolveUsageTimes: () => resolveUsageTimes,
58
65
  resultInvalidDate: () => resultInvalidDate,
59
66
  scheduleByDependencies: () => scheduleByDependencies,
60
67
  shiftTask: () => shiftTask,
68
+ sliceRangeItems: () => sliceRangeItems,
61
69
  startOfDay: () => startOfDay,
62
70
  subtractPlannedDuration: () => subtractPlannedDuration,
63
71
  toDate: () => toDate,
@@ -67,41 +75,58 @@ module.exports = __toCommonJS(index_exports);
67
75
 
68
76
  // src/styles/colors.ts
69
77
  var DEFAULT_TASK_COLORS = {
70
- task: "#4d77b3",
71
- // 普通任务实际条
72
- summary: "#475467",
73
- // 阶段条
74
- milestone: "#b57e4a",
75
- // 里程碑菱形 / 参考线默认
76
- plan: "#cbd5e1",
77
- // 计划条外部底色
78
- progress: "#367d73"
79
- // 计划条内部进度色(任务未设置 planColor 时)
78
+ task: "#409EFF",
79
+ // 普通任务实际条 · Element 主色
80
+ summary: "#909399",
81
+ // 阶段条 · Element Info
82
+ milestone: "#E6A23C",
83
+ // 里程碑菱形 / 参考线默认 · Element Warning
84
+ plan: "#C6E2FF",
85
+ // 计划条外部底色 · 主色浅阶
86
+ progress: "#67C23A"
87
+ // 计划条内部进度色 · Element Success
80
88
  };
81
89
  var DEFAULT_HOUR_COLORS = {
82
- plan: "#cbd5e1",
83
- // 计划条外部底色
84
- progress: "#367d73",
85
- // 计划条内部进度色(任务未设置 planColor 时)
86
- milestone: "#b57e4a"
90
+ plan: "#409EFF",
91
+ // 小时视图只有计划条,用主色保证在白底网格上可见
92
+ progress: "#67C23A",
93
+ // 兼容保留,小时视图不再绘制进度填充
94
+ milestone: "#E6A23C"
87
95
  // 里程碑菱形 / 参考线默认
88
96
  };
89
- var RESOURCE_COLOR_PALETTE = ["#f10755", "#9b87c4", "#509b81", "#c18f67", "#5e7fb0"];
97
+ var DEFAULT_RESOURCE_COLORS = {
98
+ booking: "#409EFF",
99
+ assignment: "#909399"
100
+ };
101
+ var DEFAULT_WORKLOAD_COLORS = {
102
+ used: "#67C23A",
103
+ // 已排工时徽章 · Element Success
104
+ over: "#F56C6C",
105
+ // 超负荷徽章 / 超载面积条 · Element Danger
106
+ area: "#409EFF"
107
+ // capacity 模式容量面积条 · Element 主色
108
+ };
109
+ var RESOURCE_COLOR_PALETTE = [DEFAULT_RESOURCE_COLORS.booking];
110
+ var RESOURCE_EDITOR_COLOR_OPTIONS = [
111
+ "#409eff",
112
+ "#79bbff",
113
+ "#909399"
114
+ ];
90
115
  var EDITOR_COLOR_OPTIONS = [
91
- "#4d77b3",
92
- "#8f77c5",
93
- "#c16794",
94
- "#b57e4a",
95
- "#b3a24d",
96
- "#47ae8f",
97
- "#3f99a6",
98
- "#64748b"
116
+ "#409eff",
117
+ "#66b1ff",
118
+ "#67c23a",
119
+ "#e6a23c",
120
+ "#f56c6c",
121
+ "#909399",
122
+ "#9b87c4",
123
+ "#36cfc9"
99
124
  ];
100
- var OWNER_COLOR_PALETTE = ["#c2708b", "#9b87c4", "#509b81", "#c18f67", "#5e7fb0"];
125
+ var OWNER_COLOR_PALETTE = ["#409EFF", "#67C23A", "#E6A23C", "#F56C6C", "#909399"];
101
126
 
102
127
  // src/types/index.ts
103
128
  var defaultConfig = {
104
- viewMode: "month",
129
+ viewMode: "day",
105
130
  rowHeight: 44,
106
131
  columnWidth: 30,
107
132
  headerHeight: 50,
@@ -120,11 +145,16 @@ var defaultConfig = {
120
145
  showLinkRejectionNotice: true,
121
146
  virtualScroll: true,
122
147
  taskColors: { ...DEFAULT_TASK_COLORS },
148
+ resourceUsageColors: { ...DEFAULT_RESOURCE_COLORS },
149
+ workloadColors: { ...DEFAULT_WORKLOAD_COLORS },
123
150
  timeUnit: "day",
124
151
  hourWidth: 12,
125
152
  autoSchedule: true,
126
153
  editable: true,
127
- enableSelection: false
154
+ enableSelection: false,
155
+ showAddTaskColumn: true,
156
+ addTaskAs: "child",
157
+ showAddUsageColumn: true
128
158
  };
129
159
 
130
160
  // src/services/checkCyclicDependency.ts
@@ -234,12 +264,21 @@ function flattenTasks(tasks, collapsedIds = /* @__PURE__ */ new Set()) {
234
264
  const children = /* @__PURE__ */ new Map();
235
265
  for (const task of tasks) {
236
266
  const parentId = task.parentId ?? null;
237
- const bucket = children.get(parentId) ?? [];
238
- bucket.push(task);
239
- children.set(parentId, bucket);
267
+ const bucket = children.get(parentId);
268
+ if (bucket) {
269
+ bucket.push(task);
270
+ } else {
271
+ children.set(parentId, [task]);
272
+ }
240
273
  }
241
274
  const flattened = [];
275
+ const visited = /* @__PURE__ */ new Set();
276
+ const taskIds = new Set(tasks.map((task) => task.id));
242
277
  const visit = (task, depth) => {
278
+ if (visited.has(task.id)) {
279
+ return;
280
+ }
281
+ visited.add(task.id);
243
282
  const childTasks = children.get(task.id) ?? [];
244
283
  const collapsed = collapsedIds.has(task.id);
245
284
  flattened.push({
@@ -258,6 +297,12 @@ function flattenTasks(tasks, collapsedIds = /* @__PURE__ */ new Set()) {
258
297
  for (const root of children.get(null) ?? []) {
259
298
  visit(root, 0);
260
299
  }
300
+ for (const task of tasks) {
301
+ if (visited.has(task.id)) continue;
302
+ const parentId = task.parentId ?? null;
303
+ if (parentId && taskIds.has(parentId)) continue;
304
+ visit(task, 0);
305
+ }
261
306
  return flattened;
262
307
  }
263
308
 
@@ -359,6 +404,18 @@ function isValidDate(value) {
359
404
  const date = value instanceof Date ? value : new Date(value);
360
405
  return !Number.isNaN(date.getTime());
361
406
  }
407
+ function dateExtent(dates) {
408
+ let min = Number.POSITIVE_INFINITY;
409
+ let max = Number.NEGATIVE_INFINITY;
410
+ for (const value of dates) {
411
+ const time = typeof value === "number" ? value : value.getTime();
412
+ if (!Number.isFinite(time)) continue;
413
+ if (time < min) min = time;
414
+ if (time > max) max = time;
415
+ }
416
+ if (!Number.isFinite(min) || !Number.isFinite(max)) return void 0;
417
+ return { start: new Date(min), end: new Date(max) };
418
+ }
362
419
  function formatDate(date) {
363
420
  const value = toDate(date);
364
421
  const year = value.getFullYear();
@@ -463,6 +520,51 @@ function computeHourScale(start, end, hourWidth) {
463
520
  return { days, hours, start: rangeStart, end: rangeEnd };
464
521
  }
465
522
 
523
+ // src/services/computeVisibleWindow.ts
524
+ function computeVisibleWindow(scroll, viewportSize, itemSize, itemCount, overscan = 8) {
525
+ if (itemCount <= 0 || itemSize <= 0) {
526
+ return { start: 0, end: -1, before: 0, after: 0 };
527
+ }
528
+ if (viewportSize <= 0) {
529
+ return { start: 0, end: itemCount - 1, before: 0, after: 0 };
530
+ }
531
+ const start = Math.max(0, Math.floor(scroll / itemSize) - overscan);
532
+ const end = Math.min(
533
+ itemCount - 1,
534
+ Math.ceil((scroll + viewportSize) / itemSize) + overscan
535
+ );
536
+ return {
537
+ start,
538
+ end,
539
+ before: start * itemSize,
540
+ after: Math.max(0, (itemCount - end - 1) * itemSize)
541
+ };
542
+ }
543
+ function sliceRangeItems(items, scrollLeft, viewportWidth, overscanPx = 320) {
544
+ if (viewportWidth <= 0 || items.length === 0) {
545
+ return items;
546
+ }
547
+ const min = scrollLeft - overscanPx;
548
+ const max = scrollLeft + viewportWidth + overscanPx;
549
+ return items.filter((item) => item.left + item.width >= min && item.left <= max);
550
+ }
551
+
552
+ // src/utils/mergeConfig.ts
553
+ function mergeGanttConfig(base, patch = {}) {
554
+ return {
555
+ ...base,
556
+ ...patch,
557
+ taskColors: { ...base.taskColors, ...patch.taskColors },
558
+ columnWidths: { ...base.columnWidths, ...patch.columnWidths },
559
+ resourceColors: { ...base.resourceColors, ...patch.resourceColors },
560
+ resourceUsageColors: { ...base.resourceUsageColors, ...patch.resourceUsageColors },
561
+ workloadColors: { ...base.workloadColors, ...patch.workloadColors }
562
+ };
563
+ }
564
+ function resolveGanttConfig(patch = {}) {
565
+ return mergeGanttConfig(defaultConfig, patch);
566
+ }
567
+
466
568
  // src/engines/scheduling.ts
467
569
  function scheduleByDependencies(tasks, links) {
468
570
  const cycle = checkCyclicDependency(links);
@@ -491,8 +593,18 @@ function scheduleByDependencies(tasks, links) {
491
593
  }
492
594
  };
493
595
  }
494
- incoming.set(link.targetId, [...incoming.get(link.targetId) ?? [], link]);
495
- outgoing.set(link.sourceId, [...outgoing.get(link.sourceId) ?? [], link]);
596
+ const incomingList = incoming.get(link.targetId);
597
+ if (incomingList) {
598
+ incomingList.push(link);
599
+ } else {
600
+ incoming.set(link.targetId, [link]);
601
+ }
602
+ const outgoingList = outgoing.get(link.sourceId);
603
+ if (outgoingList) {
604
+ outgoingList.push(link);
605
+ } else {
606
+ outgoing.set(link.sourceId, [link]);
607
+ }
496
608
  }
497
609
  const ordered = topologicalOrder(tasks.map((task) => task.id), links);
498
610
  for (const taskId of ordered) {
@@ -550,12 +662,20 @@ function topologicalOrder(ids, links) {
550
662
  const outgoing = /* @__PURE__ */ new Map();
551
663
  for (const link of links) {
552
664
  indegree.set(link.targetId, (indegree.get(link.targetId) ?? 0) + 1);
553
- outgoing.set(link.sourceId, [...outgoing.get(link.sourceId) ?? [], link.targetId]);
665
+ const targets = outgoing.get(link.sourceId);
666
+ if (targets) {
667
+ targets.push(link.targetId);
668
+ } else {
669
+ outgoing.set(link.sourceId, [link.targetId]);
670
+ }
554
671
  }
555
672
  const queue = ids.filter((id) => (indegree.get(id) ?? 0) === 0);
556
673
  const ordered = [];
557
- while (queue.length) {
558
- const current = queue.shift();
674
+ let cursor = 0;
675
+ while (cursor < queue.length) {
676
+ const current = queue[cursor];
677
+ cursor += 1;
678
+ if (!current) continue;
559
679
  ordered.push(current);
560
680
  for (const target of outgoing.get(current) ?? []) {
561
681
  indegree.set(target, (indegree.get(target) ?? 1) - 1);
@@ -590,7 +710,7 @@ function shiftTask(task, start) {
590
710
 
591
711
  // src/engines/computeLayout.ts
592
712
  function computeLayout(tasks, links, config, collapsedIds = /* @__PURE__ */ new Set(), viewport) {
593
- const mergedConfig = { ...defaultConfig, ...config };
713
+ const mergedConfig = resolveGanttConfig(config);
594
714
  for (const task of tasks) {
595
715
  if (!isValidDate(task.actual.start) || !isValidDate(task.actual.end)) {
596
716
  return {
@@ -608,7 +728,7 @@ function computeLayout(tasks, links, config, collapsedIds = /* @__PURE__ */ new
608
728
  return scheduled;
609
729
  }
610
730
  const flatTasks = flattenTasks(scheduled.data, collapsedIds);
611
- const firstDate = mergedConfig.visibleRange ? toDate(mergedConfig.visibleRange.start) : minDate(scheduled.data.map((task) => toDate(task.actual.start)));
731
+ const firstDate = mergedConfig.visibleRange ? toDate(mergedConfig.visibleRange.start) : dateExtent(scheduled.data.map((task) => toDate(task.actual.start)))?.start ?? toDate(/* @__PURE__ */ new Date());
612
732
  const visibleStart = viewport ? Math.max(0, Math.floor(viewport.scrollTop / mergedConfig.rowHeight) - 8) : 0;
613
733
  const visibleEnd = viewport ? Math.ceil((viewport.scrollTop + viewport.clientHeight) / mergedConfig.rowHeight) + 8 : Number.POSITIVE_INFINITY;
614
734
  const layouts = flatTasks.filter((flat) => flat.rowIndex >= visibleStart && flat.rowIndex <= visibleEnd).map((flat) => {
@@ -627,9 +747,6 @@ function computeLayout(tasks, links, config, collapsedIds = /* @__PURE__ */ new
627
747
  });
628
748
  return { ok: true, data: layouts };
629
749
  }
630
- function minDate(dates) {
631
- return new Date(Math.min(...dates.map((date) => date.getTime())));
632
- }
633
750
 
634
751
  // src/engines/computeImpact.ts
635
752
  function computeImpact(taskId, patch, tasks, links, config) {
@@ -718,8 +835,14 @@ function resolveResourceColor(resource, resourceColors) {
718
835
  const source = resource.name || resource.id;
719
836
  return RESOURCE_COLOR_PALETTE[colorHash(source) % RESOURCE_COLOR_PALETTE.length];
720
837
  }
721
- function resolveUsageColor(usage, resource, resourceColors) {
722
- return usage.color || resolveResourceColor(resource, resourceColors);
838
+ function resolveUsageColor(usage, resource, resourceColors, resourceUsageColors) {
839
+ if (usage.color) {
840
+ return usage.color;
841
+ }
842
+ if (resource.color || resourceColors?.[resource.id]) {
843
+ return resolveResourceColor(resource, resourceColors);
844
+ }
845
+ return usage.type === "assignment" ? resourceUsageColors?.assignment ?? DEFAULT_RESOURCE_COLORS.assignment : resourceUsageColors?.booking ?? DEFAULT_RESOURCE_COLORS.booking;
723
846
  }
724
847
  function resolveUsageTimes(usage, timeUnit) {
725
848
  if (timeUnit === "hour") {
@@ -730,7 +853,7 @@ function resolveUsageTimes(usage, timeUnit) {
730
853
  return { start: toDate(usage.start), end: toDate(usage.end) };
731
854
  }
732
855
  function computeResourceLayout(resources, usages, config, viewport) {
733
- const mergedConfig = { ...defaultConfig, ...config };
856
+ const mergedConfig = resolveGanttConfig(config);
734
857
  const timeUnit = mergedConfig.timeUnit ?? "day";
735
858
  const hourMode = timeUnit === "hour";
736
859
  const hourW = mergedConfig.hourWidth ?? 12;
@@ -763,7 +886,12 @@ function computeResourceLayout(resources, usages, config, viewport) {
763
886
  const resourceById = new Map(resources.map((resource) => [resource.id, resource]));
764
887
  const usagesByResource = /* @__PURE__ */ new Map();
765
888
  for (const usage of usages) {
766
- usagesByResource.set(usage.resourceId, [...usagesByResource.get(usage.resourceId) ?? [], usage]);
889
+ const grouped = usagesByResource.get(usage.resourceId);
890
+ if (grouped) {
891
+ grouped.push(usage);
892
+ } else {
893
+ usagesByResource.set(usage.resourceId, [usage]);
894
+ }
767
895
  }
768
896
  const rows = [];
769
897
  const usageLayouts = [];
@@ -808,8 +936,8 @@ function computeResourceLayout(resources, usages, config, viewport) {
808
936
  const visibleStart = viewport ? Math.max(0, Math.floor(viewport.scrollTop / mergedConfig.rowHeight) - 8) : 0;
809
937
  const visibleEnd = viewport ? Math.ceil((viewport.scrollTop + viewport.clientHeight) / mergedConfig.rowHeight) + 8 : Number.POSITIVE_INFINITY;
810
938
  const firstDate = hourMode ? startOfDay(
811
- mergedConfig.visibleRange ? toDateTime(mergedConfig.visibleRange.start) : usages.length ? minDate2(usages.map((usage) => resolveUsageTimes(usage, "hour").start)) : toDateTime(/* @__PURE__ */ new Date())
812
- ) : mergedConfig.visibleRange ? toDate(mergedConfig.visibleRange.start) : usages.length ? minDate2(usages.map((usage) => toDate(usage.start))) : toDate(/* @__PURE__ */ new Date());
939
+ mergedConfig.visibleRange ? toDateTime(mergedConfig.visibleRange.start) : dateExtent(usages.map((usage) => resolveUsageTimes(usage, "hour").start))?.start ?? toDateTime(/* @__PURE__ */ new Date())
940
+ ) : mergedConfig.visibleRange ? toDate(mergedConfig.visibleRange.start) : dateExtent(usages.map((usage) => toDate(usage.start)))?.start ?? toDate(/* @__PURE__ */ new Date());
813
941
  for (const row of rows) {
814
942
  if (row.rowIndex < visibleStart || row.rowIndex > visibleEnd) {
815
943
  continue;
@@ -846,16 +974,13 @@ function computeResourceLayout(resources, usages, config, viewport) {
846
974
  function isLaneFree(laneEnd, start, hourMode) {
847
975
  return hourMode ? diffHours(laneEnd, start) >= 0 : diffDays(laneEnd, start) > 0;
848
976
  }
849
- function minDate2(dates) {
850
- return new Date(Math.min(...dates.map((date) => date.getTime())));
851
- }
852
977
 
853
978
  // src/engines/computeWorkload.ts
854
979
  function computeWorkload(tasks, people, departments = [], range) {
855
980
  const dated = range ?? inferRange(tasks);
856
981
  if (!dated) return { dates: [], departments: [], ungrouped: [] };
857
982
  const dates = datesBetween(dated.start, dated.end);
858
- const dateSet = new Set(dates);
983
+ const dateIndex = new Map(dates.map((date, index) => [date, index]));
859
984
  const rows = new Map(people.map((person) => [person.id, createPerson(person, dates)]));
860
985
  for (const task of tasks) {
861
986
  if (task.type === "summary" || task.type === "milestone") continue;
@@ -865,21 +990,32 @@ function computeWorkload(tasks, people, departments = [], range) {
865
990
  for (const personId of ids) {
866
991
  const row = rows.get(personId);
867
992
  if (!row) continue;
868
- for (const [date, hours] of Object.entries(values)) if (dateSet.has(date)) row.days.find((day) => day.date === date).hours += hours;
993
+ for (const [date, hours] of Object.entries(values)) {
994
+ const index = dateIndex.get(date);
995
+ if (index !== void 0) row.days[index].hours += hours;
996
+ }
869
997
  }
870
998
  }
871
999
  for (const row of rows.values()) finalize(row);
872
1000
  const grouped = /* @__PURE__ */ new Map();
873
1001
  const ungrouped = [];
874
- for (const row of rows.values()) (row.person.departmentId ? grouped.get(row.person.departmentId) ?? (grouped.set(row.person.departmentId, []), grouped.get(row.person.departmentId)) : ungrouped).push(row);
1002
+ for (const row of rows.values()) {
1003
+ if (row.person.departmentId) {
1004
+ const members = grouped.get(row.person.departmentId);
1005
+ if (members) members.push(row);
1006
+ else grouped.set(row.person.departmentId, [row]);
1007
+ } else {
1008
+ ungrouped.push(row);
1009
+ }
1010
+ }
875
1011
  const departmentMap = new Map(departments.map((item) => [item.id, item]));
876
1012
  const result = [...grouped].map(([id, members]) => aggregateDepartment(departmentMap.get(id) ?? { id, name: id }, members, dates));
877
1013
  return { dates, departments: result, ungrouped };
878
1014
  }
879
1015
  function inferRange(tasks) {
880
1016
  if (!tasks.length) return void 0;
881
- const dates = tasks.flatMap((t) => [toDate(t.plan.start), toDate(t.plan.end)]);
882
- return { start: new Date(Math.min(...dates.map((d) => d.getTime()))), end: new Date(Math.max(...dates.map((d) => d.getTime()))) };
1017
+ const extent = dateExtent(tasks.flatMap((task) => [toDate(task.plan.start), toDate(task.plan.end)]));
1018
+ return extent ? { start: extent.start, end: extent.end } : void 0;
883
1019
  }
884
1020
  function datesBetween(start, end) {
885
1021
  const values = [];
@@ -952,7 +1088,7 @@ var GanttEngine = class {
952
1088
  constructor(options = {}) {
953
1089
  this.tasks = options.tasks ? options.tasks.map((task) => ({ ...task })) : [];
954
1090
  this.links = options.links ? options.links.map((link) => ({ ...link })) : [];
955
- this.config = { ...defaultConfig, ...options.config };
1091
+ this.config = mergeGanttConfig({ ...defaultConfig }, { ...options.config });
956
1092
  this.container = options.container ?? null;
957
1093
  this.collapsedIds = new Set(options.collapsedIds ?? []);
958
1094
  this.markers = options.markers ? options.markers.map((marker) => ({ ...marker })) : [];
@@ -986,22 +1122,22 @@ var GanttEngine = class {
986
1122
  setTasks(tasks) {
987
1123
  this.assertNotDestroyed();
988
1124
  this.tasks = tasks.map((task) => ({ ...task }));
989
- this.emit("taskschange", this.getTasks());
1125
+ this.emit("taskschange", this.tasks);
990
1126
  }
991
1127
  setLinks(links) {
992
1128
  this.assertNotDestroyed();
993
1129
  this.links = links.map((link) => ({ ...link }));
994
- this.emit("linkschange", this.getLinks());
1130
+ this.emit("linkschange", this.links);
995
1131
  }
996
1132
  setMarkers(markers) {
997
1133
  this.assertNotDestroyed();
998
1134
  this.markers = markers.map((marker) => ({ ...marker }));
999
- this.emit("markerschange", this.getMarkers());
1135
+ this.emit("markerschange", this.markers);
1000
1136
  }
1001
1137
  /** 合并配置 patch,等价于 setConfig(mergeConfig(patch)) */
1002
1138
  mergeConfig(patch) {
1003
1139
  this.assertNotDestroyed();
1004
- this.config = { ...this.config, ...patch };
1140
+ this.config = mergeGanttConfig(this.config, patch);
1005
1141
  this.emit("configchange", this.getConfig());
1006
1142
  }
1007
1143
  setConfig(config) {
@@ -1121,10 +1257,8 @@ var GanttEngine = class {
1121
1257
  const today = toDate(/* @__PURE__ */ new Date());
1122
1258
  return { start: today, end: addDays(today, 30) };
1123
1259
  }
1124
- return {
1125
- start: new Date(Math.min(...dates.map((d) => d.getTime()))),
1126
- end: new Date(Math.max(...dates.map((d) => d.getTime())))
1127
- };
1260
+ const extent = dateExtent(dates);
1261
+ return extent ?? { start: dates[0], end: dates[0] };
1128
1262
  }
1129
1263
  getTimeScale() {
1130
1264
  const range = this.getDateRange();
@@ -1289,12 +1423,15 @@ function createGanttEngine(options = {}) {
1289
1423
  0 && (module.exports = {
1290
1424
  DAY_MS,
1291
1425
  DEFAULT_HOUR_COLORS,
1426
+ DEFAULT_RESOURCE_COLORS,
1292
1427
  DEFAULT_TASK_COLORS,
1428
+ DEFAULT_WORKLOAD_COLORS,
1293
1429
  EDITOR_COLOR_OPTIONS,
1294
1430
  GanttEngine,
1295
1431
  HOUR_MS,
1296
1432
  OWNER_COLOR_PALETTE,
1297
1433
  RESOURCE_COLOR_PALETTE,
1434
+ RESOURCE_EDITOR_COLOR_OPTIONS,
1298
1435
  addDays,
1299
1436
  addHours,
1300
1437
  addPlannedDuration,
@@ -1305,8 +1442,10 @@ function createGanttEngine(options = {}) {
1305
1442
  computeLayout,
1306
1443
  computeResourceLayout,
1307
1444
  computeTimeScale,
1445
+ computeVisibleWindow,
1308
1446
  computeWorkload,
1309
1447
  createGanttEngine,
1448
+ dateExtent,
1310
1449
  defaultConfig,
1311
1450
  diffDays,
1312
1451
  diffHours,
@@ -1316,15 +1455,18 @@ function createGanttEngine(options = {}) {
1316
1455
  hasTimeComponent,
1317
1456
  inclusiveDays,
1318
1457
  isValidDate,
1458
+ mergeGanttConfig,
1319
1459
  mergeTaskPatch,
1320
1460
  normalizeLinks,
1321
1461
  plannedDurationBetween,
1462
+ resolveGanttConfig,
1322
1463
  resolveResourceColor,
1323
1464
  resolveUsageColor,
1324
1465
  resolveUsageTimes,
1325
1466
  resultInvalidDate,
1326
1467
  scheduleByDependencies,
1327
1468
  shiftTask,
1469
+ sliceRangeItems,
1328
1470
  startOfDay,
1329
1471
  subtractPlannedDuration,
1330
1472
  toDate,