"use client";
import * as React from "react";
import { ownerDocument } from "../../../../utils/esm/owner.js";
import { useControlled } from "../../../../utils/esm/useControlled.js";
import { useStableCallback } from "../../../../utils/esm/useStableCallback.js";
import { useValueAsRef } from "../../../../utils/esm/useValueAsRef.js";
import { useIsoLayoutEffect } from "../../../../utils/esm/useIsoLayoutEffect.js";
import { warn } from "../../../../utils/esm/warn.js";
import { createChangeEventDetails, createGenericEventDetails } from "../../utils/createBaseUIEventDetails.js";
import { useValueChanged } from "../../utils/useValueChanged.js";
import { useBaseUiId } from "../../utils/useBaseUiId.js";
import { useRenderElement } from "../../utils/useRenderElement.js";
import { clamp } from "../../utils/clamp.js";
import { areArraysEqual } from "../../utils/areArraysEqual.js";
import { CompositeList } from "../../composite/list/CompositeList.js";
import { useField } from "../../field/useField.js";
import { useFieldRootContext } from "../../field/root/FieldRootContext.js";
import { useFormContext } from "../../form/FormContext.js";
import { useLabelableContext } from "../../labelable-provider/LabelableContext.js";
import { asc } from "../utils/asc.js";
import { getSliderValue } from "../utils/getSliderValue.js";
import { validateMinimumDistance } from "../utils/validateMinimumDistance.js";
import { sliderStateAttributesMapping } from "./stateAttributesMapping.js";
import { SliderRootContext } from "./SliderRootContext.js";
import { jsx } from "react/jsx-runtime";
import { activeElement } from "../../floating-ui-react/utils/element.js";
import { none, keyboard, inputChange } from "../../utils/reason-parts.js";
function getSliderChangeEventReason(event2) {
  return "key" in event2 ? keyboard : inputChange;
}
function areValuesEqual(newValue, oldValue) {
  if (typeof newValue === "number" && typeof oldValue === "number") {
    return newValue === oldValue;
  }
  if (Array.isArray(newValue) && Array.isArray(oldValue)) {
    return areArraysEqual(newValue, oldValue);
  }
  return false;
}
const SliderRoot = /* @__PURE__ */ React.forwardRef(function SliderRoot2(componentProps, forwardedRef) {
  const {
    "aria-labelledby": ariaLabelledByProp,
    className,
    defaultValue,
    disabled: disabledProp = false,
    id: idProp,
    format,
    largeStep = 10,
    locale,
    render,
    max = 100,
    min = 0,
    minStepsBetweenValues = 0,
    name: nameProp,
    onValueChange: onValueChangeProp,
    onValueCommitted: onValueCommittedProp,
    orientation = "horizontal",
    step = 1,
    thumbCollisionBehavior = "push",
    thumbAlignment = "center",
    value: valueProp,
    ...elementProps
  } = componentProps;
  const id = useBaseUiId(idProp);
  const onValueChange = useStableCallback(onValueChangeProp);
  const onValueCommitted = useStableCallback(onValueCommittedProp);
  const {
    clearErrors
  } = useFormContext();
  const {
    state: fieldState,
    disabled: fieldDisabled,
    name: fieldName,
    setTouched,
    setDirty,
    validityData,
    shouldValidateOnChange,
    validation
  } = useFieldRootContext();
  const {
    labelId
  } = useLabelableContext();
  const ariaLabelledby = ariaLabelledByProp ?? labelId;
  const disabled = fieldDisabled || disabledProp;
  const name = fieldName ?? nameProp;
  const [valueUnwrapped, setValueUnwrapped] = useControlled({
    controlled: valueProp,
    default: defaultValue ?? min,
    name: "Slider"
  });
  const sliderRef = React.useRef(null);
  const controlRef = React.useRef(null);
  const thumbRefs = React.useRef([]);
  const pressedInputRef = React.useRef(null);
  const pressedThumbCenterOffsetRef = React.useRef(null);
  const pressedThumbIndexRef = React.useRef(-1);
  const pressedValuesRef = React.useRef(null);
  const lastChangedValueRef = React.useRef(null);
  const lastChangeReasonRef = React.useRef("none");
  const formatOptionsRef = useValueAsRef(format);
  const [active, setActiveState] = React.useState(-1);
  const [lastUsedThumbIndex, setLastUsedThumbIndex] = React.useState(-1);
  const [dragging, setDragging] = React.useState(false);
  const [thumbMap, setThumbMap] = React.useState(() => /* @__PURE__ */ new Map());
  const [indicatorPosition, setIndicatorPosition] = React.useState([void 0, void 0]);
  const setActive = useStableCallback((value) => {
    setActiveState(value);
    if (value !== -1) {
      setLastUsedThumbIndex(value);
    }
  });
  useField({
    id,
    commit: validation.commit,
    value: valueUnwrapped,
    controlRef,
    name,
    getValue: () => valueUnwrapped
  });
  useValueChanged(valueUnwrapped, () => {
    clearErrors(name);
    if (shouldValidateOnChange()) {
      validation.commit(valueUnwrapped);
    } else {
      validation.commit(valueUnwrapped, true);
    }
    const initialValue = validityData.initialValue;
    let isDirty;
    if (Array.isArray(valueUnwrapped) && Array.isArray(initialValue)) {
      isDirty = !areArraysEqual(valueUnwrapped, initialValue);
    } else {
      isDirty = valueUnwrapped !== initialValue;
    }
    setDirty(isDirty);
  });
  const registerFieldControlRef = useStableCallback((element2) => {
    if (element2) {
      controlRef.current = element2;
    }
  });
  const range = Array.isArray(valueUnwrapped);
  const values = React.useMemo(() => {
    if (!range) {
      return [clamp(valueUnwrapped, min, max)];
    }
    return valueUnwrapped.slice().sort(asc);
  }, [max, min, range, valueUnwrapped]);
  const setValue = useStableCallback((newValue, details) => {
    if (Number.isNaN(newValue) || areValuesEqual(newValue, valueUnwrapped)) {
      return;
    }
    const changeDetails = details ?? createChangeEventDetails(none, void 0, void 0, {
      activeThumbIndex: -1
    });
    lastChangeReasonRef.current = changeDetails.reason;
    const clonedEvent = new event.constructor(event.type, event);
    Object.defineProperty(clonedEvent, "target", {
      writable: true,
      value: {
        value: newValue,
        name
      }
    });
    changeDetails.event = clonedEvent;
    lastChangedValueRef.current = newValue;
    onValueChange(newValue, changeDetails);
    if (changeDetails.isCanceled) {
      return;
    }
    setValueUnwrapped(newValue);
  });
  const handleInputChange = useStableCallback((valueInput, index, event2) => {
    const newValue = getSliderValue(valueInput, index, min, max, range, values);
    if (validateMinimumDistance(newValue, step, minStepsBetweenValues)) {
      const reason = getSliderChangeEventReason(event2);
      setValue(newValue, createChangeEventDetails(reason, event2.nativeEvent, void 0, {
        activeThumbIndex: index
      }));
      setTouched(true);
      const nextValue = lastChangedValueRef.current ?? newValue;
      onValueCommitted(nextValue, createGenericEventDetails(reason, event2.nativeEvent));
    }
  });
  if (process.env.NODE_ENV !== "production") {
    if (min >= max) {
      warn("Slider `max` must be greater than `min`.");
    }
  }
  useIsoLayoutEffect(() => {
    const activeEl = activeElement(ownerDocument(sliderRef.current));
    if (disabled && activeEl && sliderRef.current?.contains(activeEl)) {
      activeEl.blur();
    }
  }, [disabled]);
  if (disabled && active !== -1) {
    setActive(-1);
  }
  const state = React.useMemo(() => ({
    ...fieldState,
    activeThumbIndex: active,
    disabled,
    dragging,
    orientation,
    max,
    min,
    minStepsBetweenValues,
    step,
    values
  }), [fieldState, active, disabled, dragging, max, min, minStepsBetweenValues, orientation, step, values]);
  const contextValue = React.useMemo(() => ({
    active,
    controlRef,
    disabled,
    dragging,
    validation,
    formatOptionsRef,
    handleInputChange,
    indicatorPosition,
    inset: thumbAlignment !== "center",
    labelId: ariaLabelledby,
    largeStep,
    lastUsedThumbIndex,
    lastChangedValueRef,
    lastChangeReasonRef,
    locale,
    max,
    min,
    minStepsBetweenValues,
    name,
    onValueCommitted,
    orientation,
    pressedInputRef,
    pressedThumbCenterOffsetRef,
    pressedThumbIndexRef,
    pressedValuesRef,
    registerFieldControlRef,
    renderBeforeHydration: thumbAlignment === "edge",
    setActive,
    setDragging,
    setIndicatorPosition,
    setValue,
    state,
    step,
    thumbCollisionBehavior,
    thumbMap,
    thumbRefs,
    values
  }), [active, controlRef, ariaLabelledby, disabled, dragging, validation, formatOptionsRef, handleInputChange, indicatorPosition, largeStep, lastUsedThumbIndex, lastChangedValueRef, lastChangeReasonRef, locale, max, min, minStepsBetweenValues, name, onValueCommitted, orientation, pressedInputRef, pressedThumbCenterOffsetRef, pressedThumbIndexRef, pressedValuesRef, registerFieldControlRef, setActive, setDragging, setIndicatorPosition, setValue, state, step, thumbCollisionBehavior, thumbAlignment, thumbMap, thumbRefs, values]);
  const element = useRenderElement("div", componentProps, {
    state,
    ref: [forwardedRef, sliderRef],
    props: [{
      "aria-labelledby": ariaLabelledby,
      id,
      role: "group"
    }, validation.getValidationProps, elementProps],
    stateAttributesMapping: sliderStateAttributesMapping
  });
  return /* @__PURE__ */ jsx(SliderRootContext.Provider, {
    value: contextValue,
    children: /* @__PURE__ */ jsx(CompositeList, {
      elementsRef: thumbRefs,
      onMapChange: setThumbMap,
      children: element
    })
  });
});
if (process.env.NODE_ENV !== "production") SliderRoot.displayName = "SliderRoot";
export {
  SliderRoot
};
//# sourceMappingURL=SliderRoot.js.map
