import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { cn } from "../../../lib/utils";
import { componentFrameBgColorVariants, } from "../../componentFrameColors";
// The catch geometry stays 40px (used for hit-testing in DragInsertionOverlay);
// only the rendered indicator is the slim bar below.
export const INSERTION_ZONE_THICKNESS = 40;
const VERTICAL_OUTSIDE_ZONE_OFFSET = 4;
const INSERTION_BAR_THICKNESS = 3;
const insertAccentVar = {
    default: "var(--color-component-default)",
    shared: "var(--color-component-shared)",
    layout: "var(--color-highlight-100)",
};
/**
 * The single "where will it land" indicator shown during a drag: a thin colored
 * bar at the exact insertion gap, tagged with the target placeholder + position.
 * One calm signal - it replaced the heavy 40px "drop zone" band so the drag
 * canvas isn't a stack of competing highlights. Purely presentational; positions
 * are overlay/document coordinates.
 */
export function InsertionLine({ zone, placeholderRect, visualMode = "directional", visualAnchor, visualTargetRect, color, animate, phase = "enter", label, }) {
    if (visualMode === "none")
        return null;
    const isEmptyPlaceholder = zone.placeholder.components.length === 0;
    if (visualMode === "neutral" && !isEmptyPlaceholder)
        return null;
    const targetRect = visualTargetRect ?? zone.targetRect ?? placeholderRect;
    const anchor = visualAnchor ?? zone.anchor;
    const zoneRect = visualMode === "between"
        ? targetRect
        : visualMode === "neutral"
            ? getEmptyPlaceholderNeutralZoneRect({ zone, targetRect })
            : getDirectionalInsertionZoneRect({ zone, targetRect, anchor });
    // A vertical placeholder (stacked components) gets a horizontal insertion bar.
    const horizontalBar = zone.orientation === "vertical";
    // Pin the bar to the resolved gap; centre it for an empty placeholder.
    const mainPos = isEmptyPlaceholder
        ? horizontalBar
            ? zoneRect.y + zoneRect.height / 2
            : zoneRect.x + zoneRect.width / 2
        : horizontalBar
            ? zone.position.y
            : zone.position.x;
    const barStyle = horizontalBar
        ? {
            left: zoneRect.x,
            top: mainPos - INSERTION_BAR_THICKNESS / 2,
            width: zoneRect.width,
            height: INSERTION_BAR_THICKNESS,
        }
        : {
            left: mainPos - INSERTION_BAR_THICKNESS / 2,
            top: zoneRect.y,
            width: INSERTION_BAR_THICKNESS,
            height: zoneRect.height,
        };
    const labelStyle = horizontalBar
        ? { left: zoneRect.x, top: mainPos - 22 }
        : { left: mainPos + 8, top: zoneRect.y };
    const accent = insertAccentVar[color];
    return (_jsxs("div", { "data-testid": "drag-insertion-line", "data-motion-phase": phase, className: cn("pointer-events-none absolute inset-0", animate &&
            (phase === "exit"
                ? "parhelia-drop-zone-overlay-exit"
                : "parhelia-drop-zone-overlay-enter")), style: { zIndex: 860 }, children: [_jsx("div", { "data-testid": "drag-insertion-zone", "data-visual-mode": visualMode, 
                // No position transition: the bar snaps to each gap so it stays locked
                // to the active "+" dot. The constant React key already prevents the
                // remount/re-fade that caused the per-gap flashing, and gliding made the
                // bar lag behind the cursor's gap.
                className: "absolute rounded-full", style: { ...barStyle, backgroundColor: accent } }), label && (_jsx("div", { "data-testid": "drag-insertion-label", className: cn("absolute flex max-w-[min(18rem,calc(100vw-3rem))] items-center rounded-[4px] px-2 py-0.5 text-[11px] leading-none font-medium whitespace-nowrap text-white shadow-sm", componentFrameBgColorVariants[color]), style: labelStyle, children: _jsx("span", { className: "truncate", children: label }) }))] }));
}
export function getDirectionalInsertionZoneRect({ zone, targetRect, anchor, }) {
    const isVerticalPlaceholder = zone.orientation === "vertical";
    const isEmptyPlaceholder = zone.placeholder.components.length === 0;
    const zoneThickness = INSERTION_ZONE_THICKNESS;
    return isVerticalPlaceholder
        ? {
            x: targetRect.x,
            y: isEmptyPlaceholder
                ? zone.position.y - zoneThickness / 2
                : anchor === "top"
                    ? targetRect.y - zoneThickness - VERTICAL_OUTSIDE_ZONE_OFFSET
                    : targetRect.y + targetRect.height + VERTICAL_OUTSIDE_ZONE_OFFSET,
            width: targetRect.width,
            height: zoneThickness,
        }
        : {
            x: isEmptyPlaceholder
                ? zone.position.x - zoneThickness / 2
                : anchor === "left"
                    ? targetRect.x - zoneThickness
                    : targetRect.x + targetRect.width,
            y: targetRect.y,
            width: zoneThickness,
            height: targetRect.height,
        };
}
export function getDirectionalInsertionHitZoneRect({ zone, targetRect, anchor, }) {
    const visualRect = getDirectionalInsertionZoneRect({
        zone,
        targetRect,
        anchor,
    });
    const isVerticalPlaceholder = zone.orientation === "vertical";
    const isEmptyPlaceholder = zone.placeholder.components.length === 0;
    if (!isVerticalPlaceholder || isEmptyPlaceholder)
        return visualRect;
    switch (anchor) {
        case "top":
            return {
                ...visualRect,
                height: visualRect.height + VERTICAL_OUTSIDE_ZONE_OFFSET,
            };
        case "bottom":
            return {
                ...visualRect,
                y: targetRect.y + targetRect.height,
                height: visualRect.height + VERTICAL_OUTSIDE_ZONE_OFFSET,
            };
        case "left":
        case "right":
            return visualRect;
    }
}
export function getBetweenInsertionZoneRect({ zone, previousRect, nextRect, }) {
    if (zone.orientation === "horizontal") {
        const y = Math.min(previousRect.y, nextRect.y);
        const bottom = Math.max(previousRect.y + previousRect.height, nextRect.y + nextRect.height);
        return {
            x: zone.position.x - INSERTION_ZONE_THICKNESS / 2,
            width: INSERTION_ZONE_THICKNESS,
            y,
            height: bottom - y,
        };
    }
    const x = Math.min(previousRect.x, nextRect.x);
    const right = Math.max(previousRect.x + previousRect.width, nextRect.x + nextRect.width);
    return {
        x,
        y: zone.position.y - INSERTION_ZONE_THICKNESS / 2,
        height: INSERTION_ZONE_THICKNESS,
        width: right - x,
    };
}
export function getEmptyPlaceholderNeutralZoneRect({ zone, targetRect, }) {
    if (zone.orientation === "horizontal") {
        return {
            x: zone.position.x - INSERTION_ZONE_THICKNESS / 2,
            y: targetRect.y,
            width: INSERTION_ZONE_THICKNESS,
            height: targetRect.height,
        };
    }
    return {
        x: targetRect.x,
        y: zone.position.y - INSERTION_ZONE_THICKNESS / 2,
        width: targetRect.width,
        height: INSERTION_ZONE_THICKNESS,
    };
}
//# sourceMappingURL=InsertionLine.js.map