"use client";
import * as React from 'react';
import { clsx } from 'clsx';
import { twMerge } from 'tailwind-merge';
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';

function cn(...inputs) {
  return twMerge(clsx(inputs));
}
var HEADER_HEIGHT = 40;
var ROW_PADDING = 6;
function Gantt({
  tasks,
  width = 800,
  rowHeight = 32,
  labelMargin = 140,
  tickCount = 6,
  onTaskClick,
  className,
  ...rest
}) {
  const laidOut = React.useMemo(
    () => layout(tasks, width, rowHeight, labelMargin, tickCount),
    [tasks, width, rowHeight, labelMargin, tickCount]
  );
  const totalHeight = HEADER_HEIGHT + tasks.length * rowHeight + ROW_PADDING;
  const desc = `Gantt with ${tasks.length} task${tasks.length === 1 ? "" : "s"}, range ${laidOut.startLabel} to ${laidOut.endLabel}`;
  const arrowId = React.useId().replace(/:/g, "-");
  return /* @__PURE__ */ jsxs(
    "svg",
    {
      ...rest,
      "data-hex-gantt": true,
      role: "img",
      width,
      height: totalHeight,
      viewBox: `0 0 ${width} ${totalHeight}`,
      className: cn("block", className),
      children: [
        /* @__PURE__ */ jsx("title", { children: "Gantt chart" }),
        /* @__PURE__ */ jsx("desc", { children: desc }),
        /* @__PURE__ */ jsx("defs", { children: /* @__PURE__ */ jsx(
          "marker",
          {
            id: `hex-gantt-arrow-${arrowId}`,
            viewBox: "0 0 10 10",
            refX: "10",
            refY: "5",
            markerWidth: "5",
            markerHeight: "5",
            orient: "auto-start-reverse",
            children: /* @__PURE__ */ jsx("path", { d: "M 0 0 L 10 5 L 0 10 z", fill: "hsl(var(--muted-foreground))" })
          }
        ) }),
        /* @__PURE__ */ jsxs("g", { "data-hex-gantt-axis": true, children: [
          /* @__PURE__ */ jsx(
            "line",
            {
              x1: labelMargin,
              x2: width - 16,
              y1: HEADER_HEIGHT - 8,
              y2: HEADER_HEIGHT - 8,
              stroke: "hsl(var(--muted-foreground))",
              strokeWidth: 1
            }
          ),
          laidOut.ticks.map((t, i) => /* @__PURE__ */ jsxs("g", { "data-hex-gantt-tick": true, children: [
            /* @__PURE__ */ jsx(
              "line",
              {
                x1: t.x,
                x2: t.x,
                y1: HEADER_HEIGHT - 8,
                y2: totalHeight - 4,
                stroke: "hsl(var(--muted-foreground))",
                strokeOpacity: 0.15,
                strokeWidth: 1
              }
            ),
            /* @__PURE__ */ jsx(
              "text",
              {
                x: t.x,
                y: HEADER_HEIGHT - 14,
                textAnchor: "middle",
                fontSize: 10,
                fill: "hsl(var(--muted-foreground))",
                children: t.label
              }
            )
          ] }, `tick-${i}`))
        ] }),
        /* @__PURE__ */ jsx("g", { "data-hex-gantt-labels": true, children: laidOut.tasks.map((t) => /* @__PURE__ */ jsx(
          "text",
          {
            x: labelMargin - 8,
            y: t.y + t.h / 2,
            dy: "0.35em",
            textAnchor: "end",
            fontSize: 11,
            fill: "hsl(var(--foreground))",
            children: t.task.label
          },
          `label-${t.task.id}`
        )) }),
        /* @__PURE__ */ jsx("g", { "data-hex-gantt-deps": true, fill: "none", children: laidOut.deps.map((d) => {
          const ELBOW = 8;
          const needsJog = d.to.x < d.from.x + ELBOW;
          const path = needsJog ? `M${d.from.x},${d.from.y} L${d.from.x + ELBOW},${d.from.y} L${d.from.x + ELBOW},${d.to.y} L${d.to.x},${d.to.y}` : `M${d.from.x},${d.from.y} L${(d.from.x + d.to.x) / 2},${d.from.y} L${(d.from.x + d.to.x) / 2},${d.to.y} L${d.to.x},${d.to.y}`;
          return /* @__PURE__ */ jsx(
            "path",
            {
              "data-hex-gantt-dep": true,
              d: path,
              stroke: "hsl(var(--muted-foreground))",
              strokeOpacity: 0.55,
              strokeWidth: 1,
              markerEnd: `url(#hex-gantt-arrow-${arrowId})`
            },
            d.id
          );
        }) }),
        /* @__PURE__ */ jsx("g", { "data-hex-gantt-tasks": true, children: laidOut.tasks.map((t) => {
          const interactive = Boolean(onTaskClick);
          const handleActivate = () => onTaskClick?.(t.task);
          return /* @__PURE__ */ jsxs(
            "g",
            {
              "data-hex-gantt-task": true,
              "data-row": t.rowIndex,
              className: interactive ? "focus-visible:outline-none focus-visible:outline-2 focus-visible:outline-ring" : void 0,
              role: interactive ? "button" : void 0,
              tabIndex: interactive ? 0 : void 0,
              "aria-label": interactive ? `${t.task.label}, ${formatDate(toDate(t.task.start))} to ${formatDate(toDate(t.task.end))}${t.task.progress != null ? `, ${Math.round((t.task.progress ?? 0) * 100)}% complete` : ""}` : void 0,
              style: interactive ? { cursor: "pointer" } : void 0,
              onClick: interactive ? handleActivate : void 0,
              onKeyDown: interactive ? (e) => activateOnKey(e, handleActivate) : void 0,
              children: [
                /* @__PURE__ */ jsx(
                  "rect",
                  {
                    x: t.x,
                    y: t.y,
                    width: Math.max(2, t.w),
                    height: t.h,
                    rx: 4,
                    ry: 4,
                    fill: "hsl(var(--primary))",
                    fillOpacity: 0.25,
                    stroke: "hsl(var(--primary))",
                    strokeWidth: 1
                  }
                ),
                t.progressW > 0 ? /* @__PURE__ */ jsxs(Fragment, { children: [
                  /* @__PURE__ */ jsx(
                    "rect",
                    {
                      x: t.x,
                      y: t.y,
                      width: t.progressW,
                      height: t.h,
                      rx: 4,
                      ry: 4,
                      fill: "hsl(var(--primary))",
                      fillOpacity: 0.7
                    }
                  ),
                  t.progressW < t.w - 0.5 ? /* @__PURE__ */ jsx(
                    "line",
                    {
                      x1: t.x + t.progressW,
                      x2: t.x + t.progressW,
                      y1: t.y,
                      y2: t.y + t.h,
                      stroke: "hsl(var(--primary))",
                      strokeWidth: 1
                    }
                  ) : null
                ] }) : null
              ]
            },
            t.task.id
          );
        }) })
      ]
    }
  );
}
function layout(tasks, width, rowHeight, labelMargin, tickCount) {
  if (tasks.length === 0) {
    return { tasks: [], deps: [], ticks: [], startLabel: "\u2014", endLabel: "\u2014" };
  }
  const axisLeft = labelMargin;
  const axisRight = width - 16;
  const usable = axisRight - axisLeft;
  const allTimes = tasks.flatMap((t) => [toDate(t.start).getTime(), toDate(t.end).getTime()]).filter((t) => Number.isFinite(t));
  if (allTimes.length === 0) {
    return { tasks: [], deps: [], ticks: [], startLabel: "\u2014", endLabel: "\u2014" };
  }
  const minTs = Math.min(...allTimes);
  const maxTs = Math.max(...allTimes);
  const span = Math.max(1, maxTs - minTs);
  const tToX = (t) => axisLeft + (t - minTs) / span * usable;
  const laidOutTasks = tasks.map((task, i) => {
    const startTs = toDate(task.start).getTime();
    const endTs = toDate(task.end).getTime();
    const x = tToX(startTs);
    const w = Math.max(0, tToX(endTs) - x);
    const y = HEADER_HEIGHT + i * rowHeight + ROW_PADDING / 2;
    const h = rowHeight - ROW_PADDING;
    const progress = clamp01(task.progress ?? 0);
    return {
      task,
      rowIndex: i,
      x,
      y,
      w,
      h,
      progressW: w * progress
    };
  });
  const byId = new Map(laidOutTasks.map((t) => [t.task.id, t]));
  const deps = [];
  laidOutTasks.forEach((t) => {
    (t.task.dependencies ?? []).forEach((depId, k) => {
      const from = byId.get(depId);
      if (!from) return;
      deps.push({
        from: { x: from.x + from.w, y: from.y + from.h / 2 },
        to: { x: t.x, y: t.y + t.h / 2 },
        id: `${depId}-${t.task.id}-${k}`
      });
    });
  });
  const rawTicks = [];
  for (let i = 0; i < tickCount; i++) {
    const ts = minTs + i / Math.max(1, tickCount - 1) * span;
    rawTicks.push({ x: tToX(ts), label: formatTick(new Date(ts), span) });
  }
  const ticks = rawTicks.map((t, i) => ({
    x: t.x,
    label: i > 0 && rawTicks[i - 1]?.label === t.label ? "" : t.label
  }));
  return {
    tasks: laidOutTasks,
    deps,
    ticks,
    startLabel: formatDate(new Date(minTs)),
    endLabel: formatDate(new Date(maxTs))
  };
}
function toDate(v) {
  if (v instanceof Date) return v;
  if (typeof v === "number") return new Date(v);
  return new Date(v);
}
function clamp01(v) {
  return v < 0 ? 0 : v > 1 ? 1 : v;
}
function formatDate(d) {
  if (Number.isNaN(d.getTime())) return "\u2014";
  return d.toISOString().slice(0, 10);
}
function formatTick(d, spanMs) {
  if (Number.isNaN(d.getTime())) return "\u2014";
  const ONE_DAY = 24 * 60 * 60 * 1e3;
  if (spanMs <= 90 * ONE_DAY) return d.toISOString().slice(5, 10);
  if (spanMs <= 730 * ONE_DAY) return d.toISOString().slice(0, 7);
  return String(d.getUTCFullYear());
}
function activateOnKey(e, fn) {
  if (e.key === "Enter" || e.key === " ") {
    e.preventDefault();
    fn();
  }
}

export { Gantt };
//# sourceMappingURL=gantt.js.map
//# sourceMappingURL=gantt.js.map