"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.createInlineMiddleware = createInlineMiddleware;
exports.getInlineRectTriggerProps = getInlineRectTriggerProps;
exports.updateInlineRectCoords = updateInlineRectCoords;
var _dom = require("@floating-ui/utils/dom");
// Floating UI ships an `inline()` middleware. This local version mirrors its line-rect
// selection while adding trigger identity checks, delayed-open hit-line reuse, and
// improved left/right edge grouping for Preview Card's reusable trigger model.

function createRect(left, top, right, bottom) {
  return {
    left,
    top,
    right,
    bottom,
    x: left,
    y: top,
    width: right - left,
    height: bottom - top
  };
}
function copyRect(rect) {
  return {
    left: rect.left,
    top: rect.top,
    right: rect.right,
    bottom: rect.bottom,
    width: rect.width,
    height: rect.height
  };
}
function getLineRects(rects) {
  const lines = [];
  let previousRect;
  let left = Number.POSITIVE_INFINITY;
  let top = Number.POSITIVE_INFINITY;
  let right = Number.NEGATIVE_INFINITY;
  let bottom = Number.NEGATIVE_INFINITY;
  for (const rect of Array.from(rects).sort((a, b) => a.top - b.top)) {
    left = Math.min(left, rect.left);
    top = Math.min(top, rect.top);
    right = Math.max(right, rect.right);
    bottom = Math.max(bottom, rect.bottom);
    if (!previousRect || rect.top - previousRect.top > previousRect.height / 2) {
      lines.push(copyRect(rect));
    } else {
      const line = lines[lines.length - 1];
      line.left = Math.min(line.left, rect.left);
      line.right = Math.max(line.right, rect.right);
      line.bottom = Math.max(line.bottom, rect.bottom);
      line.width = line.right - line.left;
      line.height = line.bottom - line.top;
    }
    previousRect = rect;
  }
  return {
    lines,
    fallback: createRect(left, top, right, bottom)
  };
}
function findLineIndex(lines, x, y) {
  return lines.findIndex(lineRect => x > lineRect.left - 2 && x < lineRect.right + 2 && y > lineRect.top - 2 && y < lineRect.bottom + 2);
}
function createClientRect(rect) {
  return createRect(rect.left, rect.top, rect.right, rect.bottom);
}
function getInlineRectCoords(element, clientX, clientY) {
  const {
    lines
  } = getLineRects(element.getClientRects());
  if (lines.length < 2) {
    return undefined;
  }
  const lineIndex = findLineIndex(lines, clientX, clientY);
  return {
    x: clientX,
    y: clientY,
    lineIndex: lineIndex === -1 ? undefined : lineIndex,
    element
  };
}
function getInlineReferenceRect(reference, placement, coords) {
  const {
    lines,
    fallback
  } = getLineRects(reference.getClientRects());
  if (lines.length < 2) {
    return null;
  }
  const x = coords?.x;
  const y = coords?.y;
  const side = placement[0];
  if (coords?.lineIndex != null && lines[coords.lineIndex]) {
    return createClientRect(lines[coords.lineIndex]);
  }
  if (x != null && y != null) {
    const lineIndex = findLineIndex(lines, x, y);
    if (lineIndex !== -1) {
      return createClientRect(lines[lineIndex]);
    }
  }
  if (lines.length === 2 && lines[0].left > lines[1].right && x != null && y != null) {
    return fallback;
  }
  if (side === 't' || side === 'b') {
    const firstRect = lines[0];
    const lastRect = lines[lines.length - 1];
    const targetRect = side === 't' ? firstRect : lastRect;
    return createRect(targetRect.left, firstRect.top, targetRect.right, lastRect.bottom);
  }
  const isLeft = side === 'l';
  let left = lines[0].left;
  let right = lines[0].right;
  let edge = isLeft ? Number.POSITIVE_INFINITY : Number.NEGATIVE_INFINITY;
  let targetFirstRect = lines[0];
  let targetLastRect = lines[0];
  for (const rect of lines) {
    left = Math.min(left, rect.left);
    right = Math.max(right, rect.right);
    const nextEdge = isLeft ? rect.left : rect.right;
    if (isLeft && nextEdge < edge || !isLeft && nextEdge > edge) {
      edge = nextEdge;
      targetFirstRect = rect;
      targetLastRect = rect;
    } else if (nextEdge === edge) {
      targetLastRect = rect;
    }
  }
  return createRect(left, targetFirstRect.top, right, targetLastRect.bottom);
}
function getContextElement(reference) {
  if ('contextElement' in reference && reference.contextElement) {
    return reference.contextElement;
  }
  return (0, _dom.isElement)(reference) ? reference : undefined;
}
function getInlineRectTriggerProps(coordsRef, isOpen) {
  function updateCoords(event) {
    updateInlineRectCoords(coordsRef, event.currentTarget, event.clientX, event.clientY);
  }
  function updateCoordsOnMove(event) {
    if (!isOpen) {
      updateCoords(event);
    }
  }
  return {
    onFocus() {
      coordsRef.current = undefined;
    },
    onMouseEnter: updateCoords,
    onMouseMove: updateCoordsOnMove
  };
}
function updateInlineRectCoords(coordsRef, element, clientX, clientY) {
  const nextCoords = getInlineRectCoords(element, clientX, clientY);
  coordsRef.current = nextCoords;
  return nextCoords;
}
function createInlineMiddleware(coordsRef) {
  return {
    name: 'inline',
    async fn(state) {
      const reference = state.elements.reference;
      if (typeof reference?.getClientRects !== 'function') {
        return {};
      }
      const contextElement = getContextElement(reference);
      const coords = coordsRef.current;
      const currentCoords = coords?.element === reference || coords?.element === contextElement ? coords : undefined;
      const rect = getInlineReferenceRect(reference, state.placement, currentCoords);
      if (!rect || typeof state.platform.getElementRects !== 'function') {
        return {};
      }
      const resetRects = await state.platform.getElementRects({
        reference: {
          contextElement,
          getBoundingClientRect() {
            return rect;
          }
        },
        floating: state.elements.floating,
        strategy: state.strategy
      });
      if (state.rects.reference.x === resetRects.reference.x && state.rects.reference.y === resetRects.reference.y && state.rects.reference.width === resetRects.reference.width && state.rects.reference.height === resetRects.reference.height) {
        return {};
      }
      return {
        reset: {
          rects: resetRects
        }
      };
    }
  };
}