ct-gantt-core 1.0.2 → 1.0.3
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 +373 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +103 -1
- package/dist/index.d.ts +103 -1
- package/dist/index.js +370 -0
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/engine/GanttEngine.ts +432 -0
- package/src/index.ts +1 -0
- package/tests/GanttEngine.test.ts +387 -0
package/dist/index.cjs
CHANGED
|
@@ -21,17 +21,20 @@ 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
|
+
GanttEngine: () => GanttEngine,
|
|
24
25
|
addDays: () => addDays,
|
|
25
26
|
checkCyclicDependency: () => checkCyclicDependency,
|
|
26
27
|
computeImpact: () => computeImpact,
|
|
27
28
|
computeLayout: () => computeLayout,
|
|
28
29
|
computeTimeScale: () => computeTimeScale,
|
|
30
|
+
createGanttEngine: () => createGanttEngine,
|
|
29
31
|
defaultConfig: () => defaultConfig,
|
|
30
32
|
diffDays: () => diffDays,
|
|
31
33
|
flattenTasks: () => flattenTasks,
|
|
32
34
|
formatDate: () => formatDate,
|
|
33
35
|
inclusiveDays: () => inclusiveDays,
|
|
34
36
|
isValidDate: () => isValidDate,
|
|
37
|
+
mergeTaskPatch: () => mergeTaskPatch,
|
|
35
38
|
normalizeLinks: () => normalizeLinks,
|
|
36
39
|
resultInvalidDate: () => resultInvalidDate,
|
|
37
40
|
scheduleByDependencies: () => scheduleByDependencies,
|
|
@@ -546,20 +549,390 @@ function computeImpact(taskId, patch, tasks, links, config) {
|
|
|
546
549
|
}));
|
|
547
550
|
return { ok: true, data: { changed, conflicts } };
|
|
548
551
|
}
|
|
552
|
+
|
|
553
|
+
// src/engine/GanttEngine.ts
|
|
554
|
+
function mergeTaskPatch(task, patch) {
|
|
555
|
+
return {
|
|
556
|
+
...task,
|
|
557
|
+
...patch,
|
|
558
|
+
plan: {
|
|
559
|
+
...task.plan,
|
|
560
|
+
start: patch.planStart ?? task.plan.start,
|
|
561
|
+
end: patch.planEnd ?? task.plan.end,
|
|
562
|
+
progress: patch.progress ?? task.plan.progress
|
|
563
|
+
},
|
|
564
|
+
actual: {
|
|
565
|
+
...task.actual,
|
|
566
|
+
start: patch.actualStart ?? task.actual.start,
|
|
567
|
+
end: patch.actualEnd ?? task.actual.end,
|
|
568
|
+
progress: patch.progress ?? task.actual.progress
|
|
569
|
+
},
|
|
570
|
+
custom: patch.custom ? { ...task.custom, ...patch.custom } : task.custom
|
|
571
|
+
};
|
|
572
|
+
}
|
|
573
|
+
var GanttEngine = class {
|
|
574
|
+
tasks;
|
|
575
|
+
links;
|
|
576
|
+
config;
|
|
577
|
+
container;
|
|
578
|
+
collapsedIds;
|
|
579
|
+
dragPreview = null;
|
|
580
|
+
markers;
|
|
581
|
+
listeners;
|
|
582
|
+
destroyed = false;
|
|
583
|
+
constructor(options = {}) {
|
|
584
|
+
this.tasks = options.tasks ? options.tasks.map((task) => ({ ...task })) : [];
|
|
585
|
+
this.links = options.links ? options.links.map((link) => ({ ...link })) : [];
|
|
586
|
+
this.config = { ...defaultConfig, ...options.config };
|
|
587
|
+
this.container = options.container ?? null;
|
|
588
|
+
this.collapsedIds = new Set(options.collapsedIds ?? []);
|
|
589
|
+
this.markers = options.markers ? options.markers.map((marker) => ({ ...marker })) : [];
|
|
590
|
+
this.listeners = /* @__PURE__ */ new Map();
|
|
591
|
+
queueMicrotask(() => this.emit("ready"));
|
|
592
|
+
}
|
|
593
|
+
// ── 状态查询 ──
|
|
594
|
+
getTasks() {
|
|
595
|
+
return this.tasks.map((task) => ({ ...task }));
|
|
596
|
+
}
|
|
597
|
+
getLinks() {
|
|
598
|
+
return this.links.map((link) => ({ ...link }));
|
|
599
|
+
}
|
|
600
|
+
getMarkers() {
|
|
601
|
+
return this.markers.map((marker) => ({ ...marker }));
|
|
602
|
+
}
|
|
603
|
+
getConfig() {
|
|
604
|
+
return { ...this.config };
|
|
605
|
+
}
|
|
606
|
+
getTask(id) {
|
|
607
|
+
const task = this.tasks.find((item) => item.id === id);
|
|
608
|
+
return task ? { ...task } : void 0;
|
|
609
|
+
}
|
|
610
|
+
getCollapsedIds() {
|
|
611
|
+
return Array.from(this.collapsedIds);
|
|
612
|
+
}
|
|
613
|
+
isDestroyed() {
|
|
614
|
+
return this.destroyed;
|
|
615
|
+
}
|
|
616
|
+
// ── 命令式变更(均触发对应事件) ──
|
|
617
|
+
setTasks(tasks) {
|
|
618
|
+
this.assertNotDestroyed();
|
|
619
|
+
this.tasks = tasks.map((task) => ({ ...task }));
|
|
620
|
+
this.emit("taskschange", this.getTasks());
|
|
621
|
+
}
|
|
622
|
+
setLinks(links) {
|
|
623
|
+
this.assertNotDestroyed();
|
|
624
|
+
this.links = links.map((link) => ({ ...link }));
|
|
625
|
+
this.emit("linkschange", this.getLinks());
|
|
626
|
+
}
|
|
627
|
+
setMarkers(markers) {
|
|
628
|
+
this.assertNotDestroyed();
|
|
629
|
+
this.markers = markers.map((marker) => ({ ...marker }));
|
|
630
|
+
this.emit("markerschange", this.getMarkers());
|
|
631
|
+
}
|
|
632
|
+
/** 合并配置 patch,等价于 setConfig(mergeConfig(patch)) */
|
|
633
|
+
mergeConfig(patch) {
|
|
634
|
+
this.assertNotDestroyed();
|
|
635
|
+
this.config = { ...this.config, ...patch };
|
|
636
|
+
this.emit("configchange", this.getConfig());
|
|
637
|
+
}
|
|
638
|
+
setConfig(config) {
|
|
639
|
+
this.mergeConfig(config);
|
|
640
|
+
}
|
|
641
|
+
/** 用 mergeTaskPatch 把扁平 patch 合并回嵌套结构后更新单个任务 */
|
|
642
|
+
setTask(id, patch) {
|
|
643
|
+
this.assertNotDestroyed();
|
|
644
|
+
const target = this.tasks.find((task) => task.id === id);
|
|
645
|
+
if (!target) {
|
|
646
|
+
return;
|
|
647
|
+
}
|
|
648
|
+
const updated = mergeTaskPatch(target, patch);
|
|
649
|
+
this.tasks = this.tasks.map((task) => task.id === id ? updated : task);
|
|
650
|
+
this.emit("taskchange", id, patch, { ...updated });
|
|
651
|
+
}
|
|
652
|
+
addTask(task) {
|
|
653
|
+
this.assertNotDestroyed();
|
|
654
|
+
this.tasks = [...this.tasks, { ...task }];
|
|
655
|
+
this.emit("taskcreate", { ...task });
|
|
656
|
+
}
|
|
657
|
+
removeTask(id) {
|
|
658
|
+
this.assertNotDestroyed();
|
|
659
|
+
const removed = this.tasks.find((task) => task.id === id);
|
|
660
|
+
if (!removed) return;
|
|
661
|
+
this.tasks = this.tasks.filter((task) => task.id !== id);
|
|
662
|
+
this.collapsedIds.delete(id);
|
|
663
|
+
this.emit("taskdelete", id);
|
|
664
|
+
}
|
|
665
|
+
collapse(id, collapsed = true) {
|
|
666
|
+
this.assertNotDestroyed();
|
|
667
|
+
if (collapsed) this.collapsedIds.add(id);
|
|
668
|
+
else this.collapsedIds.delete(id);
|
|
669
|
+
this.emit("collapsechange", this.getCollapsedIds());
|
|
670
|
+
}
|
|
671
|
+
toggleCollapse(id) {
|
|
672
|
+
this.collapse(id, !this.collapsedIds.has(id));
|
|
673
|
+
}
|
|
674
|
+
/** 批量折叠/展开多个任务(如"折叠全部分组") */
|
|
675
|
+
setCollapsed(ids, collapsed = true) {
|
|
676
|
+
this.assertNotDestroyed();
|
|
677
|
+
const next = new Set(this.collapsedIds);
|
|
678
|
+
for (const id of ids) {
|
|
679
|
+
if (collapsed) {
|
|
680
|
+
next.add(id);
|
|
681
|
+
} else {
|
|
682
|
+
next.delete(id);
|
|
683
|
+
}
|
|
684
|
+
}
|
|
685
|
+
this.collapsedIds = next;
|
|
686
|
+
this.emit("collapsechange", this.getCollapsedIds());
|
|
687
|
+
}
|
|
688
|
+
// ── 拖拽预览(交互态源;组件写入迁移到 engine,dateRange 可据此扩展) ──
|
|
689
|
+
setPreview(preview) {
|
|
690
|
+
this.assertNotDestroyed();
|
|
691
|
+
this.dragPreview = {
|
|
692
|
+
taskId: preview.taskId,
|
|
693
|
+
patch: { ...preview.patch },
|
|
694
|
+
affected: preview.affected ? { ...preview.affected } : void 0
|
|
695
|
+
};
|
|
696
|
+
this.emit("previewchange", this.getPreview());
|
|
697
|
+
}
|
|
698
|
+
clearPreview() {
|
|
699
|
+
if (!this.dragPreview) {
|
|
700
|
+
return;
|
|
701
|
+
}
|
|
702
|
+
this.dragPreview = null;
|
|
703
|
+
this.emit("previewchange", null);
|
|
704
|
+
}
|
|
705
|
+
getPreview() {
|
|
706
|
+
if (!this.dragPreview) {
|
|
707
|
+
return null;
|
|
708
|
+
}
|
|
709
|
+
return {
|
|
710
|
+
taskId: this.dragPreview.taskId,
|
|
711
|
+
patch: { ...this.dragPreview.patch },
|
|
712
|
+
affected: this.dragPreview.affected ? { ...this.dragPreview.affected } : void 0
|
|
713
|
+
};
|
|
714
|
+
}
|
|
715
|
+
// ── 计算(delegate 到 core 纯函数) ──
|
|
716
|
+
/** 数据真实日期范围(未含 viewport pad) */
|
|
717
|
+
getDateRange() {
|
|
718
|
+
const dates = [];
|
|
719
|
+
for (const task of this.tasks) {
|
|
720
|
+
dates.push(
|
|
721
|
+
toDate(task.plan.start),
|
|
722
|
+
toDate(task.plan.end),
|
|
723
|
+
toDate(task.actual.start),
|
|
724
|
+
toDate(task.actual.end)
|
|
725
|
+
);
|
|
726
|
+
}
|
|
727
|
+
for (const marker of this.markers) {
|
|
728
|
+
dates.push(toDate(marker.date));
|
|
729
|
+
}
|
|
730
|
+
const preview = this.dragPreview;
|
|
731
|
+
if (preview) {
|
|
732
|
+
const ids = [preview.taskId, ...Object.keys(preview.affected ?? {})];
|
|
733
|
+
for (const id of ids) {
|
|
734
|
+
const task = this.tasks.find((item) => item.id === id);
|
|
735
|
+
if (!task) {
|
|
736
|
+
continue;
|
|
737
|
+
}
|
|
738
|
+
const patch = preview.taskId === id ? preview.patch : preview.affected?.[id];
|
|
739
|
+
if (!patch) {
|
|
740
|
+
continue;
|
|
741
|
+
}
|
|
742
|
+
const merged = mergeTaskPatch(task, patch);
|
|
743
|
+
dates.push(
|
|
744
|
+
toDate(merged.plan.start),
|
|
745
|
+
toDate(merged.plan.end),
|
|
746
|
+
toDate(merged.actual.start),
|
|
747
|
+
toDate(merged.actual.end)
|
|
748
|
+
);
|
|
749
|
+
}
|
|
750
|
+
}
|
|
751
|
+
if (!dates.length) {
|
|
752
|
+
const today = toDate(/* @__PURE__ */ new Date());
|
|
753
|
+
return { start: today, end: addDays(today, 30) };
|
|
754
|
+
}
|
|
755
|
+
return {
|
|
756
|
+
start: new Date(Math.min(...dates.map((d) => d.getTime()))),
|
|
757
|
+
end: new Date(Math.max(...dates.map((d) => d.getTime())))
|
|
758
|
+
};
|
|
759
|
+
}
|
|
760
|
+
getTimeScale() {
|
|
761
|
+
const range = this.getDateRange();
|
|
762
|
+
return computeTimeScale(
|
|
763
|
+
range.start,
|
|
764
|
+
range.end,
|
|
765
|
+
this.config.viewMode,
|
|
766
|
+
this.config.columnWidth,
|
|
767
|
+
this.config.firstDayOfWeek
|
|
768
|
+
);
|
|
769
|
+
}
|
|
770
|
+
getLayout() {
|
|
771
|
+
return computeLayout(
|
|
772
|
+
this.tasks,
|
|
773
|
+
this.links,
|
|
774
|
+
this.config,
|
|
775
|
+
this.collapsedIds
|
|
776
|
+
);
|
|
777
|
+
}
|
|
778
|
+
getFlatTasks() {
|
|
779
|
+
return flattenTasks(this.tasks, this.collapsedIds);
|
|
780
|
+
}
|
|
781
|
+
getTotalWidth() {
|
|
782
|
+
return this.getTimeScale().reduce((sum, tick) => sum + tick.width, 0);
|
|
783
|
+
}
|
|
784
|
+
getTotalHeight() {
|
|
785
|
+
const rows = this.getFlatTasks().length;
|
|
786
|
+
return this.config.headerHeight + rows * this.config.rowHeight;
|
|
787
|
+
}
|
|
788
|
+
// ── 视口命令(需要 container) ──
|
|
789
|
+
getScrollLeft() {
|
|
790
|
+
return this.container?.scrollLeft ?? 0;
|
|
791
|
+
}
|
|
792
|
+
setScrollLeft(px) {
|
|
793
|
+
if (!this.container) return;
|
|
794
|
+
const max = Math.max(0, this.container.scrollWidth - this.container.clientWidth);
|
|
795
|
+
this.container.scrollLeft = Math.max(0, Math.min(max, px));
|
|
796
|
+
}
|
|
797
|
+
/** 把当前 scrollLeft 限制到 [0, maxScrollLeft]。
|
|
798
|
+
* 拖拽预览收缩(松手/取消)后 timeline 总宽度变小,scrollLeft 可能超出新边界,
|
|
799
|
+
* 导致 canvas translate 超出内容区、右侧网格未覆盖。此时调用本方法防超界。 */
|
|
800
|
+
clampScrollLeft() {
|
|
801
|
+
if (!this.container) return;
|
|
802
|
+
const max = Math.max(0, this.container.scrollWidth - this.container.clientWidth);
|
|
803
|
+
if (this.container.scrollLeft > max) {
|
|
804
|
+
this.container.scrollLeft = max;
|
|
805
|
+
}
|
|
806
|
+
}
|
|
807
|
+
getScrollTop() {
|
|
808
|
+
return this.container?.scrollTop ?? 0;
|
|
809
|
+
}
|
|
810
|
+
setScrollTop(px) {
|
|
811
|
+
if (!this.container) return;
|
|
812
|
+
const max = Math.max(0, this.container.scrollHeight - this.container.clientHeight);
|
|
813
|
+
this.container.scrollTop = Math.max(0, Math.min(max, px));
|
|
814
|
+
}
|
|
815
|
+
/** 滚动到包含目标日期的 tick 列(跨 viewMode 精确) */
|
|
816
|
+
scrollToDate(date) {
|
|
817
|
+
if (!this.container) return;
|
|
818
|
+
const target = toDate(date);
|
|
819
|
+
const scale = this.getTimeScale();
|
|
820
|
+
const tick = scale.find((t) => target >= t.start && target <= t.end);
|
|
821
|
+
const left = tick ? tick.left : diffDays(this.getDateRange().start, target) * this.config.columnWidth;
|
|
822
|
+
this.setScrollLeft(left);
|
|
823
|
+
}
|
|
824
|
+
scrollToTask(id) {
|
|
825
|
+
const layout = this.getLayout();
|
|
826
|
+
if (!layout.ok) return;
|
|
827
|
+
const item = layout.data.find((row) => row.taskId === id);
|
|
828
|
+
if (item) this.setScrollLeft(item.left);
|
|
829
|
+
}
|
|
830
|
+
scrollToStart() {
|
|
831
|
+
this.setScrollLeft(0);
|
|
832
|
+
}
|
|
833
|
+
scrollToEnd() {
|
|
834
|
+
if (!this.container) return;
|
|
835
|
+
this.setScrollLeft(this.getTotalWidth());
|
|
836
|
+
}
|
|
837
|
+
/** 让整个 timeline 总宽度≈视口宽度(调 columnWidth) */
|
|
838
|
+
zoomToFit(padding = 1) {
|
|
839
|
+
if (!this.container) return;
|
|
840
|
+
const spanDays = Math.max(1, diffDays(this.getDateRange().start, this.getDateRange().end) + 1);
|
|
841
|
+
const target = this.container.clientWidth * padding / spanDays;
|
|
842
|
+
this.mergeConfig({ columnWidth: this.clampColumnWidth(target) });
|
|
843
|
+
}
|
|
844
|
+
/** 让指定日期范围占满视口宽度(调 columnWidth) */
|
|
845
|
+
zoomToRange(start, end) {
|
|
846
|
+
if (!this.container) return;
|
|
847
|
+
const span = Math.max(1, diffDays(start, end) + 1);
|
|
848
|
+
const target = this.container.clientWidth / span;
|
|
849
|
+
this.mergeConfig({ columnWidth: this.clampColumnWidth(target) });
|
|
850
|
+
}
|
|
851
|
+
clampColumnWidth(value) {
|
|
852
|
+
return Math.max(4, Math.min(400, Math.round(value)));
|
|
853
|
+
}
|
|
854
|
+
// ── 事件订阅 ──
|
|
855
|
+
on(event, fn) {
|
|
856
|
+
this.assertNotDestroyed();
|
|
857
|
+
let set = this.listeners.get(event);
|
|
858
|
+
if (!set) {
|
|
859
|
+
set = /* @__PURE__ */ new Set();
|
|
860
|
+
this.listeners.set(event, set);
|
|
861
|
+
}
|
|
862
|
+
set.add(fn);
|
|
863
|
+
return () => {
|
|
864
|
+
const current = this.listeners.get(event);
|
|
865
|
+
if (current) {
|
|
866
|
+
current.delete(fn);
|
|
867
|
+
if (!current.size) this.listeners.delete(event);
|
|
868
|
+
}
|
|
869
|
+
};
|
|
870
|
+
}
|
|
871
|
+
once(event, fn) {
|
|
872
|
+
const off = this.on(event, (...args) => {
|
|
873
|
+
off();
|
|
874
|
+
fn(...args);
|
|
875
|
+
});
|
|
876
|
+
return off;
|
|
877
|
+
}
|
|
878
|
+
off(event, fn) {
|
|
879
|
+
const set = this.listeners.get(event);
|
|
880
|
+
if (!set) return;
|
|
881
|
+
if (fn) {
|
|
882
|
+
set.delete(fn);
|
|
883
|
+
if (!set.size) this.listeners.delete(event);
|
|
884
|
+
} else {
|
|
885
|
+
this.listeners.delete(event);
|
|
886
|
+
}
|
|
887
|
+
}
|
|
888
|
+
emit(event, ...args) {
|
|
889
|
+
const set = this.listeners.get(event);
|
|
890
|
+
if (!set) return;
|
|
891
|
+
for (const fn of Array.from(set)) {
|
|
892
|
+
try {
|
|
893
|
+
fn(...args);
|
|
894
|
+
} catch (error) {
|
|
895
|
+
if (typeof console !== "undefined") {
|
|
896
|
+
console.error(`[GanttEngine] listener for "${event}" threw`, error);
|
|
897
|
+
}
|
|
898
|
+
}
|
|
899
|
+
}
|
|
900
|
+
}
|
|
901
|
+
// ── 生命周期 ──
|
|
902
|
+
destroy() {
|
|
903
|
+
if (this.destroyed) return;
|
|
904
|
+
this.destroyed = true;
|
|
905
|
+
this.emit("destroy");
|
|
906
|
+
this.listeners.clear();
|
|
907
|
+
this.tasks = [];
|
|
908
|
+
this.links = [];
|
|
909
|
+
}
|
|
910
|
+
assertNotDestroyed() {
|
|
911
|
+
if (this.destroyed) {
|
|
912
|
+
throw new Error("GanttEngine: operation on destroyed instance");
|
|
913
|
+
}
|
|
914
|
+
}
|
|
915
|
+
};
|
|
916
|
+
function createGanttEngine(options = {}) {
|
|
917
|
+
return new GanttEngine(options);
|
|
918
|
+
}
|
|
549
919
|
// Annotate the CommonJS export names for ESM import in node:
|
|
550
920
|
0 && (module.exports = {
|
|
551
921
|
DAY_MS,
|
|
922
|
+
GanttEngine,
|
|
552
923
|
addDays,
|
|
553
924
|
checkCyclicDependency,
|
|
554
925
|
computeImpact,
|
|
555
926
|
computeLayout,
|
|
556
927
|
computeTimeScale,
|
|
928
|
+
createGanttEngine,
|
|
557
929
|
defaultConfig,
|
|
558
930
|
diffDays,
|
|
559
931
|
flattenTasks,
|
|
560
932
|
formatDate,
|
|
561
933
|
inclusiveDays,
|
|
562
934
|
isValidDate,
|
|
935
|
+
mergeTaskPatch,
|
|
563
936
|
normalizeLinks,
|
|
564
937
|
resultInvalidDate,
|
|
565
938
|
scheduleByDependencies,
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/types/index.ts","../src/services/checkCyclicDependency.ts","../src/services/normalizeLinks.ts","../src/services/flattenTasks.ts","../src/utils/date.ts","../src/services/computeTimeScale.ts","../src/engines/scheduling.ts","../src/engines/computeLayout.ts","../src/engines/computeImpact.ts"],"sourcesContent":["export * from \"./types\"\nexport * from \"./services/checkCyclicDependency\"\nexport * from \"./services/normalizeLinks\"\nexport * from \"./services/flattenTasks\"\nexport * from \"./services/computeTimeScale\"\nexport * from \"./engines/computeLayout\"\nexport * from \"./engines/computeImpact\"\nexport * from \"./engines/scheduling\"\nexport * from \"./utils/date\"\n","export type ViewMode = \"day\" | \"week\" | \"month\" | \"quarter\" | \"year\"\n\nexport type LinkType = \"FS\" | \"SS\" | \"FF\" | \"SF\"\nexport type LagUnit = \"calendar\" | \"working\"\n\nexport type Result<T> =\n | { ok: true; data: T }\n | { ok: false; error: GanttError }\n\nexport interface GanttError {\n code:\n | \"CYCLE_DEPENDENCY\"\n | \"INVALID_DATE\"\n | \"MISSING_TASK\"\n | \"ORPHAN_DEPENDENCY\"\n | \"INVALID_DEPENDENCY\"\n message: string\n details?: unknown\n}\n\nexport interface DateRange {\n start: string | Date\n end: string | Date\n progress?: number\n}\n\nexport interface Dependency {\n id?: string\n predecessorId: string\n type: LinkType\n lag: number\n lagUnit: LagUnit\n}\n\nexport interface GanttTask {\n id: string\n name: string\n type: \"task\" | \"milestone\" | \"summary\"\n plan: DateRange\n actual: Required<DateRange>\n dependencies?: Dependency[]\n parentId?: string | null\n color?: string\n planColor?: string\n calendarId?: string\n resources?: string[]\n segments?: Array<{ start: string | Date; end: string | Date }>\n constraint?: {\n type: \"SNET\" | \"SNLT\" | \"MSO\" | \"MFO\" | \"ASAP\" | \"ALAP\"\n date?: string | Date\n }\n schedulingMode?: \"auto\" | \"manual\"\n duration?: number\n custom?: Record<string, unknown>\n}\n\nexport interface GanttMarker {\n id: string\n name: string\n date: string | Date\n color?: string\n}\n\nexport interface GanttEditorField {\n key: string\n label: string\n visible?: boolean\n editable?: boolean\n type?: \"text\" | \"number\" | \"date\" | \"select\"\n options?: Array<{ label: string; value: string | number }>\n placeholder?: string\n}\n\nexport interface CustomColumn {\n key: string\n label: string\n width?: number\n visible?: boolean\n align?: \"left\" | \"center\" | \"right\"\n editable?: boolean\n type?: \"text\" | \"number\" | \"date\" | \"select\"\n options?: Array<{ label: string; value: string | number }>\n placeholder?: string\n editor?: Omit<GanttEditorField, \"key\" | \"label\">\n formatter?: (value: unknown, task: GanttTask) => string\n cellClass?: string | ((task: GanttTask) => string)\n cellStyle?: Record<string, string | number> | ((task: GanttTask) => Record<string, string | number>)\n render?: (task: GanttTask) => { text: string; className?: string }\n}\n\nexport interface GanttConfig {\n viewMode: ViewMode\n rowHeight: number\n columnWidth: number\n headerHeight: number\n taskListWidth: number\n width?: string | number\n height?: string | number\n locale: string\n firstDayOfWeek: 0 | 1\n dateFormat: string\n customColumns?: CustomColumn[]\n columns?: CustomColumn[]\n editorFields?: GanttEditorField[]\n columnWidths?: Partial<Record<ViewMode, number>>\n theme?: \"light\" | \"dark\" | string\n visibleRange?: {\n start: string | Date\n end: string | Date\n }\n showPlanBar?: boolean\n showActualBar?: boolean\n showTimelineWhenEmpty?: boolean\n builtInTaskEditor?: boolean\n builtInMarkerEditor?: boolean\n editablePlan?: boolean\n editableActual?: boolean\n enableLinkCreation?: boolean\n showLinkRejectionNotice?: boolean\n virtualScroll?: boolean\n taskColors?: {\n task?: string\n summary?: string\n milestone?: string\n plan?: string\n progress?: string\n }\n autoSchedule?: boolean\n editable?: boolean\n}\n\nexport interface GanttLink {\n id: string\n sourceId: string\n targetId: string\n type: LinkType\n lag?: number\n lagUnit?: LagUnit\n}\n\nexport interface TaskLayout {\n taskId: string\n rowIndex: number\n left: number\n width: number\n top: number\n depth: number\n isCritical: boolean\n}\n\nexport interface FlatTask {\n task: GanttTask\n depth: number\n rowIndex: number\n hasChildren: boolean\n collapsed: boolean\n}\n\nexport interface Calendar {\n id: string\n workingDays: number[]\n holidays: string[]\n hours: [number, number][]\n}\n\nexport interface TimeScale {\n start: Date\n end: Date\n left: number\n width: number\n}\n\nexport interface Viewport {\n scrollTop: number\n scrollLeft: number\n clientWidth: number\n clientHeight: number\n dpr: number\n}\n\nexport interface AffectedTasks {\n changed: Array<{\n taskId: string\n actualStart: string | Date\n actualEnd: string | Date\n rowIndex: number\n }>\n conflicts: Array<{\n taskId: string\n constraintType: string\n message: string\n }>\n}\n\nexport interface PatchTask {\n planStart?: string | Date\n planEnd?: string | Date\n actualStart?: string | Date\n actualEnd?: string | Date\n progress?: number\n name?: string\n type?: GanttTask[\"type\"]\n parentId?: string | null\n color?: string\n planColor?: string\n duration?: number\n schedulingMode?: \"auto\" | \"manual\"\n resources?: string[]\n calendarId?: string\n custom?: Record<string, unknown>\n}\n\nexport const defaultConfig: GanttConfig = {\n viewMode: \"month\",\n rowHeight: 44,\n columnWidth: 30,\n headerHeight: 50,\n taskListWidth: 280,\n locale: \"zh-CN\",\n firstDayOfWeek: 0,\n dateFormat: \"YYYY-MM-DD\",\n showPlanBar: true,\n showActualBar: true,\n showTimelineWhenEmpty: false,\n builtInTaskEditor: true,\n builtInMarkerEditor: true,\n editablePlan: false,\n editableActual: true,\n enableLinkCreation: true,\n showLinkRejectionNotice: true,\n virtualScroll: true,\n taskColors: {\n task: \"#2563eb\",\n summary: \"#475467\",\n milestone: \"#d97706\",\n plan: \"#cbd5e1\",\n progress: \"#0f766e\"\n },\n autoSchedule: true,\n editable: true\n}\n","import type { GanttLink } from \"../types\"\n\nexport function checkCyclicDependency(\n links: GanttLink[]\n): { hasCycle: boolean; cyclePath?: string[] } {\n const graph = new Map<string, string[]>()\n\n for (const link of links) {\n const targets = graph.get(link.sourceId) ?? []\n targets.push(link.targetId)\n graph.set(link.sourceId, targets)\n if (!graph.has(link.targetId)) {\n graph.set(link.targetId, [])\n }\n }\n\n const visiting = new Set<string>()\n const visited = new Set<string>()\n const path: string[] = []\n\n const dfs = (node: string): string[] | undefined => {\n if (visiting.has(node)) {\n const start = path.indexOf(node)\n return [...path.slice(start), node]\n }\n if (visited.has(node)) {\n return undefined\n }\n\n visiting.add(node)\n path.push(node)\n\n for (const next of graph.get(node) ?? []) {\n const cycle = dfs(next)\n if (cycle) {\n return cycle\n }\n }\n\n path.pop()\n visiting.delete(node)\n visited.add(node)\n return undefined\n }\n\n for (const node of graph.keys()) {\n const cyclePath = dfs(node)\n if (cyclePath) {\n return { hasCycle: true, cyclePath }\n }\n }\n\n return { hasCycle: false }\n}\n","import type { GanttLink, GanttTask } from \"../types\"\n\nexport function normalizeLinks(tasks: GanttTask[], standaloneLinks: GanttLink[] = []): GanttLink[] {\n const taskIds = new Set(tasks.map((task) => task.id))\n const byTaskPair = new Map<string, GanttLink>()\n const outgoing = new Map<string, Set<string>>()\n\n const createsCycle = (sourceId: string, targetId: string): boolean => {\n const pending = [targetId]\n const visited = new Set<string>()\n while (pending.length > 0) {\n const current = pending.pop()!\n if (current === sourceId) {\n return true\n }\n if (visited.has(current)) {\n continue\n }\n visited.add(current)\n pending.push(...(outgoing.get(current) ?? []))\n }\n return false\n }\n\n const append = (link: GanttLink) => {\n if (\n !taskIds.has(link.sourceId)\n || !taskIds.has(link.targetId)\n || link.sourceId === link.targetId\n ) {\n return\n }\n\n const normalized: GanttLink = {\n ...link,\n id: link.id || `link-${link.sourceId}-${link.targetId}`,\n lag: link.lag ?? 0,\n lagUnit: link.lagUnit ?? \"calendar\"\n }\n const pairKey = `${normalized.sourceId}|${normalized.targetId}`\n if (byTaskPair.has(pairKey) || createsCycle(normalized.sourceId, normalized.targetId)) {\n return\n }\n\n byTaskPair.set(pairKey, normalized)\n const targets = outgoing.get(normalized.sourceId) ?? new Set<string>()\n targets.add(normalized.targetId)\n outgoing.set(normalized.sourceId, targets)\n }\n\n for (const task of tasks) {\n for (const dependency of task.dependencies ?? []) {\n append({\n id: dependency.id || `link-${dependency.predecessorId}-${task.id}`,\n sourceId: dependency.predecessorId,\n targetId: task.id,\n type: dependency.type,\n lag: dependency.lag,\n lagUnit: dependency.lagUnit\n })\n }\n }\n\n for (const link of standaloneLinks) {\n append(link)\n }\n\n return [...byTaskPair.values()]\n}\n","import type { FlatTask, GanttTask } from \"../types\"\n\nexport function flattenTasks(tasks: GanttTask[], collapsedIds: Set<string> = new Set()): FlatTask[] {\n const children = new Map<string | null, GanttTask[]>()\n\n for (const task of tasks) {\n const parentId = task.parentId ?? null\n const bucket = children.get(parentId) ?? []\n bucket.push(task)\n children.set(parentId, bucket)\n }\n\n const flattened: FlatTask[] = []\n const visit = (task: GanttTask, depth: number) => {\n const childTasks = children.get(task.id) ?? []\n const collapsed = collapsedIds.has(task.id)\n\n flattened.push({\n task,\n depth,\n rowIndex: flattened.length,\n hasChildren: childTasks.length > 0,\n collapsed\n })\n\n if (!collapsed) {\n for (const child of childTasks) {\n visit(child, depth + 1)\n }\n }\n }\n\n for (const root of children.get(null) ?? []) {\n visit(root, 0)\n }\n\n return flattened\n}\n","import type { Result } from \"../types\"\n\nexport const DAY_MS = 24 * 60 * 60 * 1000\n\nexport function toDate(value: string | Date): Date {\n if (value instanceof Date) {\n return startOfDay(value)\n }\n\n const match = /^(\\d{4})-(\\d{2})-(\\d{2})/.exec(value)\n if (match) {\n return new Date(Number(match[1]), Number(match[2]) - 1, Number(match[3]))\n }\n\n return startOfDay(new Date(value))\n}\n\nexport function startOfDay(date: Date): Date {\n return new Date(date.getFullYear(), date.getMonth(), date.getDate())\n}\n\nexport function addDays(date: string | Date, days: number): Date {\n const next = toDate(date)\n next.setDate(next.getDate() + days)\n return startOfDay(next)\n}\n\nexport function diffDays(start: string | Date, end: string | Date): number {\n return Math.round((toDate(end).getTime() - toDate(start).getTime()) / DAY_MS)\n}\n\nexport function inclusiveDays(start: string | Date, end: string | Date): number {\n return Math.max(0, diffDays(start, end) + 1)\n}\n\nexport function isValidDate(value: string | Date): boolean {\n const date = value instanceof Date ? value : new Date(value)\n return !Number.isNaN(date.getTime())\n}\n\nexport function formatDate(date: string | Date): string {\n const value = toDate(date)\n const year = value.getFullYear()\n const month = String(value.getMonth() + 1).padStart(2, \"0\")\n const day = String(value.getDate()).padStart(2, \"0\")\n return `${year}-${month}-${day}`\n}\n\nexport function resultInvalidDate<T>(message: string, details?: unknown): Result<T> {\n return {\n ok: false,\n error: { code: \"INVALID_DATE\", message, details }\n }\n}\n","import type { TimeScale, ViewMode } from \"../types\"\nimport { addDays, diffDays, startOfDay } from \"../utils/date\"\n\nexport function computeTimeScale(\n start: Date,\n end: Date,\n viewMode: ViewMode,\n columnWidth: number,\n firstDayOfWeek: 0 | 1\n): TimeScale[] {\n const rangeStart = alignStart(start, viewMode, firstDayOfWeek)\n const endDate = startOfDay(end)\n const rangeEnd = viewMode === \"day\"\n ? addDays(endDate, (firstDayOfWeek + 6 - endDate.getDay() + 7) % 7)\n : endDate\n const scale: TimeScale[] = []\n let cursor = rangeStart\n let left = 0\n\n while (cursor.getTime() <= rangeEnd.getTime()) {\n const next = nextUnit(cursor, viewMode)\n const unitEnd = addDays(next, -1)\n const width = Math.max(1, diffDays(cursor, next)) * columnWidth\n\n scale.push({\n start: cursor,\n end: unitEnd,\n left,\n width\n })\n\n left += width\n cursor = next\n }\n\n return scale\n}\n\nfunction alignStart(date: Date, viewMode: ViewMode, firstDayOfWeek: 0 | 1): Date {\n const start = startOfDay(date)\n if (viewMode === \"day\" || viewMode === \"week\") {\n const delta = (start.getDay() - firstDayOfWeek + 7) % 7\n return addDays(start, -delta)\n }\n if (viewMode === \"month\") {\n return new Date(start.getFullYear(), start.getMonth(), 1)\n }\n if (viewMode === \"quarter\") {\n return new Date(start.getFullYear(), Math.floor(start.getMonth() / 3) * 3, 1)\n }\n if (viewMode === \"year\") {\n return new Date(start.getFullYear(), 0, 1)\n }\n return start\n}\n\nfunction nextUnit(date: Date, viewMode: ViewMode): Date {\n if (viewMode === \"week\") {\n return addDays(date, 7)\n }\n if (viewMode === \"month\") {\n return new Date(date.getFullYear(), date.getMonth() + 1, 1)\n }\n if (viewMode === \"quarter\") {\n return new Date(date.getFullYear(), date.getMonth() + 3, 1)\n }\n if (viewMode === \"year\") {\n return new Date(date.getFullYear() + 1, 0, 1)\n }\n return addDays(date, 1)\n}\n","import type { GanttLink, GanttTask, LinkType, Result } from \"../types\"\nimport { addDays, diffDays, inclusiveDays, toDate } from \"../utils/date\"\nimport { checkCyclicDependency } from \"../services/checkCyclicDependency\"\n\nexport function scheduleByDependencies(tasks: GanttTask[], links: GanttLink[]): Result<GanttTask[]> {\n const cycle = checkCyclicDependency(links)\n if (cycle.hasCycle) {\n return {\n ok: false,\n error: {\n code: \"CYCLE_DEPENDENCY\",\n message: \"Dependency graph contains a cycle.\",\n details: cycle.cyclePath\n }\n }\n }\n\n const taskMap = new Map(tasks.map((task) => [task.id, cloneTask(task)]))\n const incoming = new Map<string, GanttLink[]>()\n const outgoing = new Map<string, GanttLink[]>()\n\n for (const link of links) {\n const source = taskMap.get(link.sourceId)\n const target = taskMap.get(link.targetId)\n if (!source || !target) {\n return {\n ok: false,\n error: {\n code: \"ORPHAN_DEPENDENCY\",\n message: `Dependency ${link.id} references a missing task.`\n }\n }\n }\n incoming.set(link.targetId, [...(incoming.get(link.targetId) ?? []), link])\n outgoing.set(link.sourceId, [...(outgoing.get(link.sourceId) ?? []), link])\n }\n\n const ordered = topologicalOrder(tasks.map((task) => task.id), links)\n\n for (const taskId of ordered) {\n const task = taskMap.get(taskId)\n if (!task || task.schedulingMode === \"manual\") {\n continue\n }\n\n const linksToTask = incoming.get(taskId) ?? []\n let start = toDate(task.actual.start)\n let end = toDate(task.actual.end)\n const duration = Math.max(0, task.duration ?? inclusiveDays(start, end))\n\n for (const link of linksToTask) {\n const source = taskMap.get(link.sourceId)\n if (!source) {\n continue\n }\n\n const candidate = applyDependency(source, start, end, duration, link.type, link.lag ?? 0)\n if (candidate.start.getTime() > start.getTime()) {\n start = candidate.start\n }\n if (candidate.end.getTime() > end.getTime()) {\n end = candidate.end\n }\n }\n\n const normalizedEnd = task.type === \"milestone\" ? start : addDays(start, Math.max(0, duration - 1))\n task.actual = {\n ...task.actual,\n start,\n end: normalizedEnd\n }\n }\n\n return { ok: true, data: tasks.map((task) => taskMap.get(task.id) ?? task) }\n}\n\nfunction applyDependency(\n source: GanttTask,\n currentStart: Date,\n currentEnd: Date,\n duration: number,\n type: LinkType,\n lag: number\n): { start: Date; end: Date } {\n const sourceStart = toDate(source.actual.start)\n const sourceEnd = toDate(source.actual.end)\n const span = Math.max(0, duration - 1)\n\n if (type === \"FS\") {\n const start = addDays(sourceEnd, lag + 1)\n return { start, end: addDays(start, span) }\n }\n\n if (type === \"SS\") {\n const start = addDays(sourceStart, lag)\n return { start, end: addDays(start, span) }\n }\n\n if (type === \"FF\") {\n const end = addDays(sourceEnd, lag)\n return { start: addDays(end, -span), end }\n }\n\n const end = addDays(sourceStart, lag)\n return { start: addDays(end, -span), end: end.getTime() > currentEnd.getTime() ? end : currentEnd }\n}\n\nfunction topologicalOrder(ids: string[], links: GanttLink[]): string[] {\n const indegree = new Map(ids.map((id) => [id, 0]))\n const outgoing = new Map<string, string[]>()\n\n for (const link of links) {\n indegree.set(link.targetId, (indegree.get(link.targetId) ?? 0) + 1)\n outgoing.set(link.sourceId, [...(outgoing.get(link.sourceId) ?? []), link.targetId])\n }\n\n const queue = ids.filter((id) => (indegree.get(id) ?? 0) === 0)\n const ordered: string[] = []\n\n while (queue.length) {\n const current = queue.shift()!\n ordered.push(current)\n for (const target of outgoing.get(current) ?? []) {\n indegree.set(target, (indegree.get(target) ?? 1) - 1)\n if (indegree.get(target) === 0) {\n queue.push(target)\n }\n }\n }\n\n return ordered.length === ids.length ? ordered : ids\n}\n\nfunction cloneTask(task: GanttTask): GanttTask {\n return {\n ...task,\n plan: { ...task.plan },\n actual: { ...task.actual },\n dependencies: task.dependencies?.map((dependency) => ({ ...dependency }))\n }\n}\n\nexport function shiftTask(task: GanttTask, start: string | Date): GanttTask {\n const currentStart = toDate(task.actual.start)\n const nextStart = toDate(start)\n const delta = diffDays(currentStart, nextStart)\n return {\n ...task,\n actual: {\n ...task.actual,\n start: nextStart,\n end: addDays(toDate(task.actual.end), delta)\n }\n }\n}\n","import type { GanttConfig, GanttLink, GanttTask, Result, TaskLayout, Viewport } from \"../types\"\nimport { defaultConfig } from \"../types\"\nimport { flattenTasks } from \"../services/flattenTasks\"\nimport { normalizeLinks } from \"../services/normalizeLinks\"\nimport { scheduleByDependencies } from \"./scheduling\"\nimport { diffDays, inclusiveDays, isValidDate, toDate } from \"../utils/date\"\n\nexport function computeLayout(\n tasks: GanttTask[],\n links: GanttLink[],\n config: Partial<GanttConfig>,\n collapsedIds: Set<string> = new Set(),\n viewport?: Viewport\n): Result<TaskLayout[]> {\n const mergedConfig = { ...defaultConfig, ...config }\n\n for (const task of tasks) {\n if (!isValidDate(task.actual.start) || !isValidDate(task.actual.end)) {\n return {\n ok: false,\n error: {\n code: \"INVALID_DATE\",\n message: `Task ${task.id} has invalid actual dates.`\n }\n }\n }\n }\n\n const normalizedLinks = normalizeLinks(tasks, links)\n const scheduled = mergedConfig.autoSchedule === false\n ? { ok: true as const, data: tasks }\n : scheduleByDependencies(tasks, normalizedLinks)\n\n if (!scheduled.ok) {\n return scheduled\n }\n\n const flatTasks = flattenTasks(scheduled.data, collapsedIds)\n const firstDate = mergedConfig.visibleRange\n ? toDate(mergedConfig.visibleRange.start)\n : minDate(scheduled.data.map((task) => toDate(task.actual.start)))\n\n const visibleStart = viewport\n ? Math.max(0, Math.floor(viewport.scrollTop / mergedConfig.rowHeight) - 8)\n : 0\n const visibleEnd = viewport\n ? Math.ceil((viewport.scrollTop + viewport.clientHeight) / mergedConfig.rowHeight) + 8\n : Number.POSITIVE_INFINITY\n\n const layouts = flatTasks\n .filter((flat) => flat.rowIndex >= visibleStart && flat.rowIndex <= visibleEnd)\n .map<TaskLayout>((flat) => {\n const start = toDate(flat.task.actual.start)\n const end = toDate(flat.task.actual.end)\n const duration = flat.task.type === \"milestone\" ? 0 : inclusiveDays(start, end)\n\n return {\n taskId: flat.task.id,\n rowIndex: flat.rowIndex,\n left: diffDays(firstDate, start) * mergedConfig.columnWidth,\n width: Math.max(flat.task.type === \"milestone\" ? mergedConfig.columnWidth / 2 : mergedConfig.columnWidth, duration * mergedConfig.columnWidth),\n top: mergedConfig.headerHeight + flat.rowIndex * mergedConfig.rowHeight,\n depth: flat.depth,\n isCritical: false\n }\n })\n\n return { ok: true, data: layouts }\n}\n\nfunction minDate(dates: Date[]): Date {\n return new Date(Math.min(...dates.map((date) => date.getTime())))\n}\n","import type { AffectedTasks, GanttConfig, GanttLink, GanttTask, PatchTask, Result } from \"../types\"\nimport { flattenTasks } from \"../services/flattenTasks\"\nimport { scheduleByDependencies, shiftTask } from \"./scheduling\"\nimport { addDays, inclusiveDays, toDate } from \"../utils/date\"\n\nexport function computeImpact(\n taskId: string,\n patch: PatchTask,\n tasks: GanttTask[],\n links: GanttLink[],\n config: Partial<GanttConfig>\n): Result<AffectedTasks> {\n const target = tasks.find((task) => task.id === taskId)\n if (!target) {\n return {\n ok: false,\n error: {\n code: \"MISSING_TASK\",\n message: `Task ${taskId} does not exist.`\n }\n }\n }\n\n const patchedTasks = tasks.map((task) => {\n if (task.id !== taskId) {\n return task\n }\n\n let next = { ...task, actual: { ...task.actual } }\n if (patch.actualStart) {\n next = shiftTask(next, patch.actualStart)\n }\n if (patch.actualEnd) {\n next.actual.end = patch.actualEnd\n }\n if (typeof patch.progress === \"number\") {\n next.actual.progress = patch.progress\n }\n if (patch.duration) {\n next.duration = patch.duration\n next.actual.end = addDays(toDate(next.actual.start), Math.max(0, patch.duration - 1))\n }\n if (patch.name) {\n next.name = patch.name\n }\n if (patch.type) {\n next.type = patch.type\n }\n if (\"parentId\" in patch) {\n next.parentId = patch.parentId\n }\n if (patch.color) {\n next.color = patch.color\n }\n if (\"planColor\" in patch) {\n next.planColor = patch.planColor\n }\n if (patch.schedulingMode) {\n next.schedulingMode = patch.schedulingMode\n }\n return next\n })\n\n const scheduled = config.autoSchedule === false\n ? { ok: true as const, data: patchedTasks }\n : scheduleByDependencies(patchedTasks, links)\n\n if (!scheduled.ok) {\n return scheduled\n }\n\n const rows = new Map(flattenTasks(scheduled.data).map((flat) => [flat.task.id, flat.rowIndex]))\n const originalById = new Map(tasks.map((task) => [task.id, task]))\n const changed = scheduled.data\n .filter((task) => {\n const original = originalById.get(task.id)\n return original && (\n String(original.actual.start) !== String(task.actual.start) ||\n String(original.actual.end) !== String(task.actual.end)\n )\n })\n .map((task) => ({\n taskId: task.id,\n actualStart: task.actual.start,\n actualEnd: task.actual.end,\n rowIndex: rows.get(task.id) ?? 0\n }))\n\n const conflicts = scheduled.data\n .filter((task) => task.constraint?.date && inclusiveDays(task.actual.start, task.constraint.date) < 0)\n .map((task) => ({\n taskId: task.id,\n constraintType: task.constraint!.type,\n message: \"Task violates its configured constraint date.\"\n }))\n\n return { ok: true, data: { changed, conflicts } }\n}\n"],"mappings":"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","names":["end"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/types/index.ts","../src/services/checkCyclicDependency.ts","../src/services/normalizeLinks.ts","../src/services/flattenTasks.ts","../src/utils/date.ts","../src/services/computeTimeScale.ts","../src/engines/scheduling.ts","../src/engines/computeLayout.ts","../src/engines/computeImpact.ts","../src/engine/GanttEngine.ts"],"sourcesContent":["export * from \"./types\"\nexport * from \"./services/checkCyclicDependency\"\nexport * from \"./services/normalizeLinks\"\nexport * from \"./services/flattenTasks\"\nexport * from \"./services/computeTimeScale\"\nexport * from \"./engines/computeLayout\"\nexport * from \"./engines/computeImpact\"\nexport * from \"./engines/scheduling\"\nexport * from \"./utils/date\"\nexport * from \"./engine/GanttEngine\"\n","export type ViewMode = \"day\" | \"week\" | \"month\" | \"quarter\" | \"year\"\n\nexport type LinkType = \"FS\" | \"SS\" | \"FF\" | \"SF\"\nexport type LagUnit = \"calendar\" | \"working\"\n\nexport type Result<T> =\n | { ok: true; data: T }\n | { ok: false; error: GanttError }\n\nexport interface GanttError {\n code:\n | \"CYCLE_DEPENDENCY\"\n | \"INVALID_DATE\"\n | \"MISSING_TASK\"\n | \"ORPHAN_DEPENDENCY\"\n | \"INVALID_DEPENDENCY\"\n message: string\n details?: unknown\n}\n\nexport interface DateRange {\n start: string | Date\n end: string | Date\n progress?: number\n}\n\nexport interface Dependency {\n id?: string\n predecessorId: string\n type: LinkType\n lag: number\n lagUnit: LagUnit\n}\n\nexport interface GanttTask {\n id: string\n name: string\n type: \"task\" | \"milestone\" | \"summary\"\n plan: DateRange\n actual: Required<DateRange>\n dependencies?: Dependency[]\n parentId?: string | null\n color?: string\n planColor?: string\n calendarId?: string\n resources?: string[]\n segments?: Array<{ start: string | Date; end: string | Date }>\n constraint?: {\n type: \"SNET\" | \"SNLT\" | \"MSO\" | \"MFO\" | \"ASAP\" | \"ALAP\"\n date?: string | Date\n }\n schedulingMode?: \"auto\" | \"manual\"\n duration?: number\n custom?: Record<string, unknown>\n}\n\nexport interface GanttMarker {\n id: string\n name: string\n date: string | Date\n color?: string\n}\n\nexport interface GanttEditorField {\n key: string\n label: string\n visible?: boolean\n editable?: boolean\n type?: \"text\" | \"number\" | \"date\" | \"select\"\n options?: Array<{ label: string; value: string | number }>\n placeholder?: string\n}\n\nexport interface CustomColumn {\n key: string\n label: string\n width?: number\n visible?: boolean\n align?: \"left\" | \"center\" | \"right\"\n editable?: boolean\n type?: \"text\" | \"number\" | \"date\" | \"select\"\n options?: Array<{ label: string; value: string | number }>\n placeholder?: string\n editor?: Omit<GanttEditorField, \"key\" | \"label\">\n formatter?: (value: unknown, task: GanttTask) => string\n cellClass?: string | ((task: GanttTask) => string)\n cellStyle?: Record<string, string | number> | ((task: GanttTask) => Record<string, string | number>)\n render?: (task: GanttTask) => { text: string; className?: string }\n}\n\nexport interface GanttConfig {\n viewMode: ViewMode\n rowHeight: number\n columnWidth: number\n headerHeight: number\n taskListWidth: number\n width?: string | number\n height?: string | number\n locale: string\n firstDayOfWeek: 0 | 1\n dateFormat: string\n customColumns?: CustomColumn[]\n columns?: CustomColumn[]\n editorFields?: GanttEditorField[]\n columnWidths?: Partial<Record<ViewMode, number>>\n theme?: \"light\" | \"dark\" | string\n visibleRange?: {\n start: string | Date\n end: string | Date\n }\n showPlanBar?: boolean\n showActualBar?: boolean\n showTimelineWhenEmpty?: boolean\n builtInTaskEditor?: boolean\n builtInMarkerEditor?: boolean\n editablePlan?: boolean\n editableActual?: boolean\n enableLinkCreation?: boolean\n showLinkRejectionNotice?: boolean\n virtualScroll?: boolean\n taskColors?: {\n task?: string\n summary?: string\n milestone?: string\n plan?: string\n progress?: string\n }\n autoSchedule?: boolean\n editable?: boolean\n}\n\nexport interface GanttLink {\n id: string\n sourceId: string\n targetId: string\n type: LinkType\n lag?: number\n lagUnit?: LagUnit\n}\n\nexport interface TaskLayout {\n taskId: string\n rowIndex: number\n left: number\n width: number\n top: number\n depth: number\n isCritical: boolean\n}\n\nexport interface FlatTask {\n task: GanttTask\n depth: number\n rowIndex: number\n hasChildren: boolean\n collapsed: boolean\n}\n\nexport interface Calendar {\n id: string\n workingDays: number[]\n holidays: string[]\n hours: [number, number][]\n}\n\nexport interface TimeScale {\n start: Date\n end: Date\n left: number\n width: number\n}\n\nexport interface Viewport {\n scrollTop: number\n scrollLeft: number\n clientWidth: number\n clientHeight: number\n dpr: number\n}\n\nexport interface AffectedTasks {\n changed: Array<{\n taskId: string\n actualStart: string | Date\n actualEnd: string | Date\n rowIndex: number\n }>\n conflicts: Array<{\n taskId: string\n constraintType: string\n message: string\n }>\n}\n\nexport interface PatchTask {\n planStart?: string | Date\n planEnd?: string | Date\n actualStart?: string | Date\n actualEnd?: string | Date\n progress?: number\n name?: string\n type?: GanttTask[\"type\"]\n parentId?: string | null\n color?: string\n planColor?: string\n duration?: number\n schedulingMode?: \"auto\" | \"manual\"\n resources?: string[]\n calendarId?: string\n custom?: Record<string, unknown>\n}\n\nexport const defaultConfig: GanttConfig = {\n viewMode: \"month\",\n rowHeight: 44,\n columnWidth: 30,\n headerHeight: 50,\n taskListWidth: 280,\n locale: \"zh-CN\",\n firstDayOfWeek: 0,\n dateFormat: \"YYYY-MM-DD\",\n showPlanBar: true,\n showActualBar: true,\n showTimelineWhenEmpty: false,\n builtInTaskEditor: true,\n builtInMarkerEditor: true,\n editablePlan: false,\n editableActual: true,\n enableLinkCreation: true,\n showLinkRejectionNotice: true,\n virtualScroll: true,\n taskColors: {\n task: \"#2563eb\",\n summary: \"#475467\",\n milestone: \"#d97706\",\n plan: \"#cbd5e1\",\n progress: \"#0f766e\"\n },\n autoSchedule: true,\n editable: true\n}\n","import type { GanttLink } from \"../types\"\n\nexport function checkCyclicDependency(\n links: GanttLink[]\n): { hasCycle: boolean; cyclePath?: string[] } {\n const graph = new Map<string, string[]>()\n\n for (const link of links) {\n const targets = graph.get(link.sourceId) ?? []\n targets.push(link.targetId)\n graph.set(link.sourceId, targets)\n if (!graph.has(link.targetId)) {\n graph.set(link.targetId, [])\n }\n }\n\n const visiting = new Set<string>()\n const visited = new Set<string>()\n const path: string[] = []\n\n const dfs = (node: string): string[] | undefined => {\n if (visiting.has(node)) {\n const start = path.indexOf(node)\n return [...path.slice(start), node]\n }\n if (visited.has(node)) {\n return undefined\n }\n\n visiting.add(node)\n path.push(node)\n\n for (const next of graph.get(node) ?? []) {\n const cycle = dfs(next)\n if (cycle) {\n return cycle\n }\n }\n\n path.pop()\n visiting.delete(node)\n visited.add(node)\n return undefined\n }\n\n for (const node of graph.keys()) {\n const cyclePath = dfs(node)\n if (cyclePath) {\n return { hasCycle: true, cyclePath }\n }\n }\n\n return { hasCycle: false }\n}\n","import type { GanttLink, GanttTask } from \"../types\"\n\nexport function normalizeLinks(tasks: GanttTask[], standaloneLinks: GanttLink[] = []): GanttLink[] {\n const taskIds = new Set(tasks.map((task) => task.id))\n const byTaskPair = new Map<string, GanttLink>()\n const outgoing = new Map<string, Set<string>>()\n\n const createsCycle = (sourceId: string, targetId: string): boolean => {\n const pending = [targetId]\n const visited = new Set<string>()\n while (pending.length > 0) {\n const current = pending.pop()!\n if (current === sourceId) {\n return true\n }\n if (visited.has(current)) {\n continue\n }\n visited.add(current)\n pending.push(...(outgoing.get(current) ?? []))\n }\n return false\n }\n\n const append = (link: GanttLink) => {\n if (\n !taskIds.has(link.sourceId)\n || !taskIds.has(link.targetId)\n || link.sourceId === link.targetId\n ) {\n return\n }\n\n const normalized: GanttLink = {\n ...link,\n id: link.id || `link-${link.sourceId}-${link.targetId}`,\n lag: link.lag ?? 0,\n lagUnit: link.lagUnit ?? \"calendar\"\n }\n const pairKey = `${normalized.sourceId}|${normalized.targetId}`\n if (byTaskPair.has(pairKey) || createsCycle(normalized.sourceId, normalized.targetId)) {\n return\n }\n\n byTaskPair.set(pairKey, normalized)\n const targets = outgoing.get(normalized.sourceId) ?? new Set<string>()\n targets.add(normalized.targetId)\n outgoing.set(normalized.sourceId, targets)\n }\n\n for (const task of tasks) {\n for (const dependency of task.dependencies ?? []) {\n append({\n id: dependency.id || `link-${dependency.predecessorId}-${task.id}`,\n sourceId: dependency.predecessorId,\n targetId: task.id,\n type: dependency.type,\n lag: dependency.lag,\n lagUnit: dependency.lagUnit\n })\n }\n }\n\n for (const link of standaloneLinks) {\n append(link)\n }\n\n return [...byTaskPair.values()]\n}\n","import type { FlatTask, GanttTask } from \"../types\"\n\nexport function flattenTasks(tasks: GanttTask[], collapsedIds: Set<string> = new Set()): FlatTask[] {\n const children = new Map<string | null, GanttTask[]>()\n\n for (const task of tasks) {\n const parentId = task.parentId ?? null\n const bucket = children.get(parentId) ?? []\n bucket.push(task)\n children.set(parentId, bucket)\n }\n\n const flattened: FlatTask[] = []\n const visit = (task: GanttTask, depth: number) => {\n const childTasks = children.get(task.id) ?? []\n const collapsed = collapsedIds.has(task.id)\n\n flattened.push({\n task,\n depth,\n rowIndex: flattened.length,\n hasChildren: childTasks.length > 0,\n collapsed\n })\n\n if (!collapsed) {\n for (const child of childTasks) {\n visit(child, depth + 1)\n }\n }\n }\n\n for (const root of children.get(null) ?? []) {\n visit(root, 0)\n }\n\n return flattened\n}\n","import type { Result } from \"../types\"\n\nexport const DAY_MS = 24 * 60 * 60 * 1000\n\nexport function toDate(value: string | Date): Date {\n if (value instanceof Date) {\n return startOfDay(value)\n }\n\n const match = /^(\\d{4})-(\\d{2})-(\\d{2})/.exec(value)\n if (match) {\n return new Date(Number(match[1]), Number(match[2]) - 1, Number(match[3]))\n }\n\n return startOfDay(new Date(value))\n}\n\nexport function startOfDay(date: Date): Date {\n return new Date(date.getFullYear(), date.getMonth(), date.getDate())\n}\n\nexport function addDays(date: string | Date, days: number): Date {\n const next = toDate(date)\n next.setDate(next.getDate() + days)\n return startOfDay(next)\n}\n\nexport function diffDays(start: string | Date, end: string | Date): number {\n return Math.round((toDate(end).getTime() - toDate(start).getTime()) / DAY_MS)\n}\n\nexport function inclusiveDays(start: string | Date, end: string | Date): number {\n return Math.max(0, diffDays(start, end) + 1)\n}\n\nexport function isValidDate(value: string | Date): boolean {\n const date = value instanceof Date ? value : new Date(value)\n return !Number.isNaN(date.getTime())\n}\n\nexport function formatDate(date: string | Date): string {\n const value = toDate(date)\n const year = value.getFullYear()\n const month = String(value.getMonth() + 1).padStart(2, \"0\")\n const day = String(value.getDate()).padStart(2, \"0\")\n return `${year}-${month}-${day}`\n}\n\nexport function resultInvalidDate<T>(message: string, details?: unknown): Result<T> {\n return {\n ok: false,\n error: { code: \"INVALID_DATE\", message, details }\n }\n}\n","import type { TimeScale, ViewMode } from \"../types\"\nimport { addDays, diffDays, startOfDay } from \"../utils/date\"\n\nexport function computeTimeScale(\n start: Date,\n end: Date,\n viewMode: ViewMode,\n columnWidth: number,\n firstDayOfWeek: 0 | 1\n): TimeScale[] {\n const rangeStart = alignStart(start, viewMode, firstDayOfWeek)\n const endDate = startOfDay(end)\n const rangeEnd = viewMode === \"day\"\n ? addDays(endDate, (firstDayOfWeek + 6 - endDate.getDay() + 7) % 7)\n : endDate\n const scale: TimeScale[] = []\n let cursor = rangeStart\n let left = 0\n\n while (cursor.getTime() <= rangeEnd.getTime()) {\n const next = nextUnit(cursor, viewMode)\n const unitEnd = addDays(next, -1)\n const width = Math.max(1, diffDays(cursor, next)) * columnWidth\n\n scale.push({\n start: cursor,\n end: unitEnd,\n left,\n width\n })\n\n left += width\n cursor = next\n }\n\n return scale\n}\n\nfunction alignStart(date: Date, viewMode: ViewMode, firstDayOfWeek: 0 | 1): Date {\n const start = startOfDay(date)\n if (viewMode === \"day\" || viewMode === \"week\") {\n const delta = (start.getDay() - firstDayOfWeek + 7) % 7\n return addDays(start, -delta)\n }\n if (viewMode === \"month\") {\n return new Date(start.getFullYear(), start.getMonth(), 1)\n }\n if (viewMode === \"quarter\") {\n return new Date(start.getFullYear(), Math.floor(start.getMonth() / 3) * 3, 1)\n }\n if (viewMode === \"year\") {\n return new Date(start.getFullYear(), 0, 1)\n }\n return start\n}\n\nfunction nextUnit(date: Date, viewMode: ViewMode): Date {\n if (viewMode === \"week\") {\n return addDays(date, 7)\n }\n if (viewMode === \"month\") {\n return new Date(date.getFullYear(), date.getMonth() + 1, 1)\n }\n if (viewMode === \"quarter\") {\n return new Date(date.getFullYear(), date.getMonth() + 3, 1)\n }\n if (viewMode === \"year\") {\n return new Date(date.getFullYear() + 1, 0, 1)\n }\n return addDays(date, 1)\n}\n","import type { GanttLink, GanttTask, LinkType, Result } from \"../types\"\nimport { addDays, diffDays, inclusiveDays, toDate } from \"../utils/date\"\nimport { checkCyclicDependency } from \"../services/checkCyclicDependency\"\n\nexport function scheduleByDependencies(tasks: GanttTask[], links: GanttLink[]): Result<GanttTask[]> {\n const cycle = checkCyclicDependency(links)\n if (cycle.hasCycle) {\n return {\n ok: false,\n error: {\n code: \"CYCLE_DEPENDENCY\",\n message: \"Dependency graph contains a cycle.\",\n details: cycle.cyclePath\n }\n }\n }\n\n const taskMap = new Map(tasks.map((task) => [task.id, cloneTask(task)]))\n const incoming = new Map<string, GanttLink[]>()\n const outgoing = new Map<string, GanttLink[]>()\n\n for (const link of links) {\n const source = taskMap.get(link.sourceId)\n const target = taskMap.get(link.targetId)\n if (!source || !target) {\n return {\n ok: false,\n error: {\n code: \"ORPHAN_DEPENDENCY\",\n message: `Dependency ${link.id} references a missing task.`\n }\n }\n }\n incoming.set(link.targetId, [...(incoming.get(link.targetId) ?? []), link])\n outgoing.set(link.sourceId, [...(outgoing.get(link.sourceId) ?? []), link])\n }\n\n const ordered = topologicalOrder(tasks.map((task) => task.id), links)\n\n for (const taskId of ordered) {\n const task = taskMap.get(taskId)\n if (!task || task.schedulingMode === \"manual\") {\n continue\n }\n\n const linksToTask = incoming.get(taskId) ?? []\n let start = toDate(task.actual.start)\n let end = toDate(task.actual.end)\n const duration = Math.max(0, task.duration ?? inclusiveDays(start, end))\n\n for (const link of linksToTask) {\n const source = taskMap.get(link.sourceId)\n if (!source) {\n continue\n }\n\n const candidate = applyDependency(source, start, end, duration, link.type, link.lag ?? 0)\n if (candidate.start.getTime() > start.getTime()) {\n start = candidate.start\n }\n if (candidate.end.getTime() > end.getTime()) {\n end = candidate.end\n }\n }\n\n const normalizedEnd = task.type === \"milestone\" ? start : addDays(start, Math.max(0, duration - 1))\n task.actual = {\n ...task.actual,\n start,\n end: normalizedEnd\n }\n }\n\n return { ok: true, data: tasks.map((task) => taskMap.get(task.id) ?? task) }\n}\n\nfunction applyDependency(\n source: GanttTask,\n currentStart: Date,\n currentEnd: Date,\n duration: number,\n type: LinkType,\n lag: number\n): { start: Date; end: Date } {\n const sourceStart = toDate(source.actual.start)\n const sourceEnd = toDate(source.actual.end)\n const span = Math.max(0, duration - 1)\n\n if (type === \"FS\") {\n const start = addDays(sourceEnd, lag + 1)\n return { start, end: addDays(start, span) }\n }\n\n if (type === \"SS\") {\n const start = addDays(sourceStart, lag)\n return { start, end: addDays(start, span) }\n }\n\n if (type === \"FF\") {\n const end = addDays(sourceEnd, lag)\n return { start: addDays(end, -span), end }\n }\n\n const end = addDays(sourceStart, lag)\n return { start: addDays(end, -span), end: end.getTime() > currentEnd.getTime() ? end : currentEnd }\n}\n\nfunction topologicalOrder(ids: string[], links: GanttLink[]): string[] {\n const indegree = new Map(ids.map((id) => [id, 0]))\n const outgoing = new Map<string, string[]>()\n\n for (const link of links) {\n indegree.set(link.targetId, (indegree.get(link.targetId) ?? 0) + 1)\n outgoing.set(link.sourceId, [...(outgoing.get(link.sourceId) ?? []), link.targetId])\n }\n\n const queue = ids.filter((id) => (indegree.get(id) ?? 0) === 0)\n const ordered: string[] = []\n\n while (queue.length) {\n const current = queue.shift()!\n ordered.push(current)\n for (const target of outgoing.get(current) ?? []) {\n indegree.set(target, (indegree.get(target) ?? 1) - 1)\n if (indegree.get(target) === 0) {\n queue.push(target)\n }\n }\n }\n\n return ordered.length === ids.length ? ordered : ids\n}\n\nfunction cloneTask(task: GanttTask): GanttTask {\n return {\n ...task,\n plan: { ...task.plan },\n actual: { ...task.actual },\n dependencies: task.dependencies?.map((dependency) => ({ ...dependency }))\n }\n}\n\nexport function shiftTask(task: GanttTask, start: string | Date): GanttTask {\n const currentStart = toDate(task.actual.start)\n const nextStart = toDate(start)\n const delta = diffDays(currentStart, nextStart)\n return {\n ...task,\n actual: {\n ...task.actual,\n start: nextStart,\n end: addDays(toDate(task.actual.end), delta)\n }\n }\n}\n","import type { GanttConfig, GanttLink, GanttTask, Result, TaskLayout, Viewport } from \"../types\"\nimport { defaultConfig } from \"../types\"\nimport { flattenTasks } from \"../services/flattenTasks\"\nimport { normalizeLinks } from \"../services/normalizeLinks\"\nimport { scheduleByDependencies } from \"./scheduling\"\nimport { diffDays, inclusiveDays, isValidDate, toDate } from \"../utils/date\"\n\nexport function computeLayout(\n tasks: GanttTask[],\n links: GanttLink[],\n config: Partial<GanttConfig>,\n collapsedIds: Set<string> = new Set(),\n viewport?: Viewport\n): Result<TaskLayout[]> {\n const mergedConfig = { ...defaultConfig, ...config }\n\n for (const task of tasks) {\n if (!isValidDate(task.actual.start) || !isValidDate(task.actual.end)) {\n return {\n ok: false,\n error: {\n code: \"INVALID_DATE\",\n message: `Task ${task.id} has invalid actual dates.`\n }\n }\n }\n }\n\n const normalizedLinks = normalizeLinks(tasks, links)\n const scheduled = mergedConfig.autoSchedule === false\n ? { ok: true as const, data: tasks }\n : scheduleByDependencies(tasks, normalizedLinks)\n\n if (!scheduled.ok) {\n return scheduled\n }\n\n const flatTasks = flattenTasks(scheduled.data, collapsedIds)\n const firstDate = mergedConfig.visibleRange\n ? toDate(mergedConfig.visibleRange.start)\n : minDate(scheduled.data.map((task) => toDate(task.actual.start)))\n\n const visibleStart = viewport\n ? Math.max(0, Math.floor(viewport.scrollTop / mergedConfig.rowHeight) - 8)\n : 0\n const visibleEnd = viewport\n ? Math.ceil((viewport.scrollTop + viewport.clientHeight) / mergedConfig.rowHeight) + 8\n : Number.POSITIVE_INFINITY\n\n const layouts = flatTasks\n .filter((flat) => flat.rowIndex >= visibleStart && flat.rowIndex <= visibleEnd)\n .map<TaskLayout>((flat) => {\n const start = toDate(flat.task.actual.start)\n const end = toDate(flat.task.actual.end)\n const duration = flat.task.type === \"milestone\" ? 0 : inclusiveDays(start, end)\n\n return {\n taskId: flat.task.id,\n rowIndex: flat.rowIndex,\n left: diffDays(firstDate, start) * mergedConfig.columnWidth,\n width: Math.max(flat.task.type === \"milestone\" ? mergedConfig.columnWidth / 2 : mergedConfig.columnWidth, duration * mergedConfig.columnWidth),\n top: mergedConfig.headerHeight + flat.rowIndex * mergedConfig.rowHeight,\n depth: flat.depth,\n isCritical: false\n }\n })\n\n return { ok: true, data: layouts }\n}\n\nfunction minDate(dates: Date[]): Date {\n return new Date(Math.min(...dates.map((date) => date.getTime())))\n}\n","import type { AffectedTasks, GanttConfig, GanttLink, GanttTask, PatchTask, Result } from \"../types\"\nimport { flattenTasks } from \"../services/flattenTasks\"\nimport { scheduleByDependencies, shiftTask } from \"./scheduling\"\nimport { addDays, inclusiveDays, toDate } from \"../utils/date\"\n\nexport function computeImpact(\n taskId: string,\n patch: PatchTask,\n tasks: GanttTask[],\n links: GanttLink[],\n config: Partial<GanttConfig>\n): Result<AffectedTasks> {\n const target = tasks.find((task) => task.id === taskId)\n if (!target) {\n return {\n ok: false,\n error: {\n code: \"MISSING_TASK\",\n message: `Task ${taskId} does not exist.`\n }\n }\n }\n\n const patchedTasks = tasks.map((task) => {\n if (task.id !== taskId) {\n return task\n }\n\n let next = { ...task, actual: { ...task.actual } }\n if (patch.actualStart) {\n next = shiftTask(next, patch.actualStart)\n }\n if (patch.actualEnd) {\n next.actual.end = patch.actualEnd\n }\n if (typeof patch.progress === \"number\") {\n next.actual.progress = patch.progress\n }\n if (patch.duration) {\n next.duration = patch.duration\n next.actual.end = addDays(toDate(next.actual.start), Math.max(0, patch.duration - 1))\n }\n if (patch.name) {\n next.name = patch.name\n }\n if (patch.type) {\n next.type = patch.type\n }\n if (\"parentId\" in patch) {\n next.parentId = patch.parentId\n }\n if (patch.color) {\n next.color = patch.color\n }\n if (\"planColor\" in patch) {\n next.planColor = patch.planColor\n }\n if (patch.schedulingMode) {\n next.schedulingMode = patch.schedulingMode\n }\n return next\n })\n\n const scheduled = config.autoSchedule === false\n ? { ok: true as const, data: patchedTasks }\n : scheduleByDependencies(patchedTasks, links)\n\n if (!scheduled.ok) {\n return scheduled\n }\n\n const rows = new Map(flattenTasks(scheduled.data).map((flat) => [flat.task.id, flat.rowIndex]))\n const originalById = new Map(tasks.map((task) => [task.id, task]))\n const changed = scheduled.data\n .filter((task) => {\n const original = originalById.get(task.id)\n return original && (\n String(original.actual.start) !== String(task.actual.start) ||\n String(original.actual.end) !== String(task.actual.end)\n )\n })\n .map((task) => ({\n taskId: task.id,\n actualStart: task.actual.start,\n actualEnd: task.actual.end,\n rowIndex: rows.get(task.id) ?? 0\n }))\n\n const conflicts = scheduled.data\n .filter((task) => task.constraint?.date && inclusiveDays(task.actual.start, task.constraint.date) < 0)\n .map((task) => ({\n taskId: task.id,\n constraintType: task.constraint!.type,\n message: \"Task violates its configured constraint date.\"\n }))\n\n return { ok: true, data: { changed, conflicts } }\n}\n","import type {\n GanttConfig,\n GanttTask,\n GanttLink,\n GanttMarker,\n PatchTask,\n TaskLayout,\n TimeScale,\n FlatTask,\n Result\n} from \"../types\"\nimport { defaultConfig } from \"../types\"\nimport { computeLayout } from \"../engines/computeLayout\"\nimport { computeTimeScale } from \"../services/computeTimeScale\"\nimport { flattenTasks } from \"../services/flattenTasks\"\nimport { toDate, diffDays, addDays } from \"../utils/date\"\n\n/**\n * 把扁平的 PatchTask 合并回嵌套的 GanttTask。\n * PatchTask 用 planStart/planEnd/actualStart/actualEnd 表示日期,\n * GanttTask 用 plan.start/end、actual.start/end 嵌套表示——这是组件层\n * 和数据层之间的桥,本该在引擎层而不是散落在各 demo 里。\n */\nexport function mergeTaskPatch(task: GanttTask, patch: PatchTask): GanttTask {\n return {\n ...task,\n ...patch,\n plan: {\n ...task.plan,\n start: patch.planStart ?? task.plan.start,\n end: patch.planEnd ?? task.plan.end,\n progress: patch.progress ?? task.plan.progress\n },\n actual: {\n ...task.actual,\n start: patch.actualStart ?? task.actual.start,\n end: patch.actualEnd ?? task.actual.end,\n progress: patch.progress ?? task.actual.progress\n },\n custom: patch.custom ? { ...task.custom, ...patch.custom } : task.custom\n }\n}\n\nexport interface GanttEngineOptions {\n tasks?: GanttTask[]\n links?: GanttLink[]\n config?: Partial<GanttConfig>\n /** 滚动容器元素;命令式视口 API(scrollToDate / zoomToFit)需要它。纯计算场景可不传。 */\n container?: HTMLElement | null\n /** 初始折叠的任务 id */\n collapsedIds?: Iterable<string>\n /** 里程碑标记 */\n markers?: GanttMarker[]\n}\n\nexport type GanttEngineEvent =\n | \"ready\"\n | \"taskschange\"\n | \"taskchange\"\n | \"taskcreate\"\n | \"taskdelete\"\n | \"linkschange\"\n | \"configchange\"\n | \"collapsechange\"\n | \"previewchange\"\n | \"markerschange\"\n | \"destroy\"\n\ntype Listener = (...args: unknown[]) => void\n\n/** 命令式甘特图引擎。框架无关,可被 Vue/React/原生 各自的薄壳组件驱动。 */\nexport class GanttEngine {\n private tasks: GanttTask[]\n private links: GanttLink[]\n private config: GanttConfig\n private readonly container: HTMLElement | null\n private collapsedIds: Set<string>\n private dragPreview: { taskId: string; patch: PatchTask; affected?: Record<string, PatchTask> } | null = null\n private markers: GanttMarker[]\n private readonly listeners: Map<GanttEngineEvent, Set<Listener>>\n private destroyed = false\n\n constructor(options: GanttEngineOptions = {}) {\n this.tasks = options.tasks ? options.tasks.map((task) => ({ ...task })) : []\n this.links = options.links ? options.links.map((link) => ({ ...link })) : []\n this.config = { ...defaultConfig, ...options.config }\n this.container = options.container ?? null\n this.collapsedIds = new Set(options.collapsedIds ?? [])\n this.markers = options.markers ? options.markers.map((marker) => ({ ...marker })) : []\n this.listeners = new Map()\n // 异步发 ready,确保订阅者能在构造后、首次 emit 前注册\n queueMicrotask(() => this.emit(\"ready\"))\n }\n\n // ── 状态查询 ──\n getTasks(): GanttTask[] {\n return this.tasks.map((task) => ({ ...task }))\n }\n getLinks(): GanttLink[] {\n return this.links.map((link) => ({ ...link }))\n }\n getMarkers(): GanttMarker[] {\n return this.markers.map((marker) => ({ ...marker }))\n }\n getConfig(): GanttConfig {\n return { ...this.config }\n }\n getTask(id: string): GanttTask | undefined {\n const task = this.tasks.find((item) => item.id === id)\n return task ? { ...task } : undefined\n }\n getCollapsedIds(): string[] {\n return Array.from(this.collapsedIds)\n }\n isDestroyed(): boolean {\n return this.destroyed\n }\n\n // ── 命令式变更(均触发对应事件) ──\n setTasks(tasks: GanttTask[]): void {\n this.assertNotDestroyed()\n this.tasks = tasks.map((task) => ({ ...task }))\n this.emit(\"taskschange\", this.getTasks())\n }\n setLinks(links: GanttLink[]): void {\n this.assertNotDestroyed()\n this.links = links.map((link) => ({ ...link }))\n this.emit(\"linkschange\", this.getLinks())\n }\n setMarkers(markers: GanttMarker[]): void {\n this.assertNotDestroyed()\n this.markers = markers.map((marker) => ({ ...marker }))\n this.emit(\"markerschange\", this.getMarkers())\n }\n /** 合并配置 patch,等价于 setConfig(mergeConfig(patch)) */\n mergeConfig(patch: Partial<GanttConfig>): void {\n this.assertNotDestroyed()\n this.config = { ...this.config, ...patch }\n this.emit(\"configchange\", this.getConfig())\n }\n setConfig(config: Partial<GanttConfig>): void {\n this.mergeConfig(config)\n }\n /** 用 mergeTaskPatch 把扁平 patch 合并回嵌套结构后更新单个任务 */\n setTask(id: string, patch: PatchTask): void {\n this.assertNotDestroyed()\n const target = this.tasks.find((task) => task.id === id)\n if (!target) {\n return\n }\n const updated = mergeTaskPatch(target, patch)\n this.tasks = this.tasks.map((task) => (task.id === id ? updated : task))\n this.emit(\"taskchange\", id, patch, { ...updated })\n }\n addTask(task: GanttTask): void {\n this.assertNotDestroyed()\n this.tasks = [...this.tasks, { ...task }]\n this.emit(\"taskcreate\", { ...task })\n }\n removeTask(id: string): void {\n this.assertNotDestroyed()\n const removed = this.tasks.find((task) => task.id === id)\n if (!removed) return\n this.tasks = this.tasks.filter((task) => task.id !== id)\n this.collapsedIds.delete(id)\n this.emit(\"taskdelete\", id)\n }\n collapse(id: string, collapsed = true): void {\n this.assertNotDestroyed()\n if (collapsed) this.collapsedIds.add(id)\n else this.collapsedIds.delete(id)\n this.emit(\"collapsechange\", this.getCollapsedIds())\n }\n toggleCollapse(id: string): void {\n this.collapse(id, !this.collapsedIds.has(id))\n }\n /** 批量折叠/展开多个任务(如\"折叠全部分组\") */\n setCollapsed(ids: string[], collapsed = true): void {\n this.assertNotDestroyed()\n const next = new Set(this.collapsedIds)\n for (const id of ids) {\n if (collapsed) {\n next.add(id)\n } else {\n next.delete(id)\n }\n }\n this.collapsedIds = next\n this.emit(\"collapsechange\", this.getCollapsedIds())\n }\n\n // ── 拖拽预览(交互态源;组件写入迁移到 engine,dateRange 可据此扩展) ──\n setPreview(preview: { taskId: string; patch: PatchTask; affected?: Record<string, PatchTask> }): void {\n this.assertNotDestroyed()\n this.dragPreview = {\n taskId: preview.taskId,\n patch: { ...preview.patch },\n affected: preview.affected ? { ...preview.affected } : undefined\n }\n this.emit(\"previewchange\", this.getPreview())\n }\n clearPreview(): void {\n if (!this.dragPreview) {\n return\n }\n this.dragPreview = null\n this.emit(\"previewchange\", null)\n }\n getPreview(): { taskId: string; patch: PatchTask; affected?: Record<string, PatchTask> } | null {\n if (!this.dragPreview) {\n return null\n }\n return {\n taskId: this.dragPreview.taskId,\n patch: { ...this.dragPreview.patch },\n affected: this.dragPreview.affected ? { ...this.dragPreview.affected } : undefined\n }\n }\n\n // ── 计算(delegate 到 core 纯函数) ──\n /** 数据真实日期范围(未含 viewport pad) */\n getDateRange(): { start: Date; end: Date } {\n const dates: Date[] = []\n for (const task of this.tasks) {\n dates.push(\n toDate(task.plan.start),\n toDate(task.plan.end),\n toDate(task.actual.start),\n toDate(task.actual.end)\n )\n }\n for (const marker of this.markers) {\n dates.push(toDate(marker.date))\n }\n // 合并拖拽预览:用 mergeTaskPatch 算 patch 后日期扩范围(只扩不缩)\n const preview = this.dragPreview\n if (preview) {\n const ids = [preview.taskId, ...Object.keys(preview.affected ?? {})]\n for (const id of ids) {\n const task = this.tasks.find((item) => item.id === id)\n if (!task) {\n continue\n }\n const patch = preview.taskId === id ? preview.patch : preview.affected?.[id]\n if (!patch) {\n continue\n }\n const merged = mergeTaskPatch(task, patch)\n dates.push(\n toDate(merged.plan.start),\n toDate(merged.plan.end),\n toDate(merged.actual.start),\n toDate(merged.actual.end)\n )\n }\n }\n if (!dates.length) {\n const today = toDate(new Date())\n return { start: today, end: addDays(today, 30) }\n }\n return {\n start: new Date(Math.min(...dates.map((d) => d.getTime()))),\n end: new Date(Math.max(...dates.map((d) => d.getTime())))\n }\n }\n getTimeScale(): TimeScale[] {\n const range = this.getDateRange()\n return computeTimeScale(\n range.start,\n range.end,\n this.config.viewMode,\n this.config.columnWidth,\n this.config.firstDayOfWeek\n )\n }\n getLayout(): Result<TaskLayout[]> {\n return computeLayout(\n this.tasks,\n this.links,\n this.config,\n this.collapsedIds\n )\n }\n getFlatTasks(): FlatTask[] {\n return flattenTasks(this.tasks, this.collapsedIds)\n }\n getTotalWidth(): number {\n return this.getTimeScale().reduce((sum, tick) => sum + tick.width, 0)\n }\n getTotalHeight(): number {\n const rows = this.getFlatTasks().length\n return this.config.headerHeight + rows * this.config.rowHeight\n }\n\n // ── 视口命令(需要 container) ──\n getScrollLeft(): number {\n return this.container?.scrollLeft ?? 0\n }\n setScrollLeft(px: number): void {\n if (!this.container) return\n const max = Math.max(0, this.container.scrollWidth - this.container.clientWidth)\n this.container.scrollLeft = Math.max(0, Math.min(max, px))\n }\n /** 把当前 scrollLeft 限制到 [0, maxScrollLeft]。\n * 拖拽预览收缩(松手/取消)后 timeline 总宽度变小,scrollLeft 可能超出新边界,\n * 导致 canvas translate 超出内容区、右侧网格未覆盖。此时调用本方法防超界。 */\n clampScrollLeft(): void {\n if (!this.container) return\n const max = Math.max(0, this.container.scrollWidth - this.container.clientWidth)\n if (this.container.scrollLeft > max) {\n this.container.scrollLeft = max\n }\n }\n getScrollTop(): number {\n return this.container?.scrollTop ?? 0\n }\n setScrollTop(px: number): void {\n if (!this.container) return\n const max = Math.max(0, this.container.scrollHeight - this.container.clientHeight)\n this.container.scrollTop = Math.max(0, Math.min(max, px))\n }\n /** 滚动到包含目标日期的 tick 列(跨 viewMode 精确) */\n scrollToDate(date: string | Date): void {\n if (!this.container) return\n const target = toDate(date)\n const scale = this.getTimeScale()\n const tick = scale.find((t) => target >= t.start && target <= t.end)\n const left = tick ? tick.left : diffDays(this.getDateRange().start, target) * this.config.columnWidth\n this.setScrollLeft(left)\n }\n scrollToTask(id: string): void {\n const layout = this.getLayout()\n if (!layout.ok) return\n const item = layout.data.find((row) => row.taskId === id)\n if (item) this.setScrollLeft(item.left)\n }\n scrollToStart(): void {\n this.setScrollLeft(0)\n }\n scrollToEnd(): void {\n if (!this.container) return\n this.setScrollLeft(this.getTotalWidth())\n }\n /** 让整个 timeline 总宽度≈视口宽度(调 columnWidth) */\n zoomToFit(padding = 1): void {\n if (!this.container) return\n const spanDays = Math.max(1, diffDays(this.getDateRange().start, this.getDateRange().end) + 1)\n const target = (this.container.clientWidth * padding) / spanDays\n this.mergeConfig({ columnWidth: this.clampColumnWidth(target) })\n }\n /** 让指定日期范围占满视口宽度(调 columnWidth) */\n zoomToRange(start: string | Date, end: string | Date): void {\n if (!this.container) return\n const span = Math.max(1, diffDays(start, end) + 1)\n const target = this.container.clientWidth / span\n this.mergeConfig({ columnWidth: this.clampColumnWidth(target) })\n }\n private clampColumnWidth(value: number): number {\n return Math.max(4, Math.min(400, Math.round(value)))\n }\n\n // ── 事件订阅 ──\n on(event: GanttEngineEvent, fn: Listener): () => void {\n this.assertNotDestroyed()\n let set = this.listeners.get(event)\n if (!set) {\n set = new Set()\n this.listeners.set(event, set)\n }\n set.add(fn)\n return () => {\n const current = this.listeners.get(event)\n if (current) {\n current.delete(fn)\n if (!current.size) this.listeners.delete(event)\n }\n }\n }\n once(event: GanttEngineEvent, fn: Listener): () => void {\n const off = this.on(event, (...args: unknown[]) => {\n off()\n fn(...args)\n })\n return off\n }\n off(event: GanttEngineEvent, fn?: Listener): void {\n const set = this.listeners.get(event)\n if (!set) return\n if (fn) {\n set.delete(fn)\n if (!set.size) this.listeners.delete(event)\n } else {\n this.listeners.delete(event)\n }\n }\n emit(event: GanttEngineEvent, ...args: unknown[]): void {\n const set = this.listeners.get(event)\n if (!set) return\n // 复制遍历,避免回调中增删导致迭代错乱\n for (const fn of Array.from(set)) {\n try {\n fn(...args)\n } catch (error) {\n // 单个监听器抛错不应打断其他监听器\n if (typeof console !== \"undefined\") {\n console.error(`[GanttEngine] listener for \"${event}\" threw`, error)\n }\n }\n }\n }\n\n // ── 生命周期 ──\n destroy(): void {\n if (this.destroyed) return\n this.destroyed = true\n this.emit(\"destroy\")\n this.listeners.clear()\n this.tasks = []\n this.links = []\n }\n\n private assertNotDestroyed(): void {\n if (this.destroyed) {\n throw new Error(\"GanttEngine: operation on destroyed instance\")\n }\n }\n}\n\n/** 工厂函数,对应成熟做法的 new GanttEngine(container, config) 入口 */\nexport function createGanttEngine(options: GanttEngineOptions = {}): GanttEngine {\n return new GanttEngine(options)\n}\n"],"mappings":"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","names":["end"]}
|