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

function cn(...inputs) {
  return twMerge(clsx(inputs));
}
var HEADER_PADDING = 16;
var MESSAGE_TOP_PADDING = 24;
function Sequence({
  actors,
  messages,
  width = 720,
  headerHeight = 40,
  messageGap = 36,
  onActorClick,
  onMessageClick,
  className,
  ...rest
}) {
  const laidOut = React.useMemo(
    () => layout(actors, messages, width, headerHeight, messageGap),
    [actors, messages, width, headerHeight, messageGap]
  );
  const desc = `Sequence diagram with ${actors.length} actor${actors.length === 1 ? "" : "s"} and ${messages.length} message${messages.length === 1 ? "" : "s"}`;
  const arrowId = React.useId().replace(/:/g, "-");
  const SELF_CALL_DROP = Math.min(14, Math.max(6, messageGap * 0.4));
  const SELF_CALL_OUT = 28;
  return /* @__PURE__ */ jsxs(
    "svg",
    {
      ...rest,
      "data-hex-sequence": true,
      role: "img",
      width,
      height: laidOut.totalHeight,
      viewBox: `0 0 ${width} ${laidOut.totalHeight}`,
      className: cn("block", className),
      children: [
        /* @__PURE__ */ jsx("title", { children: "Sequence diagram" }),
        /* @__PURE__ */ jsx("desc", { children: desc }),
        /* @__PURE__ */ jsx("defs", { children: /* @__PURE__ */ jsx(
          "marker",
          {
            id: `hex-sequence-arrow-${arrowId}`,
            viewBox: "0 0 10 10",
            refX: "10",
            refY: "5",
            markerWidth: "6",
            markerHeight: "6",
            orient: "auto-start-reverse",
            children: /* @__PURE__ */ jsx("path", { d: "M 0 0 L 10 5 L 0 10 z", fill: "hsl(var(--foreground))" })
          }
        ) }),
        /* @__PURE__ */ jsx("g", { "data-hex-sequence-lifelines": true, children: laidOut.actors.map((a) => /* @__PURE__ */ jsx(
          "line",
          {
            "data-hex-sequence-lifeline": true,
            x1: a.x,
            x2: a.x,
            y1: headerHeight,
            y2: laidOut.totalHeight - 8,
            stroke: "hsl(var(--muted-foreground))",
            strokeOpacity: 0.7,
            strokeDasharray: "3 4",
            strokeWidth: 1
          },
          `lifeline-${a.actor.id}`
        )) }),
        /* @__PURE__ */ jsx("g", { "data-hex-sequence-actors": true, children: laidOut.actors.map((a) => {
          const interactive = Boolean(onActorClick);
          const handleActivate = () => onActorClick?.(a.actor);
          return /* @__PURE__ */ jsxs(
            "g",
            {
              "data-hex-sequence-actor": true,
              "data-depth": a.depth,
              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 ? a.actor.label : 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: a.x - 64,
                    y: 4,
                    width: 128,
                    height: headerHeight - 8,
                    rx: 4,
                    ry: 4,
                    fill: "hsl(var(--card))",
                    stroke: "hsl(var(--border))",
                    strokeWidth: 1
                  }
                ),
                /* @__PURE__ */ jsx(
                  "text",
                  {
                    x: a.x,
                    y: headerHeight / 2,
                    dy: "0.35em",
                    textAnchor: "middle",
                    fontSize: 12,
                    fontWeight: 600,
                    fill: "hsl(var(--foreground))",
                    style: { pointerEvents: "none" },
                    children: a.actor.label
                  }
                )
              ]
            },
            a.actor.id
          );
        }) }),
        /* @__PURE__ */ jsx("g", { "data-hex-sequence-messages": true, children: laidOut.messages.map((m, i) => {
          const interactive = Boolean(onMessageClick);
          const handleActivate = () => onMessageClick?.(m.message);
          const stroke = "hsl(var(--foreground))";
          const dashed = m.message.type === "return" ? "4 3" : void 0;
          const strokeWidth = m.message.type === "async" ? 1 : 1.25;
          return /* @__PURE__ */ jsxs(
            "g",
            {
              "data-hex-sequence-message": true,
              "data-depth": m.depth,
              "data-type": m.message.type ?? "sync",
              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 ? `Message ${i + 1}: from ${m.from.actor.label} to ${m.to.actor.label}${m.message.label ? `, "${m.message.label}"` : ""}` : void 0,
              style: interactive ? { cursor: "pointer" } : void 0,
              onClick: interactive ? handleActivate : void 0,
              onKeyDown: interactive ? (e) => activateOnKey(e, handleActivate) : void 0,
              children: [
                m.isSelfCall ? (
                  // Loopback: out + down + back. Drop scales with messageGap.
                  /* @__PURE__ */ jsx(
                    "path",
                    {
                      d: `M${m.from.x},${m.y} L${m.from.x + SELF_CALL_OUT},${m.y} L${m.from.x + SELF_CALL_OUT},${m.y + SELF_CALL_DROP} L${m.from.x + 4},${m.y + SELF_CALL_DROP}`,
                      fill: "none",
                      stroke,
                      strokeWidth,
                      strokeDasharray: dashed,
                      markerEnd: `url(#hex-sequence-arrow-${arrowId})`
                    }
                  )
                ) : /* @__PURE__ */ jsx(
                  "line",
                  {
                    x1: m.from.x,
                    x2: m.to.x,
                    y1: m.y,
                    y2: m.y,
                    stroke,
                    strokeWidth,
                    strokeDasharray: dashed,
                    markerEnd: `url(#hex-sequence-arrow-${arrowId})`
                  }
                ),
                m.message.label ? /* @__PURE__ */ jsx(
                  "text",
                  {
                    x: m.isSelfCall ? m.from.x + SELF_CALL_OUT + 4 : (m.from.x + m.to.x) / 2,
                    y: m.y - 4,
                    textAnchor: m.isSelfCall ? "start" : "middle",
                    fontSize: 11,
                    fill: "hsl(var(--foreground))",
                    style: {
                      paintOrder: "stroke",
                      pointerEvents: "none"
                    },
                    stroke: "hsl(var(--background))",
                    strokeWidth: 3,
                    strokeLinejoin: "round",
                    children: m.message.label
                  }
                ) : null
              ]
            },
            `${m.message.from}-${m.message.to}-${i}`
          );
        }) })
      ]
    }
  );
}
function layout(actors, messages, width, headerHeight, messageGap) {
  if (actors.length === 0) {
    return { actors: [], messages: [], totalHeight: headerHeight + 16 };
  }
  const usableWidth = width - HEADER_PADDING * 2;
  const colStep = actors.length > 1 ? usableWidth / (actors.length - 1) : 0;
  const actorPositions = actors.map((a, i) => ({
    actor: a,
    x: HEADER_PADDING + colStep * i,
    depth: i
  }));
  const byId = new Map(actorPositions.map((a) => [a.actor.id, a]));
  const laidOutMessages = messages.map((message, i) => {
    const from = byId.get(message.from);
    const to = byId.get(message.to);
    if (!from || !to) return null;
    return {
      message,
      from,
      to,
      y: headerHeight + MESSAGE_TOP_PADDING + i * messageGap,
      depth: i,
      isSelfCall: message.from === message.to
    };
  }).filter((m) => m !== null);
  const totalHeight = headerHeight + MESSAGE_TOP_PADDING + Math.max(0, laidOutMessages.length - 1) * messageGap + 32;
  return { actors: actorPositions, messages: laidOutMessages, totalHeight };
}
function activateOnKey(e, fn) {
  if (e.key === "Enter" || e.key === " ") {
    e.preventDefault();
    fn();
  }
}

export { Sequence };
//# sourceMappingURL=sequence.js.map
//# sourceMappingURL=sequence.js.map