"use client";
'use strict';

var jsxRuntime = require('react/jsx-runtime');
var React = require('react');
var utils = require('@windrun-huaiin/lib/utils');
var proxy = require('../node_modules/.pnpm/framer-motion@12.38.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/framer-motion/dist/es/render/components/motion/proxy.js');

const DEFAULT_THEME_COLOR = '#3b82f6';
const TRACK_COLOR = 'rgba(148, 163, 184, 0.22)';
const BODY_LENGTH_RATIO = 0.26;
const EXIT_DURATION_MS = 260;
const LOOP_DURATION_SECONDS = 1.85;
const DEFAULT_CIRCLE_STROKE = 2;
const DEFAULT_RECT_STROKE = 3;
const MIN_FRAME_SIZE = 2;
const MIN_BODY_LENGTH = 24;
const MAX_BODY_LENGTH_RATIO = 0.36;
const RECT_MIN_STROKE_WIDTH = 3;
function clampProgress(progress) {
    if (!Number.isFinite(progress)) {
        return 0;
    }
    return Math.min(100, Math.max(0, progress));
}
function hexToRgb(hex) {
    const normalized = hex.replace('#', '').trim();
    if (!/^[\da-fA-F]{6}$/.test(normalized)) {
        return null;
    }
    return [
        Number.parseInt(normalized.slice(0, 2), 16),
        Number.parseInt(normalized.slice(2, 4), 16),
        Number.parseInt(normalized.slice(4, 6), 16),
    ];
}
function createBodyTailColor(themeColor) {
    const rgb = hexToRgb(themeColor);
    if (!rgb) {
        return 'rgba(59, 130, 246, 0.18)';
    }
    return `rgba(${rgb[0]}, ${rgb[1]}, ${rgb[2]}, 0.18)`;
}
function createHeadGlowColor(themeColor) {
    const rgb = hexToRgb(themeColor);
    if (!rgb) {
        return 'rgba(59, 130, 246, 0.94)';
    }
    return `rgba(${rgb[0]}, ${rgb[1]}, ${rgb[2]}, 0.94)`;
}
function createSweepTailColor(themeColor) {
    const rgb = hexToRgb(themeColor);
    if (!rgb) {
        return 'rgba(59, 130, 246, 0.32)';
    }
    return `rgba(${rgb[0]}, ${rgb[1]}, ${rgb[2]}, 0.32)`;
}
function parseRadiusValue(value) {
    const parts = value
        .split(/\s+/)
        .map((part) => Number.parseFloat(part))
        .filter((part) => Number.isFinite(part));
    if (parts.length === 0) {
        return { x: 0, y: 0 };
    }
    if (parts.length === 1) {
        return { x: parts[0], y: parts[0] };
    }
    return { x: parts[0], y: parts[1] };
}
function clampCornerRadius(radius, maxX, maxY) {
    return {
        x: Math.max(0, Math.min(radius.x, maxX)),
        y: Math.max(0, Math.min(radius.y, maxY)),
    };
}
function scaleHorizontalPair(start, end, limit) {
    const sum = start.x + end.x;
    if (sum <= limit || sum === 0) {
        return [start, end];
    }
    const scale = limit / sum;
    return [
        Object.assign(Object.assign({}, start), { x: start.x * scale }),
        Object.assign(Object.assign({}, end), { x: end.x * scale }),
    ];
}
function scaleVerticalPair(start, end, limit) {
    const sum = start.y + end.y;
    if (sum <= limit || sum === 0) {
        return [start, end];
    }
    const scale = limit / sum;
    return [
        Object.assign(Object.assign({}, start), { y: start.y * scale }),
        Object.assign(Object.assign({}, end), { y: end.y * scale }),
    ];
}
function normalizeRectRadii(width, height, input) {
    let topLeft = clampCornerRadius(input.topLeft, width / 2, height / 2);
    let topRight = clampCornerRadius(input.topRight, width / 2, height / 2);
    let bottomRight = clampCornerRadius(input.bottomRight, width / 2, height / 2);
    let bottomLeft = clampCornerRadius(input.bottomLeft, width / 2, height / 2);
    [topLeft, topRight] = scaleHorizontalPair(topLeft, topRight, width);
    [bottomLeft, bottomRight] = scaleHorizontalPair(bottomLeft, bottomRight, width);
    [topLeft, bottomLeft] = scaleVerticalPair(topLeft, bottomLeft, height);
    [topRight, bottomRight] = scaleVerticalPair(topRight, bottomRight, height);
    return {
        topLeft,
        topRight,
        bottomRight,
        bottomLeft,
    };
}
function buildRoundedRectPath(x, y, width, height, radii) {
    const { topLeft, topRight, bottomRight, bottomLeft } = normalizeRectRadii(width, height, radii);
    return [
        `M ${x + topLeft.x} ${y}`,
        `H ${x + Math.max(topLeft.x, width - topRight.x)}`,
        topRight.x > 0 || topRight.y > 0
            ? `A ${topRight.x} ${topRight.y} 0 0 1 ${x + width} ${y + topRight.y}`
            : `L ${x + width} ${y}`,
        `V ${y + Math.max(topRight.y, height - bottomRight.y)}`,
        bottomRight.x > 0 || bottomRight.y > 0
            ? `A ${bottomRight.x} ${bottomRight.y} 0 0 1 ${x + width - bottomRight.x} ${y + height}`
            : `L ${x + width} ${y + height}`,
        `H ${x + Math.min(width - bottomRight.x, bottomLeft.x)}`,
        bottomLeft.x > 0 || bottomLeft.y > 0
            ? `A ${bottomLeft.x} ${bottomLeft.y} 0 0 1 ${x} ${y + height - bottomLeft.y}`
            : `L ${x} ${y + height}`,
        `V ${y + Math.min(height - bottomLeft.y, topLeft.y)}`,
        topLeft.x > 0 || topLeft.y > 0
            ? `A ${topLeft.x} ${topLeft.y} 0 0 1 ${x + topLeft.x} ${y}`
            : `L ${x} ${y}`,
        'Z',
    ].join(' ');
}
function createCircleGeometry(width, height, strokeWidth) {
    const safeWidth = Math.max(width, MIN_FRAME_SIZE);
    const safeHeight = Math.max(height, MIN_FRAME_SIZE);
    const radius = Math.max(0, Math.min(safeWidth, safeHeight) / 2 - strokeWidth / 2);
    const centerX = safeWidth / 2;
    const centerY = safeHeight / 2;
    return {
        viewBox: `0 0 ${safeWidth} ${safeHeight}`,
        path: `M ${centerX} ${centerY - radius} A ${radius} ${radius} 0 1 1 ${centerX} ${centerY + radius} A ${radius} ${radius} 0 1 1 ${centerX} ${centerY - radius}`,
        length: Math.max(0, 2 * Math.PI * radius),
        strokeWidth,
    };
}
function createRoundedRectGeometry(width, height, strokeWidth, radii) {
    const safeWidth = Math.max(width, MIN_FRAME_SIZE);
    const safeHeight = Math.max(height, MIN_FRAME_SIZE);
    const inset = strokeWidth / 2;
    const innerWidth = Math.max(safeWidth - strokeWidth, MIN_FRAME_SIZE);
    const innerHeight = Math.max(safeHeight - strokeWidth, MIN_FRAME_SIZE);
    const adjustedRadii = normalizeRectRadii(innerWidth, innerHeight, {
        topLeft: {
            x: Math.max(0, radii.topLeft.x - inset),
            y: Math.max(0, radii.topLeft.y - inset),
        },
        topRight: {
            x: Math.max(0, radii.topRight.x - inset),
            y: Math.max(0, radii.topRight.y - inset),
        },
        bottomRight: {
            x: Math.max(0, radii.bottomRight.x - inset),
            y: Math.max(0, radii.bottomRight.y - inset),
        },
        bottomLeft: {
            x: Math.max(0, radii.bottomLeft.x - inset),
            y: Math.max(0, radii.bottomLeft.y - inset),
        },
    });
    return {
        viewBox: `0 0 ${safeWidth} ${safeHeight}`,
        path: buildRoundedRectPath(inset, inset, innerWidth, innerHeight, adjustedRadii),
        length: 0,
        strokeWidth,
    };
}
function readRectRadii(element) {
    const computedStyle = window.getComputedStyle(element);
    return {
        topLeft: parseRadiusValue(computedStyle.borderTopLeftRadius),
        topRight: parseRadiusValue(computedStyle.borderTopRightRadius),
        bottomRight: parseRadiusValue(computedStyle.borderBottomRightRadius),
        bottomLeft: parseRadiusValue(computedStyle.borderBottomLeftRadius),
    };
}
function SnakeRingSvg({ containerRef, shape, themeColor, progressRatio, animate, strokeWidth, }) {
    var _a, _b;
    const gradientId = React.useId().replace(/:/g, '-');
    createBodyTailColor(themeColor);
    const headGlowColor = createHeadGlowColor(themeColor);
    const sweepTailColor = createSweepTailColor(themeColor);
    const [geometry, setGeometry] = React.useState(null);
    const pathMeasureRef = React.useRef(null);
    const measuredLengthRef = React.useRef(0);
    React.useEffect(() => {
        const container = containerRef.current;
        if (!container) {
            return;
        }
        const updateGeometry = () => {
            const rect = container.getBoundingClientRect();
            const preferredStrokeWidth = strokeWidth !== null && strokeWidth !== void 0 ? strokeWidth : (shape === 'circle' ? DEFAULT_CIRCLE_STROKE : DEFAULT_RECT_STROKE);
            const resolvedStrokeWidth = shape === 'rounded-rect'
                ? Math.max(RECT_MIN_STROKE_WIDTH, preferredStrokeWidth)
                : preferredStrokeWidth;
            const nextGeometry = shape === 'circle'
                ? createCircleGeometry(rect.width, rect.height, resolvedStrokeWidth)
                : createRoundedRectGeometry(rect.width, rect.height, resolvedStrokeWidth, readRectRadii(container));
            measuredLengthRef.current = 0;
            setGeometry(nextGeometry);
        };
        updateGeometry();
        const resizeObserver = new ResizeObserver(() => {
            updateGeometry();
        });
        const mutationObserver = new MutationObserver(() => {
            updateGeometry();
        });
        resizeObserver.observe(container);
        mutationObserver.observe(container, {
            attributes: true,
            attributeFilter: ['class', 'style'],
        });
        return () => {
            resizeObserver.disconnect();
            mutationObserver.disconnect();
        };
    }, [containerRef, shape, strokeWidth]);
    React.useEffect(() => {
        if (!geometry || shape === 'circle' || !pathMeasureRef.current) {
            return;
        }
        const measuredLength = pathMeasureRef.current.getTotalLength();
        const normalizedLength = Number.isFinite(measuredLength)
            ? Math.max(0, measuredLength)
            : 0;
        if (normalizedLength <= 0) {
            return;
        }
        if (Math.abs(measuredLengthRef.current - normalizedLength) < 0.1) {
            return;
        }
        measuredLengthRef.current = normalizedLength;
        setGeometry((current) => {
            if (!current || current.path !== geometry.path) {
                return current;
            }
            if (Math.abs(current.length - normalizedLength) < 0.1) {
                return current;
            }
            return Object.assign(Object.assign({}, current), { length: normalizedLength });
        });
    }, [geometry, shape]);
    const resolvedGeometry = React.useMemo(() => geometry, [geometry]);
    if (!resolvedGeometry) {
        return null;
    }
    const effectiveLength = resolvedGeometry.length > 0
        ? resolvedGeometry.length
        : Math.max(1, 2 * Math.max(0, resolvedGeometry.strokeWidth), 2 *
            (Math.max(0, Number.parseFloat((_a = resolvedGeometry.viewBox.split(' ')[2]) !== null && _a !== void 0 ? _a : '0')) +
                Math.max(0, Number.parseFloat((_b = resolvedGeometry.viewBox.split(' ')[3]) !== null && _b !== void 0 ? _b : '0'))));
    const [, , viewBoxWidthRaw, viewBoxHeightRaw] = resolvedGeometry.viewBox.split(' ');
    const viewBoxWidth = Math.max(0, Number.parseFloat(viewBoxWidthRaw !== null && viewBoxWidthRaw !== void 0 ? viewBoxWidthRaw : '0'));
    const viewBoxHeight = Math.max(0, Number.parseFloat(viewBoxHeightRaw !== null && viewBoxHeightRaw !== void 0 ? viewBoxHeightRaw : '0'));
    const centerX = viewBoxWidth / 2;
    const centerY = viewBoxHeight / 2;
    const isCircle = shape === 'circle';
    const tailTransparentStart = isCircle ? '18%' : '26%';
    const tailColorStart = isCircle ? '39%' : '46%';
    const tailTransparentEnd = isCircle ? '90%' : '82%';
    const headTransparentStart = isCircle ? '32%' : '40%';
    const headColorStart = isCircle ? '48%' : '53%';
    const headTransparentEnd = isCircle ? '82%' : '73%';
    const bodyLength = Math.min(effectiveLength * MAX_BODY_LENGTH_RATIO, Math.max(MIN_BODY_LENGTH, effectiveLength * BODY_LENGTH_RATIO));
    const bodyDashArray = `${bodyLength} ${effectiveLength}`;
    const staticDashOffset = effectiveLength * (1 - progressRatio);
    const tailStrokeWidth = shape === 'circle'
        ? resolvedGeometry.strokeWidth + 1.2
        : resolvedGeometry.strokeWidth + Math.min(1.2, resolvedGeometry.strokeWidth * 0.32);
    return (jsxRuntime.jsxs("svg", { className: "pointer-events-none absolute inset-0 h-full w-full", viewBox: resolvedGeometry.viewBox, preserveAspectRatio: "none", "aria-hidden": "true", children: [shape === 'rounded-rect' ? (jsxRuntime.jsx("path", { ref: pathMeasureRef, d: resolvedGeometry.path, fill: "none", stroke: "transparent" })) : null, animate ? (jsxRuntime.jsxs("defs", { children: [jsxRuntime.jsxs("linearGradient", { id: `${gradientId}-sweep-tail`, x1: "0", y1: "0", x2: String(viewBoxWidth), y2: "0", gradientUnits: "userSpaceOnUse", children: [jsxRuntime.jsx("stop", { offset: "0%", stopColor: "transparent" }), jsxRuntime.jsx("stop", { offset: tailTransparentStart, stopColor: "transparent" }), jsxRuntime.jsx("stop", { offset: tailColorStart, stopColor: sweepTailColor }), jsxRuntime.jsx("stop", { offset: "64%", stopColor: headGlowColor }), jsxRuntime.jsx("stop", { offset: tailTransparentEnd, stopColor: "transparent" }), jsxRuntime.jsx("stop", { offset: "100%", stopColor: "transparent" }), jsxRuntime.jsx("animateTransform", { attributeName: "gradientTransform", type: "rotate", from: `0 ${centerX} ${centerY}`, to: `360 ${centerX} ${centerY}`, dur: `${LOOP_DURATION_SECONDS}s`, repeatCount: "indefinite" })] }), jsxRuntime.jsxs("linearGradient", { id: `${gradientId}-sweep-head`, x1: "0", y1: "0", x2: String(viewBoxWidth), y2: "0", gradientUnits: "userSpaceOnUse", children: [jsxRuntime.jsx("stop", { offset: "0%", stopColor: "transparent" }), jsxRuntime.jsx("stop", { offset: headTransparentStart, stopColor: "transparent" }), jsxRuntime.jsx("stop", { offset: headColorStart, stopColor: themeColor }), jsxRuntime.jsx("stop", { offset: "63%", stopColor: headGlowColor }), jsxRuntime.jsx("stop", { offset: headTransparentEnd, stopColor: "transparent" }), jsxRuntime.jsx("stop", { offset: "100%", stopColor: "transparent" }), jsxRuntime.jsx("animateTransform", { attributeName: "gradientTransform", type: "rotate", from: `0 ${centerX} ${centerY}`, to: `360 ${centerX} ${centerY}`, dur: `${LOOP_DURATION_SECONDS}s`, repeatCount: "indefinite" })] })] })) : null, jsxRuntime.jsx("path", { d: resolvedGeometry.path, fill: "none", stroke: TRACK_COLOR, strokeWidth: resolvedGeometry.strokeWidth, strokeLinecap: "round", strokeLinejoin: "round" }), animate ? (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("path", { d: resolvedGeometry.path, fill: "none", stroke: `url(#${gradientId}-sweep-tail)`, strokeWidth: tailStrokeWidth, strokeLinecap: "round", strokeLinejoin: "round" }), jsxRuntime.jsx("path", { d: resolvedGeometry.path, fill: "none", stroke: `url(#${gradientId}-sweep-head)`, strokeWidth: resolvedGeometry.strokeWidth, strokeLinecap: "round", strokeLinejoin: "round" })] })) : null, !animate ? (jsxRuntime.jsx("path", { d: resolvedGeometry.path, fill: "none", stroke: themeColor, strokeWidth: resolvedGeometry.strokeWidth, strokeLinecap: "round", strokeLinejoin: "round", strokeDasharray: bodyDashArray, strokeDashoffset: staticDashOffset })) : null] }));
}
function SnakeFrameBase({ shape, loading, children, className, themeColor = DEFAULT_THEME_COLOR, previewProgress, strokeWidth, contentClassName, }) {
    const containerRef = React.useRef(null);
    const [showOverlay, setShowOverlay] = React.useState(loading || previewProgress !== undefined);
    const exitTimerRef = React.useRef(null);
    const resolvedStrokeWidth = strokeWidth !== null && strokeWidth !== void 0 ? strokeWidth : (shape === 'circle' ? DEFAULT_CIRCLE_STROKE : DEFAULT_RECT_STROKE);
    const circleContentInset = shape === 'circle' ? Math.max(6, resolvedStrokeWidth + 4) : 0;
    const progressRatio = clampProgress(previewProgress !== null && previewProgress !== void 0 ? previewProgress : 0) / 100;
    React.useEffect(() => {
        if (previewProgress !== undefined) {
            setShowOverlay(true);
            return;
        }
        if (loading) {
            if (exitTimerRef.current !== null) {
                window.clearTimeout(exitTimerRef.current);
                exitTimerRef.current = null;
            }
            setShowOverlay(true);
            return;
        }
        exitTimerRef.current = window.setTimeout(() => {
            setShowOverlay(false);
            exitTimerRef.current = null;
        }, EXIT_DURATION_MS);
        return () => {
            if (exitTimerRef.current !== null) {
                window.clearTimeout(exitTimerRef.current);
                exitTimerRef.current = null;
            }
        };
    }, [loading, previewProgress]);
    return (jsxRuntime.jsxs("div", { ref: containerRef, className: utils.cn('relative isolate', shape === 'circle' ? 'rounded-full' : 'rounded-none', className), children: [jsxRuntime.jsx("div", { className: utils.cn('relative z-0 overflow-hidden', shape === 'circle'
                    ? 'absolute flex items-center justify-center rounded-full'
                    : 'h-full w-full', contentClassName), style: shape === 'circle'
                    ? {
                        inset: circleContentInset,
                    }
                    : undefined, children: children }), showOverlay ? (jsxRuntime.jsx(proxy.motion.div, { className: "pointer-events-none absolute inset-0 overflow-visible", initial: false, animate: { opacity: loading || previewProgress !== undefined ? 1 : 0 }, transition: { duration: EXIT_DURATION_MS / 1000, ease: 'easeOut' }, children: jsxRuntime.jsx(SnakeRingSvg, { containerRef: containerRef, shape: shape, themeColor: themeColor, progressRatio: progressRatio, animate: previewProgress === undefined && loading, strokeWidth: resolvedStrokeWidth }) })) : null] }));
}
function SnakeLoadingFrame(props) {
    return jsxRuntime.jsx(SnakeFrameBase, Object.assign({}, props));
}
function SnakeLoadingPreview({ shape, children, className, themeColor = DEFAULT_THEME_COLOR, defaultProgress = 32, strokeWidth, contentClassName, }) {
    const [progress, setProgress] = React.useState(clampProgress(defaultProgress));
    const sliderFillColor = themeColor;
    const sliderGlowColor = createBodyTailColor(themeColor);
    const sliderBackground = `linear-gradient(90deg, ${sliderGlowColor} 0%, ${sliderFillColor} ${progress}%, rgba(148, 163, 184, 0.24) ${progress}%, rgba(148, 163, 184, 0.24) 100%)`;
    return (jsxRuntime.jsxs("div", { className: "space-y-3", children: [jsxRuntime.jsx(SnakeFrameBase, { shape: shape, loading: true, previewProgress: progress, className: className, themeColor: themeColor, strokeWidth: strokeWidth, contentClassName: contentClassName, children: children }), jsxRuntime.jsxs("div", { className: "space-y-2", children: [jsxRuntime.jsxs("div", { className: "flex items-center justify-between text-[11px] font-medium uppercase tracking-[0.14em] text-slate-500 dark:text-slate-400", children: [jsxRuntime.jsx("span", { children: "Snake Preview" }), jsxRuntime.jsxs("span", { children: [progress, "%"] })] }), jsxRuntime.jsx("input", { type: "range", min: 0, max: 100, value: progress, onChange: (event) => {
                            setProgress(clampProgress(Number(event.target.value)));
                        }, className: "h-2 w-full cursor-pointer appearance-none rounded-full", style: {
                            background: sliderBackground,
                            accentColor: themeColor,
                        }, "aria-label": "Preview snake loading progress" })] })] }));
}

exports.SnakeLoadingFrame = SnakeLoadingFrame;
exports.SnakeLoadingPreview = SnakeLoadingPreview;
