/**
 * Stage 4.1 port of Base UI React's `useInteractions` hook.
 *
 * React source:
 *   `base-ui/packages/react/src/floating-ui-react/hooks/useInteractions.ts`.
 *
 * Merges the prop bags produced by individual interaction hooks (`useHover`,
 * `useFocus`, `useClick`, `useDismiss`, `useListNavigation`, `useRole`, ...)
 * into three prop-getters (`getReferenceProps`, `getFloatingProps`,
 * `getItemProps`) plus a fourth `getTriggerProps` that Base UI's fork adds
 * for separate trigger/reference handling.
 *
 * ### React → Solid deviations
 *
 * 1. React memoises each getter with `useCallback` keyed on per-element
 *    `propsList` slices so the identity is stable across renders. Solid
 *    components don't re-run their bodies, so the returned getters are
 *    plain functions — identity is stable for the lifetime of the call
 *    site already.
 *
 * 2. React's hand-rolled `mergeProps` loop duplicates the merge semantics
 *    that `mergePropsN` (`src/internals/merge-props-n.ts`) already
 *    implements for the rest of the Solid port: event handlers chain
 *    instead of overwriting, `class` / `style` compose, right-most
 *    non-`undefined` wins for scalars. The port delegates to
 *    `mergePropsN` instead of reimplementing. One consequence: the
 *    `preventBaseUIHandler()` chain-short-circuit that `mergePropsN`
 *    arms on the event is automatically honored here too (React's
 *    source has no equivalent — it returns the first non-undefined
 *    result from the handler array, which is a different contract).
 *
 * 3. React's `for…in` enumeration of source objects in `mergeProps`
 *    walks prototype-inherited keys; Solid's `mergePropsN` walks
 *    `Object.keys` only. Hook-produced bags are plain objects in both
 *    ports, so the distinction doesn't matter in practice.
 *
 * 4. React uses `React.HTMLProps<Element>` for the user-prop parameter
 *    type. The Solid port accepts `ElementPropsBag` from `../types`,
 *    which is `JSX.HTMLAttributes<any> & Record<string, unknown>` —
 *    the same loose bag already used for inter-hook prop passing.
 */

import { mergePropsN } from "../../merge-props-n.jsx";
import { ACTIVE_KEY, FOCUSABLE_ATTRIBUTE, SELECTED_KEY } from "../utils/constants.jsx";
/**
 * Strip the `item`-scope-only `active` / `selected` keys from a prop bag —
 * they are used to parameterise item getter callbacks, not to be forwarded
 * as DOM attributes.
 */
function stripItemScopeKeys(source) {
  if (!source) return source;
  if (!(ACTIVE_KEY in source) && !(SELECTED_KEY in source)) return source;
  const out = {};
  for (const key of Object.keys(source)) {
    if (key === ACTIVE_KEY || key === SELECTED_KEY) continue;
    out[key] = source[key];
  }
  return out;
}

/**
 * Resolve the per-element prop bag out of an interaction-hook return. For
 * `item`-scope, the bag can be a function that receives the user props
 * (including `active` / `selected`) and returns the concrete DOM props;
 * React's source invokes it lazily inside `mergeProps`. We do the same.
 */
function resolvePropsFor(entry, elementKey, userProps) {
  if (!entry) return undefined;
  const propsOrGetter = entry[elementKey];
  if (propsOrGetter == null) return undefined;
  if (typeof propsOrGetter === "function") {
    if (!userProps) return undefined;
    const resolved = propsOrGetter(userProps);
    return resolved;
  }
  return propsOrGetter;
}

/**
 * Merges an array of interaction-hook prop bags into the four prop-getters
 * consumed by Base UI's floating surfaces. Each getter runs `mergePropsN`
 * at call time, so event-handler chaining and `preventBaseUIHandler` work
 * consistently with the rest of the Solid internals.
 */
export function useInteractions(propsList = []) {
  function mergeFor(elementKey, userProps, seed) {
    const isItem = elementKey === "item";
    const sources = [];
    if (seed) sources.push(seed);
    for (let i = 0; i < propsList.length; i += 1) {
      const resolved = resolvePropsFor(propsList[i], elementKey, userProps);
      sources.push(isItem ? stripItemScopeKeys(resolved) : resolved);
    }
    sources.push(isItem ? stripItemScopeKeys(userProps) : userProps);
    return mergePropsN(sources);
  }
  function getReferenceProps(userProps) {
    return mergeFor("reference", userProps);
  }
  function getFloatingProps(userProps) {
    // `tabIndex: -1` + `data-quoin-focusable` seed the floating element
    // as focusable-but-not-tabbable; later sources may override either.
    const seed = {
      tabIndex: -1,
      [FOCUSABLE_ATTRIBUTE]: ""
    };
    return mergeFor("floating", userProps, seed);
  }
  function getItemProps(userProps) {
    return mergeFor("item", userProps);
  }
  function getTriggerProps(userProps) {
    return mergeFor("trigger", userProps);
  }
  return {
    getReferenceProps,
    getFloatingProps,
    getItemProps,
    getTriggerProps
  };
}
//# sourceMappingURL=use-interactions.jsx.map
