import { clamp, evaluate, getAlignment, getAlignmentAxis, getAxisLength, getPaddingObject } from "@floating-ui/utils";
import { isElement } from "@floating-ui/utils/dom";
function resolveArrowElement(element) {
  if (element == null) {
    return null;
  }
  if (typeof element === "function") {
    return element();
  }
  if (typeof element === "object" && "current" in element) {
    return element.current;
  }
  return isElement(element) ? element : null;
}

/**
 * Fork of `@floating-ui/dom`'s `arrow` middleware that accepts an
 * `offsetParent` option ('real' vs 'floating').
 *
 * The React source splits this into `baseArrow` + `arrow` with a `deps`
 * array so React can memoize the middleware. Solid doesn't need that
 * — consumers produce a new middleware each reactive run via a `createMemo`
 * or by referencing signals — so this port keeps only the base form.
 */
export const arrow = options => ({
  name: "arrow",
  options,
  async fn(state) {
    const {
      x,
      y,
      placement,
      rects,
      platform,
      elements,
      middlewareData
    } = state;
    const {
      element,
      padding = 0,
      offsetParent = "real"
    } = evaluate(options, state) || {};
    const arrowElement = resolveArrowElement(element);
    if (arrowElement == null) {
      return {};
    }
    const paddingObject = getPaddingObject(padding);
    const coords = {
      x,
      y
    };
    const axis = getAlignmentAxis(placement);
    const length = getAxisLength(axis);
    const arrowDimensions = await platform.getDimensions(arrowElement);
    const isYAxis = axis === "y";
    const minProp = isYAxis ? "top" : "left";
    const maxProp = isYAxis ? "bottom" : "right";
    const clientProp = isYAxis ? "clientHeight" : "clientWidth";
    const endDiff = rects.reference[length] + rects.reference[axis] - coords[axis] - rects.floating[length];
    const startDiff = coords[axis] - rects.reference[axis];
    const arrowOffsetParent = offsetParent === "real" ? await platform.getOffsetParent?.(arrowElement) : elements.floating;
    let clientSize = elements.floating[clientProp] || rects.floating[length];

    // DOM platform can return `window` as the `offsetParent`.
    if (!clientSize || !(await platform.isElement?.(arrowOffsetParent))) {
      clientSize = elements.floating[clientProp] || rects.floating[length];
    }
    const centerToReference = endDiff / 2 - startDiff / 2;

    // If padding is large enough that it causes the arrow to no longer be
    // centered, clamp the padding so the arrow stays centered.
    const largestPossiblePadding = clientSize / 2 - arrowDimensions[length] / 2 - 1;
    const minPadding = Math.min(paddingObject[minProp], largestPossiblePadding);
    const maxPadding = Math.min(paddingObject[maxProp], largestPossiblePadding);

    // Prevent the arrow from overflowing the floating element when the
    // center point is outside the floating element's bounds.
    const min = minPadding;
    const max = clientSize - arrowDimensions[length] - maxPadding;
    const center = clientSize / 2 - arrowDimensions[length] / 2 + centerToReference;
    const offset = clamp(min, center, max);

    // If the reference is small enough that the arrow's padding causes it
    // to point to nothing for an aligned placement, adjust the offset of
    // the floating element itself. A single reset keeps `shift()` active.
    const shouldAddOffset = !middlewareData.arrow && getAlignment(placement) != null && center !== offset && rects.reference[length] / 2 - (center < min ? minPadding : maxPadding) - arrowDimensions[length] / 2 < 0;
    let alignmentOffset = 0;
    if (shouldAddOffset) {
      alignmentOffset = center < min ? center - min : center - max;
    }
    return {
      [axis]: coords[axis] + alignmentOffset,
      data: {
        [axis]: offset,
        centerOffset: center - offset - alignmentOffset,
        ...(shouldAddOffset && {
          alignmentOffset
        })
      },
      reset: shouldAddOffset
    };
  }
});
//# sourceMappingURL=arrow.jsx.map
