ct-gantt-core 1.0.1

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 ADDED
@@ -0,0 +1,570 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ DAY_MS: () => DAY_MS,
24
+ addDays: () => addDays,
25
+ checkCyclicDependency: () => checkCyclicDependency,
26
+ computeImpact: () => computeImpact,
27
+ computeLayout: () => computeLayout,
28
+ computeTimeScale: () => computeTimeScale,
29
+ defaultConfig: () => defaultConfig,
30
+ diffDays: () => diffDays,
31
+ flattenTasks: () => flattenTasks,
32
+ formatDate: () => formatDate,
33
+ inclusiveDays: () => inclusiveDays,
34
+ isValidDate: () => isValidDate,
35
+ normalizeLinks: () => normalizeLinks,
36
+ resultInvalidDate: () => resultInvalidDate,
37
+ scheduleByDependencies: () => scheduleByDependencies,
38
+ shiftTask: () => shiftTask,
39
+ startOfDay: () => startOfDay,
40
+ toDate: () => toDate
41
+ });
42
+ module.exports = __toCommonJS(index_exports);
43
+
44
+ // src/types/index.ts
45
+ var defaultConfig = {
46
+ viewMode: "month",
47
+ rowHeight: 44,
48
+ columnWidth: 30,
49
+ headerHeight: 50,
50
+ taskListWidth: 280,
51
+ locale: "zh-CN",
52
+ firstDayOfWeek: 0,
53
+ dateFormat: "YYYY-MM-DD",
54
+ showPlanBar: true,
55
+ showActualBar: true,
56
+ showTimelineWhenEmpty: false,
57
+ builtInTaskEditor: true,
58
+ builtInMarkerEditor: true,
59
+ editablePlan: false,
60
+ editableActual: true,
61
+ enableLinkCreation: true,
62
+ showLinkRejectionNotice: true,
63
+ virtualScroll: true,
64
+ taskColors: {
65
+ task: "#2563eb",
66
+ summary: "#475467",
67
+ milestone: "#d97706",
68
+ plan: "#cbd5e1",
69
+ progress: "#0f766e"
70
+ },
71
+ autoSchedule: true,
72
+ editable: true
73
+ };
74
+
75
+ // src/services/checkCyclicDependency.ts
76
+ function checkCyclicDependency(links) {
77
+ const graph = /* @__PURE__ */ new Map();
78
+ for (const link of links) {
79
+ const targets = graph.get(link.sourceId) ?? [];
80
+ targets.push(link.targetId);
81
+ graph.set(link.sourceId, targets);
82
+ if (!graph.has(link.targetId)) {
83
+ graph.set(link.targetId, []);
84
+ }
85
+ }
86
+ const visiting = /* @__PURE__ */ new Set();
87
+ const visited = /* @__PURE__ */ new Set();
88
+ const path = [];
89
+ const dfs = (node) => {
90
+ if (visiting.has(node)) {
91
+ const start = path.indexOf(node);
92
+ return [...path.slice(start), node];
93
+ }
94
+ if (visited.has(node)) {
95
+ return void 0;
96
+ }
97
+ visiting.add(node);
98
+ path.push(node);
99
+ for (const next of graph.get(node) ?? []) {
100
+ const cycle = dfs(next);
101
+ if (cycle) {
102
+ return cycle;
103
+ }
104
+ }
105
+ path.pop();
106
+ visiting.delete(node);
107
+ visited.add(node);
108
+ return void 0;
109
+ };
110
+ for (const node of graph.keys()) {
111
+ const cyclePath = dfs(node);
112
+ if (cyclePath) {
113
+ return { hasCycle: true, cyclePath };
114
+ }
115
+ }
116
+ return { hasCycle: false };
117
+ }
118
+
119
+ // src/services/normalizeLinks.ts
120
+ function normalizeLinks(tasks, standaloneLinks = []) {
121
+ const taskIds = new Set(tasks.map((task) => task.id));
122
+ const byTaskPair = /* @__PURE__ */ new Map();
123
+ const outgoing = /* @__PURE__ */ new Map();
124
+ const createsCycle = (sourceId, targetId) => {
125
+ const pending = [targetId];
126
+ const visited = /* @__PURE__ */ new Set();
127
+ while (pending.length > 0) {
128
+ const current = pending.pop();
129
+ if (current === sourceId) {
130
+ return true;
131
+ }
132
+ if (visited.has(current)) {
133
+ continue;
134
+ }
135
+ visited.add(current);
136
+ pending.push(...outgoing.get(current) ?? []);
137
+ }
138
+ return false;
139
+ };
140
+ const append = (link) => {
141
+ if (!taskIds.has(link.sourceId) || !taskIds.has(link.targetId) || link.sourceId === link.targetId) {
142
+ return;
143
+ }
144
+ const normalized = {
145
+ ...link,
146
+ id: link.id || `link-${link.sourceId}-${link.targetId}`,
147
+ lag: link.lag ?? 0,
148
+ lagUnit: link.lagUnit ?? "calendar"
149
+ };
150
+ const pairKey = `${normalized.sourceId}|${normalized.targetId}`;
151
+ if (byTaskPair.has(pairKey) || createsCycle(normalized.sourceId, normalized.targetId)) {
152
+ return;
153
+ }
154
+ byTaskPair.set(pairKey, normalized);
155
+ const targets = outgoing.get(normalized.sourceId) ?? /* @__PURE__ */ new Set();
156
+ targets.add(normalized.targetId);
157
+ outgoing.set(normalized.sourceId, targets);
158
+ };
159
+ for (const task of tasks) {
160
+ for (const dependency of task.dependencies ?? []) {
161
+ append({
162
+ id: dependency.id || `link-${dependency.predecessorId}-${task.id}`,
163
+ sourceId: dependency.predecessorId,
164
+ targetId: task.id,
165
+ type: dependency.type,
166
+ lag: dependency.lag,
167
+ lagUnit: dependency.lagUnit
168
+ });
169
+ }
170
+ }
171
+ for (const link of standaloneLinks) {
172
+ append(link);
173
+ }
174
+ return [...byTaskPair.values()];
175
+ }
176
+
177
+ // src/services/flattenTasks.ts
178
+ function flattenTasks(tasks, collapsedIds = /* @__PURE__ */ new Set()) {
179
+ const children = /* @__PURE__ */ new Map();
180
+ for (const task of tasks) {
181
+ const parentId = task.parentId ?? null;
182
+ const bucket = children.get(parentId) ?? [];
183
+ bucket.push(task);
184
+ children.set(parentId, bucket);
185
+ }
186
+ const flattened = [];
187
+ const visit = (task, depth) => {
188
+ const childTasks = children.get(task.id) ?? [];
189
+ const collapsed = collapsedIds.has(task.id);
190
+ flattened.push({
191
+ task,
192
+ depth,
193
+ rowIndex: flattened.length,
194
+ hasChildren: childTasks.length > 0,
195
+ collapsed
196
+ });
197
+ if (!collapsed) {
198
+ for (const child of childTasks) {
199
+ visit(child, depth + 1);
200
+ }
201
+ }
202
+ };
203
+ for (const root of children.get(null) ?? []) {
204
+ visit(root, 0);
205
+ }
206
+ return flattened;
207
+ }
208
+
209
+ // src/utils/date.ts
210
+ var DAY_MS = 24 * 60 * 60 * 1e3;
211
+ function toDate(value) {
212
+ if (value instanceof Date) {
213
+ return startOfDay(value);
214
+ }
215
+ const match = /^(\d{4})-(\d{2})-(\d{2})/.exec(value);
216
+ if (match) {
217
+ return new Date(Number(match[1]), Number(match[2]) - 1, Number(match[3]));
218
+ }
219
+ return startOfDay(new Date(value));
220
+ }
221
+ function startOfDay(date) {
222
+ return new Date(date.getFullYear(), date.getMonth(), date.getDate());
223
+ }
224
+ function addDays(date, days) {
225
+ const next = toDate(date);
226
+ next.setDate(next.getDate() + days);
227
+ return startOfDay(next);
228
+ }
229
+ function diffDays(start, end) {
230
+ return Math.round((toDate(end).getTime() - toDate(start).getTime()) / DAY_MS);
231
+ }
232
+ function inclusiveDays(start, end) {
233
+ return Math.max(0, diffDays(start, end) + 1);
234
+ }
235
+ function isValidDate(value) {
236
+ const date = value instanceof Date ? value : new Date(value);
237
+ return !Number.isNaN(date.getTime());
238
+ }
239
+ function formatDate(date) {
240
+ const value = toDate(date);
241
+ const year = value.getFullYear();
242
+ const month = String(value.getMonth() + 1).padStart(2, "0");
243
+ const day = String(value.getDate()).padStart(2, "0");
244
+ return `${year}-${month}-${day}`;
245
+ }
246
+ function resultInvalidDate(message, details) {
247
+ return {
248
+ ok: false,
249
+ error: { code: "INVALID_DATE", message, details }
250
+ };
251
+ }
252
+
253
+ // src/services/computeTimeScale.ts
254
+ function computeTimeScale(start, end, viewMode, columnWidth, firstDayOfWeek) {
255
+ const rangeStart = alignStart(start, viewMode, firstDayOfWeek);
256
+ const endDate = startOfDay(end);
257
+ const rangeEnd = viewMode === "day" ? addDays(endDate, (firstDayOfWeek + 6 - endDate.getDay() + 7) % 7) : endDate;
258
+ const scale = [];
259
+ let cursor = rangeStart;
260
+ let left = 0;
261
+ while (cursor.getTime() <= rangeEnd.getTime()) {
262
+ const next = nextUnit(cursor, viewMode);
263
+ const unitEnd = addDays(next, -1);
264
+ const width = Math.max(1, diffDays(cursor, next)) * columnWidth;
265
+ scale.push({
266
+ start: cursor,
267
+ end: unitEnd,
268
+ left,
269
+ width
270
+ });
271
+ left += width;
272
+ cursor = next;
273
+ }
274
+ return scale;
275
+ }
276
+ function alignStart(date, viewMode, firstDayOfWeek) {
277
+ const start = startOfDay(date);
278
+ if (viewMode === "day" || viewMode === "week") {
279
+ const delta = (start.getDay() - firstDayOfWeek + 7) % 7;
280
+ return addDays(start, -delta);
281
+ }
282
+ if (viewMode === "month") {
283
+ return new Date(start.getFullYear(), start.getMonth(), 1);
284
+ }
285
+ if (viewMode === "quarter") {
286
+ return new Date(start.getFullYear(), Math.floor(start.getMonth() / 3) * 3, 1);
287
+ }
288
+ if (viewMode === "year") {
289
+ return new Date(start.getFullYear(), 0, 1);
290
+ }
291
+ return start;
292
+ }
293
+ function nextUnit(date, viewMode) {
294
+ if (viewMode === "week") {
295
+ return addDays(date, 7);
296
+ }
297
+ if (viewMode === "month") {
298
+ return new Date(date.getFullYear(), date.getMonth() + 1, 1);
299
+ }
300
+ if (viewMode === "quarter") {
301
+ return new Date(date.getFullYear(), date.getMonth() + 3, 1);
302
+ }
303
+ if (viewMode === "year") {
304
+ return new Date(date.getFullYear() + 1, 0, 1);
305
+ }
306
+ return addDays(date, 1);
307
+ }
308
+
309
+ // src/engines/scheduling.ts
310
+ function scheduleByDependencies(tasks, links) {
311
+ const cycle = checkCyclicDependency(links);
312
+ if (cycle.hasCycle) {
313
+ return {
314
+ ok: false,
315
+ error: {
316
+ code: "CYCLE_DEPENDENCY",
317
+ message: "Dependency graph contains a cycle.",
318
+ details: cycle.cyclePath
319
+ }
320
+ };
321
+ }
322
+ const taskMap = new Map(tasks.map((task) => [task.id, cloneTask(task)]));
323
+ const incoming = /* @__PURE__ */ new Map();
324
+ const outgoing = /* @__PURE__ */ new Map();
325
+ for (const link of links) {
326
+ const source = taskMap.get(link.sourceId);
327
+ const target = taskMap.get(link.targetId);
328
+ if (!source || !target) {
329
+ return {
330
+ ok: false,
331
+ error: {
332
+ code: "ORPHAN_DEPENDENCY",
333
+ message: `Dependency ${link.id} references a missing task.`
334
+ }
335
+ };
336
+ }
337
+ incoming.set(link.targetId, [...incoming.get(link.targetId) ?? [], link]);
338
+ outgoing.set(link.sourceId, [...outgoing.get(link.sourceId) ?? [], link]);
339
+ }
340
+ const ordered = topologicalOrder(tasks.map((task) => task.id), links);
341
+ for (const taskId of ordered) {
342
+ const task = taskMap.get(taskId);
343
+ if (!task || task.schedulingMode === "manual") {
344
+ continue;
345
+ }
346
+ const linksToTask = incoming.get(taskId) ?? [];
347
+ let start = toDate(task.actual.start);
348
+ let end = toDate(task.actual.end);
349
+ const duration = Math.max(0, task.duration ?? inclusiveDays(start, end));
350
+ for (const link of linksToTask) {
351
+ const source = taskMap.get(link.sourceId);
352
+ if (!source) {
353
+ continue;
354
+ }
355
+ const candidate = applyDependency(source, start, end, duration, link.type, link.lag ?? 0);
356
+ if (candidate.start.getTime() > start.getTime()) {
357
+ start = candidate.start;
358
+ }
359
+ if (candidate.end.getTime() > end.getTime()) {
360
+ end = candidate.end;
361
+ }
362
+ }
363
+ const normalizedEnd = task.type === "milestone" ? start : addDays(start, Math.max(0, duration - 1));
364
+ task.actual = {
365
+ ...task.actual,
366
+ start,
367
+ end: normalizedEnd
368
+ };
369
+ }
370
+ return { ok: true, data: tasks.map((task) => taskMap.get(task.id) ?? task) };
371
+ }
372
+ function applyDependency(source, currentStart, currentEnd, duration, type, lag) {
373
+ const sourceStart = toDate(source.actual.start);
374
+ const sourceEnd = toDate(source.actual.end);
375
+ const span = Math.max(0, duration - 1);
376
+ if (type === "FS") {
377
+ const start = addDays(sourceEnd, lag + 1);
378
+ return { start, end: addDays(start, span) };
379
+ }
380
+ if (type === "SS") {
381
+ const start = addDays(sourceStart, lag);
382
+ return { start, end: addDays(start, span) };
383
+ }
384
+ if (type === "FF") {
385
+ const end2 = addDays(sourceEnd, lag);
386
+ return { start: addDays(end2, -span), end: end2 };
387
+ }
388
+ const end = addDays(sourceStart, lag);
389
+ return { start: addDays(end, -span), end: end.getTime() > currentEnd.getTime() ? end : currentEnd };
390
+ }
391
+ function topologicalOrder(ids, links) {
392
+ const indegree = new Map(ids.map((id) => [id, 0]));
393
+ const outgoing = /* @__PURE__ */ new Map();
394
+ for (const link of links) {
395
+ indegree.set(link.targetId, (indegree.get(link.targetId) ?? 0) + 1);
396
+ outgoing.set(link.sourceId, [...outgoing.get(link.sourceId) ?? [], link.targetId]);
397
+ }
398
+ const queue = ids.filter((id) => (indegree.get(id) ?? 0) === 0);
399
+ const ordered = [];
400
+ while (queue.length) {
401
+ const current = queue.shift();
402
+ ordered.push(current);
403
+ for (const target of outgoing.get(current) ?? []) {
404
+ indegree.set(target, (indegree.get(target) ?? 1) - 1);
405
+ if (indegree.get(target) === 0) {
406
+ queue.push(target);
407
+ }
408
+ }
409
+ }
410
+ return ordered.length === ids.length ? ordered : ids;
411
+ }
412
+ function cloneTask(task) {
413
+ return {
414
+ ...task,
415
+ plan: { ...task.plan },
416
+ actual: { ...task.actual },
417
+ dependencies: task.dependencies?.map((dependency) => ({ ...dependency }))
418
+ };
419
+ }
420
+ function shiftTask(task, start) {
421
+ const currentStart = toDate(task.actual.start);
422
+ const nextStart = toDate(start);
423
+ const delta = diffDays(currentStart, nextStart);
424
+ return {
425
+ ...task,
426
+ actual: {
427
+ ...task.actual,
428
+ start: nextStart,
429
+ end: addDays(toDate(task.actual.end), delta)
430
+ }
431
+ };
432
+ }
433
+
434
+ // src/engines/computeLayout.ts
435
+ function computeLayout(tasks, links, config, collapsedIds = /* @__PURE__ */ new Set(), viewport) {
436
+ const mergedConfig = { ...defaultConfig, ...config };
437
+ for (const task of tasks) {
438
+ if (!isValidDate(task.actual.start) || !isValidDate(task.actual.end)) {
439
+ return {
440
+ ok: false,
441
+ error: {
442
+ code: "INVALID_DATE",
443
+ message: `Task ${task.id} has invalid actual dates.`
444
+ }
445
+ };
446
+ }
447
+ }
448
+ const normalizedLinks = normalizeLinks(tasks, links);
449
+ const scheduled = mergedConfig.autoSchedule === false ? { ok: true, data: tasks } : scheduleByDependencies(tasks, normalizedLinks);
450
+ if (!scheduled.ok) {
451
+ return scheduled;
452
+ }
453
+ const flatTasks = flattenTasks(scheduled.data, collapsedIds);
454
+ const firstDate = mergedConfig.visibleRange ? toDate(mergedConfig.visibleRange.start) : minDate(scheduled.data.map((task) => toDate(task.actual.start)));
455
+ const visibleStart = viewport ? Math.max(0, Math.floor(viewport.scrollTop / mergedConfig.rowHeight) - 8) : 0;
456
+ const visibleEnd = viewport ? Math.ceil((viewport.scrollTop + viewport.clientHeight) / mergedConfig.rowHeight) + 8 : Number.POSITIVE_INFINITY;
457
+ const layouts = flatTasks.filter((flat) => flat.rowIndex >= visibleStart && flat.rowIndex <= visibleEnd).map((flat) => {
458
+ const start = toDate(flat.task.actual.start);
459
+ const end = toDate(flat.task.actual.end);
460
+ const duration = flat.task.type === "milestone" ? 0 : inclusiveDays(start, end);
461
+ return {
462
+ taskId: flat.task.id,
463
+ rowIndex: flat.rowIndex,
464
+ left: diffDays(firstDate, start) * mergedConfig.columnWidth,
465
+ width: Math.max(flat.task.type === "milestone" ? mergedConfig.columnWidth / 2 : mergedConfig.columnWidth, duration * mergedConfig.columnWidth),
466
+ top: mergedConfig.headerHeight + flat.rowIndex * mergedConfig.rowHeight,
467
+ depth: flat.depth,
468
+ isCritical: false
469
+ };
470
+ });
471
+ return { ok: true, data: layouts };
472
+ }
473
+ function minDate(dates) {
474
+ return new Date(Math.min(...dates.map((date) => date.getTime())));
475
+ }
476
+
477
+ // src/engines/computeImpact.ts
478
+ function computeImpact(taskId, patch, tasks, links, config) {
479
+ const target = tasks.find((task) => task.id === taskId);
480
+ if (!target) {
481
+ return {
482
+ ok: false,
483
+ error: {
484
+ code: "MISSING_TASK",
485
+ message: `Task ${taskId} does not exist.`
486
+ }
487
+ };
488
+ }
489
+ const patchedTasks = tasks.map((task) => {
490
+ if (task.id !== taskId) {
491
+ return task;
492
+ }
493
+ let next = { ...task, actual: { ...task.actual } };
494
+ if (patch.actualStart) {
495
+ next = shiftTask(next, patch.actualStart);
496
+ }
497
+ if (patch.actualEnd) {
498
+ next.actual.end = patch.actualEnd;
499
+ }
500
+ if (typeof patch.progress === "number") {
501
+ next.actual.progress = patch.progress;
502
+ }
503
+ if (patch.duration) {
504
+ next.duration = patch.duration;
505
+ next.actual.end = addDays(toDate(next.actual.start), Math.max(0, patch.duration - 1));
506
+ }
507
+ if (patch.name) {
508
+ next.name = patch.name;
509
+ }
510
+ if (patch.type) {
511
+ next.type = patch.type;
512
+ }
513
+ if ("parentId" in patch) {
514
+ next.parentId = patch.parentId;
515
+ }
516
+ if (patch.color) {
517
+ next.color = patch.color;
518
+ }
519
+ if ("planColor" in patch) {
520
+ next.planColor = patch.planColor;
521
+ }
522
+ if (patch.schedulingMode) {
523
+ next.schedulingMode = patch.schedulingMode;
524
+ }
525
+ return next;
526
+ });
527
+ const scheduled = config.autoSchedule === false ? { ok: true, data: patchedTasks } : scheduleByDependencies(patchedTasks, links);
528
+ if (!scheduled.ok) {
529
+ return scheduled;
530
+ }
531
+ const rows = new Map(flattenTasks(scheduled.data).map((flat) => [flat.task.id, flat.rowIndex]));
532
+ const originalById = new Map(tasks.map((task) => [task.id, task]));
533
+ const changed = scheduled.data.filter((task) => {
534
+ const original = originalById.get(task.id);
535
+ return original && (String(original.actual.start) !== String(task.actual.start) || String(original.actual.end) !== String(task.actual.end));
536
+ }).map((task) => ({
537
+ taskId: task.id,
538
+ actualStart: task.actual.start,
539
+ actualEnd: task.actual.end,
540
+ rowIndex: rows.get(task.id) ?? 0
541
+ }));
542
+ const conflicts = scheduled.data.filter((task) => task.constraint?.date && inclusiveDays(task.actual.start, task.constraint.date) < 0).map((task) => ({
543
+ taskId: task.id,
544
+ constraintType: task.constraint.type,
545
+ message: "Task violates its configured constraint date."
546
+ }));
547
+ return { ok: true, data: { changed, conflicts } };
548
+ }
549
+ // Annotate the CommonJS export names for ESM import in node:
550
+ 0 && (module.exports = {
551
+ DAY_MS,
552
+ addDays,
553
+ checkCyclicDependency,
554
+ computeImpact,
555
+ computeLayout,
556
+ computeTimeScale,
557
+ defaultConfig,
558
+ diffDays,
559
+ flattenTasks,
560
+ formatDate,
561
+ inclusiveDays,
562
+ isValidDate,
563
+ normalizeLinks,
564
+ resultInvalidDate,
565
+ scheduleByDependencies,
566
+ shiftTask,
567
+ startOfDay,
568
+ toDate
569
+ });
570
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +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"]}