ct-gantt-core 1.0.5 → 1.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,80 +1,83 @@
1
- # ct-gantt-core
2
-
3
- 框架无关的甘特图数据、布局、依赖排程和命令式引擎。该包不包含界面,可用于 Vue、React、原生 JavaScript、服务端计算或自定义渲染器。
4
-
5
- ## 安装
6
-
7
- ```bash
8
- pnpm add ct-gantt-core
9
- ```
10
-
11
- 也可以使用 `npm install ct-gantt-core` 或 `yarn add ct-gantt-core`。
12
-
13
- ## 最小示例
14
-
15
- ```ts
16
- import { GanttEngine, type GanttTask } from "ct-gantt-core"
17
-
18
- const tasks: GanttTask[] = [
19
- {
20
- id: "task-1",
21
- name: "需求分析",
22
- type: "task",
23
- plan: { start: "2026-07-01", end: "2026-07-05" },
24
- actual: { start: "2026-07-01", end: "2026-07-06", progress: 60 }
25
- }
26
- ]
27
-
28
- const engine = new GanttEngine({
29
- tasks,
30
- config: { viewMode: "day", columnWidth: 30 }
31
- })
32
-
33
- const layout = engine.getLayout()
34
- if (layout.ok) {
35
- console.log(layout.data)
36
- }
37
-
38
- engine.setTask("task-1", { progress: 80 })
39
- engine.destroy()
40
- ```
41
-
42
- ## 依赖排程
43
-
44
- ```ts
45
- import { scheduleByDependencies, type GanttLink } from "ct-gantt-core"
46
-
47
- const links: GanttLink[] = [
48
- { id: "design-to-dev", sourceId: "design", targetId: "dev", type: "FS" }
49
- ]
50
-
51
- const result = scheduleByDependencies(tasks, links)
52
- if (result.ok) {
53
- console.log(result.data)
54
- }
55
- ```
56
-
57
- 支持 `FS`、`SS`、`FF`、`SF` 四种依赖类型,以及自然日或工作日间隔。
58
-
59
- ## 主要导出
60
-
61
- | API | 用途 |
62
- | --- | --- |
63
- | `GanttEngine` | 管理任务、依赖、折叠、预览、布局和视口命令 |
64
- | `computeLayout` | 计算任务条位置和尺寸 |
65
- | `computeTimeScale` | 计算时间刻度 |
66
- | `scheduleByDependencies` | 按依赖关系调整任务日期 |
67
- | `computeImpact` | 分析任务变更的影响和约束冲突 |
68
- | `checkCyclicDependency` | 检查循环依赖 |
69
- | `normalizeLinks` | 统一任务内依赖与独立依赖数据 |
70
- | `flattenTasks` | 将阶段树转换为可渲染行 |
71
- | `toDate`、`addDays`、`diffDays` | 日期工具 |
72
-
73
- ## 数据说明
74
-
75
- - `plan` 表示计划日期。
76
- - `actual` 表示实际日期和完成进度。
77
- - `summary` 表示阶段,`task` 表示普通任务,`milestone` 表示任务型里程碑。
78
- - Core 不负责绘制界面;需要现成 Vue 界面时请安装 `ct-gantt-vue`。
79
-
80
- 完整类型、配置和示例请查看[项目文档](https://github.com/moonlight-219/ganttu#readme)。
1
+ # ct-gantt-core
2
+
3
+ 框架无关的甘特图数据、布局、依赖排程和命令式引擎。该包不包含界面,可用于 Vue、React、原生 JavaScript、服务端计算或自定义渲染器。
4
+
5
+ ## 安装
6
+
7
+ ```bash
8
+ pnpm add ct-gantt-core
9
+ ```
10
+
11
+ 也可以使用 `npm install ct-gantt-core` 或 `yarn add ct-gantt-core`。
12
+
13
+ ## 最小示例
14
+
15
+ ```ts
16
+ import { GanttEngine, type GanttTask } from "ct-gantt-core"
17
+
18
+ const tasks: GanttTask[] = [
19
+ {
20
+ id: "task-1",
21
+ name: "需求分析",
22
+ type: "task",
23
+ plan: { start: "2026-07-01", end: "2026-07-05" },
24
+ actual: { start: "2026-07-01", end: "2026-07-06", progress: 60 }
25
+ }
26
+ ]
27
+
28
+ const engine = new GanttEngine({
29
+ tasks,
30
+ config: { viewMode: "day", columnWidth: 30 }
31
+ })
32
+
33
+ const layout = engine.getLayout()
34
+ if (layout.ok) {
35
+ console.log(layout.data)
36
+ }
37
+
38
+ engine.setTask("task-1", { progress: 80 })
39
+ engine.destroy()
40
+ ```
41
+
42
+ ## 依赖排程
43
+
44
+ ```ts
45
+ import { scheduleByDependencies, type GanttLink } from "ct-gantt-core"
46
+
47
+ const links: GanttLink[] = [
48
+ { id: "design-to-dev", sourceId: "design", targetId: "dev", type: "FS" }
49
+ ]
50
+
51
+ const result = scheduleByDependencies(tasks, links)
52
+ if (result.ok) {
53
+ console.log(result.data)
54
+ }
55
+ ```
56
+
57
+ 支持 `FS`、`SS`、`FF`、`SF` 四种依赖类型,以及自然日或工作日间隔。
58
+
59
+ ## 主要导出
60
+
61
+ | API | 用途 |
62
+ | --- | --- |
63
+ | `GanttEngine` | 管理任务、依赖、折叠、预览、布局和视口命令 |
64
+ | `computeLayout` | 计算任务条位置和尺寸 |
65
+ | `computeTimeScale` | 计算时间刻度(day/week/month/quarter/year) |
66
+ | `computeHourScale` | 计算小时级时间刻度(每天 24 个小时列,顶行日期 + 底部整点小时) |
67
+ | `computeResourceLayout` | 资源视图布局:资源行 + 占用色条(支持 day/hour 粒度与车道堆叠) |
68
+ | `resolveUsageTimes` | 将资源占用解析为布局用起止时间(hour 粒度下纯日期占用含结束日整天) |
69
+ | `scheduleByDependencies` | 按依赖关系调整任务日期 |
70
+ | `computeImpact` | 分析任务变更的影响和约束冲突 |
71
+ | `checkCyclicDependency` | 检查循环依赖 |
72
+ | `normalizeLinks` | 统一任务内依赖与独立依赖数据 |
73
+ | `flattenTasks` | 将阶段树转换为可渲染行 |
74
+ | `toDate`、`toDateTime`、`addDays`、`addHours`、`diffDays`、`diffHours`、`formatDate`、`formatDateTime` | 日期工具(`toDateTime`/`diffHours` 保留时间,用于小时级计算) |
75
+
76
+ ## 数据说明
77
+
78
+ - `plan` 表示计划日期。
79
+ - `actual` 表示实际日期和完成进度。
80
+ - `summary` 表示阶段,`task` 表示普通任务,`milestone` 表示任务型里程碑。
81
+ - Core 不负责绘制界面;需要现成 Vue 界面时请安装 `ct-gantt-vue`。
82
+
83
+ 完整类型、配置和示例请查看[项目文档](https://github.com/moonlight-219/ganttu#readme)。
package/dist/index.cjs CHANGED
@@ -21,29 +21,79 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
21
21
  var index_exports = {};
22
22
  __export(index_exports, {
23
23
  DAY_MS: () => DAY_MS,
24
+ DEFAULT_HOUR_COLORS: () => DEFAULT_HOUR_COLORS,
25
+ DEFAULT_TASK_COLORS: () => DEFAULT_TASK_COLORS,
26
+ EDITOR_COLOR_OPTIONS: () => EDITOR_COLOR_OPTIONS,
24
27
  GanttEngine: () => GanttEngine,
28
+ HOUR_MS: () => HOUR_MS,
29
+ OWNER_COLOR_PALETTE: () => OWNER_COLOR_PALETTE,
30
+ RESOURCE_COLOR_PALETTE: () => RESOURCE_COLOR_PALETTE,
25
31
  addDays: () => addDays,
32
+ addHours: () => addHours,
26
33
  checkCyclicDependency: () => checkCyclicDependency,
34
+ computeHourScale: () => computeHourScale,
27
35
  computeImpact: () => computeImpact,
28
36
  computeLayout: () => computeLayout,
37
+ computeResourceLayout: () => computeResourceLayout,
29
38
  computeTimeScale: () => computeTimeScale,
30
39
  createGanttEngine: () => createGanttEngine,
31
40
  defaultConfig: () => defaultConfig,
32
41
  diffDays: () => diffDays,
42
+ diffHours: () => diffHours,
33
43
  flattenTasks: () => flattenTasks,
34
44
  formatDate: () => formatDate,
45
+ formatDateTime: () => formatDateTime,
46
+ hasTimeComponent: () => hasTimeComponent,
35
47
  inclusiveDays: () => inclusiveDays,
36
48
  isValidDate: () => isValidDate,
37
49
  mergeTaskPatch: () => mergeTaskPatch,
38
50
  normalizeLinks: () => normalizeLinks,
51
+ resolveResourceColor: () => resolveResourceColor,
52
+ resolveUsageColor: () => resolveUsageColor,
53
+ resolveUsageTimes: () => resolveUsageTimes,
39
54
  resultInvalidDate: () => resultInvalidDate,
40
55
  scheduleByDependencies: () => scheduleByDependencies,
41
56
  shiftTask: () => shiftTask,
42
57
  startOfDay: () => startOfDay,
43
- toDate: () => toDate
58
+ toDate: () => toDate,
59
+ toDateTime: () => toDateTime
44
60
  });
45
61
  module.exports = __toCommonJS(index_exports);
46
62
 
63
+ // src/styles/colors.ts
64
+ var DEFAULT_TASK_COLORS = {
65
+ task: "#4d77b3",
66
+ // 普通任务实际条
67
+ summary: "#475467",
68
+ // 阶段条
69
+ milestone: "#b57e4a",
70
+ // 里程碑菱形 / 参考线默认
71
+ plan: "#cbd5e1",
72
+ // 计划条外部底色
73
+ progress: "#367d73"
74
+ // 计划条内部进度色(任务未设置 planColor 时)
75
+ };
76
+ var DEFAULT_HOUR_COLORS = {
77
+ plan: "#cbd5e1",
78
+ // 计划条外部底色
79
+ progress: "#367d73",
80
+ // 计划条内部进度色(任务未设置 planColor 时)
81
+ milestone: "#b57e4a"
82
+ // 里程碑菱形 / 参考线默认
83
+ };
84
+ var RESOURCE_COLOR_PALETTE = ["#f10755", "#9b87c4", "#509b81", "#c18f67", "#5e7fb0"];
85
+ var EDITOR_COLOR_OPTIONS = [
86
+ "#4d77b3",
87
+ "#8f77c5",
88
+ "#c16794",
89
+ "#b57e4a",
90
+ "#b3a24d",
91
+ "#47ae8f",
92
+ "#3f99a6",
93
+ "#64748b"
94
+ ];
95
+ var OWNER_COLOR_PALETTE = ["#c2708b", "#9b87c4", "#509b81", "#c18f67", "#5e7fb0"];
96
+
47
97
  // src/types/index.ts
48
98
  var defaultConfig = {
49
99
  viewMode: "month",
@@ -64,13 +114,9 @@ var defaultConfig = {
64
114
  enableLinkCreation: true,
65
115
  showLinkRejectionNotice: true,
66
116
  virtualScroll: true,
67
- taskColors: {
68
- task: "#2563eb",
69
- summary: "#475467",
70
- milestone: "#d97706",
71
- plan: "#cbd5e1",
72
- progress: "#0f766e"
73
- },
117
+ taskColors: { ...DEFAULT_TASK_COLORS },
118
+ timeUnit: "day",
119
+ hourWidth: 12,
74
120
  autoSchedule: true,
75
121
  editable: true
76
122
  };
@@ -211,6 +257,7 @@ function flattenTasks(tasks, collapsedIds = /* @__PURE__ */ new Set()) {
211
257
 
212
258
  // src/utils/date.ts
213
259
  var DAY_MS = 24 * 60 * 60 * 1e3;
260
+ var HOUR_MS = 60 * 60 * 1e3;
214
261
  function toDate(value) {
215
262
  if (value instanceof Date) {
216
263
  return startOfDay(value);
@@ -221,6 +268,21 @@ function toDate(value) {
221
268
  }
222
269
  return startOfDay(new Date(value));
223
270
  }
271
+ function hasTimeComponent(value) {
272
+ return typeof value === "string" && /T\d|:\d/.test(value);
273
+ }
274
+ function toDateTime(value) {
275
+ if (value instanceof Date) {
276
+ return new Date(value.getTime());
277
+ }
278
+ if (hasTimeComponent(value)) {
279
+ const date = new Date(value.replace(" ", "T"));
280
+ if (!Number.isNaN(date.getTime())) {
281
+ return date;
282
+ }
283
+ }
284
+ return toDate(value);
285
+ }
224
286
  function startOfDay(date) {
225
287
  return new Date(date.getFullYear(), date.getMonth(), date.getDate());
226
288
  }
@@ -232,6 +294,12 @@ function addDays(date, days) {
232
294
  function diffDays(start, end) {
233
295
  return Math.round((toDate(end).getTime() - toDate(start).getTime()) / DAY_MS);
234
296
  }
297
+ function addHours(date, hours) {
298
+ return new Date(toDateTime(date).getTime() + hours * HOUR_MS);
299
+ }
300
+ function diffHours(start, end) {
301
+ return (toDateTime(end).getTime() - toDateTime(start).getTime()) / HOUR_MS;
302
+ }
235
303
  function inclusiveDays(start, end) {
236
304
  return Math.max(0, diffDays(start, end) + 1);
237
305
  }
@@ -246,6 +314,12 @@ function formatDate(date) {
246
314
  const day = String(value.getDate()).padStart(2, "0");
247
315
  return `${year}-${month}-${day}`;
248
316
  }
317
+ function formatDateTime(date) {
318
+ const value = toDateTime(date);
319
+ const hours = String(value.getHours()).padStart(2, "0");
320
+ const minutes = String(value.getMinutes()).padStart(2, "0");
321
+ return `${formatDate(value)} ${hours}:${minutes}`;
322
+ }
249
323
  function resultInvalidDate(message, details) {
250
324
  return {
251
325
  ok: false,
@@ -309,6 +383,34 @@ function nextUnit(date, viewMode) {
309
383
  return addDays(date, 1);
310
384
  }
311
385
 
386
+ // src/services/computeHourScale.ts
387
+ function computeHourScale(start, end, hourWidth) {
388
+ const rangeStart = startOfDay(start);
389
+ const rangeEnd = startOfDay(end);
390
+ const totalDays = Math.max(1, inclusiveDays(rangeStart, rangeEnd));
391
+ const days = [];
392
+ const hours = [];
393
+ for (let d = 0; d < totalDays; d += 1) {
394
+ const dayStart = addDays(rangeStart, d);
395
+ days.push({
396
+ start: dayStart,
397
+ end: addHours(dayStart, 24),
398
+ left: d * 24 * hourWidth,
399
+ width: 24 * hourWidth
400
+ });
401
+ for (let h = 0; h < 24; h += 1) {
402
+ const hourStart = addHours(dayStart, h);
403
+ hours.push({
404
+ start: hourStart,
405
+ end: addHours(hourStart, 1),
406
+ left: (d * 24 + h) * hourWidth,
407
+ width: hourWidth
408
+ });
409
+ }
410
+ }
411
+ return { days, hours, start: rangeStart, end: rangeEnd };
412
+ }
413
+
312
414
  // src/engines/scheduling.ts
313
415
  function scheduleByDependencies(tasks, links) {
314
416
  const cycle = checkCyclicDependency(links);
@@ -550,6 +652,152 @@ function computeImpact(taskId, patch, tasks, links, config) {
550
652
  return { ok: true, data: { changed, conflicts } };
551
653
  }
552
654
 
655
+ // src/engines/computeResourceLayout.ts
656
+ function colorHash(source) {
657
+ return [...source].reduce((sum, char) => sum + (char.codePointAt(0) ?? 0), 0);
658
+ }
659
+ function resolveResourceColor(resource, resourceColors) {
660
+ if (resource.color) {
661
+ return resource.color;
662
+ }
663
+ if (resourceColors?.[resource.id]) {
664
+ return resourceColors[resource.id];
665
+ }
666
+ const source = resource.name || resource.id;
667
+ return RESOURCE_COLOR_PALETTE[colorHash(source) % RESOURCE_COLOR_PALETTE.length];
668
+ }
669
+ function resolveUsageColor(usage, resource, resourceColors) {
670
+ return usage.color || resolveResourceColor(resource, resourceColors);
671
+ }
672
+ function resolveUsageTimes(usage, timeUnit) {
673
+ if (timeUnit === "hour") {
674
+ const start = toDateTime(usage.start);
675
+ const endRaw = toDateTime(usage.end);
676
+ return { start, end: hasTimeComponent(usage.end) ? endRaw : addHours(endRaw, 24) };
677
+ }
678
+ return { start: toDate(usage.start), end: toDate(usage.end) };
679
+ }
680
+ function computeResourceLayout(resources, usages, config, viewport) {
681
+ const mergedConfig = { ...defaultConfig, ...config };
682
+ const timeUnit = mergedConfig.timeUnit ?? "day";
683
+ const hourMode = timeUnit === "hour";
684
+ const hourW = mergedConfig.hourWidth ?? 12;
685
+ for (const usage of usages) {
686
+ const { start, end } = resolveUsageTimes(usage, timeUnit);
687
+ if (!isValidDate(start) || !isValidDate(end)) {
688
+ return {
689
+ ok: false,
690
+ error: {
691
+ code: "INVALID_DATE",
692
+ message: `Resource usage ${usage.id} has invalid dates.`
693
+ }
694
+ };
695
+ }
696
+ }
697
+ const orderedIds = [];
698
+ const seen = /* @__PURE__ */ new Set();
699
+ for (const resource of resources) {
700
+ if (!seen.has(resource.id)) {
701
+ seen.add(resource.id);
702
+ orderedIds.push(resource.id);
703
+ }
704
+ }
705
+ for (const usage of usages) {
706
+ if (!seen.has(usage.resourceId)) {
707
+ seen.add(usage.resourceId);
708
+ orderedIds.push(usage.resourceId);
709
+ }
710
+ }
711
+ const resourceById = new Map(resources.map((resource) => [resource.id, resource]));
712
+ const usagesByResource = /* @__PURE__ */ new Map();
713
+ for (const usage of usages) {
714
+ usagesByResource.set(usage.resourceId, [...usagesByResource.get(usage.resourceId) ?? [], usage]);
715
+ }
716
+ const rows = [];
717
+ const usageLayouts = [];
718
+ const laneIndexByUsage = /* @__PURE__ */ new Map();
719
+ orderedIds.forEach((resourceId, rowIndex) => {
720
+ const resource = resourceById.get(resourceId) ?? {
721
+ id: resourceId,
722
+ name: resourceId
723
+ };
724
+ const grouped = [...usagesByResource.get(resourceId) ?? []].sort((a, b) => {
725
+ const as = resolveUsageTimes(a, timeUnit);
726
+ const bs = resolveUsageTimes(b, timeUnit);
727
+ return as.start.getTime() - bs.start.getTime() || as.end.getTime() - bs.end.getTime();
728
+ });
729
+ const laneEnds = [];
730
+ for (const usage of grouped) {
731
+ const { start, end } = resolveUsageTimes(usage, timeUnit);
732
+ let laneIndex = -1;
733
+ for (let k = 0; k < laneEnds.length; k += 1) {
734
+ const laneEnd = laneEnds[k];
735
+ if (laneEnd === null || isLaneFree(laneEnd, start, hourMode)) {
736
+ laneIndex = k;
737
+ break;
738
+ }
739
+ }
740
+ if (laneIndex === -1) {
741
+ laneIndex = laneEnds.length;
742
+ laneEnds.push(null);
743
+ }
744
+ laneEnds[laneIndex] = end;
745
+ laneIndexByUsage.set(usage.id, laneIndex);
746
+ }
747
+ rows.push({
748
+ resourceId,
749
+ rowIndex,
750
+ laneCount: laneEnds.length,
751
+ color: resolveResourceColor(resource, mergedConfig.resourceColors),
752
+ usageIds: grouped.map((usage) => usage.id)
753
+ });
754
+ });
755
+ const usageById = new Map(usages.map((usage) => [usage.id, usage]));
756
+ const visibleStart = viewport ? Math.max(0, Math.floor(viewport.scrollTop / mergedConfig.rowHeight) - 8) : 0;
757
+ const visibleEnd = viewport ? Math.ceil((viewport.scrollTop + viewport.clientHeight) / mergedConfig.rowHeight) + 8 : Number.POSITIVE_INFINITY;
758
+ const firstDate = hourMode ? startOfDay(
759
+ mergedConfig.visibleRange ? toDateTime(mergedConfig.visibleRange.start) : usages.length ? minDate2(usages.map((usage) => resolveUsageTimes(usage, "hour").start)) : toDateTime(/* @__PURE__ */ new Date())
760
+ ) : mergedConfig.visibleRange ? toDate(mergedConfig.visibleRange.start) : usages.length ? minDate2(usages.map((usage) => toDate(usage.start))) : toDate(/* @__PURE__ */ new Date());
761
+ for (const row of rows) {
762
+ if (row.rowIndex < visibleStart || row.rowIndex > visibleEnd) {
763
+ continue;
764
+ }
765
+ const resource = resourceById.get(row.resourceId) ?? { id: row.resourceId, name: row.resourceId };
766
+ const laneCount = Math.max(1, row.laneCount);
767
+ const slot = mergedConfig.rowHeight / laneCount;
768
+ const barHeight = Math.max(6, Math.min(14, slot - 4));
769
+ for (const usageId of row.usageIds) {
770
+ const usage = usageById.get(usageId);
771
+ if (!usage) {
772
+ continue;
773
+ }
774
+ const { start, end } = resolveUsageTimes(usage, timeUnit);
775
+ const laneIndex = laneIndexByUsage.get(usageId) ?? 0;
776
+ const laneTop = laneIndex * slot + (slot - barHeight) / 2;
777
+ const left = hourMode ? diffHours(firstDate, start) * hourW : diffDays(firstDate, start) * mergedConfig.columnWidth;
778
+ const width = hourMode ? Math.max(hourW, diffHours(start, end) * hourW) : Math.max(mergedConfig.columnWidth, inclusiveDays(start, end) * mergedConfig.columnWidth);
779
+ usageLayouts.push({
780
+ usageId,
781
+ resourceId: row.resourceId,
782
+ rowIndex: row.rowIndex,
783
+ laneIndex,
784
+ laneCount,
785
+ left,
786
+ width,
787
+ top: mergedConfig.headerHeight + row.rowIndex * mergedConfig.rowHeight + laneTop,
788
+ height: barHeight
789
+ });
790
+ }
791
+ }
792
+ return { ok: true, data: { rows, usages: usageLayouts } };
793
+ }
794
+ function isLaneFree(laneEnd, start, hourMode) {
795
+ return hourMode ? diffHours(laneEnd, start) >= 0 : diffDays(laneEnd, start) > 0;
796
+ }
797
+ function minDate2(dates) {
798
+ return new Date(Math.min(...dates.map((date) => date.getTime())));
799
+ }
800
+
553
801
  // src/engine/GanttEngine.ts
554
802
  function mergeTaskPatch(task, patch) {
555
803
  return {
@@ -919,25 +1167,41 @@ function createGanttEngine(options = {}) {
919
1167
  // Annotate the CommonJS export names for ESM import in node:
920
1168
  0 && (module.exports = {
921
1169
  DAY_MS,
1170
+ DEFAULT_HOUR_COLORS,
1171
+ DEFAULT_TASK_COLORS,
1172
+ EDITOR_COLOR_OPTIONS,
922
1173
  GanttEngine,
1174
+ HOUR_MS,
1175
+ OWNER_COLOR_PALETTE,
1176
+ RESOURCE_COLOR_PALETTE,
923
1177
  addDays,
1178
+ addHours,
924
1179
  checkCyclicDependency,
1180
+ computeHourScale,
925
1181
  computeImpact,
926
1182
  computeLayout,
1183
+ computeResourceLayout,
927
1184
  computeTimeScale,
928
1185
  createGanttEngine,
929
1186
  defaultConfig,
930
1187
  diffDays,
1188
+ diffHours,
931
1189
  flattenTasks,
932
1190
  formatDate,
1191
+ formatDateTime,
1192
+ hasTimeComponent,
933
1193
  inclusiveDays,
934
1194
  isValidDate,
935
1195
  mergeTaskPatch,
936
1196
  normalizeLinks,
1197
+ resolveResourceColor,
1198
+ resolveUsageColor,
1199
+ resolveUsageTimes,
937
1200
  resultInvalidDate,
938
1201
  scheduleByDependencies,
939
1202
  shiftTask,
940
1203
  startOfDay,
941
- toDate
1204
+ toDate,
1205
+ toDateTime
942
1206
  });
943
1207
  //# sourceMappingURL=index.cjs.map