@ganttloom/gantt-core 0.2.0 → 0.2.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.js CHANGED
@@ -140,7 +140,6 @@ function computeCriticalPath(tasks, dependencies) {
140
140
  }
141
141
  for (const e of edges) {
142
142
  outgoing.get(e.fromId)?.push(e);
143
- incoming.get(e.fromId) === void 0 ? void 0 : void 0;
144
143
  incoming.get(e.toId)?.push(e);
145
144
  }
146
145
  const inDegree = /* @__PURE__ */ new Map();
@@ -225,11 +224,9 @@ function computeCriticalPath(tasks, dependencies) {
225
224
  criticalLinks.add(linkKey(e.fromId, e.toId));
226
225
  }
227
226
  }
228
- const taskMap = new Map(tasks.map((t) => [t.id, t]));
229
227
  for (const task of tasks) {
230
228
  if (!task.isGroup) continue;
231
229
  let hasCriticalDescendant = false;
232
- let cur = task;
233
230
  const descendantStack = [task.id];
234
231
  const visited = /* @__PURE__ */ new Set();
235
232
  while (descendantStack.length > 0) {
@@ -244,8 +241,6 @@ function computeCriticalPath(tasks, dependencies) {
244
241
  }
245
242
  }
246
243
  if (hasCriticalDescendant) criticalTasks.add(task.id);
247
- void cur;
248
- void taskMap;
249
244
  }
250
245
  return { criticalTasks, criticalLinks };
251
246
  }
@@ -640,6 +635,9 @@ function flatten(roots) {
640
635
  }
641
636
  return out;
642
637
  }
638
+ function estimateTextWidth(text, fontSize) {
639
+ return text.length * fontSize * 0.62;
640
+ }
643
641
  function anchorPoint(bar, side) {
644
642
  const y = bar.y + bar.height / 2;
645
643
  return side === "start" ? { x: bar.x, y } : { x: bar.x + bar.width, y };
@@ -765,8 +763,9 @@ function computeLayout(input) {
765
763
  const end = row.node.computedEnd;
766
764
  if (!start || !end) return;
767
765
  const x = dateToX(start, paddedStart, viewMode, columnWidth);
768
- const width2 = Math.max(0, dateToX(end, paddedStart, viewMode, columnWidth) - x);
769
- if (!Number.isFinite(x) || !Number.isFinite(width2)) return;
766
+ const rawWidth = Math.max(0, dateToX(end, paddedStart, viewMode, columnWidth) - x);
767
+ if (!Number.isFinite(x) || !Number.isFinite(rawWidth)) return;
768
+ const width2 = rawWidth > 0 ? Math.max(rawWidth, 3) : rawWidth;
770
769
  const progress = task.progress !== void 0 ? Math.min(100, Math.max(0, task.progress)) : autoRollupProgress ? row.node.computedProgress : 0;
771
770
  const barHeight = theme.barHeight;
772
771
  const barY = y + (theme.rowHeight - barHeight) / 2;
@@ -874,7 +873,13 @@ function computeLayout(input) {
874
873
  })).filter((m) => Number.isFinite(m.x));
875
874
  let width = 0;
876
875
  for (const tick of ticks) width = Math.max(width, tick.x);
877
- for (const bar of bars) width = Math.max(width, bar.x + bar.width);
876
+ for (const bar of bars) {
877
+ width = Math.max(width, bar.x + bar.width);
878
+ if (bar.label) {
879
+ const labelOffset = bar.isMilestone ? theme.barHeight * 0.4 + 8 : bar.width + 6;
880
+ width = Math.max(width, bar.x + labelOffset + estimateTextWidth(bar.label, theme.fontSize));
881
+ }
882
+ }
878
883
  width += columnWidth;
879
884
  const height = rows.length * theme.rowHeight;
880
885
  return {
@@ -1373,7 +1378,9 @@ var GanttRenderer = class {
1373
1378
  }
1374
1379
  }
1375
1380
  renderMarkers(group, model) {
1376
- for (const marker of model.markers) {
1381
+ const sorted = [...model.markers].sort((a, b) => a.x - b.x);
1382
+ let defs = null;
1383
+ sorted.forEach((marker, i) => {
1377
1384
  const line = svgEl("line");
1378
1385
  line.setAttribute("x1", String(marker.x));
1379
1386
  line.setAttribute("x2", String(marker.x));
@@ -1385,16 +1392,33 @@ var GanttRenderer = class {
1385
1392
  line.dataset.ganttMarker = marker.label;
1386
1393
  group.appendChild(line);
1387
1394
  if (marker.label) {
1395
+ const nextX = sorted[i + 1]?.x ?? model.width;
1396
+ const cellWidth = Math.max(0, nextX - marker.x);
1397
+ if (!defs) {
1398
+ defs = svgEl("defs");
1399
+ group.insertBefore(defs, group.firstChild);
1400
+ }
1401
+ const clipId = `${this.markerDefsId}-marker-${i}`;
1402
+ const clipPath = svgEl("clipPath");
1403
+ clipPath.setAttribute("id", clipId);
1404
+ const clipRect = svgEl("rect");
1405
+ clipRect.setAttribute("x", String(marker.x));
1406
+ clipRect.setAttribute("y", "0");
1407
+ clipRect.setAttribute("width", String(cellWidth));
1408
+ clipRect.setAttribute("height", String(model.height));
1409
+ clipPath.appendChild(clipRect);
1410
+ defs.appendChild(clipPath);
1388
1411
  const label = svgEl("text");
1389
1412
  label.setAttribute("x", String(marker.x + 4));
1390
1413
  label.setAttribute("y", "12");
1414
+ label.setAttribute("clip-path", `url(#${clipId})`);
1391
1415
  label.setAttribute("fill", marker.color);
1392
1416
  label.setAttribute("font-size", String(model.theme.fontSize));
1393
1417
  label.setAttribute("font-family", model.theme.fontFamily);
1394
1418
  label.textContent = marker.label;
1395
1419
  group.appendChild(label);
1396
1420
  }
1397
- }
1421
+ });
1398
1422
  }
1399
1423
  renderHeader(model) {
1400
1424
  let headerGroup = this.svg.querySelector(".gantt-header-group");
@@ -1408,16 +1432,32 @@ var GanttRenderer = class {
1408
1432
  bg.setAttribute("height", String(model.headerHeight));
1409
1433
  bg.style.fill = themedFill("backgroundColor", model.theme.backgroundColor);
1410
1434
  headerGroup.appendChild(bg);
1411
- for (const tick of model.ticks) {
1435
+ const defs = svgEl("defs");
1436
+ const ticks = model.ticks;
1437
+ for (let i = 0; i < ticks.length; i++) {
1438
+ const tick = ticks[i];
1439
+ const cellWidth = (ticks[i + 1]?.x ?? model.width) - tick.x;
1440
+ const clipId = `${this.markerDefsId}-tick-${i}`;
1441
+ const clipPath = svgEl("clipPath");
1442
+ clipPath.setAttribute("id", clipId);
1443
+ const clipRect = svgEl("rect");
1444
+ clipRect.setAttribute("x", String(tick.x));
1445
+ clipRect.setAttribute("y", "0");
1446
+ clipRect.setAttribute("width", String(Math.max(0, cellWidth)));
1447
+ clipRect.setAttribute("height", String(model.headerHeight));
1448
+ clipPath.appendChild(clipRect);
1449
+ defs.appendChild(clipPath);
1412
1450
  const text = svgEl("text");
1413
1451
  text.setAttribute("x", String(tick.x + 4));
1414
1452
  text.setAttribute("y", String(model.headerHeight - 8));
1453
+ text.setAttribute("clip-path", `url(#${clipId})`);
1415
1454
  text.style.fill = themedFill("textColor", model.theme.textColor);
1416
1455
  text.setAttribute("font-size", String(model.theme.fontSize));
1417
1456
  text.setAttribute("font-family", model.theme.fontFamily);
1418
1457
  text.textContent = tick.label;
1419
1458
  headerGroup.appendChild(text);
1420
1459
  }
1460
+ headerGroup.insertBefore(defs, headerGroup.firstChild);
1421
1461
  this.svg.appendChild(headerGroup);
1422
1462
  }
1423
1463
  /**
@@ -2501,7 +2541,7 @@ var _GanttChart = class _GanttChart {
2501
2541
  const newStart = edge === "left" ? new Date(task.start.getTime() + dxMs) : task.start;
2502
2542
  const newEnd = edge === "right" ? new Date(task.end.getTime() + dxMs) : task.end;
2503
2543
  if (newEnd.getTime() <= newStart.getTime()) return;
2504
- let newSegments = task.segments?.map((s) => ({ ...s }));
2544
+ const newSegments = task.segments?.map((s) => ({ ...s }));
2505
2545
  if (newSegments && newSegments.length > 0) {
2506
2546
  if (edge === "left") newSegments[0] = { ...newSegments[0], start: newStart };
2507
2547
  else newSegments[newSegments.length - 1] = { ...newSegments[newSegments.length - 1], end: newEnd };