"use client";
import * as React5 from 'react';
import { clsx } from 'clsx';
import { twMerge } from 'tailwind-merge';
import { jsx, jsxs } from 'react/jsx-runtime';
import * as LabelPrimitive from '@radix-ui/react-label';
import { cva } from 'class-variance-authority';
import * as SliderPrimitive from '@radix-ui/react-slider';
import * as PopoverPrimitive from '@radix-ui/react-popover';

function cn(...inputs) {
  return twMerge(clsx(inputs));
}

// src/lib/color.ts
function parseHslTriplet(triplet) {
  const parts = triplet.trim().split(/\s+/);
  return {
    h: Number.parseFloat(parts[0]) || 0,
    s: Number.parseFloat(parts[1]) || 0,
    l: Number.parseFloat(parts[2]) || 0
  };
}
function formatHslTriplet({ h, s, l }) {
  const round = (n) => Math.abs(n - Math.round(n)) < 1e-6 ? `${Math.round(n)}` : n.toFixed(1);
  return `${Math.round(h)} ${round(s)}% ${round(l)}%`;
}
function hslToRgb(h, s, l) {
  const sN = s / 100;
  const lN = l / 100;
  const k = (n) => (n + h / 30) % 12;
  const a = sN * Math.min(lN, 1 - lN);
  const f = (n) => lN - a * Math.max(-1, Math.min(k(n) - 3, 9 - k(n), 1));
  return {
    r: Math.round(255 * f(0)),
    g: Math.round(255 * f(8)),
    b: Math.round(255 * f(4))
  };
}
function rgbToHsl(r, g, b) {
  const rN = r / 255;
  const gN = g / 255;
  const bN = b / 255;
  const max = Math.max(rN, gN, bN);
  const min = Math.min(rN, gN, bN);
  let h = 0;
  let s = 0;
  const l = (max + min) / 2;
  if (max !== min) {
    const d = max - min;
    s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
    if (max === rN) h = (gN - bN) / d + (gN < bN ? 6 : 0);
    else if (max === gN) h = (bN - rN) / d + 2;
    else h = (rN - gN) / d + 4;
    h /= 6;
  }
  return { h: h * 360, s: s * 100, l: l * 100 };
}
function hslTripletToHex(triplet) {
  const { h, s, l } = parseHslTriplet(triplet);
  const { r, g, b } = hslToRgb(h, s, l);
  const toHex = (n) => n.toString(16).padStart(2, "0");
  return `#${toHex(r)}${toHex(g)}${toHex(b)}`;
}
function hexToHslTriplet(hex) {
  const clean = hex.trim().replace(/^#/, "");
  let normalized;
  if (/^[0-9a-fA-F]{3}$/.test(clean)) {
    normalized = clean.split("").map((c) => c + c).join("");
  } else if (/^[0-9a-fA-F]{6}$/.test(clean)) {
    normalized = clean;
  } else {
    return null;
  }
  const r = Number.parseInt(normalized.slice(0, 2), 16);
  const g = Number.parseInt(normalized.slice(2, 4), 16);
  const b = Number.parseInt(normalized.slice(4, 6), 16);
  return formatHslTriplet(rgbToHsl(r, g, b));
}
var Input = React5.forwardRef(
  ({ className, type, ...props }, ref) => {
    return /* @__PURE__ */ jsx(
      "input",
      {
        type,
        className: cn(
          "flex h-[var(--control-height-md,2.5rem)] w-full rounded-md border border-input bg-background px-[var(--space-3,0.75rem)] py-[var(--space-2,0.5rem)] text-sm",
          "transition-all duration-[var(--duration-normal,200ms)] ease-out",
          // inset-ring gives a self-borne edge so the input field is visible on flat
          // surfaces (token border alone is too low-contrast on bg-background=white).
          "shadow-sm inset-ring-1 inset-ring-foreground/[0.06]",
          "file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground",
          "placeholder:text-muted-foreground",
          "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
          "focus-visible:shadow-md focus-visible:border-ring/50",
          "hover:border-ring/30 hover:shadow-md",
          "disabled:cursor-not-allowed disabled:opacity-50",
          className
        ),
        ref,
        ...props
      }
    );
  }
);
Input.displayName = "Input";
var labelVariants = cva(
  "text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
);
var Label = React5.forwardRef(
  ({ className, ...props }, ref) => /* @__PURE__ */ jsx(LabelPrimitive.Root, { ref, className: cn(labelVariants(), className), ...props })
);
Label.displayName = "Label";
var Slider = React5.forwardRef(({ className, thumbLabels, ...props }, ref) => {
  const values = props.value ?? props.defaultValue ?? [0];
  const rootLabel = props["aria-label"];
  const rootLabelledBy = props["aria-labelledby"];
  if (typeof process !== "undefined" && process.env?.NODE_ENV !== "production" && thumbLabels && thumbLabels.length !== values.length) {
    console.warn(
      `Slider: thumbLabels.length (${thumbLabels.length}) does not match value.length (${values.length}). Missing labels fall back to indexed names; extra labels are ignored.`
    );
  }
  return /* @__PURE__ */ jsxs(
    SliderPrimitive.Root,
    {
      ref,
      className: cn("relative flex w-full touch-none select-none items-center", className),
      ...props,
      children: [
        /* @__PURE__ */ jsx(SliderPrimitive.Track, { className: "relative h-2 w-full grow overflow-hidden rounded-full border border-foreground/[0.08] bg-secondary", children: /* @__PURE__ */ jsx(SliderPrimitive.Range, { className: "absolute h-full bg-primary" }) }),
        values.map((_, i) => {
          const explicit = thumbLabels?.[i];
          const fallback = values.length === 1 ? rootLabel : rootLabel ? `${rootLabel} (${i + 1} of ${values.length})` : void 0;
          return /* @__PURE__ */ jsx(
            SliderPrimitive.Thumb,
            {
              "aria-label": explicit ?? fallback,
              "aria-labelledby": explicit || fallback ? void 0 : rootLabelledBy,
              className: cn(
                "block h-5 w-5 rounded-full border-2 border-primary bg-background",
                "transition-all duration-[var(--duration-normal,200ms)] ease-out shadow-md",
                "hover:shadow-lg hover:scale-110",
                "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
                "disabled:pointer-events-none disabled:opacity-50"
              )
            },
            i
          );
        })
      ]
    }
  );
});
Slider.displayName = "Slider";
var Popover = PopoverPrimitive.Root;
var PopoverTrigger = PopoverPrimitive.Trigger;
var PopoverContent = React5.forwardRef(({ className, align = "center", sideOffset = 4, ...props }, ref) => /* @__PURE__ */ jsx(PopoverPrimitive.Portal, { children: /* @__PURE__ */ jsx(
  PopoverPrimitive.Content,
  {
    ref,
    align,
    sideOffset,
    className: cn(
      "z-50 w-72 rounded-md border border-foreground/[0.08] bg-popover p-[var(--space-4,1rem)] text-popover-foreground shadow-md outline-none",
      "data-[state=open]:animate-in data-[state=closed]:animate-out",
      "data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
      "data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95",
      "data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
      className
    ),
    ...props
  }
) }));
PopoverContent.displayName = "PopoverContent";
var INTEGER_EPSILON = 1e-6;
var looksInteger = (n) => Math.abs(n - Math.round(n)) < INTEGER_EPSILON;
function ColorPicker({
  value,
  onChange,
  disabled,
  "aria-label": ariaLabel = "Pick color",
  className
}) {
  const hsl = React5.useMemo(() => parseHslTriplet(value), [value]);
  const hex = React5.useMemo(() => hslTripletToHex(value), [value]);
  const update = React5.useCallback(
    (patch) => {
      onChange(formatHslTriplet({ ...hsl, ...patch }));
    },
    [hsl, onChange]
  );
  const hexInputRef = React5.useRef(null);
  const [hexBuffer, setHexBuffer] = React5.useState(hex);
  React5.useEffect(() => {
    if (typeof document === "undefined" || document.activeElement !== hexInputRef.current) {
      setHexBuffer(hex);
    }
  }, [hex]);
  const handleHexChange = (e) => {
    const next = e.target.value;
    setHexBuffer(next);
    const triplet = hexToHslTriplet(next);
    if (triplet !== null) onChange(triplet);
  };
  const hexId = React5.useId();
  return /* @__PURE__ */ jsxs(Popover, { children: [
    /* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(
      "button",
      {
        type: "button",
        disabled,
        "aria-label": ariaLabel,
        className: cn(
          "inline-flex h-9 items-center gap-2 rounded-md border border-input bg-background px-3 text-sm shadow-sm",
          "transition-all duration-[var(--duration-normal,200ms)] ease-out",
          "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
          "hover:shadow-md disabled:pointer-events-none disabled:opacity-50",
          className
        ),
        children: [
          /* @__PURE__ */ jsx(
            "span",
            {
              "aria-hidden": "true",
              className: "h-5 w-5 rounded-sm border border-border",
              style: { backgroundColor: `hsl(${value})` }
            }
          ),
          /* @__PURE__ */ jsx("span", { className: "font-mono text-xs uppercase", children: hex })
        ]
      }
    ) }),
    /* @__PURE__ */ jsx(PopoverContent, { className: "w-72 p-4", align: "start", children: /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
      /* @__PURE__ */ jsx(
        SliderRow,
        {
          label: "Hue",
          suffix: "\xB0",
          value: hsl.h,
          max: 360,
          step: 1,
          onChange: (h) => update({ h })
        }
      ),
      /* @__PURE__ */ jsx(
        SliderRow,
        {
          label: "Saturation",
          suffix: "%",
          value: hsl.s,
          max: 100,
          step: 0.1,
          onChange: (s) => update({ s })
        }
      ),
      /* @__PURE__ */ jsx(
        SliderRow,
        {
          label: "Lightness",
          suffix: "%",
          value: hsl.l,
          max: 100,
          step: 0.1,
          onChange: (l) => update({ l })
        }
      ),
      /* @__PURE__ */ jsxs("div", { className: "flex items-end gap-2", children: [
        /* @__PURE__ */ jsxs("div", { className: "flex-1 space-y-1", children: [
          /* @__PURE__ */ jsx(Label, { htmlFor: hexId, className: "text-xs", children: "Hex" }),
          /* @__PURE__ */ jsx(
            Input,
            {
              id: hexId,
              ref: hexInputRef,
              value: hexBuffer,
              onChange: handleHexChange,
              className: "font-mono text-xs uppercase",
              spellCheck: false,
              autoComplete: "off"
            }
          )
        ] }),
        /* @__PURE__ */ jsx(
          "span",
          {
            "aria-hidden": "true",
            className: "h-9 w-9 shrink-0 rounded-md border border-border",
            style: { backgroundColor: `hsl(${value})` }
          }
        )
      ] })
    ] }) })
  ] });
}
function SliderRow({ label, suffix, value, max, step, onChange }) {
  const display = looksInteger(value) ? `${Math.round(value)}` : value.toFixed(1);
  return /* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
    /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
      /* @__PURE__ */ jsx(Label, { className: "text-xs", children: label }),
      /* @__PURE__ */ jsxs("span", { className: "font-mono text-xs tabular-nums text-muted-foreground", children: [
        display,
        suffix
      ] })
    ] }),
    /* @__PURE__ */ jsx(
      Slider,
      {
        value: [value],
        min: 0,
        max,
        step,
        "aria-label": label,
        onValueChange: (values) => onChange(values[0] ?? 0)
      }
    )
  ] });
}

export { ColorPicker };
//# sourceMappingURL=color-picker.js.map
//# sourceMappingURL=color-picker.js.map