import { jsx, jsxs, Fragment } from "react/jsx-runtime";
import * as React from "react";
import { Star } from "lucide-react";
import { cn } from "../../lib/utils.js";
import { useFieldContext, useResolvedFieldDisabled, useResolvedFieldSize } from "../Field/field-context.js";
const SIZE_PX = { xs: 20, sm: 20, md: 24, lg: 24 };
const CONTAINER_HEIGHT = {
  xs: "h-field-xs",
  sm: "h-field-sm",
  md: "h-field-md",
  lg: "h-field-lg"
};
const Rating = React.forwardRef(
  ({
    value,
    defaultValue = 0,
    onChange,
    max = 5,
    size: sizeProp,
    precision = "full",
    readOnly = false,
    disabled: disabledProp,
    loading = false,
    icon: Icon = Star,
    className,
    ...props
  }, ref) => {
    const fieldCtx = useFieldContext();
    const disabled = useResolvedFieldDisabled(disabledProp);
    const size = useResolvedFieldSize(sizeProp, "xs");
    const [internalValue, setInternalValue] = React.useState(defaultValue);
    const [hoverValue, setHoverValue] = React.useState(null);
    const isControlled = value !== void 0;
    const currentValue = isControlled ? value : internalValue;
    const displayValue = hoverValue ?? currentValue;
    const iconPx = SIZE_PX[size];
    const isInteractive = !readOnly && !disabled && !loading;
    const setValue = (v) => {
      if (!isControlled) setInternalValue(v);
      onChange == null ? void 0 : onChange(v);
    };
    const handleKeyDown = (e) => {
      if (!isInteractive) return;
      const step = precision === "half" ? 0.5 : 1;
      if (e.key === "ArrowRight" || e.key === "ArrowUp") {
        e.preventDefault();
        setValue(Math.min(max, currentValue + step));
      } else if (e.key === "ArrowLeft" || e.key === "ArrowDown") {
        e.preventDefault();
        setValue(Math.max(0, currentValue - step));
      } else if (e.key === "Home") {
        e.preventDefault();
        setValue(0);
      } else if (e.key === "End") {
        e.preventDefault();
        setValue(max);
      }
    };
    return /* @__PURE__ */ jsx(
      "div",
      {
        ref,
        role: isInteractive ? "slider" : "img",
        "aria-labelledby": isInteractive ? fieldCtx == null ? void 0 : fieldCtx.labelId : void 0,
        "aria-valuenow": isInteractive ? currentValue : void 0,
        "aria-valuemin": isInteractive ? 0 : void 0,
        "aria-valuemax": isInteractive ? max : void 0,
        "aria-valuetext": isInteractive ? `${currentValue} of ${max} stars` : void 0,
        "aria-disabled": disabled || void 0,
        "aria-busy": loading || void 0,
        tabIndex: isInteractive ? 0 : void 0,
        onKeyDown: handleKeyDown,
        onMouseLeave: () => setHoverValue(null),
        className: cn(
          "inline-flex items-center gap-1",
          // Container 對齊 field-height family,讓 Rating 可與 Input/Select/Button 並排 row-align
          CONTAINER_HEIGHT[size],
          "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 rounded-md",
          // disabled 跟 loading 視覺相同(composite uniform dim),semantic 由 aria-disabled / aria-busy 區分
          (disabled || loading) && "opacity-disabled pointer-events-none",
          className
        ),
        ...props,
        children: Array.from({ length: max }, (_, i) => {
          const starValue = i + 1;
          const fillRatio = Math.max(0, Math.min(1, displayValue - i));
          const isHalf = precision === "half" && fillRatio > 0 && fillRatio < 1;
          return /* @__PURE__ */ jsx(
            StarIcon,
            {
              Icon,
              sizePx: iconPx,
              fillRatio,
              isHalf,
              interactive: isInteractive,
              onHover: (halfFirst) => {
                if (!isInteractive) return;
                const v = precision === "half" && halfFirst ? starValue - 0.5 : starValue;
                setHoverValue(v);
              },
              onClick: (halfFirst) => {
                if (!isInteractive) return;
                const v = precision === "half" && halfFirst ? starValue - 0.5 : starValue;
                setValue(v);
              }
            },
            i
          );
        })
      }
    );
  }
);
Rating.displayName = "Rating";
const FILL_FILLED = "var(--warning)";
const FILL_EMPTY = "var(--divider)";
function StarIcon({ Icon, sizePx, fillRatio, isHalf, interactive, onHover, onClick }) {
  if (!isHalf) {
    const fill = fillRatio >= 1 ? FILL_FILLED : FILL_EMPTY;
    return /* @__PURE__ */ jsx(
      "span",
      {
        role: "presentation",
        onMouseEnter: interactive ? () => onHover(false) : void 0,
        onClick: interactive ? () => onClick(false) : void 0,
        className: cn(
          "inline-flex",
          interactive ? "cursor-pointer" : "cursor-default"
        ),
        style: { color: fill },
        "aria-hidden": true,
        children: /* @__PURE__ */ jsx(Icon, { size: sizePx, fill, stroke: "none", className: "shrink-0" })
      }
    );
  }
  return /* @__PURE__ */ jsxs("span", { className: "relative inline-flex", style: { width: sizePx, height: sizePx }, children: [
    /* @__PURE__ */ jsx(Icon, { size: sizePx, fill: FILL_EMPTY, stroke: "none", className: "absolute inset-0", style: { color: FILL_EMPTY } }),
    /* @__PURE__ */ jsx("span", { className: "absolute inset-0 overflow-hidden", style: { width: sizePx * fillRatio }, children: /* @__PURE__ */ jsx(Icon, { size: sizePx, fill: FILL_FILLED, stroke: "none", style: { color: FILL_FILLED } }) }),
    interactive && /* @__PURE__ */ jsxs(Fragment, { children: [
      /* @__PURE__ */ jsx(
        "span",
        {
          role: "presentation",
          onMouseEnter: () => onHover(true),
          onClick: () => onClick(true),
          className: "absolute inset-y-0 left-0 w-1/2 cursor-pointer",
          "aria-hidden": true
        }
      ),
      /* @__PURE__ */ jsx(
        "span",
        {
          role: "presentation",
          onMouseEnter: () => onHover(false),
          onClick: () => onClick(false),
          className: "absolute inset-y-0 right-0 w-1/2 cursor-pointer",
          "aria-hidden": true
        }
      )
    ] })
  ] });
}
const ratingMeta = {
  component: "Rating",
  family: null,
  // self-contained primitive(對齊 spec frontmatter self-contained + body L24;非 Family 4)
  variants: {},
  sizes: {},
  states: ["default", "hover", "active", "focus-visible", "disabled"],
  tokens: {
    bg: ["bg-transparent"],
    fg: [],
    ring: ["ring-ring"]
  }
};
export {
  Rating,
  ratingMeta
};
//# sourceMappingURL=rating.js.map
