/**
 * Stage 3 port of Base UI React's `FloatingTree`
 * (`packages/react/src/floating-ui-react/components/FloatingTree.tsx`).
 *
 * Supplies two contexts used by nested floating surfaces that are not DOM
 * descendants of their parent:
 *
 *  - `FloatingNodeContext`  — the parent node for the subtree (id + parentId).
 *  - `FloatingTreeContext`  — the shared `FloatingTreeStore` that tracks
 *    every node in the subtree.
 *
 * Consumers use these to look up siblings / parents for dismiss bubbling,
 * virtual focus navigation between nested menus, and cross-tree events.
 *
 * Port notes:
 * - React's `useRefWithInit(() => externalTree ?? new FloatingTreeStore())`
 *   pattern becomes a plain singleton assignment during setup (Solid
 *   components only "render" once, so `new FloatingTreeStore()` in the
 *   body runs exactly once per `FloatingTree` mount).
 * - `useFloatingNodeId` registers the node via `useIsoLayoutEffect` in
 *   React; the Solid port uses `useIsoLayoutEffect` (from
 *   `src/internals/use-iso-layout-effect.ts`, which aliases
 *   `createRenderEffect`). Cleanup runs via `onCleanup` inside the effect
 *   body.
 * - `FloatingNode` creates a per-render memo for its context value in
 *   React; Solid provides the value via a plain object since the
 *   component body doesn't re-run.
 */
import { createContext, createUniqueId, useContext } from "solid-js";
import { useIsoLayoutEffect } from "../../use-iso-layout-effect.jsx";
import { FloatingTreeStore } from "./floating-tree-store.jsx";
const FloatingNodeContext = createContext(null);
const FloatingTreeContext = createContext(null);

/**
 * Returns the parent node id for nested floating elements, if available.
 * Returns `null` for top-level floating elements.
 */
export function useFloatingParentNodeId() {
  const ctx = useContext(FloatingNodeContext);
  return ctx?.id ?? null;
}

/**
 * Returns the nearest floating tree context, if available.
 */
export function useFloatingTree(externalTree) {
  const contextTree = useContext(FloatingTreeContext);
  return externalTree ?? contextTree;
}

/**
 * Registers a node into the `FloatingTree`, returning its id. If no tree is
 * mounted above, the id is still returned but no registration happens.
 *
 * @see https://floating-ui.com/docs/FloatingTree
 */
export function useFloatingNodeId(externalTree) {
  const id = createUniqueId();
  const tree = useFloatingTree(externalTree);
  const parentId = useFloatingParentNodeId();
  useIsoLayoutEffect(() => undefined, () => {
    if (!id) {
      return;
    }
    const node = {
      id,
      parentId
    };
    tree?.addNode(node);
    return () => {
      tree?.removeNode(node);
    };
  });
  return id;
}
/**
 * Provides parent node context for nested floating elements.
 * @see https://floating-ui.com/docs/FloatingTree
 * @internal
 */
export function FloatingNode(props) {
  const parentId = useFloatingParentNodeId();

  // Matches React's `useMemo(() => ({ id, parentId }), [id, parentId])` —
  // a getter object keeps the `id` field reactive if callers pass a
  // signal-driven `props.id`.
  const value = {
    get id() {
      return props.id;
    },
    parentId
  };
  return <FloatingNodeContext value={value}>{props.children}</FloatingNodeContext>;
}
/**
 * Provides context for nested floating elements when they are not children
 * of each other on the DOM.
 *
 * Not necessary in all cases — only required when there must be explicit
 * communication between parent and child floating elements, including:
 *
 *  - The `bubbles` option in `useDismiss()`.
 *  - Nested virtual list navigation.
 *  - Nested floating elements that each open on hover.
 *  - Custom communication between parent and child floating elements.
 *
 * @see https://floating-ui.com/docs/FloatingTree
 * @internal
 */
export function FloatingTree(props) {
  // One-shot store instantiation — Solid component bodies only execute
  // once per mount so this matches React's `useRefWithInit` exactly.
  const tree = props.externalTree ?? new FloatingTreeStore();
  return <FloatingTreeContext value={tree}>{props.children}</FloatingTreeContext>;
}
//# sourceMappingURL=floating-tree.jsx.map
